2015-03-26 1 views
1

У меня есть упрощенная и многозадачная версия angularjs 1.3, отлично работающая на ie8. К сожалению, когда mootools включен на страницу, существует довольно много конфликтов. Мне удалось получить дескриптор для всех, кроме одного, который содержит добавление/удаление EventListener и dispatchEvent в Window.prototype, HTMLDocument.prototype и Element.prototype. Он проверяет, загружен ли mootools, и, если это так, он добавляет их по-разному.mootools 1.4.2 и угловой 1.3, прекрасно играющий вместе в ie8

!window.addEventListener && (function (WindowPrototype, DocumentPrototype, ElementPrototype, addEventListener, removeEventListener, dispatchEvent, registry) { 
     var addEventListenerFn = function(type, listener) { 
      var target = this; 
      registry.unshift([target, type, listener, 
       function (event) { 
        event.currentTarget = target; 
        event.preventDefault = function() { 
         event.returnValue = false; 
        }; 
        event.stopPropagation = function() { 
         event.cancelBubble = true; 
        }; 
        event.target = event.srcElement || target; 
        listener.call(target, event); 
       }]); 

      // http://msdn.microsoft.com/en-us/library/ie/hh180173%28v=vs.85%29.aspx 
      if (type === 'load' && this.tagName && this.tagName === 'SCRIPT') { 
       var reg = registry[0][3]; 
       this.onreadystatechange = function (event) { 
        if (this.readyState === "loaded" || this.readyState === "complete") { 
         reg.call(this, { 
          type: "load" 
         }); 
        } 
       } 
      } else { 
       this.attachEvent('on' + type, registry[0][3]); 
      } 
     }; 

     var removeEventListenerFn = function(type, listener) { 
      for (var index = 0, register; register = registry[index]; ++index) { 
       if (register[0] == this && register[1] == type && register[2] == listener) { 
        if (type === 'load' && this.tagName && this.tagName === 'SCRIPT') { 
         this.onreadystatechange = null; 
        } 

        return this.detachEvent('on' + type, registry.splice(index, 1)[0][3]); 
       } 
      } 
     }; 

     var dispatchEventFn = function(eventObject) { 
      return this.fireEvent('on' + eventObject.type, eventObject); 
     }; 

     if(Element.prototype.$constructor && typeof Element.prototype.$constructor === 'function') { 
      Element.implement(addEventListener, addEventListenerFn); 
      Element.implement(removeEventListener, removeEventListenerFn); 
      Element.implement(dispatchEvent, dispatchEventFn); 
      Window.implement(addEventListener, addEventListenerFn); 
      Window.implement(removeEventListener, removeEventListenerFn); 
      Window.implement(dispatchEvent, dispatchEventFn); 
     } else { 
      WindowPrototype[addEventListener] = ElementPrototype[addEventListener] = addEventListenerFn; 
      WindowPrototype[removeEventListener] = ElementPrototype[removeEventListener] = removeEventListenerFn; 
      WindowPrototype[dispatchEvent] = ElementPrototype[dispatchEvent] = dispatchEventFn; 
     } 
     DocumentPrototype[addEventListener] = addEventListenerFn; 
     DocumentPrototype[removeEventListener] = removeEventListenerFn; 
     DocumentPrototype[dispatchEvent] = dispatchEventFn; 
    })(Window.prototype, HTMLDocument.prototype, Element.prototype, 'addEventListener', 'removeEventListener', 'dispatchEvent', []); 

Это позволило устранить все мои ошибки. Когда эта функция вызывается в Angular, когда mootools находится на странице, а элемент - это форма addEventListener не определена.

addEventListenerFn = function(element, type, fn) { 
     element.addEventListener(type, fn, false); 
    } 

конкретно эта функция вызывается из formDirective как углам главного так

addEventListenerFn(formElement[0], 'submit', handleFormSubmission); 

Любые идеи, почему элемент формы еще dosn't имеют функцию addEventListener доступны?

+1

Почему 'Element.implement (addEventListener, addEventListenerFn);'? почему бы не использовать MooTools 'addEvent'? – Sergio

+0

нулевые угловые вызовы addEventListener не addEvent, и я бы предпочел как можно ближе приблизиться к исходным реализациям, где это возможно. Я действительно не хочу иметь ничего общего с кодом mootools – Ir1sh

+2

erm. в IE8 возникают проблемы с расширением прототипа элемента. DOM API прикосновен и ушел, он подвергается определенной степени, но есть отсутствующие реквизиты и отсутствие спецификации. MooTools обращается к этому путем копирования методов на элементы элементов непосредственно, когда вы передаете их через '$'/'document.id'. вы можете добавить в 'HTMLFormElement.prototype' прямо в IE8, но никаких обещаний. http://perfectionkills.com/whats-wrong-with-extending-the-dom/ - достойное чтение. Еще одно решение для вас - обернуть элемент в $, но это дерьмо. ('$ (элемент) .addEventListener (type, fn, false);'). –

ответ

2

Расширение родного типа через Element.prototype в IE8 считается очень ненадежным, поскольку прототип только частично открыт, и некоторые вещи не наследуются от него/неправильно.

http://perfectionkills.com/whats-wrong-with-extending-the-dom/

Что MooTools делает в этом случае вместо работы вокруг причуд всех edgecases, которые не прилипают к правильной цепи прото (и из-за IE6/7 и до этого), это скопировать элемент прототипов на объектах узлов DOM при передаче через селектор $.

Это не идеально, потому что.

var foo = document.id('foo'); 
// all known methods from Element.prototype are copied on foo, which now hasOwnProperty for them 
Element.prototype.bar = function(){}; 
foo.bar(); // no own property bar, going up the chain may fail dependent on nodeType 

Во всяком случае, в сторону - вы можете исправить вашу конкретную проблему путем копирования ваших методов из Element.prototype специальной HTMLFormElement.prototype - любые любые другие элементы конструкторы вы можете найти отличаться.

Это не масштабируемый, вы можете получить сообщение об ошибке HTMLInputElement и т. Д., Где вы рисуете линию?

Смежные вопросы