|
spike - библиотека внедряет W3C-шные методы в IE
Снова всем привет, хочу представить вам новую свою разработку.
Данная библиотека предназначена именно для Internet Explorer 6,7,8 а в дальнейшем возможно будет что-то добавлять и в IE9. Скажу сразу, поддержку IE6 я не планировал, но реализация привела к тому что она очень даже хорошо работает в IE6, так что уж не обессудьте. Что именно делает эта библиотека, а делает она очень простые вещи. Добавляет W3C-шные методы в ослобраузер, такие как addEventListener, querySelector и т.д. Каждая реализация, а точнее модель разделена и при необходимости легко извлекается. То-есть библиотеку вы можете построить самостоятельно. Об этом чуть ниже. DOM Element.prototype: В IE7 и ниже нет возможности расширять элементы новыми прототипами, которые мы хотим делегировать всем элементам, для этого я написал небольшую модель для ее эмуляции в IE<8. Теперь она дает возможность нам расширить элементы своими методами. Вот ниже один из способов будет корректно работать в IE 7-ой версии и ниже: var div = document.createElement( 'div' ); Element.prototype.ourNewMethod = function() { alert( 'Привет мир!' ) } div.ourNewMethod(); // alerts 'Привет мир!'и другие вариации которые вам придут в голову. Методы которые добавляет данная библиотека: .addEventListener полная поддержка событий, включая возможность ловить события во время погружения, то-есть третий параметр метода не бездействует..removeEventListener полная поддержка удаления событий, так же удаляет в зависимости от типа фазы распространения..dispatchEvent полная поддержка ручного запуска события.document.createEvent частичная поддержка создания событий, поддерживает события только DOM Level 2, то-есть Event, CustomEvent, UIEvent, MouseEvent. В дальнейшем возможно будет расширена.Полная поддержка экземпляра события, поддерживает такие методы как: .preventDefault() отменить действие по умолчанию..stopPropagation() прервать событие на следующей фазе или другом элементе..stopImmediatePropagation() полная остановка распространение события. (новое в HTML5)и прочие свойства экземпляра события по требованиям DOM Level 2 Так же присутствуют константы указывающие тип фазы: Event.CAPTURING_PHASE Event.AT_TARGET Event.BUBBLING_PHASE Селекторы: .querySelectorAll полный CSS3 селектор для поиска списка элементов, в IE8 добавляет поддержку только тех селекторов которые не имеет нативный метод..querySelector полный CSS3 селектор для поиска одного элемента.getElementsByClassName полная поддержка поиска по классу элемента, так же можно указывать список классов которые обязательно должны будут присутствовать в искомом элементе.matchesSelector полный CSS3 селектор для проверки элементаВсе это на данный момент работает в IE 6,7,8. Жестких тестов не проводил, но во время разработки тесты дали положительный результат. Если будет желание потестить, или найдете ошибку, сообщайте мне и я от нее немедленно избавлюсь. Все это добро вы как всегда можете найти у меня на гитхабе: https://github.com/devote/spike Файлы в корне это собранная библиотека из трех моделей, сами модели вы можете найти в папке models. element.js - нужен для IE ниже 8-й версии, подключать самым первымПостепенно я буду дополнять дополнительные модели, если у вас есть пожелания по написанию моделей я с удовольствием выслушаю. Всем приятной разработки скриптов с мыслью о нормальной кросс-браузерности. Спасибо за внимание! С Уважением, Дмитрий! PS. Не забываем фоловится на гитхабе |
Если я правильно понял, то Element.prototype хранилище методов, ссылки на которые копируются в каждый элемент при вызове одного из добавленных или перезаписанных методов типа createElement, а еще после загрузки документа выполняется такое копирование для всех найденных элементов? Я ожидал какую-нибудь магию с VB-скриптми и htc-файлами
![]() Расскажи, пожалуйста, как реализуется event capturing. |
Цитата:
Цитата:
Картина примерно такая: ![]() Здесь иллюстрируется не совсем понятно, но допустим при возникновении события на элементе TD, не срабатывает всплытие, а идет перенаправление на прокси метод, который запоминает ссылку на элемент в котором произошло событие, и так для каждого элемента до самого верха. После того как событие достигло верхнего элемента, запускается уже планировщик, который проходит по всем элементам которые прокси сохранил в неком кеше для планировщика. В итоге планировщик по ним проходит дважды, сначала сверху-вниз, затем снизу-вверх. Тем самым получая нужный нам эффект. Мда, объясняющий с меня херовый конечно :D |
Выслушаю предложения и пожелания. Если у вас есть желание иметь какие-то возможности в ИЕ но их там нет, то можете внести свое предложение и я рассмотрю его в полной мере. Но методы должны входить в спецификацию w3c, то-есть писать левый функционал которого нет ни в одном браузере, в этой библиотеке я не планирую.
|
devote,
Я правильно понял, что Element.prototype теперь работает? P.S. Да, ещё можно добавить полную поддержку getComputedStyle. P.P.S. Ещё идея, можно добавить геттеры-сеттеры |
Цитата:
Цитата:
Цитата:
|
Цитата:
|
Цитата:
Хотя конечно можно ее организовать как обычно в отдельной модели, которую легко можно будет отключить. Просто я немного не понимаю как подобное решение должно выглядеть. А создавать методы не входящие в стандарты я не хочу. |
Хочу отметить важное замечание, метод .getElementsByClassName реализован полностью по указаниям спецификации, то-есть все реализации лежащие по инету не правильные, и сделаны из-за невнимательности прочтения документа.
Как работает метод, который все выкладывают по инету: допустим мы хотим найти элемент с классом .blah document.getElementsByClassName( 'blah' ); // все как и вездеНо если указать список классов: document.getElementsByClassName( 'blah lala' );То в этом случае реализации кишащие по инету выдадут все элементы с классом .blah и элементы с классом .lala то-есть: <div class="blah"></div> <div class="lala"></div>Найдет оба элемента, так как они удовлетворяют запросам. Как же все таки реально должен работать этот метод, то-есть как описано в спецификации. При попытке искать со списком классов, то-есть у нас есть HTML: <div class="blah"></div> <div class="lala"></div>и мы пытаемся найти элементы: document.getElementsByClassName( 'blah lala' );Нам метод не выдаст ни одного элемента, потому что по критериям не проходят. Отличия тут таковы, что список этих классов должен иметь один и тот-же элемент, если хоть одного класса в элементе нет, то он пропускается. То-есть наш код найдет элемент например вот такой: <div class="lala blah"></div>или такой: <div class="lala test some blah"></div> Вот такие вот секреты рассказывает нам этот метод и спецификация, которую почему-то все читают не так как я :-? |
Цитата:
Если не срабатывает fireEvent, то listener'ы запускаются синхронно? Может фейковый эвент инициировать, чтобы ошибка в listener'е не останавливала выполнение кода. Когда fireEvent ошибку выдаёт? В фазе capturing не имеет смысла обращаться к window.event, чтобы достать дополнительную информацию? |
Цитата:
При навешивании событий на какой либо элемент при помощи addEventListener моя библиотека смотрит, есть ли у нее уже навешанное такое событие на верхний элемент(document) если видит проверка дала отрицательный результат, то она тоже навешивает такое же событие на на самый верхний элемент(document) то-есть раньше чем то что навешивает разработчик. То-есть получается что событие в библиотеке повешено самым первым, что и дает возможность узнать что фаза bubbling закончилась. К примеру вы где-то в своем коде пишите: <div id="lala"></div> <script> document.getElementById('lala').addEventListener( 'click', function( e ) { // здесь не нужно обращаться к window.event // первый параметр вернет этот же объект но с исправлениями // и дополнительными методами alert( e ); // [object Event] }, true ); </script>по сути обычное действие. Далее при вызове метода addEventListener моя библиотека делает действия примерно в таком порядке: ищет у себя в стеке уже про инициализированный планировщик на это событие. если находит, то просто вешает событие через attachEvent при этом обертывая вызов функции что передали вторым аргументом в некий прокси метод, который и будет вызван при клике. Если не находит, то создает планировщик для этого события. В нашем случае это click и слушает самый верхний элемент документа. Далее при срабатывании события вызываются прокси метод, на элементе получившем событие, а тот в свою очередь кладет элемент в стек, что бы потом планировщик с ним далее мог работать. Самым последним получает событие сам верний элемент и в нашем случае тот самый планировщик, так как планировщик был повешен самым первым и поэтому срабатывает самым последним, то-есть он точно знает что за ним более нет слушателей. Ну а потом планировщик уже обрабатывает тот самый кеш, то-есть в кеше лежит список элементов которые должны получить событие. Вот по этим элементам он и проходит обрабатывая при этом результативные значения, такие как stopPropagation, preventDefault и т.д. А после окончания обработки, очищает кеш для следующего наполнения по событию. Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
Конструкция вроде этой будет корректно работать: document.addEventListener( 'myevent', function(){ alert( 'fired myevent' ); }, false ); var evt = document.createEvent( 'Event' ); evt.initEvent( 'myevent', true, true ); document.dispatchEvent( evt ); |
Цитата:
Цитата:
http://javascript.ru/forum/project/7...-potokakh.html Цитата:
|
Цитата:
Цитата:
|
Цитата:
<!DOCTYPE html> <html> <head> <script type="text/javascript" src="https://raw.github.com/devote/spike/master/spike.min.js"></script> </head> <body> <div id="blah"></div> <script type="text/javascript"> // получаем ссылку на элемент var a = document.getElementById( "blah" ); // создаем новый прототип уже после того как получили ссылку на элемент Element.prototype.testNewProto = function() { alert( 'lalalalalala' ) } // выполняем наш новый метод a.testNewProto(); </script> </body> </html>Все для вас, наслаждайтесь :) |
для
var a = document.*!*createElement( "div" )*/!*; Element.prototype.testNewProto = function() { alert( 'lalalalalala' ) } a.testNewProto(); не работает, потому что элемент не в дереве |
Цитата:
Если да, то я буду смотреть библиотеку, если нет, то я просто забуду что существовали ie6,7,8 и 9. :) |
Цитата:
|
Цитата:
|
примерно так получилось:
<!DOCTYPE html> <html> <head> <script type="text/javascript" src="https://raw.github.com/devote/spike/master/spike.min.js"></script> </head> <body> <div id="blah"></div> <script type="text/javascript"> // создаем элемент var div = document.createElement( "div" ); // создаем новый прототип уже после того как получили ссылку на элемент Element.prototype.testNewProto = function() { alert( 'lalalalalala' ); this.innerHTML = "hehe"; document.body.appendChild( this ); } // выполняем наш новый метод div.testNewProto(); </script> </body> </html> |
Что-то вы не того наворотили с capture. При генерации события сначала происходит фаза погружения (capturing), потом фаза всплытия (bubbling). У вас, как я понял, наоборот.
Как можно в IE поймать несуществующую фазу погружения я, к сожалению, не знаю. Может я что-то не понял и у вас решена задача века? |
Обновил первый топик.
P.S. Octane, надеюсь текущая реализация вполне нормальная. |
Цитата:
Цитата:
|
Ага, т.е. всё будет работать похоже на правду, если абсолютно все обработчики будут навешиваться вашей функцией? Так не интересно :)
И как-то много всего вы делаете с DOM-ом в IE. Он не помрёт от натуги в приложении средней сложности? |
Цитата:
if ( document.addEventListener ) { document.addEventListener( ... ) } else { document.attachEvent( ... ) }поэтому да, будет срабатывать моя функция Цитата:
|
Цитата:
В общем одни заглушки будут. Я сейчас тоже занимаюсь проблемами расхода памяти и тестами, ой как там всё страшно. Если приложение большое, то там и без заглушек память может утечь, а с заглушками сам ктулху повелел. Хотя такая библиотека для меня была бы очень желанной. Ну разве что -ie6, там можно даже не пытаться. |
Цитата:
|
Цитата:
|
Function.prototype.bind? Можешь мой вариант посмотреть https://github.com/Octane/jsCore/blo...on/function.js :) В отличие от MDN'овского варианта, бесполезно добавлять свойства в прототип bound-функции, ну и на некоторых тестах со сменой контекста не заваливается.
|
Цитата:
|
Сегодня допилил модель Element
Возможности модели максимально приведены в нормальное состояние, возможность добавления методов полностью реализована без ограничений. Модель инициализируется даже до полной загрузки DOM модели, то-есть обращаться к прототипам элементов вы можете не дожидаясь полной загрузки страницы. небольшой пример, который вы можете запустить в ИЕ 7 и ниже: <html> <head> <script type="text/javascript" src="https://raw.github.com/devote/spike/master/models/element.js"></script> </head> <body> <i></i> <script type="text/javascript"> var div1 = document.createElement( 'div' ); div1.className = "elem_div1"; Element.prototype.test1 = function() { alert( 'это функция "test1" на элементе: ' + this.nodeName + "." + this.className ); } div1.test1(); // нужно добавить элемент в DOM что бы было отслеживание // свойства innerHTML, к сожалению отследить изменение // этого свойства можно лишь тогда когда элемент находится // в DOM модели документа, но я считаю это не большим минусом // так как уважающий себя программист данным свойством // пользуется очень редко, ну или для других целей. document.body.appendChild( div1 ); div1.innerHTML = '<b class="elem_B"></b>'; div1.firstChild.test1(); var div2 = document.createElement( 'div' ); Element.prototype.test2 = function() { alert( 'это функция "test2" на элементе: ' + this.nodeName + "." + this.className ); } alert( [ !!div1.test1, !!div1.test2 ] ); // true,true alert( [ !!div2.test1, !!div2.test2 ] ); // true,true // ищем элемент I в DOM var i = document.getElementsByTagName( 'i' )[0]; // проверяем у него присутствие наших новых методов alert( [ !!i.test1, !!i.test2 ] ); // true,true </script> </body> </html> |
Обновил модель селекторов, теперь она стала весить чуть ли не в два раза меньше чем весила. Селектор рассчитан только для ИЕ<9 поэтому был оптимизирован только для ИЕ, в других браузерах он не будет инициализирован. Используйте его вместе с моделью element и у вас будет полноценные селекторы в ИЕ6-7-8, подробнее о включениях читайте первый топик.
|
devote, блин, спасибо огромное. Для HTA приложений, которые в XP запускаются в ie6 (а в нашей конторе ещё в непропатченном, в некоторых случаях), лучше не придумаешь. Время появится, оттестирую в таких условиях.
|
Цитата:
<!DOCTYPE HTML> <div>div.</div> <div>div.</div> <div>div.</div> <div>div.</div> <script> var stylesheet = document.createStyleSheet(), all = document.all; function find(selector) { stylesheet.addRule(selector, "a:b", 0); for(var i = 0, result = []; i in all; i += 1) { *!* if (all[i].currentStyle.a === "b") { // магия :) */!* result.push(all[i]); } } stylesheet.removeRule(0); return result; } (function(){ var els = find("div"); for(i = 0; i in els; i += 1) els[i].style.border = (i+1)+"px green dashed"; })(); </script> |
GuardCat, всегда рад помочь)
melky, спасибо! Очень интересное решение, я обязательно его рассмотрю и испробую. |
devote, первые тесты показывают, что как-то неожиданно работает getElementsByClass. По заданному имени класса, до подключения библиотеки находит 3 элемента (как и есть), а с подключением — уже 39.
Пропатченый IE6. Запрос выглядит так: document.getElementsByClassName( "needCheck" ); Разметка такая: <HTA:APPLICATION APPLICATIONNAME="Simple credit calc" ID="sc" VERSION="1.6.0.1" BORDER="thick" INNERBORDER="no" ICON="calculator.ico" CONTEXTMENU="no"/> <head> <meta charset = "utf-8"> <title>Удобный кредитный калькулятор</title> <link rel = "stylesheet" href = "styles.css" type = "text/css"></link> </head> <body> <div class = 'header'>Simple credit calc: простой расчёт кредита</div> <sub class = "comment">Честно, наглядно, просто.</sub> <form name = "calc" class = "calc"> <label> <input name = "sum" placeholder = "столько" type = "text" class = "needCheck"></abbr> нужная сумма </label> <label> <input name = "term" placeholder = "на столько" type = "text" class = "needCheck"> срок в месяцах (можно ввести так: «2 года 5 мес.» или «5 лет») </label> <label> <input name = "rate" placeholder = "за столько % в год" type = "text" class = "needCheck"> годовая процентная ставка (не ПСК и не переплата) </label> <label> <input name = "firstPayment" placeholder = "столько внесу" type = "text" class = "txt" title = "Необязательное поле"> размер первоначального взноса (добавьте «%», если в процентах) </label> <h3>Тип платежей</h3> <label> <input type = "radio" name = "paymentType" value = "annuitet" checked></input> Все одинаковые (аннуитетные) </label> <label> <input type = "radio" name = "paymentType" value = "differ" ></input> Уменьшающиеся каждый месяц (дифференцированные) </label> <nobr><input id = "go" type = "button" value = " Расчёт"><img src = 'print.png' onclick = 'print();' alt = "Печать расчётов"></nobr> </form> <div id = "report"></div> <div class = "footer"> <hr noshade size = "2px"> Кредитный калькулятор, использующий стандартные формулы для расчётов © <a title = "Посмотреть профиль автора на одном из форумов" href = "http://javascript.ru/forum/members/15847-guardcat/">Guardcat</a> 2012 </div> <script src = "spike.js"> </script> <script src = "newCredit.js"> </script> <script src = "main.js"> </script> <script src = "operator.js"> </script> </body> </html> |
GuardCat, сейчас посмотрю в чем причина
|
Я исправил ошибку, приношу свои извинения..
|
Цитата:
|
Цитата:
почитав MDN, увидел там ЭТО: Цитата:
мои результаты сравнения говорят, что strict mode тормозит выполнение примерно на 1% (стабильно, в чроме, и файрфоксе.). сравнивал на css.js |
Часовой пояс GMT +3, время: 03:57. |
|