Advertisement
Guest User

Untitled

a guest
Jul 20th, 2017
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * Handler.js  Переносимые функции регистрации и отмены регистрации
  3.  *
  4.  * Этот модуль определяет функции регистрации и отмены регистрации
  5.  * обработчиков событий Handler.add() и Handler.remove(). Обе функции
  6.  * принимают три аргумента:
  7.  *
  8.  * element: DOMэлемент, документ или окно, куда добавляется
  9.  * или откуда удаляется обработчик события.
  10.  *
  11.  * eventType: строка, определяющая тип события, для обработки которого
  12.  * вызывается обработчик. Используются имена типов в соответствии
  13.  * со стандартом DOM, в которых отсутствует префикс "on".
  14.  * Примеры: "click", "load", "mouseover".
  15.  *
  16.  * handler: Функция, которая вызывается при возникновении указанного
  17.  * события в заданном элементе. Данная функция вызывается как метод
  18.  * элемента, в котором она зарегистрирована, и ключевое слово "this"
  19.  * будет ссылаться на этот элемент. Функцииобработчику в качестве
  20.  * аргумента передается объект события. Данный объект будет либо
  21.  * стандартным объектом Event, либо смоделированным объектом.
  22.  * В случае передачи смоделированного объекта он будет обладать
  23.  * следующими свойствами, совместимыми со стандартом DOM: type, target,
  24.  * currentTarget, relatedTarget, eventPhase, clientX, clientY, screenX,
  25.  * screenY, altKey, ctrlKey, shiftKey, charCode, stopPropagation()
  26.  * и preventDefault()
  27.  *
  28.  * Функции Handler.add() и Handler.remove() не имеют возвращаемых значений.
  29.  *
  30.  * Handler.add() игнорирует повторные попытки зарегистрировать один и тот
  31.  * же обработчик события для одного и того же типа события и элемента.
  32.  * Handler.remove() не выполняет никаких действий, если вызывается
  33.  * для удаления незарегистрированного обработчика.
  34.  *
  35.  * Примечания к реализации:
  36.  *
  37.  * В броузерах, поддерживающих стандартные функции регистрации
  38.  * addEventListener() и removeEventListener(), Handler.add()
  39.  * и Handler.remove() просто вызывают эти функции, передавая значение false
  40.  * в третьем аргументе (это означает, что обработчики событий никогда
  41.  * не будут зарегистрированы как перехватывающие обработчики событий).
  42.  *
  43.  * В версиях Internet Explorer, поддерживающих attachEvent(), функции
  44.  * Handler.add() и Handler.remove() используют методы attachEvent()
  45.  * и detachEvent(). Для вызова функцийобработчиков с корректным значением
  46.  * ключевого слова this используются замыкания.
  47.  * Поскольку в Internet Explorer замыкания могут приводить к утечкам памяти,
  48.  * Handler.add() автоматически регистрирует обработчик события onunload,
  49.  * в котором отменяется регистрация всех обработчиков при выгрузке страницы.
  50. 432 Глава 17. События и обработка событий
  51.  * Для хранения информации о зарегистрированных обработчиках функция
  52.  * Handler.add() создает в объекте Window свойство с именем _allHandlers,
  53.  * а во всех элементах, для которых регистрируются обработчики, создается
  54.  * свойство с именем _handlers.
  55.  */
  56. var Handler = {};
  57. // В DOMсовместимых броузерах наши функции являются тривиальными
  58. // обертками вокруг addEventListener() и removeEventListener().
  59. if (document.addEventListener) {
  60.  Handler.add = function(element, eventType, handler) {
  61.  element.addEventListener(eventType, handler, false);
  62.  };
  63.  Handler.remove = function(element, eventType, handler) {
  64.  element.removeEventListener(eventType, handler, false);
  65.  };
  66. }
  67. // В IE 5 и более поздних версиях используются attachEvent() и detachEvent()
  68. // с применением некоторых приемов, делающих их совместимыми
  69. // с addEventListener и removeEventListener.
  70. else if (document.attachEvent) {
  71.  Handler.add = function(element, eventType, handler) {
  72.  // Не допускать повторную регистрацию обработчика
  73.  // _find()  частная вспомогательная функция определена далее.
  74.  if (Handler._find(element, eventType, handler) != 1) return;
  75.  // Эта вложенная функция определяется для того, чтобы иметь
  76.  // возможность вызвать функцию как метод элемента.
  77.  // Эта же функция регистрируется вместо фактического обработчика событий.
  78.  var wrappedHandler = function(e) {
  79.  if (!e) e = window.event;
  80.  // Создать искусственный объект события, отчасти
  81.  // совместимый со стандартом DOM.
  82.  var event = {
  83.  _event: e, // Если потребуется настоящий объект события IE
  84.  type: e.type, // Тип события
  85.  target: e.srcElement, // Где возникло событие
  86.  currentTarget: element, // Где обрабатывается
  87.  relatedTarget: e.fromElement?e.fromElement:e.toElement,
  88.  eventPhase: (e.srcElement==element)?2:3,
  89.  // Координаты указателя мыши
  90.  clientX: e.clientX, clientY: e.clientY,
  91.  screenX: e.screenX, screenY: e.screenY,
  92.  // Состояние клавиш
  93.  altKey: e.altKey, ctrlKey: e.ctrlKey,
  94.  shiftKey: e.shiftKey, charCode: e.keyCode,
  95.  // Функции управления событиями
  96.  stopPropagation: function(){this._event.cancelBubble = true;},
  97.  preventDefault: function() {this._event.returnValue = false;}
  98.  }
  99. 17.3. Модель обработки событий Internet Explorer 433
  100.  // Вызвать функциюобработчик как метод элемента, передать
  101.  // искусственный объект события как единственный аргумент.
  102.  // Если функция Function.call() определена  использовать ее,
  103.  // иначе применить маленький трюк
  104.  if (Function.prototype.call)
  105.  handler.call(element, event);
  106.  else {
  107.  // Если функция Function.call отсутствует,
  108.  // симулировать ее вызов.
  109.  element._currentHandler = handler;
  110.  element._currentHandler(event);
  111.  element._currentHandler = null;
  112.  }
  113.  };
  114.  // Зарегистрировать вложенную функцию как обработчик события.
  115.  element.attachEvent("on" + eventType, wrappedHandler);
  116.  // Теперь необходимо сохранить информацию о пользовательской
  117.  // функцииобработчике и вложенной функции, которая вызывает этот
  118.  // обработчик. Делается это для того, чтобы можно было
  119.  // отменить регистрацию обработчика методом remove()
  120.  // или автоматически при выгрузке страницы.
  121.  // Сохранить всю информацию об обработчике в объекте.
  122.  var h = {
  123.  element: element,
  124.  eventType: eventType,
  125.  handler: handler,
  126.  wrappedHandler: wrappedHandler
  127.  };
  128.  // Определить документ, частью которого является обработчик.
  129.  // Если элемент не имеет свойства "document"  это не окно
  130.  // и не элемент документа, следовательно, это должен быть
  131.  // сам объект document.
  132.  var d = element.document || element;
  133.  // Теперь получить ссылку на объект window, связанный с этим документом.
  134.  var w = d.parentWindow;
  135.  // Необходимо связать этот обработчик с окном,
  136.  // чтобы можно было удалить его при выгрузке окна.
  137.  var id = Handler._uid(); // Сгенерировать уникальное имя свойства
  138.  if (!w._allHandlers) w._allHandlers = {}; // Создать объект, если необходимо
  139.  w._allHandlers[id] = h; // Сохранить обработчик в этом объекте
  140.  // И связать идентификатор информации об обработчике с этим элементом.
  141.  if (!element._handlers) element._handlers = [];
  142.  element._handlers.push(id);
  143.  // Если связанный с окном обработчик события onunload
  144.  // еще не зарегистрирован, зарегистрировать его.
  145.  if (!w._onunloadHandlerRegistered) {
  146.  w._onunloadHandlerRegistered = true;
  147.  w.attachEvent("onunload", Handler._removeAllHandlers);
  148.  }
  149. 434 Глава 17. События и обработка событий
  150.  };
  151.  Handler.remove = function(element, eventType, handler) {
  152.  // Отыскать заданный обработчик в массиве element._handlers[].
  153.  var i = Handler._find(element, eventType, handler);
  154.  if (i == 1) return; // Если нет зарегистрированных обработчиков,
  155.  // ничего не делать
  156.  // Получить ссылку на окно для данного элемента.
  157.  var d = element.document || element;
  158.  var w = d.parentWindow;
  159.  // Отыскать уникальный идентификатор обработчика.
  160.  var handlerId = element._handlers[i];
  161.  // И использовать его для поиска информации об обработчике.
  162.  var h = w._allHandlers[handlerId];
  163.  // Используя эту информацию, отключить обработчик от элемента.
  164.  element.detachEvent("on" + eventType, h.wrappedHandler);
  165.  // Удалить один элемент из массива element._handlers.
  166.  element._handlers.splice(i, 1);
  167.  // И удалить информацию об обработчике из объекта _allHandlers.
  168.  delete w._allHandlers[handlerId];
  169.  };
  170.  // Вспомогательная функция поиска обработчика в массиве element._handlers
  171.  // Возвращает индекс в массиве или 1, если требуемый обработчик не найден
  172.  Handler._find = function(element, eventType, handler) {
  173.  var handlers = element._handlers;
  174.  if (!handlers) return 1; // Если нет зарегистрированных обработчиков,
  175.  // ничего не делать
  176.  // Получить ссылку на окно для данного элемента
  177.  var d = element.document || element;
  178.  var w = d.parentWindow;
  179.  // Обойти в цикле обработчики, связанные с этим элементом, отыскать
  180.  // обработчик с требуемыми типом и функцией. Обход идет в обратном порядке,
  181.  // потому что отмена регистрации обработчиков, скорее всего,
  182.  // будет выполняться в порядке, обратном их регистрации.
  183.  for(var i = handlers.length1; i >= 0; i) {
  184.  var handlerId = handlers[i]; // Получить идентификатор обработчика
  185.  var h = w._allHandlers[handlerId]; // Получить информацию
  186.  // Если тип события и функция совпадают, значит, требуемый обработчик найден.
  187.  if (h.eventType == eventType && h.handler == handler)
  188.  return i;
  189.  }
  190.  return 1; // Совпадений не найдено
  191.  };
  192.  Handler._removeAllHandlers = function() {
  193.  // Данная функция регистрируется как обработчик события onunload
  194.  // с помощью attachEvent. Это означает, что ключевое слово this
  195.  // ссылается на объект window, в котором возникло это событие.
  196.  var w = this;
  197.  // Обойти все зарегистрированные обработчики
  198.  for(id in w._allHandlers) {
  199. 17.4. События мыши 435
  200.  // Получить информацию об обработчике по идентификатору
  201.  var h = w._allHandlers[id];
  202.  // Использовать ее для отключения обработчика
  203.  h.element.detachEvent("on" + h.eventType, h.wrappedHandler);
  204.  // Удалить информацию из объекта window
  205.  delete w._allHandlers[id];
  206.  }
  207.  }
  208.  // Частная вспомогательная функция для генерации уникальных
  209.  // идентификаторов обработчиков
  210.  Handler._counter = 0;
  211.  Handl
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement