JavaScript — урок 6. Ajax

Веб программирование JavaScript — урок 6. Ajax

Помечено: ,

  • В этой теме 0 ответов, 1 участник, последнее обновление 1 год, 7 месяцев назад сделано Васильев Владимир Сергеевич.
Просмотр 0 веток ответов
  • Автор
    Сообщения
    • #5142
      @admin
      StudLance.ru

      Объект XMLHttpRequest

      получение объекта XMLHttpRequest

      Для работы с ajax в используется JavaScript
      объект XMLHttpRequest. В IE7 этот объект реализован только через ActiveX.
      Даже в 7 версии ActiveX все еще предпочтительнее из-за проблем с xml, поэтому
      вначале лучше пытаться получить его.

      function getAjax(){
      if (window.ActiveXObject) // для IE
         return new ActiveXObject("Microsoft.XMLHTTP");
      else if (window.XMLHttpRequest) // для остальных
         return new XMLHttpRequest();
      else {
         alert("Browser does not support AJAX.");
         return null;
        }
      }

      Существуют различные версии ActiveX объектов реализующих XMLHttpRequest и можно опробывать
      разные.

      if (window.ActiveXObject) { // для IE до 7 версии
      var pref = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
      for(var i = 0; i < pref.length; i++)  {
        try  {
             return new ActiveXObject(pref[i] + ".XMLHTTP");
      		} catch (e) {}
        }
      }
      

      состояние запроса

      Определяется значением свойства readyState:

      • 0 — запрос не инициализирован;
      • 1 — соединение открыто;
      • 2 — заголовок получен;
      • 3 — загрузка ответа;
      • 4 — ответ загружен.

      обработка состояния запроса

      Функция обработчик изменения состояния запроса задается как значение свойства
      onreadystatechange

      var obj=getAjax();
      obj.onreadystatechange=function(){
      if(obj.readyState==4)   {
        ... 
        }
      }

      открытие соединения

      Метод open открывает соединение, и имеет следующие аргументы:

      • mode — строка определяющая способ передачи («GET» или «POST»);
      • url — файл на сервере обрабатывающий данные;
      • b — true (асинхронный режим) / false (синхронный);
      • login — имя пользователя (не обязательный арг.);
      • password — пароль (не обязательный арг.).

      отправка данных на сервер

      Данные отправляются методом send. Если для отправки используется get,
      то аргумент метода устанавливают в null.

      ответ сервера

      Определяется значением свойства status, например:

      • 200 — все ок;
      • 404 — страница не найдена.

      результирующие данные

      Данные, полученные от сервера, сохраняются в свойствах:

      • responseText — для текстовых данных;
      • responseXml — для xml данных.

      http заголовок

      • setRequestHeader(header, value) — позволяет установить значение полей http заголовка запроса, т.е. для отсылаемых данных.
        Заголовок должен устанавливаться после открытия соединения;
      • getResponseHeader(header) — позволяет получить значение полей http заголовка ответа, т.е. полученных данных;
      • getAllResponseHeaders() — получить http заголовок ответа полностью.

      Перед отсылкой данных методом post необходимо указать mime тип application/x-www-form-urlencoded, т.е.

      ajax.setRequestHeader("Content-type","application/x-www-form-urlencoded");
      Метод setRequestHeader добавляет запись к заголовку, даже если такое поле было определено ранее.

      Метод get в ajax

      Вводим текст в первом текстовом поле, а во втором отображается
      результат обработки этого текста серверным php скриптом test.php. Обработка заключается в преобразовании маленьких букв в большие. Это работает для английского языка и для некоторых русских символов. Так как в методе get протокола http аргументы передаются в строке адреса, то здесь использована функция encodeURI для
      преобразования русских букв в подходящий формат. Иначе при вводе русских букв получим знаки вопроса в квадратиках. С другими языками это может не пройти из-за различных настроек. Так на домашнем сервере (практически не настроенный) символы других языков не отображались, а на сервере хостинга отображаются. (пример делался в кодировке utf-8, что рекомендуется при работе с ajax вообще)

      <script language="javascript" type="text/javascript">
      <!-- 
      var ajax=null;
      
      function getAjax(){
      if (window.ActiveXObject) // для IE
         return new ActiveXObject("Microsoft.XMLHTTP");
      else if (window.XMLHttpRequest) 
         return new XMLHttpRequest();
      else {
         alert("Browser does not support AJAX.");
         return null;
        }
      }
      
      function ajaxFunction(){
      ajax=getAjax();
      if (ajax != null) {
      ajax.open("GET", 
      "test.php?in="+
        encodeURI(document.getElementById("in").value), 
      true);
      ajax.send(null);
      ajax.onreadystatechange = function(){
        if(ajax.readyState==4)  
            document.getElementById("out").value=ajax.responseText;  
        }
      }
      }
      -->
      </script>

      <form name="myform" action="" >
      Input text: <input type="text" onkeyup="ajaxFunction();" 
                      name="in" id="in" />
      ajax result: <input type="text" name="out" 
                      id="out" />
      </form>
      

      Серверный файл выглядит так

      <?php
      if (isset($_GET['in'])) 
        echo strtoupper($_GET['in']); // для простоты пока так
      ?>

      кэширование

      В IE get запросы кэшируются. Проблема решается установкой
      параметров заголовка на сервере, например, для php

      // указываем, что документ устарел
      header("Expires: Sat, 1 Jan 2000 00:00:00 GMT");  
      // дата последнего обновления документа
      header("Last-Modified: " . gmdate( "D, d M Y H:i:s") . " GMT"); 
      
      //управление кэшем
      header("Cache-Control: no-cache, must-revalidate"); 
      header("Pragma: no-cache");

      Либо заголовок устанавливается в JavaScript

      ajax.setRequestHeader("Cache-Control", 
           "no-store, no-cache, must-revalidate");
      ajax.setRequestHeader("Cache-Control", 
           "post-check=0, pre-check=0");
      ajax.setRequestHeader("Pragma", "no-cache");

      Метод post в ajax

      Смысл примера аналогичен предыдущему примеру. Отличие в том, что здесь данные передаются на сервер методом post. Это удобнее, если данные имеют большой объем, так как длина строки адреса ограничена.
      демонстрация метода post

      <script language="javascript" type="text/javascript">
      <!-- 
      var ajax=null;
      
      // без изменений
      function getAjax(){
      if (window.ActiveXObject) // для IE
         return new ActiveXObject("Microsoft.XMLHTTP");
      else if (window.XMLHttpRequest) 
         return new XMLHttpRequest();
      else {
         alert("Browser does not support AJAX.");
         return null;
        }
      }
      
      function ajaxFunction(){
      ajax=getAjax();
      var param;
      if (ajax != null) {   
         // метод POST, указываем просто имя файла
         ajax.open("POST","testpost.php",true);
         
         // если параметров несколько, то они разделяются &
         param="in="+document.getElementById('in').value;
      
         // добавляем стандартный заголовок http
         // посылаемый через ajax
         ajax.setRequestHeader("Content-type", 
               "application/x-www-form-urlencoded");
         
         // вроде эти могут тормозить      
         ajax.setRequestHeader("Content-length", param.length);
         ajax.setRequestHeader("Connection", "close"); 
         
         ajax.onreadystatechange = function(){      
         if(ajax.readyState==4 && ajax.status==200)  
               document.getElementById('out').value=ajax.responseText;  
         }
      
         // посылаем наши данные или пустую строку (param="")
         // главное не null
         ajax.send(param);  
      }
      }
      -->
      </script>
      
      <form name="myform">
      Input text: <input type="text" onkeyup="ajaxFunction();" name="in" id="in" />
      ajax result: <input type="text" name="out" id="out" />
      </form>

      Серверный файл выглядит так

      <?php
      if (isset($_POST['in'])) 
        echo strtoupper($_POST['in']);
      ?>

      Кодировка в Ajax

      Хотя кажется в методе setRequestHeader и можно установить кодировку, данные отсылаются в utf-8 (может особенности браузера). Поэтому, при работе с ajax рекомендуется работать с utf как при отсылке данных так и при получении.

      По документации кодировка полученных данных определяется следующим образом. Если mime тип данных text/xml, application/xml, …+xml,text/html, то кодировка определяется по стандарту этих документов.

      Если кодировка не указана в заголовке в поле Content-type, то в полученных данных проверяется наличие одного из следующих байтовых префиксов:

      • 00 00 FE FF — utf32 be кодировка (be — старший байт в конце);
      • FF FE 00 00 — utf32 le кодировка (le — младший байт в конце);
      • FE FF — itf16 be кодировка;
      • FF FE — utf16 le кодировка;
      • EF BB BF — utf8 кодировка.

      Если префикс не указан, то полагается кодировка utf8.

      Когда возвращаемые данные генерируются скриптом, а не просто загружаются из файла, то заголовок необходимо указывать явно в начале скрипта. Например, в php это делается с помощью header

      <?php header("Content-type: text/xml; charset=windows-1251");
      // ниже генерим документ, например, xml
      ...

      Если генерируемый документ не в utf, и при этом вы хотите использовать полученные данные, то необходима конвертация. В php это делается функцией iconv
      iconv("utf-8","windows-1251",$_POST["data"]);

      Если данные передаются методом get, необходимо использовать функцию encodeURI(url). В php скрипте с кодировкой utf, такие данные не требуют преобразований.

      Xml и ajax

      В данном примере серверный файл генерирует данные в формате xml, используя текст введенный в верхнем поле. После этого клиент разбирает результирующий xml объект, и вставляет значение элемента myitem во второе поле.
      демонстрация загрузки xml

      <script language="javascript" type="text/javascript">
      <!-- 
      var ajax=null;
      
      function getAjax(){
      if (window.ActiveXObject) // для IE
         return new ActiveXObject("Microsoft.XMLHTTP");
      else if (window.XMLHttpRequest) 
         return new XMLHttpRequest();
      else {
         alert("Browser does not support AJAX.");
         return null;
        }
      }
      
      function ajaxFunction2(){
      ajax=getAjax();
      var param;
      if (ajax != null) {   
      
      ajax.open("POST","testxml.php",true);
      
      // для FF 
      if (ajax.overrideMimeType)
         ajax.overrideMimeType("text/xml"); // или "text/xml" application/xml 
         
         // если параметров несколько то они разделяются &
         param="in="+document.getElementById("in").value;
         
         ajax.setRequestHeader("Content-Type",    
         "application/x-www-form-urlencoded; charset=UTF-8"); 
             
         ajax.onreadystatechange = function(){       
         var xml;
         if(ajax.readyState==4 && ajax.status==200){  
         
              // Исправление ошибки в IE для ActveX  
      		if(!ajax.responseXML.documentElement && ajax.responseStream)			
      			 ajax.responseXML.load(ajax.responseStream);
      		
              xml=ajax.responseXML;                  
       
              document.getElementById("out").value=
              xml.getElementsByTagName("myitem")[0].firstChild.nodeValue ;
             }  
         } 
         ajax.send(param);  
      }
      }
      -->
      </script>

      Серверный файл выглядит следующим образом.
      <?php
      echo <<<EOD
      <?xml version="1.0" encoding="utf-8" ?>
      <myitem>
      Hello World,
      {$_POST['in']}
      привет мир
      EOD;
      
      if (isset($_POST['in'])) 
         echo $_POST['in'];  
         
      echo " </myitem>" ;  
      ?>

      Если будет допущена ошибка в xml, например, пропущен закрывающий тег, то xml объект не будет создан.

      Ajax приложение с jquery

      Библиотека JQuery поддерживает несколько методов для работы с ajax: get, post и ajax. Последний метод позволяет указать явно различные настройки для загрузки страницы.

      Ниже приведены предыдущие примеры переписанные с использованием JQuery.

      Demo get metod

      <form name="myform">
      Demo get metod<br>
      Input text: <input type="text" onkeyup="ajaxFunction();" 
                      name="in" id="in" />
      ajax result: <input type="text" name="out" id="out" />
      </form>
      
      <script language="javascript" type="text/javascript">
      <!-- 
      function ajaxFunction(){
        $.get("test.php", { "in" : $("#in").val()},
        function(data){
           $("#out").val(data);
        
        }, "text");
      }
      -->
      </script>

      Demo post metod

      <form>
      Demo post metod<br>
      Input text: <input type="text" onkeyup="ajaxFunction1();" 
                      name="in1" id="in1" />
      ajax result: <input type="text" name="out1" id="out1" />
      </form>
      
      <script language="javascript" type="text/javascript">
      <!-- 
      function ajaxFunction1(){
        $.post("testpost.php", { "in" : $("#in1").val()},
        function(data){
           $("#out1").val(data); 
        }, "text");
      }
      -->
      </script>

      Demo ajax metod

      <form name="form2">
      Demo ajax method <br>
      Input text: <input type="text" onkeyup="ajaxFunction2();" 
                   name="in2" id="in2" />
      <br>
      ajax result: <textarea rows=5 cols=40 name="out2" 
                    id="out2" value=""></textarea> 
      </form>
      
      <script language="javascript" type="text/javascript">
      <!-- 
      // создание XML объекта по строке
      function doXML(data){
      var xml;
      if(window.ActiveXObject){ // IE
        xml = new ActiveXObject("Microsoft.XMLDOM");
        xml.async = false;
        xml.loadXML(data);
        }
      else { 
         if (document.implementation.createDocument){ // FF и Opera
            var parser=new DOMParser();    
            xml = parser.parseFromString(data, "text/xml");
            } 
        }   
      return xml;
      }
      
      function ajaxFunction2(){
      $.ajax({
        url: "testxml.php",
        cache: false,
        type: "POST",
        data: "in="+$("#in2").val(),
        dataType: "text", // тип xml не сработал 
        success: function(data){
        var xml=doXML(data);  
        $("#out2").val( $(xml).find('myitem').text());    
        }
      });  
      }
      -->
      </script>

      1. Во многих примерах к методам get и post объект указывается без кавычек

      {in : $("#in").val()}

      Это работает только в FF. Если имя объекта закавычить, то работает и в FF и в IE

      {"in" : $("#in").val()}

      2. На всякий случай, вдруг кто запутается. Для всех трех примеров я использовал серверные файлы от предыдущих примеров, которые работают только с одной переменной in. Отсюда некоторое не соответствие имен в

      "in" : $("#in1").val()

      Ajax и innerHTML

      Суть проблемы в том, что после изменения средствами аякса innerHTML некоторого элемента, использовать это новое значение в блоке скрипта можно со второй попытки. Пусть есть следующий код

      <script type="text/javascript">
      function af(iid){
      var ajax=getAjax();
      if (ajax != null) {      
         ajax.open("POST","anytext.php",true);
         ajax.setRequestHeader("Content-type", 
               "application/x-www-form-urlencoded");
         ajax.onreadystatechange = function(){      
         if(ajax.readyState==4 && ajax.status==200)  
               document.getElementById(iid).innerHTML=ajax.responseText;  
               // здесь alert(document.getElementById(iid).innerHTML);
               // тоже будет работать корректно
               
         }
         ajax.send("");  
      }
      }
      
      function test(){
      af('test');
      // в первый раз выйдет пустая строка
      alert(document.getElementById('test').innerHTML);
      // со второго раза ок
      alert(document.getElementById('test').innerHTML);
      }
      </script>

      StudLance.ru

Просмотр 0 веток ответов
  • Для ответа в этой теме необходимо авторизоваться.
×