- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
(function(G, D) {
"use strict";
var $ = G.jQuery,
listener;
function addListener(elem, fn) {
function handler(event) {
event = event || G.event;
var dx = event.DeltaX || event.wheelDeltaX || event.detail || 0,
dy = event.DeltaY || event.wheelDeltaY || event.detail || 0;
event.dx = dx === 0 ? 0 : dx / Math.abs(dx);
event.dy = dy === 0 ? 0 : dy / Math.abs(dy);
fn(event);
}
if (elem.addEventListener) {
if (D.hasOwnProperty('onwheel')) { //Modern browsers
listener = "wheel";
} else if (D.hasOwnProperty('onmousewheel')) { //Old browsers
listener = "mousewheel";
} else { //FF<17
listener = "MozMousePixelScroll";
}
elem.addEventListener(listener, handler, false);
} else { //IE<9
elem.attachEvent("onmousewheel", handler);
listener = "onmousewheel";
}
}
function removeListener(elem) {
if (elem.removeEventListener) {
elem.removeEventListener(listener);
} else {
elem.detachEvent(listener);
}
}
$.fn.mousewheel = function(fn) {
return this.each(function() {
addListener(this, fn);
});
};
$.fn.unmousewheel = function(fn) {
return this.each(function() {
removeListener(this, fn, false);
});
};
}(this, document));
Написал плагин для jQuery, который цепляет на элементы обработчик события вращения колесика мыши. Что скажете? Как бы вы написали функцию unmousewheel()?
2. removeEventListener удаляет undefined
Только если там говна еще больше
1. Значение listener всё так же одно на всех, его всё ещё можно изменить.
2. Настоятельно рекомендую автору открыть https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.removeEventListener и кормить removeEventListener нужными ему аргументами (да и detachEvent тоже)
В новой версии добавлено:
1. typeof x === "array". В текущей версии JS typeof [] === "object". [] instanceof Array может при каких-то случаях глюкнуть, но в вашем jQuery есть isArray http://api.jquery.com/jquery.isarray/
2. for (i in this.wheelEvents) - не надо так.
3. Кажется (по сигнатуре), что removeListener удаляет только одну функцию, но нет, это обман, он удаляет все сразу.
4. А в строке 58 пропущено "elem." Из-за того, что typeof elem.wheelEvents никогда не примет значение "array", строка 58 никогда не вызовется и "use strict" не спасёт.
5. elem.wheelEvents = []; - нехорошо как-то дополнять объекты
(хотя, в jQuery, судя по исходникам (src/data/Data.js, src/event.js), дополняют объект полем с уникальным для каждого экземпляра Data именем (jQuery.expando + Math.random()) и уникальным для каждого объекта значением (Data.uid++), а данные хранят в экземпляре Data). Раз уж так вышло, что в объект что-то добавлено, можно и строку listener в сам объект складывать.
Но раз в jQuery для привязывания событий используют Data, надо бы и автору посмотреть http://api.jquery.com/jquery.data/.
Я не знаю традиций пользователей jQuery, потому меня имена немного смущают: вдруг их кто-нибудь займёт. А может, так и надо.
> $.data(elem, "wheelListener", undefined);
Ха-ха, undefined не пройдёт.
http://james.padolsey.com/jquery/#v=1.10.2&fn=_internalData:
Хранить что-либо в свойствах объекта я тоже считаю неправильным, однако же, нет никакого другого способа в данном случае корректно управлять списком обработчиков.
https://github.com/dunmaksim/mousewheel
ну что за однострочное блядство(
в общем это некрасиво, а я эстет
Я с тобой согласен. И, наверное, как минимум половина других разрабов тоже. Нормальный байткод как в жабе или шарпе был бы удобней и шустрее.
Но к сожалению минифицированный жабоскрипт это единственное промежуточное представление, которое работает в браузерах. И все новые языки типа кофейного свитка или печатного свитка компилятся именно в него. И новое внедрить будет очень сложно, а на практике - почти нереально. Так что считай это просто байткодом, и не читай :)
> Грустно все это.
Если минифицированный вариант будет длиннее где-то 500 символов, в большинстве случаев будет уже больше одной строчки. Не грусти, товарищ!
Спасибо, отпустило
Бинарники ты тоже открываешь в редакторе, а потом обзываешь нечитаемым блядством? Просто считай эти файлы бинарниками. Увидел файл .min.js - пройди мимо, или найди его оригинал на сайте разрабов.
P.S. Отладчик огненной лисы, к слову, умеет превращать этот минифицированный код в читаемый и многострочный. Правда названия переменных он уже не восстановит, и они так и останутся a, b, c и т.п.
А вдруг он олдфаг и поклонник PDP-11. А тут уже 2014й на дворе и гигабайты нечитаемого блядства.
> Отладчик огненной лисы
(для справки) И Webkit Devtools умеет, кнопка {}
mousewheel.min.map в помощь
а функции знака нет?
или компаратора -1,0,1 ?
типа
dx = comp(dx,0);
американский форум: задал вопрос - получил ответ
немецкий форум: задал вопрос - дали ссылку, где можно получить ответ
русский форум: задал вопрос - объяснили, что твоя мать шлюха и ты сам не лучше
Есть, Math.sign(dx). Но вот за что я и обожаю js:
Chrome 32
Firefox (Gecko) 25
Internet Explorer Not supported
Opera Not supported
Safari Not supported
P.S. Но деление для определения знака это все же пиздец. Достойно отдельного ГК.
не быстрее, т.к. лучше проводить сравнение: x==0?0:x>0?1:-1
не нагляднее, т.к. целых два вложенных тернарника и без скобок
Зависит от распределения: если нули встречаются чаще всех остальных чисел, ну ок, сначала лучше проверить на 0. Если положительные - то в моем варианте стоит поменять местами ветки. Но один хрен второй тернарник всяко быстрее деления...
> два вложенных тернарника и без скобок
Пыхопроблемы? :) Во всех остальных сиподобных языках цепочки тернарников нормально работают и даже неплохо читаются: если x отрицательный, то -1; если х положительный, то 1; иначе 0.
В хаски вообще можно описать унарный оператор? Или только функцию?
Компилиться, но не дает применить. Для бинарных операторов канает, sqr вместо # тоже.
Сорри за оффтоп, ничего вразумительного не могу найти, видимо слепой
Работает.
Нет.
Пруф: http://www.haskell.org/haskellwiki/Unary_operator
Но и одного унарного оператора хватит всем.
>Во всех остальных сиподобных языках цепочки тернарников нормально работают и даже неплохо читаются: если x отрицательный, то -1; если х положительный, то 1; иначе 0.
Несишкобляственно. Быстрее без ветвлений.
(x>0)-(x<0)
Это смайл если что.
Всё верно?
В каком языке? Если в жс - то почти всё неверно. Для крестов - тоже далеко не всё.
b1 `op` b2 вернет число, а не bool.
5.7:1 The additive operators + and - group left-to-right. The usual arithmetic conversions are performed for operands of arithmetic or enumeration type.
5:9 Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:
<...>
— Otherwise, the integral promotions (4.5) shall be performed on both operands [54].
<...>
54) As a consequence, operands of type bool, wchar_t, or an enumerated type are converted to some integral type.
++b и b++ всегда помещают true в b (разбирали недавно, )
5.2.6:1 After the result is noted, the value of the object is modified by adding 1 to it, unless the object is of type bool, in which case it is set to true. [Note: this use is deprecated, see annex D. ]
--b и b++ не компилится вообще (разбирали в том же треде)
5.2.6:2 The operand of postfix -- is decremented analogously to the postfix ++ operator, except that the operand shall not be of type bool.
1) Это реальный оператор языка, и мы исполняем каждую строчку твоего кода дословно, после чего она должна вернуть истину. Тогда утверждение true + true == true ложно, равно как и true + true == false.
2) Либо == тут наивно-декоративное и мы исполняем только левую часть. И если эту левую часть подставить в условие, то получим тот же самый эффект, что и если подставить туда правую часть: if (true + true) и if (true) сработают одинаково, а if (true + true) и if (false) - нет.
Т.е. true + true является истинным, но в то же время не == true...
>> Но деление для определения знака это все же пиздец. Достойно отдельного ГК.
А вот я вступлюсь за код вышеобосранного кегдана. А там ведь результатов возврата 4, а не 3.
>Красиво, въебал плюс.
Его код был пока что единственным который выдает правильные результаты на всем множестве входных параметров (проверял в других языках - логика та же)
Сделал еще неочевиднее свой вариант.
http://ideone.com/I67qbb
Данная функция имеет 5 видов возвращаемых значений: 1, -1, 0, 0 и NaN, которые означают "положительное число", "отрицательное число", "положительный ноль", "отрицательный ноль" и NaN соответственно.
А какой толк от них в жс? Чтобы делать 1/Math.abs(0) вместо 1/0?
http://ideone.com/98el0B
P.S. Побеждает код Кегдана, как самый первый из корректных. Жаль, что в нем деление.
И вообще в JS надо расширить список тестируемых значений:
http://ideone.com/nLBBIe
А вдруг...
Нет, на js без юнит-тестов писать вообще невозможно.
Вот вроде бы все тесты проходит: http://ideone.com/MGZQK4
Ещё есть {valueOf: function(){ return 42;}}, {toString: function(){ return '42';}}, подобные объекты весело ломают код Кегдана в нуле ("=== помогает", говорили они).
Блин слишком очевидно. Бульдозерный стиль. Сразу раскрывает карты NaN. Я хотел:
а) обойтись без встроенных функций
б) использовать только свойства чисел
в) чтоб код был коротким, но не очень понятным
Вот более короткий вариант:
А есть спека как sign должен себя вести в жс?
>А есть спека как sign должен себя вести в жс?
Чего я спрашиваю. Там не всё так просто. Проверяю в фф
Math.sign(null)==0
Math.sign(false)==0
Math.sign(true)==1
А fatality выдаёт NaN.
Не вижу смысла задрачивать то что не является числом.
А кстати да. И у another борманда тоже (хотя идея интересная).
Я-то только свои на бесконечностях проверял.
Ну оба tangled - мои. Всё отличие "tangled code:" от "3.14159265 code:", это отрицание и перестановка местами.
Я может и дурак, но не настолько, чтобы знак делением искать
Ну да, я уже заметил что код пришёл из оп-поста и как подсказал 1024-- он неправилен на бесконечностях.
>Я может и дурак, но не настолько, чтобы знак делением искать
А как его искать-то? Что может быть лучше и короче:
((x>0)-(x<0)) / (+x==+x))
http://jsperf.com/gc-signum
Зато у Борманда быстрее. Он не преобразует тип и снимает пенки.
Только неправильно
Math.sign(true)
Math.sign(false)
Math.sign(null)
(x===+x ? (x>0)-(x<0) : +x);
http://jsperf.com/gc-signum/2
А в хроме и опере ВНЕЗАПНО изначальное деление быстрее всех.
Деструктивный вариант близок к Math.sign http://jsperf.com/gc-signum/3
Сделал тестирование чисто на числах, ибо по всякой херне типа функций считать знак и при этом хотеть скорости будет только безумец.
Да и насторожило как туго работает родной Math.sign - может на строки и функции он не заточен?
Результаты удивляют - Math.sign - хуже всех. Даже деление его обошло.
И что удивительно fatality тоже слабовато.
PS закешил длину массива и сделал прединкремент http://jsperf.com/gc-signum/4
Особо ничего не поменялось.
http://ideone.com/fTlmN7
http://jsperf.com/gksign/2
?: реабилитирован - с минимальным фиксом даёт верный результат и эпично побеждает во всех трёх браузерах. Только фф додумался так же быстро выполнить моё странное байтоебство.
Простой код и здравый смысл восторжествовали над "умными" хаками, написанными ради потехи.
А сегодня мы будем тестить скорость работы сигнума на моём штеуде. Нечисла - питушня потому НаН, нулл и массивы оставим заедушным питушкам. Нормальные посоны используют тернарник, деление соснуло. Тернарник дал 1MOps. Питушиный Math.sign писали за еду, цари используют тернарники.
Хак (x>0)-(x<0) ему бы понравился - работает быстро в фф, на всех числах, но не всех входных значениях.
В сленг сумасшедших я не умею, потому косплея не будет.
PS> А Math.sign то действительно петушиный и абсолютно бесполезные - работает в полутора браузерах и адски медленно.
типа
3 =='3' - true
3 === '3' - false
Может креста должно быть джва?
x==+x ? (x>0)-(x<0) : +x
А главное: коротко, никаких функций, и сходу нихера непонятно как оно работает! Но работает правильно.
((x>0)-(x<0)) / (+x==x))
http://ideone.com/fTlmN7
+null==null -> false
+null==+null -> true
А в предыдущем примере - нет, т.к. null пойдёт по ветке сравнения с нулём, где правильно приведётся к нулю.
Алсо, можно как-то полностью отключить js без перезагрузки страницы, как в опере?
Я сейчас в IE 11 переключился в режим IE 7, попробовал использовать detachEvent с одним аргументом - не удаляет.
2. delete (handlers[i]); скорее всего делает не то, что Вы ожидаете, скорее всего не нужно.
3. По поводу
Во-первых, "wheelEvents" более нигде не используется, во-вторых:
3.1. $.data работает с местным хранилищем jQuery, хранятся любые объекты
3.2. $.attr - с атрибутами объекта (DOM), аналогично встроеным elem.setAttribute, elem.getAttribute, хранятся строки
3.3. elem.что-то - свойства объекта, иногда синхронизируются с атрибутами, но не эквивалентны
Если Вы хотели написать if (!elem.hasOwnProperty(HANDLERS)), ничего не выйдет, в elem нет его (см. п.п. 3.1, 3.3). Тут надо либо смотреть результат $.data, либо найти в jQuery соответствующую функцию.
4. Удаление старых обработчиков в addListeners - всё же странная фича.
1. Никаких нативных JS-функций, привязанных к конкретному браузеру. Вместо этого с помощью jQuery(elem).on(); цепляется обработчик handler.
2. Соответственно, удаление обработчика с помощью jQuery(elem).off();.
3. Свойство handlers для объекта DOM удаляется целиком с помощью delete(). Будем надеяться, что браузер сможет правильно обработать эту ситуацию.
Я человек скромный, никого ни о чём не спрашивал :) Читал javascript.ru: учебник там хороший; есть статьи, хорошие и плохие; есть форум (вот наверно там Вам кто-нибудь что-нибудь подскажет). Информации с javascript.ru мне хватало, а дальше я просто гуглил. На stackoverlflow уже заданы все вопросы и есть все ответы.
Вон там ближе к низу страницы оффтоп так оффтоп: http://govnokod.ru/16162