Заметки веб-работника
11 августа 2006

Всплывающие подсказки в духе AJAX

Модный термин в заголовке статьи не должен вводить в заблуждение. Несмотря на свою современность, техника, подобная той, что рассматривается в предложенном здесь примере, скорее соответствуют духу «old school», так как известна уже достаточно давно. Сегодня, когда компьютеры стали мощнее, а браузеры – совершеннее, целый класс приемов, раннее известный как Remote Scripting, получил второе дыхание, а вместе с ним и новое имя – AJAX.

В целом, конечно, AJAX – не просто свежий взгляд на старые приемы, это и новый подход к созданию приложений, и новый подход к разработке интерфейсов, и принципиально иная функциональность. Понятно, воплощение подобных полноценных проектов – довольно трудоемкая задача. Но очевидно также и следующее, сегодня многие передовые идеи AJAX применимы не только для «навернутых» веб-аппликаций, им по силам вдохнуть жизнь и в «обычные» домашние страницы, сделать их более интерактивными. В качестве наглядного примера такого «оживления» можно предложить и заявленное в теме статьи простое, но, несомненно, полезное решение.

Итак, реализуем механизм подсказок, которые будут появляться при подведении мыши к неким элементам в окне браузера, причем необходимые для отображения данные должны подгружаться в фоновом режиме с сервера. Роль «неких элементов» отдадим, к примеру, гиперссылкам.

Сценарий может быть следующий: находим на странице все ссылки, у которых id соответствуют заданному шаблону (например, id="hintxxx", где xxx – число); для таких ссылок создаем обработчиков событий, чтобы при наведении мыши, при помощи объекта XMLHttpRequest, подгружалась требуемая подсказка. Для упрощения примера, оставим за кадром серверную часть – запрос будет осуществляться просто к определенному текстовому файлу на сервере. Вот необходимый скрипт:

var curHintId = null; // id активной ссылки

// Делаем XMLHttpRequest "универсальным"
if(!window.XMLHttpRequest && window.ActiveXObject)
   var XMLHttpRequest = function() { return new ActiveXObject("Microsoft.XMLHTTP"); }

// Объект, для определения координат мыши
var mouse = {
   x : function(e)
   {
      if (window.event)
         return window.event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
      else if (window.captureEvents)
         return e.pageX;
      else
         return null; 
   },
   y : function(e)
   {
      if (window.event)
         return window.event.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;
      else if (window.captureEvents)
         return e.pageY;
      else
         return null;   
   }
}

function hintsForLinks()
{
   if (window.XMLHttpRequest)
   {
      var hintbox = document.getElementById("hintbox");
      var allLinks = document.getElementsByTagName("a");
      
      // Выбираем только линки для которых есть подсказки (id = "hintxxx")
      var links = new Array();
      var e = 0;
      for(i = 0; i < allLinks.length; i++)
      {
         if (allLinks[i].id.match(/hint\d+/i))
         {
            links[e] = allLinks[i];
            e++;
         }
      }
      
      // Создаем обработчиков событий для ссылок с подсказками
      for(i = 0; i < links.length; i++)
      {
         links[i].onmouseover = function()
         {
            // Здесь может быть "полноценный" запрос
            getXMLDoc("f/" + this.id + ".txt");
            curHintId = this.id;
         }
         links[i].onmouseout = function()
         {
            hintbox.style.left = "-1000px"; // прячем hintbox
            hintbox.innerHTML = "";
         }
         links[i].onmousemove = function(e)
         {
            if (mouse.x(e) && hintbox.innerHTML != "")
            {
               var dx = (document.body.clientWidth - mouse.x(e) + document.body.scrollLeft < hintbox.offsetWidth) ? hintbox.offsetWidth + 15 : 0;
               var dy = (document.body.clientHeight - mouse.y(e) + document.body.scrollTop < hintbox.offsetHeight) ? hintbox.offsetHeight + 15 : 0;
               var x = mouse.x(e) + 10 - dx;
               var y = mouse.y(e) + 10 - dy;
               hintbox.style.left = (x - document.body.scrollLeft > 0) ? x : document.body.scrollLeft;
               hintbox.style.top = (y - document.body.scrollTop > 0) ? y : document.body.scrollTop;
            }
         }
      }
   }
}

function getXMLDoc(url)
{
   try
   {
      req = new XMLHttpRequest();
      if (req)
      {
         // Обработчик, в случае изменения состояние объекта req
         req.onreadystatechange = function () 
         {
            // req.readyState == 4 - отклик с сервера получен.
            if (req.readyState == 4)
            {
               // req.status == 200 - запрос успешно выполнен.
               if (req.status == 200)
               {
                  // Для нашего случая просто заполняем hintbox текстовым содержимым файла. 
                  var hintbox = document.getElementById("hintbox");
                  hintbox.innerHTML = req.responseText;
                  try
                  {
                     document.getElementById(curHintId).fireEvent("onmousemove");
                  }
                  catch(e)
                  {
                     hintbox.style.left = mouse.x(e) + 10;
                     hintbox.style.top = mouse.y(e) + 10;
                  }
               }
            }
         }
         req.open("GET", url, true);
         req.send("");
      }
   }
   catch(e) 
   {
      return;
   }
}

Функцию hintsForLinks() «вешаем» на событие onload страницы, на которой также не забываем, во-первых, разместить див с id="hintbox" (явно или с помощью JavaScript), во-вторых, описать для него нужные стили, к примеру, такие:

#hintbox{
   position:absolute;
   z-index:1;
   width:300px;
   left:-1000px;
   padding:0.7em 1em;
   font-size:80%;
   background:#cce;
   border:1px solid #99c;
   opacity:0.9;
   filter: progid:DXImageTransform.Microsoft.Alpha(Opacity = 90);
}

Благодаря кэшированию GET-запросов браузером, в случае очередной необходимости, подсказка появится без повторного обращения к серверу. В качестве рабочего примера выступает следующий абзац.

Пример АНТИ-ПСИХОЛОГИЗМ – парадигмальная установка, постулируемая модернизмом и в особенности постмодернизмом, которая заключается в программной элиминации субъективного фактора при интерпретации феноменов культуры. В отличие от классической философии, фундированной презумпцией объективности содержания адекватного знания о мире, философия 20 в. подвергает этот «психологизм» радикальному сомнению: трансцендентализм семантически сопрягает психологизм с когнитивным натурализмом, в силу чего теория познания, отвечающая требованиям антинатурализма, мыслится как базирующаяся на парадигме анти-психологизма.


Теги: JavaScript AJAX

 

Комментарии (9)

_______

Вы можете оставить свой отзыв по данной статье:

  Имя
  E-mail (не публикуется)
  Веб-сайт

Комментарий (Теги форматирования не поддерживаются)