Прототип библиотеки jNext
Мне нравится jQuery. Нравится из-за того, с ней я могу сделать почти всё, не прибегая к нативным средствам браузера, не трахаясь с кроссбраузерностью. Но мне не нравится одно: её пихают куда ни попадя, даже в мобильные сайты. Огромная куча кода для поддержки кроссбраузерности инициируется каждый раз, когда открываешь страничку на мобильном. Анимации в jQuery сделаны старым дедовским способом: с помощью свойства style. Кроме этого, я полностью уверен в том, что в недалеком будущем (лет 5—10) она будет казаться старым пердящим запорожцем. Даже сейчас, когда IE6 практически сдох, в коде библиотеки наблюдается его поддержка. Что будет потом, когда умрет IE8? Разработчики будут выковыривать ненужные вещи? Сомневаюсь.
Поэтому я рискнул начать делать библиотеку, очень похожую на jQuery, использующую встроенные фишки по максимуму. Вся выборка элементов происходит с помощью querySelectorAll и matchesSelector, анимации сделаны на CSS3, данные, данные присваиваются элементу с помощью dataset. В дальнейшем, будет реализована работа с классами через classList и т. д. Почему я взял за пример jQuery? Потому что очень удобно было бы писать один код под те же мобилы, планшеты и полноценные компы, просто подключая ту или иную библиотеку. Скрипты на jNext будут совместимы с jQuery, но не наоборот. А потом, можно вообще забить на совместимость, предоставляя свои фишки с блекджеком и шлюхами. В будущем, если руки дойдут, напишу модуль, который определяет, может ли моя либа работать с данным браузером или нет и, исходя из этого, решать, какая библиотека будет задействована. Для примера, приведу алгоритм работы одной из функци. Допустим это siblings. 1. Берем все элементы из текущей выборки и проделываем следующие вещи 2. Допустим node — текущий элемент a) node.dataset.randomId = Math.random(); // допустим 0.1 б) node.parentNode.dataset.randomId = Math.random(); // допустим 0.2 3. Конструируем селектор, он у нас получится таким: [data-random-id=0.2] > :not([data-random-id=0.1]) 4. Применяем селектор к node.parentNode, конкатенируем полученный массив с массивом новой выборки 5. Удаляем .dataset.randomId из 2.а и 2.б Так работает большинство функций выборок и, как показал один из холиваров, в которых я участвовал, достаточно быстро. По поводу сравнения скорости с выборкой на регулярках, думаю, спорить вообще смысла нет. За пару дней набросал прототип и рассказываю это всё, чтоб поинтересоваться, кто уже делал свою библиотеку, с какими трудностями сталкивался, какие советы можно дать к организации кода, чтоб он не превратился в лапшу и пр. Я никогда не писал подобных вещей, поэтому каждый совет будет очень кстати. Чтоб не быть голословным, вот, очень простой пример: http://jsfiddle.net/finom/Yb2MH/ Вот код: http://dl.dropbox.com/u/13598455/jNext/jNext.js , в котором очень много не реализовано, что-то сделано не до конца (метод css вообще работает только на установку стилей). Это прототип, пользоваться нельзя ни в коем случае. Работает пока что только в хроме (может и в сафари) из-за вездесущих префиксов -webkit-. На всякий случай: не нужно здесь писать, что jQuery — говно. Только по коду, пожалуйста. С холиварами в оффтоп и не забудьте дать ссылку. |
Тут многие писали, что jQuery молчалива в плане вывода ошибок. Как лучше реализовать отлов и вывод ошибок?
|
И еще, я тут видел замечания о том, что хотелось бы собирать библиотеку самому, выбирая только нужные функции.
|
Цитата:
|
Рискну спросить.
Никто не может поделиться советами? Может я чем-то задел в своём сообщении? |
Да нет, молодец :)
|
Цитата:
$("#btn").hide() в случае отсутствия #btn, никакой ошибки не произойдет, а логичнее было бы получить в консоли сообщение о том, что какое-то внутреннее свойство null. Я бы сделал 2 функции и 2 набора методов для работы с одним элементом и коллекцией. $("#btn") → {node: HTMLElement} $$(".btn") → {list: Array} Работа с одним элементом: $("#btn").addClass("active") тут мы получим сообщение «node is null», если #btn отсутствует Работа c коллекцией: $$(".btn").each("addClass", "active") |
Цитата:
Цитата:
|
Забыл сделать бекап предыдущей версии, поэтому пример временно не работает.
|
FINoM, почему вы не используете github в таком интересном проекте? хотя бы из-за возможости откатиться или принять чужой фикс какой-нибудь ошибки
PS хм. трудновато понять код, когда он отдан plain'ом на маленький экранчик смартфона. больше всего не понял "класс" Selector. |
Цитата:
|
Цитата:
Самый простой пример: Selector('div').select(node); // просто напросто получает все дивы из node Сложный пример: siblings: function(selector){ selector = selector || ''; this.nodeList = Selector('{parentNode} > ' + selector + ':not({:this})', { parentNode: jNext.mapDefined(this.nodeList, function(element){ return element.parentNode; }), ':this': this.nodeList }).select(); },Первым аргументом передает шаблон селектора, где {такие штуки} в процессе работы скрипта преобразуются в [data-jnextrandomdataid="вот такие"] Вторым аргументом идет объект, ключами которого являются строки из шаблона, а значениями списки узлов, которым нужно добавить рандомный атрибут и которые как бы будут выступать {вот этими} элементами. Не уверен, что норамльно объяснил :D |
Цитата:
|
Цитата:
|
Цитата:
Плюс ко всему, придется отказаться от совместимости с jQ. |
Как правильно организовать получение текущего css? Сначала проверять style, если результат пустой, то смотреть через getComputedStyle? Можно ведь сразу смотреть getPropertyCSSValue, плохая идея?
Нужны ли хуки? Да и вообще, что нужно реализовать в первую очередь (слишком много всего предстоит)? И не хочет ли кто присоединиться на текущем, почти нулевом этапе? |
function style( elem ) { if ( elem.ownerDocument && elem.ownerDocument.defaultView ) { return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); } else if ( elem.currentStyle ) { return elem.currentStyle; } return null; } |
devote, спасибо, но как получить css свойство пользуясь твоим примером?
Цитата:
Цитата:
Ты предлагаешь не пользоваться style вообще для получений значений свойств? |
Цитата:
Цитата:
|
Цитата:
|
FINoM,
всё дело в том, что в функцию может попасть элемент из любого окна/фрейма и тогда реальный документ и объект окна нужно получать из элемента. |
Цитата:
|
devote, пардон, напомню другой вопрос: ты предлагаешь не использовать style вообще?
Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
|
ну и славо Богу, короче style полная муйня, если в теге нет атрибута style то и в style будет пусто. ну или хрень не та
|
Первые тесты производительности (в хроме):
$('div').parents();jQuery работает в 3 раза медленнее. http://jsfiddle.net/finom/4hUAv/1/ $('*').closest('.colour');jQuery медленнее на ~15% http://jsfiddle.net/finom/4hUAv/2/ В самых простых случаях, сравнение немного непредсказуемо: $('*')jQuery на треть медленнее (почему?) $('div')jQuery на 5—10% быстрее (почему?) Это чисто для себя, чтоб убедиться, что дело делаю :D. В дальнейшем нужно будет сделать много много элементов (или взять какой-то уже готовый штмл) и потестить в почти реальных условиях. В .css все-таки всунул style. Не могу быть уверен, но мне кажется геттер style быстрее работает, чем колбаса из объектов и два метода: return first.style[prop] || first.ownerDocument.defaultView.getComputedStyle( first, null ).getPropertyValue( prop ); |
Цитата:
вот пример: <style> div { width: 200px; height: 200px; } </style> <div> </div> <script> var div = document.getElementsByTagName('div')[0]; alert([ div.style.width , div.style.height ]); // нет значений function style( elem ) { if ( elem.ownerDocument && elem.ownerDocument.defaultView ) { return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); } else if ( elem.currentStyle ) { return elem.currentStyle; } return null; } alert([ style(div).width , style(div).height ]); </script> |
Цитата:
|
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
|
Цитата:
document.querySelector("#btn").className += "active"; то получим Цитата:
$("#btn").addClass("active"); почему мы не должны ждать такой же ошибки? а вот, когда работаем с коллекцией, то отсутствие ошибок вполне логично: var list = document.querySelectorAll(".btn"), i = list.length; while (i--) { … } или $(".btn").addClass("active") тут программист берет в расчет, что элементов в коллекции может и не быть, и никакие действия не выполнятся, что на чистом JS, что с помощью jQuery. Чтобы избежать этой проблемы, предлагаю не страдать фигней в погоне за совместимостью с jQuery, а сделать, как мне кажется, более удобно: function $(selector) { return new $Node(document.querySelector(selector)); } function $$(selector) { return new $NodeList(document.querySelectorAll(selector)); } function $Node(node) { this.node = node; } $Node.prototype = { addClass: …, … remove: …, … parent: …, … }; function $NodeList(list) { this.list = list; } $NodeList.prototype = { first: …, … last: …, … each: …, … }; никакого дублирования методов не нужно: $$("selector").each("method", arguments) и в коде будет наглядно: $(selector).remove(); $$(selector).each("remove") |
Цитата:
Цитата:
в случае с querySelector это лишь возврат функции которая может возвращать объекты разных типов(что в общем-то наверное не совсем правильно). когда мы работаем с выборкой, то хочется единого АПИ в независимости есть в выборке элементы или нет(в конце концов это просто состояние объекта) на практике позволяет в клиентском коде избегать ненужных if-в. ЗЫ про style сенкс. не догадывался что есть такая особенность. |
а вообще тс странный. и вступительная речь тоже.
мне например чтобы перевести своё детище на поддержку только "правильных" браузеров понадобиться ну час мб. jquery ну пускай день два. Лично мне видится её главным недостатком(ну по крайней мере сейчас, когда я не спал сколько там... 22 часа) - сверх универсальность. Под конкретные задачи можно сделать лучше. Иногода это критично. Посему к тсу - чтобы делать свой ворк/библиотеку нужен какой-то мотиватор, какая-то задача. Без этого быстро надоест. |
float, чем не задача сделать либу быстрее, чем jQuery, но с совместимостью кода?
|
В общем эта тема превращается в срач, один предлагает поддерживать старые версии ИЕ и критикует сообщения прочитав только половину, другой говорит, что нужно создать отдельные методы для одиночиых элементов, по сути отдельную библиотеку, третий обзывает меня странным, при этом сказав, что за пару часов перепишет jQuery, сделав то же самое что и я. Остальным спасибо за помощь. Если что-то будет готово, сообщу. В срачах учавствовать не буду. На всякий случай, по совету melky запилю на гитхаб после нормальной реализации метода animate.
|
Цитата:
пример: <style> div { width: 200px; height: 200px; } </style> <div id="owner"> <div id="child"></div> </div> <script> function yourStyle( elem, prop ) { return elem.style[prop] || elem.ownerDocument.defaultView.getComputedStyle( elem, null ).getPropertyValue( prop ); } function style( elem ) { if ( elem.ownerDocument && elem.ownerDocument.defaultView ) { return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); } else if ( elem.currentStyle ) { return elem.currentStyle; } return null; } var elem = document.getElementById('owner'); // проверяем твоей: alert( [ yourStyle( elem, 'width' ), yourStyle( elem, 'height' ) ] ); // проверяем моей: alert([ style( elem ).width , style( elem ).height ]); // меняем ширину у элементов: document.getElementById( 'owner' ).style.width = "auto"; document.getElementById( 'child' ).style.width = "300px"; // снова проверяем родителя: // проверяем твоей: alert( [ yourStyle( elem, 'width' ), yourStyle( elem, 'height' ) ] ); // проверяем моей: alert([ style( elem ).width , style( elem ).height ]); </script> |
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
Часовой пояс GMT +3, время: 03:30. |