Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   Прототип библиотеки jNext (https://javascript.ru/forum/project/24387-prototip-biblioteki-jnext.html)

FINoM 28.12.2011 04:35

Прототип библиотеки 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 — говно. Только по коду, пожалуйста. С холиварами в оффтоп и не забудьте дать ссылку.

FINoM 28.12.2011 04:38

Тут многие писали, что jQuery молчалива в плане вывода ошибок. Как лучше реализовать отлов и вывод ошибок?

FINoM 28.12.2011 05:05

И еще, я тут видел замечания о том, что хотелось бы собирать библиотеку самому, выбирая только нужные функции.

FINoM 28.12.2011 06:53

Цитата:

Сообщение от FINoM
Для примера, приведу алгоритм работы одной из функци. Допустим это siblings.

Только сейчас дорубил, что querySelectorAll можно использовать всего-лишь один раз и не задействуя конкатенаций. Просто нужно два раза пробежаться по элементам: сначала выставить рандомный айдишник, затем убрать. Просто непочатый край для оптимизаций.

FINoM 28.12.2011 21:42

Рискну спросить.
Никто не может поделиться советами? Может я чем-то задел в своём сообщении?

DreamTheater 28.12.2011 22:07

Да нет, молодец :)

Octane 28.12.2011 22:23

Цитата:

Сообщение от FINoM
Тут многие писали, что 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 28.12.2011 22:59

Цитата:

Сообщение от Octane
в случае отсутствия #btn, никакой ошибки не произойдет, а логичнее было бы получить в консоли сообщение о том, что какое-то внутреннее свойство null.

Да, согласен.
Цитата:

Сообщение от Octane
Я бы сделал 2 функции и 2 набора методов для работы с одним элементом и коллекцией.

Тогда будет больше кода, а производительность не сильно изменится (при одном элементе будет одна итерация цикла).

FINoM 28.12.2011 23:32

Забыл сделать бекап предыдущей версии, поэтому пример временно не работает.

melky 29.12.2011 00:12

FINoM, почему вы не используете github в таком интересном проекте? хотя бы из-за возможости откатиться или принять чужой фикс какой-нибудь ошибки


PS хм. трудновато понять код, когда он отдан plain'ом на маленький экранчик смартфона. больше всего не понял "класс" Selector.

FINoM 29.12.2011 00:20

Цитата:

Сообщение от melky
FINoM, почему вы не используете github в таком интересном проекте? хотя бы из-за возможости откатиться или принять чужой фикс какой-нибудь ошибки

Все методы пока что сделаны исключительно для демонстрации (самому себе :D) и тестирования возможностей, выкладывать пока что нечего.

FINoM 29.12.2011 03:00

Цитата:

Сообщение от melky
PS хм. трудновато понять код, когда он отдан plain'ом на маленький экранчик смартфона. больше всего не понял "класс" Selector.

Selector отвечает за работу с селекторами :D
Самый простой пример:
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

melky 29.12.2011 08:58

Цитата:

Сообщение от FINoM (Сообщение 146972)
Не уверен, что норамльно объяснил :D

прочёл ещё раз код, стало понятнее )

Kolyaj 29.12.2011 09:25

Цитата:

Сообщение от FINoM
Тогда будет больше кода, а производительность не сильно изменится (при одном элементе будет одна итерация цикла).

Производительность изменится, т.к. если просят один элемент, то достаточно найти первый, остальные не нужны, можно не искать.

FINoM 29.12.2011 15:18

Цитата:

Сообщение от Kolyaj
Производительность изменится, т.к. если просят один элемент, то достаточно найти первый, остальные не нужны, можно не искать.

Потом может быть сравню querySelector с querySelectorAll, но есть сомнения по поводу существенной разницы.

Плюс ко всему, придется отказаться от совместимости с jQ.

FINoM 30.12.2011 04:55

Как правильно организовать получение текущего css? Сначала проверять style, если результат пустой, то смотреть через getComputedStyle? Можно ведь сразу смотреть getPropertyCSSValue, плохая идея?

Нужны ли хуки?

Да и вообще, что нужно реализовать в первую очередь (слишком много всего предстоит)? И не хочет ли кто присоединиться на текущем, почти нулевом этапе?

devote 30.12.2011 05:06

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;
}

FINoM 30.12.2011 05:11

devote, спасибо, но как получить css свойство пользуясь твоим примером?
Цитата:

Сообщение от devote
elem.ownerDocument.defaultView.getComputedStyle( elem, null );

Что это за колбаса? Не проще ли window.getComputedStyle?
Цитата:

Сообщение от devote
elem.currentStyle

Это из ИЕ?

Ты предлагаешь не пользоваться style вообще для получений значений свойств?

trikadin 30.12.2011 05:13

Цитата:

Сообщение от FINoM
Что это за колбаса? Не проще ли window.getComputedStyle?

Это правильный способ получения стиля.

Цитата:

Сообщение от FINoM
Это из ИЕ?

Да.

FINoM 30.12.2011 05:14

Цитата:

Сообщение от trikadin
Это правильный способ получения стиля.

Можно подробнее? Всё дело в возможных проблемах с айфреймом?

Nekromancer 30.12.2011 05:17

FINoM,
всё дело в том, что в функцию может попасть элемент из любого окна/фрейма и тогда реальный документ и объект окна нужно получать из элемента.

devote 30.12.2011 05:18

Цитата:

Сообщение от FINoM
Можно подробнее? Всё дело в возможных проблемах с айфреймом?

IFrame, Fragment, XML и т.д.

FINoM 30.12.2011 05:22

devote, пардон, напомню другой вопрос: ты предлагаешь не использовать style вообще?
Цитата:

Сообщение от Nekromancer
всё дело в том, что в функцию может попасть элемент из любого окна/фрейма и тогда реальный документ и объект окно нужно получать из элемента.

Ок, теперь понял.

devote 30.12.2011 05:27

Цитата:

Сообщение от FINoM
ты предлагаешь не использовать style вообще?

в стайле находятся не текущие стили а стартовые, это разные вещи

FINoM 30.12.2011 05:30

Цитата:

Сообщение от devote
в стайле находятся не текущие стили а стартовые, это разные вещи

Я в курсе. Ладно, забей.

Nekromancer 30.12.2011 05:36

Цитата:

Сообщение от devote
в стайле находятся не текущие стили а стартовые, это разные вещи

Чёй то они стартовые, там просто инлайн стили.

FINoM 30.12.2011 05:42

Цитата:

Сообщение от Nekromancer
Чёй то они стартовые, там просто инлайн стили.

Он хотел сказать наоборот и я его понял :D

devote 30.12.2011 05:54

ну и славо Богу, короче style полная муйня, если в теге нет атрибута style то и в style будет пусто. ну или хрень не та

FINoM 30.12.2011 08:20

Первые тесты производительности (в хроме):
$('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 );

devote 30.12.2011 15:19

Цитата:

Сообщение от FINoM
В .css все-таки всунул style. Не могу быть уверен, но мне кажется геттер style быстрее работает, чем колбаса из объектов и два метода:

неужели так сложно понять что дело не в скорости.

вот пример:

<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>

FINoM 30.12.2011 15:40

Цитата:

Сообщение от devote
неужели так сложно понять что дело не в скорости.

Ок. Прочесть то что чуть ниже никак?

x-yuri 30.12.2011 16:06

Цитата:

Сообщение от FINoM
Нравится из-за того, с ней я могу сделать почти всё, не прибегая к нативным средствам браузера, не трахаясь с кроссбраузерностью.

очень распространенное заблуждение, либо у тебя задачи такие, подходящие

Цитата:

Сообщение от Octane
Мне в jQuery не нравится, что она всегда работает с коллекцией элементов, даже если известно, что элемент один, например:
$("#btn").hide()

в случае отсутствия #btn, никакой ошибки не произойдет, а логичнее было бы получить в консоли сообщение о том, что какое-то внутреннее свойство null.

не согласен, у каждый из двух подходов удобен в соответствующей ситуации, а выдавать ошибки... не вижу в этом необходимости

Цитата:

Сообщение от FiNOM
Тогда будет больше кода, а производительность не сильно изменится (при одном элементе будет одна итерация цикла).

насколько больше?

FINoM 30.12.2011 16:32

Цитата:

Сообщение от x-yuri
насколько больше?

На одну проверку больше: один элемент, делаем это, больше — делаем то.
Цитата:

Сообщение от x-yuri
не вижу в этом необходимости

Ну вот человек ошибся в селекторе, срипт выдал экзепшн "синтакс эррор" и фиг поймешь, в какой строке и к чему относится этот экзепшн. Так ему просто в консоли сообщать: с селектором трабл. Или другая ситуация: селектор вернул 0 элементов, человек применяет цепочку методов, но ничего не происходит. Что делать? Мне кажется вполне логичным написать в консоли, что элементов ноль, и что ничего происходить не должно.

Octane 30.12.2011 17:41

Цитата:

Сообщение от x-yuri
не согласен, у каждый из двух подходов удобен в соответствующей ситуации, а выдавать ошибки... не вижу в этом необходимости

Ну как же, когда мы пишем на чистом JS:
document.querySelector("#btn").className += "active";

то получим
Цитата:

TypeError: document.querySelector("#btn") is null
фреймворк просто сокращает запись:
$("#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")

float 30.12.2011 18:00

Цитата:

то получим
Цитата:

почему мы не должны ждать такой же ошибки?
потому, что имхо это чуть разные вещи.
в случае с querySelector это лишь возврат функции которая может возвращать объекты разных типов(что в общем-то наверное не совсем правильно).
когда мы работаем с выборкой, то хочется единого АПИ в независимости есть в выборке элементы или нет(в конце концов это просто состояние объекта)
на практике позволяет в клиентском коде избегать ненужных if-в.

ЗЫ про style сенкс. не догадывался что есть такая особенность.

float 30.12.2011 18:19

а вообще тс странный. и вступительная речь тоже.
мне например чтобы перевести своё детище на поддержку только "правильных" браузеров понадобиться ну час мб. jquery ну пускай день два.
Лично мне видится её главным недостатком(ну по крайней мере сейчас, когда я не спал сколько там... 22 часа) - сверх универсальность. Под конкретные задачи можно сделать лучше. Иногода это критично.
Посему к тсу - чтобы делать свой ворк/библиотеку нужен какой-то мотиватор, какая-то задача. Без этого быстро надоест.

FINoM 30.12.2011 18:21

float, чем не задача сделать либу быстрее, чем jQuery, но с совместимостью кода?

FINoM 30.12.2011 18:31

В общем эта тема превращается в срач, один предлагает поддерживать старые версии ИЕ и критикует сообщения прочитав только половину, другой говорит, что нужно создать отдельные методы для одиночиых элементов, по сути отдельную библиотеку, третий обзывает меня странным, при этом сказав, что за пару часов перепишет jQuery, сделав то же самое что и я. Остальным спасибо за помощь. Если что-то будет готово, сообщу. В срачах учавствовать не буду. На всякий случай, по совету melky запилю на гитхаб после нормальной реализации метода animate.

devote 30.12.2011 18:37

Цитата:

Сообщение от FINoM
Ок. Прочесть то что чуть ниже никак?

И что мне твое ниже даст?

пример:
<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>

x-yuri 30.12.2011 18:56

Цитата:

Сообщение от FINoM
На одну проверку больше: один элемент, делаем это, больше — делаем то.

выводы о значительности каждый делает сам... учитывая то, что "один элемент, делаем это" - это частный случай "больше — делаем то"

Цитата:

Сообщение от FINoM
Ну вот человек ошибся в селекторе, срипт выдал экзепшн "синтакс эррор" и фиг поймешь, в какой строке и к чему относится этот экзепшн. Так ему просто в консоли сообщать: с селектором трабл. Или другая ситуация: селектор вернул 0 элементов, человек применяет цепочку методов, но ничего не происходит. Что делать? Мне кажется вполне логичным написать в консоли, что элементов ноль, и что ничего происходить не должно.

опять абстрактные примеры? Обычно ты делаешь и проверяешь по ходу. И даже потом не сложно найти ошибку. Если сложно, тогда да, надо ее выдавать.

Цитата:

Сообщение от Octane
почему мы не должны ждать такой же ошибки?

вопрос не в последовательности а в том, будет ли это заметной помощью

Цитата:

Сообщение от Octane
Чтобы избежать этой проблемы, предлагаю не страдать фигней в погоне за совместимостью с jQuery, а сделать, как мне кажется, более удобно:

недостаток этого метода в том, что надо проверять существует ли объект: [jQuery] $('#id').addClass(...), [твой вариант] $('#id') && $('#id').addClass(...) ну или $$('#id').addClass(...), но тогда мы используем $$, несмотря на то, что нас интересует один элемент. Недостаток jQuery в том, что если надо получить доступ к этому одному элементу, надо писать $('#id')[0], вместо $('#id'). Может что-то забыл.

Цитата:

Сообщение от float
Посему к тсу - чтобы делать свой ворк/библиотеку нужен какой-то мотиватор, какая-то задача. Без этого быстро надоест.

хуже, я бы сказал, что библиотеки должны получаться в результате решения задач, а не наоборот ;)

Цитата:

Сообщение от FINoM
В общем эта тема превращается в срач, один предлагает поддерживать старые версии ИЕ и критикует сообщения прочитав только половину, другой говорит, что нужно создать отдельные методы для одиночиых элементов, по сути отдельную библиотеку, третий обзывает меня странным, при этом сказав, что за пару часов перепишет jQuery, сделав то же самое что и я.

"Вы мне, пожалуйста, все тут давайте советы, но если они мне не понравяться, я вас слушать не буду, так что не обижайтесь..."


Часовой пояс GMT +3, время: 03:30.