Pull to refresh

Comments 55

Картинка для привлечения внимания очень сильно привлекает внимание!
Оригинал, если кто не видел.
Автор — Sean Archer, самый популярный (и заслуженно) автор на 500px, из Екатеринбурга.
UFO just landed and posted this here
Пардон за битые якоря, уже исправлено.
Полезные инструменты, спасибо. Но совет с mousedown может и навредить. Я например, после того как случайно нажал кнопку, отвожу фокус от элемента и отпускаю кнопку, чтобы действие не сработало.
Очень прошу автора статьи вообще убрать этот «совет» из статьи. Ни в коем случае нельзя заменять click на mousedown. Не у каждого пользователя есть мышь, а как же клавиатура и тач устойства.
Я написал ниже, что чекбокс должен быть чекбоксом. Просто не очень удачный пример.
Неважно какой элемент. Вы упускаете суть, ваша демка не будет работать на устрйствах, в которых есть только клавиатура, и на некоторых тач устройствах. Вот вам пример — jsbin.com/vacubazehogu/4, попробуйте клавитурой на кнопки понажимать.
Как правило, элементы интерфейса — не только кнопки и чекбоксы. Совет именно для тех случаев, для которых, вам, в любом случае, прийдется писать код для работы с клавиатуры.
Приведите пример таких элементов интерфейса тогда.
Вы серьезно? Ютуб, например.
Очень остроумно. Конечно же я имел в виду элементы интерфейса ютуба.
Я не просто так просил уточнить. Если вы считаете, что play/pause//mute/fullscreen это не кнопки, то вы ошибаетесь.
Я говорю о главной странице, списке рекомандаций, списке подписок и пр.
К ссылкам применяется то же правило. Вот вам пример со ссылками, вместо кнопок — jsbin.com/radurahivofa/1#, попробуйте в нем клавиатурой понажимать.
Ни в коем случае нельзя заменять click на mousedown. Не у каждого пользователя есть мышь, а как же клавиатура и тач устойства.

Просто совет не полный. Необходимо одно событие Click заменить на несколько: mousedown, keydown и touchstart. И еще хорошо подумать: не приведет ли такое «умное» срабатывание к негативным последствиям. Например, если в результате работы скрипта выполняется переход на другую страницу, то обработчик должен быть только на Click, а если нужно обновить часть текущей страницы, то можно и Down события использовать. А можно и более просто сформулировать: результат выполнения скрипта пользователь увидит менее, чем за 0.5-1 секунду, то можно Click поменять на Down.

Правда подобные приемы сокращения времени отклика обычно применяются в десктопном или мобильном софте, а для Web они мало где заметны, т.к. время отклика как правило большое.
Необходимо одно событие Click заменить на несколько: mousedown, keydown и touchstart.


Да, только надо не забыть вызвать stopPropagation на touchstart и mousedown, чтобы они вместе не сработали. И убедиться, что keydown сработал только один раз (при залипании от срабатывает несколько раз).

В идеале, если уж так сильно хочется ускорить веб приложение этим методом, то надо байндить и mousedown и click. И в клике проверять, сработал ли недавно mousedown. И при этом, надо не забыть про ghost click (событие click сработает на некоторых тач устройствах на 350-500ms позже чем mousedown/touchstart).

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

Проще говоря, изначальный совет «замените click на mousedown и увеличьте скорость приложения» не очень корректный, и может больше навредить, чем помочь.
Проще говоря, изначальный совет «замените click на mousedown и увеличьте скорость приложения» не очень корректный, и может больше навредить, чем помочь.


А так абсолютно с любым советом. Моим самым любимым примером неудачного применения полезных практик является перегрузка паттернами. Например: The Abuse of Design Patterns in writing a Hello World Program.

Все как всегда: сначала думаем как сделать, потом думаем нужно ли оно, и только потом делаем.
Бублики на фото выглядят очень аппетитными, да.
UFO just landed and posted this here
Господа, после минуса в карму, прошу написать сюда комментарий о том, что именно вам так не понравилось.
у вас катарсис в начале статьи — нарушение всех законов драматургии. В результате читатель лишь разочаровывается — такое прекрасное начало, а дальше какие-то скудные библиотеки и плагины.
Пожалуй, мне стоит сделать паузу в публикациях на Хабр. Сказать, что я разочарован — ничего не сказать.
Я минусы ставить не умею, но за рекомендацию mousedown вместо клик и за тотальный отказ от CDN веб-разработчика можно люстрировать, ИМХО. :-)
Соглашусь, вопрос с событиями спорный, но по поводу CDN настою по следующим причинам:
1. Их слишком много. Утопичный вариант загрузки библиотеки лишь однажды для всех сайтов в интернете не сработает.
2. Версий библиотек тоже немало. Вероятность того, что пользователь, зайдя на ваш сайт, будет иметь в кеше именно ту версию библиотеки мал.
3. Лишний HTTP запрос, который не только кушает трафик, но и сам по себе медлителен.
4. Сервер может не отвечать. О фоллбеках я написал в статье.
5. Нет статистического исследования на тему того, насколько CDN увеличивает скорость загрузки страницы. Учитывая первые два пункта, предполагаю, что скорость только падает.
6. В большинстве случаев люди используют CDN из-за банальной лени и неумения собирать проект в один файл, который, кстати, при первом заходе пользователя закешируется а при следующем, вернется с кодом 304, если страница, сайт или приложение покажется интересным.
7. CDN просто-напросто может закрыться, вам прийдется обновлять все проекты, но, перед этим, потерять две трети юзеров.
Возможно, для каких-то проектов это будет справедливо. Но для большинства типовых сайтов подгрузить jquery с крупного CDN будет весьма удобно и выгодно. Вряд ли бы CDN получили такое распространение, если бы ухудшали производительность сайтов. Естественно, к их использованию надо с умом подходить, а не подключать в качестве «CDN» виртуалку вашего соседа – тогда ничего внезапно не закроется.
3. Лишний HTTP запрос, который не только кушает трафик, но и сам по себе медлителен.

jsDelivr умеет конкатинировать библиотеки в один запрос
Идея CDN в том, что вы загружаете библиотеку на одном сайте, а на другом она вернется с кодом 304. jsDelivr конкатенирует несколько разных библиотек в одну, и вероятность того, что на двух сайтах один и тот же набор библиотек — мал. Т. е. единственное спорное преимущество CDN против одного локального файла (в котором, кстати, не только библиотеки, но и скрипты, отвечающие за работу приложения) пропадает.
Не минусовал, но есть пара замечаний.

Вот в целом мне статья показалось полезной. В чем-то спорной (например, onmousedown и CDN), точнее, слишком категоричной (ситуации бывают разные, иногда CDN — добро, иногда — не очень). Но в целом интересно было поглядеть указанные вами итемы, про ту же балалайку я не слышал вообще.

Но кое-что сильно мешает — используемая лексика. Я ни разу не педант или граммар-наци, но уже привык, что в нормальных статьях (а обзор — тоже статья) используется профессиональная лексика без жаргонизмов и слов вроде «пасаны». Да и в целом стиль у вас похож на разговор с пацанами, а не на статью на хабре. Это бывает уместно, но сильно зависит от тематики.

За исключением этих двух пунктов, большое спасибо = )
По поводу пацанов — это шутка. Лично мне нравится читать статьи не перегруженные серьезностью.

По поводу CDN я уточнил в этом комментарии а этот комментарий говорит о еще одном аргументе против CDN.

CDN замечателен для «пруф-оф-концеп» страниц. Для продакшна серьезного проекта с более чем пятью пользователями нужно складывать все скрипты в один файл.
Ожидал, что цифра на бублике как то связана с бэкграундом.
procrastinate — это вы изобрели debounce, как его назвали в underscore
Как правило, таким способом отслеживают завершение ресайза окна, либо в автоподсказках в инпутах.

Загляните сюда
Пример с ресайзом окна
function debouncer( func , timeout ) {
   var timeoutID , timeout = timeout || 200;
   return function () {
      var scope = this , args = arguments;
      clearTimeout( timeoutID );
      timeoutID = setTimeout( function () {
          func.apply( scope , Array.prototype.slice.call( args ) );
      } , timeout );
   }

}


$( window ).resize( debouncer( function ( e ) {
    // do stuff 
} ) );

Задача лежит на поверхности, я не удивлен.
> Совет: меньше используйте CDN

Меня больше интересует вопрос безопасности, на сегодняшний день развелось много разных CDN, а ведь если какой-нибудь банк или любой другой сайт разместит js с моего CDN, то я смогу точечно производить атаки — внедрять зловред и т.п. для конкретного ip адреса (клиента), и это будет происходить не заметно.

PS: у меня нет своего CDN.
Я считаю, что все потенциальные риски не сравнимы с единственным спорным неисследованным преимуществом.
Кстати, это можно назвать добровольным XSS :)
Вот за наводку на mousedown спасибо!
Действительно, как-то не обращал внимания на такую мелочь, а разница заметная.
Спасибо за отзыв. Но как написали выше, это не всегда гуд.
Совет с mousedown не учитывает клавиатуру. Например, в демке не срабатывает второй чекбокс при нажатии на пробел.
Это лишь демка. Чекбокс должен оставаться чекбоксом, а такое поведение можно реализовать для кастомных вещей.
По поводу msword-filter: для представления списков Word почему-то использует параграфы вместо тегов UL и LI, поэтому их надобно парсить. Посмотрите в моей статье пример реализации. Буду рад, если мой код окажется полезным.
Хотите субъективно увеличить скорость срабатывания интерфейса? Замените событие click на mousedown, если это возможно (если нет драг-н-дропов и событий двойного щелчка). Это позволит избежать задержки в десятые или сотые доли секунды, прежде чем пользователь отпустит кнопку мыши.

Други, никогда так не делайте! У меня, к примеру (думаю, не только у меня), есть такая привычка — прижать кнопку мыши на кнопке в интерфейсе, а потом окончательно подумать, хочу ли я ее нажимать. Причем что издревле раздражало в вебовских кнопках — так это то, что когда ты прижимаешь мышью обычную кнопку и уводишь мышь в сторону, то она просто отжимается обратно. А когда так делаешь на веб-странице, то кнопка часто начинает drag-drop-иться.
Переименовал «совет» в «идею» и указал на критику в комментариях.
Хочу добавить несколько слов про addEventListener:
1. Приведённая в статье библиотека — это не полифил, как бы автор её не называл, т.к. она не реализует функционал addEventListener'ра.
1.1. Библиотека не умеет handleEvent:
let application = {
    name: 'test',
    handleEvent() { console.log(this.name) }
}
document.addEventListener('click', application);

1.2. Библиотека не умеет «захват» событий
1.3. Библиотека не заработает с любым отложенным исполнением обработчика события в IE8, т.к. в IE объект event «очищается» сразу после вызова обработчика:
document.addEventListener('mousemove', function(event) {
    console.log(event.type);// В IE8 тут будет ошибка
}.throttle(200));


2. Библиотека не заработает в IE7, во первых потому что в IE7 нету window.Element, а во вторых, потому что window.Node (который можно использовать вместо window.Element) — это не js-объект/конструктор, и его prototype не распространяет свои свойства на потомков.

3. Вероятно библиотека вызовет утечки памяти в IE8, т.к. ссылка на элемент сохраняется в скоупе обработчика события.
> Приведённая в статье библиотека — это не полифил, как бы автор её не называл, т.к. она не реализует функционал addEventListener'ра.
Она реализует простейший функционал addEventListener: нет поддержки кастомных событий, нельзя передать объект с handleEvent (кстати, что за синтаксис такой?). Её можно назвать простейшим полифилом, который был сделан в противовес массивным «полноценным», но бажным полифилам. Я не нашел ни одного достойного, пробовал, в том числе, и ваш.
> Библиотека не умеет «захват» событий
Капчуринг — проблема, да.
> .throttle(200)
Простите, что это за метод? ES5/6?
> Библиотека не заработает в IE7
В статье говорится о восьмом осле (который называют «устаревающим», но не устаревшим, к сожалению). Под седьмой сейчас мало кто пишет, как и под шестой, а тот, кто пишет, ни в коем случае не должен использовать ваниллу. Использование популярной библиотеки, типа jQuery — обязательно.
> Вероятно библиотека вызовет утечки памяти в IE8, т.к. ссылка на элемент сохраняется в скоупе обработчика события.
Мне нечего возразить. Ослы «славятся» своей очисткой памяти от мусора. Постараюсь от этого избавиться.
> кстати, что за синтаксис такой?
Если вы про ObjectLiteral то это es6. Есть про handleEvent — то это стандартный обработчик, определённый в стандарте addEventListner'а developer.mozilla.org/en-US/docs/Web/API/EventListener

>> .throttle(200)
> Простите, что это за метод? ES5/6?
Практически «стандартное» расширение прототипа функции, которое есть во многих библиотеках. Например sugarjs.com/api/Function/throttle
Похоже на вашу функцию procrastinate, которая, кстати, тоже не заработает с этой библиотекой.

>> Библиотека не заработает в IE7
> В статье говорится о восьмом осле
В описании гиста написано:
Simple addEventListener polyfill for IE7 and IE8

>> Вероятно библиотека вызовет утечки памяти в IE8, т.к. ссылка на элемент сохраняется в скоупе обработчика события.
> Мне нечего возразить. Ослы «славятся» своей очисткой памяти от мусора. Постараюсь от этого избавиться.
Моя версия полифила, хотя и громоздкая, но практически не вызывает утечек памяти. Конечно, полностью от утечек избавится не удалось, но минимизировать их удалось.
> «стандартное» расширение прототипа
Я тоже когда-то гадил в прототипы стандартных конструкторов :)
Object.defineProperty(Function.prototype, 'myFunction', {enumerable: false, value: function(){ /* do something cool */ }})
Благодаря использованию enumerable:false, этот способ не является опасным, в отличие от Function.prototype.myFunction=function(){}

Да и не так страшно расширение прототипов стандартных объектов, как его малюют, главное подходить с умом.
Ну для функций проблемы enumerable не существует, как по мне.

У меня есть большой проект, где я яростно расширял прототипы. Сейчас смотрю в этот код и путаюсь, как и в вашем. Уменя сразу возник вопрос, откуда у function есть метод throttle: стандартный он или встроенный.
От «балалайки» у меня чуть вывих челюсти не случился =) Чувствую, скоро перестану использовать jQuery в разработке =)

Самое интересное, что в большинстве своём из всей jQuery используется в лучшем случае четверть функционала. Собственный опыт разработки показал, что большая часть кода уходит в:
— Защиту от дурака: проверки типов переменных, наличия требуемых библиотек и так далее
— Методы/функции для сокращённого вызова и для обратной совместимости: сокращённые варианты вызова метода с теми или иными параметрами, устаревшие методы/функции
Sign up to leave a comment.

Articles