JavaScript

Задаем вопросы по JavaScript: оптимизация кода, примеры решений, анимация (питаю к ней неземную любовь), jQuery. Самые интересные вопросы будут добавляться прямо в статью. Большая просьба не задавать вопросов вроде «какую книгу по JavaScript советуете прочитать», «где найти уроки для начинающего кодера», «помогите найти ошибку в коде» и тому подобное — все это останется без ответа, по крайней мере с моей стороны.

Ответы

Что думаете по поводу производительности популярных фреймворков? Какой лучше использовать? Например, здесь (http://lusever.ru/css-selectors/) prototype уделывает jquery.

Тесты производительности фреймворков — такая же маркетинговая спекуляция, как и ACID тест для брузеров: на картинках все круто, а когда начинаешь использовать те же CSS-свойства, но в другой комбинации, появляется куча проблем. Например, в тестовом документе, в котором 1781 элемент, селектор p:nth-child(n) на моем ноутбуке отрабатывает за 2 мс в jQuery против 1 мс в Prototype. Это большая разница? Как часто вы имеете дело с такими большими документами?

Производительности большинства известных фреймворков достаточно для выполнения типичных задач. И самым узким местом в производительности того или иного фреймворка является сам разработчик, который его использует. Например, один человек пытался доказать мне, что jQuery — очень медленная библиотека и ее нельзя использовать. Когда я начал разбираться, увидел вот такой код: $('.some-item').mouseover(function(){ $('.some-item').addClass('hover'); }). Небольшая доработка, и код в его понимании стал «реактивным»: var elem = $('.some-item'); elem.mouseover(function(){ elem.addClass('hover'); }).

Выбор фреймворка должен определяться исключительно собственными предпочтениями, удобством использования и средой, в которой работаете (например, для RubyOnRails удобнее использовать Prototype, хотя, возможно, уже есть нормальная поддержка jQuery). Если мне понадобится исключительная производительность на каких-то задачах, я не буду менять jQuery на фреймворк, в котором селекторы быстрее работают; я сделаю решение задачи с использованием стандартных DOM-методов, которое по скорости выиграет у любого фреймворка.

Как вы относитесь к эмуляции (приватные свойства и методы, наследование и др.) механизмов и паттернов (командер, наблюдатель и др.), пришедших из классического ООП, в JavaScript? Меня лично сильно раздражает, когда, например, человек, ранее программирующий на PHP или Java, начинает лепить из JavaScript привычную ему среду, выдавая это за правильные стандарты кодирования.

В целом, разделяю ваше негодование насчет «правильных стандартов». Паттерны проектирования нужно использовать для решения типовых задач, а не потому, что так делают правильные пацаны. У каждого языка есть свои сильные и слабые стороны, которыми в первую очередь нужно научиться пользоваться. Помню, у меня был коллега, у которого стояла задача сделать простейший ховер на одном элементе (добавлять/удалять класс при наведении курсора), при том, что на проекте использовался jQuery. Так вот, вместо того, чтобы просто написать $('#myelem').hover(...), он сделал целый класс с инициализатором, свойствами и методами (а в этих методах все равно использовал jQuery), вынес его в отдельный файл и создал объект из него в другом файле. В итоге задача, решаемая одной строчкой кода, решалась 20-ю строками. На вопрос «зачем это все?» я услышал что-то невнятное насчет ООП, расширяемости (расширяемость ховера?) и инкапсулирования.

Мое мнение: нельзя загонять себя в угол стереотипов. Паттерны — это хорошо, но гораздо важнее научиться их правильно и вовремя применять. Любая книга по программированию — не руководство к действию, а пища для ума. Если говорить о JavaScript, то я сейчас крайне редко создаю прототипные классы — все чаще просто генерирую объект во время вызова функции (задолбался всюду писать this); не использую синглтон, потому что есть самовызывающиеся функции и так далее. В итоге код получается простым, компактным и модульным (не засоряется глобальная область видимости) — именно то, что нужно для веба.

98 комментариев

  1. iSergey
    13 августа 2009

    Добрый день, Сергей.

    Хотелось бы узнать подробнее как растягивать фоновую картинку на все окно браузера (см. metrostroy.com).

    Спасибо.

    P.S. Извиняюсь если написал не в ту категорию.

  2. iSergey
    13 августа 2009

    Еще интересует знак рубля, а именно есть ли какое-нибудь решение на jQuery?
    Дело в том, что при применении опубликованных способов в «Техногрете», если знак 12-14px, то результат получается не очень красивый. При увеличении текста черточка смещается и т.д.

    Спасибо.

    Про такие решения не знаю. У всех текущих решений есть один большой недостаток: зависимость от гарнитуры и размера шрифта. В связи с бурным развитием современных браузеров можно начинать пользоваться специальной гарнитурой и внедрять ее на сайт через CSS

  3. 13 августа 2009

    фоновая картинка — наверное, не самый сложный вопрос для этого сайта 🙂

  4. 13 августа 2009

    to iSergey:
    Отвечу за автора.
    Ваш вопрос относится больше к тематике html/css. Информацию о том как реализованы элементы интерфейса отдельного веб-сайта, удобно смотреть используя расширение для FireFox — Firebug.

    #back_under {
    height:50%;
    left:-50%;
    position:absolute;
    top:50%;
    width:200%;
    }

  5. Сергей Чикуенок
    13 августа 2009

    iSergey, вопрос очень хороший и мне его часто задают. Ответил в разделе HTML/CSS

  6. Dmitry
    15 августа 2009

    Сергей, как вы относитесь к эмуляции (приватные свойства и методы, наследование и др.) механизмов и паттернов (командер, наблюдатель и др.), пришедших из классического ООП, в JavaScript? Меня лично сильно раздражает, когда, например, человек, ранее программирующий на PHP или Java, начинает лепить из JavaScript привычную ему среду, выдавая это за правильные стандарты кодирования. Интересно узнать ваше мнение 🙂

  7. 20 августа 2009

    Добрый день.
    Подскажите, как проще решить такую задачу? http://h4mpy.ru/q/hover_q.png
    Есть некий скрытый блок, который появляется при наведении на заданную область. Есть некий перекрывающий блок, который частично перекрывает появляющийся блок.
    Вопрос такой: как лучше задать область наведения, чтобы она никак не пересекалась с блоками?
    На всплывающем блоке есть ссылки, интерактивные элементы, соответственно просто перекрыть неким 3 блоком не получится.
    Вопрос скорее касается верстки, но может есть какие-то способы задавать области на javascript, и им уже назначать обработчики событий…hover, click. Наподобие map, area в html.

    А перекрывающий блок должен быть именно круглым? Я вижу два варианта. Первый — самый простой, — положить сверху прозрачную картинку и применить ей image map. Можно сделать даже две картинки и расположить их слоями на разных уровнях, чтобы выезжающий блок перекрывал одну из карт. Второй способ довольно сложный. Можно заранее просчитать габариты и позицию блоков, а при движении мышки проверять вхождение курсора в эти области. Что-то подобное я делал на сайте «Мукла» (сейчас сайт почему-то не работает): там есть витрина магазина, гда размещаются коробки под разным углом наклона. Соответственно, где-то они пересекаются, поэтому обычный ховер давал неправильный результат. И там я как раз рассчитывал обрамляющий прямоугольник каждого блока и проверял, попадает ли курсор в него.

  8. 21 августа 2009

    > h4mpy

    В jQuery есть такой событие как mouseenter и mouseleave http://docs.jquery.com/Events/mouseover
    Это никак не может помочь?

  9. 22 августа 2009

    Здравствуйте Сергей,

    Я делаю сайт на основе Друпала по функционалу похожий на Швабрашвабр.
    Мне понравилась фишка с разъезжающимся блоком-подсказкой на главной http://shvabrashvabr.ru/. Скопировал себе js. Все подправил.
    Но не работает. Точнее работает, но странно. Текст не выезжает, а появляется резко и поверх остального контента.
    Если не затруднит, посмотрите пожалуйста: мне кажется для Вас ответ лежит на поверхности. Вот проблемный сайт: http://gorodkozlov.ru
    P.S. На самом Швабре и Друпал.Ру прошли мимо моего вопроса.
    Заранее спасибо.

    Сделайте так, чтобы сначала сайт загружался, тогда посмотрю

  10. 22 августа 2009

    Странно, вроде сайт доступен. (Оба)
    Сейчас заметил, что если кликнуть в тот момент, когда страница еще не догрузилась до конца, то блок «разъезжается», как положено. Но после окончания загрузки (не)работает как описано выше…

    Попробуйте из файла mainpage.js убрать первые 4 строчки

  11. 22 августа 2009

    Большое спасибо. Все заработало. =)

  12. Vii
    29 августа 2009

    Есть сайт (на одном домене) в котором через iframe вставляется некий сервис (разработанный другими людьми) находящийся на другом домене. В сервисе есть необходимость динамически менять высоту iframe’а в зависимости от ситуации (выбрали checkbox — добавились какие-то поля, например).
    Когда эти самые люди тестили все у себя на сервере, все прекрасно работало: у них есть функция, которая измеряет текущую высоту контента и через parent.window или window.frames[0] меняет высоту.
    Теперь же из-за same origin policy это не прокатывает.

    У меня из вариантов выхода из ситуации есть только: 1) передавать в location.hash iframe’а параметр со-значением текущей высоты, а мы бы каким-то образом это значение считывали; 2) переделать все на JSONP

    Была еще идея загружать все в невидимый div и измерять его высоту, но на сервере используется немало ajax-запросов, поэтому непонятно, что измерять :))

    Можешь что-нибудь посоветовать?

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

  13. fekss
    30 августа 2009

    сейчас появилось много браузерных онлайн игр, как простых(типа покера и шашек), так и сложнее(разные ММОРПГ например), и очень многие используют флеш. Вопрос, потянет ли js написание такой игры, как в анимации так и в производительности браузера.

    Флэш очень хорошо оптимизирован под различные анимации и рисования, поэтому там, конечно же, все будет работать намного быстрее. С другой стороны, если делать какой-нибудь аркадный платформер со спрайтовой графикой, то и на HTML вполне качественную вещь мнжно сделать. Кстати, я когда-то делал тетрис на JavaScript — все вполне шустро работает.

  14. 2 сентября 2009

    Сергей, почему на сайтах студии (например на http://federationtower.ru/) не практикуется сборка джс-файлов в один и последующая компрессия?

    Тогда еще не было вменяемого процесса сборки файлов, да и сильной необходимости в этом не было. Проект все-таки не высоконагруженный. Согласен, что это снижает потребительские качества проекта. У меня сейчас есть готовый Ant-скрипт, который очень легко может собирать файлы проекта; в моем текущем проекте все файлы обязательно подвергаются конкатенации и компрессии.

  15. Артем
    9 сентября 2009

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

    Грузить данные аяксом, менять hash у адресной строки. За готовым решением можете обратиться на http://fullajax.ru

  16. 16 сентября 2009

    Сергей, здравствуйте.

    Пару дней назад мы в очередной раз решили оживить огонь в логотипе на сайте http://ifun.ru/ первый вариант был выполнен аутсорсером на флеше в виде навороченной программы, там и дым и огонь обсчитывались в лучших традициях российской математической школы. Как следствие ролик тормозил.

    Вчера я сделал огонь по проще через JavaScript путём последовательной смены 5-и картинок, каждые 80 мс, получилось достаточно живенько.

    Код выглядит примерно так:

    var logo_frames = new Array();

    function logoburner() {
    var i = 0;
    var original_url = $(‘logo_fire’).src;

    for (; i < 5; i++) {
    logo_frames[i] = new Image();
    logo_frames[i].src = original_url.replace(/[0-9]-/, (i + 1) + ‘-‘);
    }
    burn(1);
    }

    function burn(frame) {
    $(‘logo_fire’).src = logo_frames[frame — 1].src;
    frame++;

    if (6 == frame)
    frame = 1;

    setTimeout(«burn(«+frame+»)», 80);
    }

    Вообщем-то классический пример из книжки, функция logoburner пускается по onload страницы.

    Таким образом я сам себе вчера сделал DOS атаку, несмотря на то, что веб-сервер(Nginx), который раздаёт ставит хедер Expires на сутки вперёд для кадров с огнём, некоторые клиенты не обращают на это внимания, никаким образом не кэшируют картинку и тупо бомбят несчастный веб-сервер запросами через каждые 80 миллисекунд.

    Интересно сталкивались ли вы с похожими проблемами при создании анимации через JavaScript и каким образом они решались?

    Мне сходу пришло в голову следующее решение: все 5 кадров разместить внутри одной картинки, картинку сделать бэкграундом к DIV и менять позиционирование бэкграунда внутри DIV, нормальное ли это решение?

    Судя по всему, проблема возникла в IE. Это давно известный баг, связанный с тем, что любое изменение свойства background инициирует новую загрузку картинки с сервера в IE6. Решается такми скриптом:

    try{
    	document.execCommand("BackgroundImageCache", false, true);
    } catch(e) {
    
    }
    

    Ну а в целом стоит загнать все эти картинки в один спрайт и просто менять background-position. Подробности можете прочитать в статье про спрайты.

  17. 16 сентября 2009

    Спасибо, так и сделал(спрайты).

  18. Neolord
    29 сентября 2009

    Хочется сделать большую надпись с наложенным на неё градиентом (возможно «текущим»). Единственное что приходит в голову — использовать векторные маски поверх картинки. Но ума не приложу как сделать векторную маску на основе текста (чтобы можно было миллион этих надписей сделать без использования заранее сгенерированных файлов), с использованием стандартных шрифтов и любых размеров.

    Может вы знаете какое то другое решение?

    Посмотрите в сторону библиотеки Raphaël, возможно, она сделает то, что вам нужно. Если градиент у вас вертикальный (то есть цвет меняется строго по вертикали), то можно поступить так: во время загрузки страницы делаете десяток дубликатов блоков с текстом, красите в разные цвета и накладываете их друг на друга. Затем с помощью CSS-свойства clip показываете несколько пикселей кадого слоя, так, чтобы в итоге получился градиет. Извращение, конечно, зато сработает везде 🙂

  19. Василий Колбасилий
    5 октября 2009

    Раскройте секрет «Десяти причин» (http://job.euroset.ru/candidates/benefits/). Я сделал фильм с помощью jTweener и вашей лекции «Третий способ борьбы…». Ну как бы получилось. Но если прокрутить кадр и уменьшить ширину браузера, левый угол фильма смещается на величину изменения, показывая кусок другого кадра. Как вам удалось этого избежать?

    Я смотрел код сайта, знаю про функцию подсчета смещения. Через setInterval прибавлял смещение фильму, если менялась ширина окошка. Работает, но даже при самом малом интервале, изменения идут скачками, особенно ужасными в Опере. Думаю, что все дело в особенностях библиотеки tween в «Десяти причинах» — у ней загадочные аргументы. В чем секрет?

    Особых секретов нет. Перед началом анимации считаем, сколько 100% ширина будет в пикселях, потом с помощью анимации смещаем контейнер на это значение влево, а после завершения анимации выставляем это смещение в проценты. Таким образом, после завершения анимации блок смещается на 100% (200, 300, 400…) влево, тем самым решается проблема с отображением соседних кадров при изменении размера окна.

  20. 12 октября 2009

    Сергей, что думаете по поводу производительности популярных фреймворков? Какой лучше использовать?

    Например, здесь (http://lusever.ru/css-selectors/) prototype уделывает jquery.

    Ответ в теле поста

  21. 23 октября 2009

    Добрый день, Сергей.

    Проблема в следующем — есть сайт на Joomla, есть компонент для менюшек SwMenu. Не могу заставить вылезать созданное в Swmenu подменю в IE (не работает ни на одной версии с шестой по восьмую), жалуется на строку
    TransMenu.initialize();

    В файрофоксе все работает без нареканий.
    Галка «padding ie6 hack» в Swmenu стоит.

    Если сделать меню одноуровневым, без выпадающих подменю, то проблема решается. Но меня это не устраивает.

    меню вот: http://www.vezem63.ru — в IE не работает, в FF все в норме

    Помогите, плз, решить вопрос!

    Если ещё актуально, поставьте этот скрипт в незапакованном виде, я посмотрю, в чём может быть дело.

  22. snetcher
    7 ноября 2009

    http://www.mooqla.ru/install.php?profile=default

    Студия к этой версии сайта не имеет никакого отношения.

  23. snetcher
    7 ноября 2009

    не хорошо как-то получается 8(

  24. Armen
    16 ноября 2009

    Здравствуйте Сергей, прошу минутку вашего внимания, нужна ваша помощь!
    Я изучаю XHTML и CSS уже больше полугода, вышел на более менее неплохой уровень, теперь хочу двигаться дальше.
    Помогите разобраться, что раньше мне нужно начать изучать, JavaScript(немного изучал, более менее имею представление) или XML(никогда не изучал.)
    У меня есть много хорошей литературы по обоим предметам, только вот не знаю от куда начать, так как времени уйдет много и чтоб потом не возвращаться назад и не начинать учить что-то из этих языков заново, понимая, что сначала нужно было уделить время другому, я прошу вашей помощи, помогите пожалуйста начинающему!
    спасибо!

  25. 27 ноября 2009

    Вот вам самый замысловатый вопрос! Как в jQuery при помощи плагина tablesort сделать сортировку по полям таблицы, в которой ячейки объеденены при помощи colspan и rowspan. 🙂

  26. Joker
    30 ноября 2009

    с помощью библиотеки jQuery можно сделать водяной знак (Watermark Input Plugin) , как такую штуку реализовать на JavaScript без подключения всяких библиотек? нужен чистый JS
    спасибо

  27. 18 декабря 2009

    Здравствуйте. Не могу найти решение следующей задачи:
    У меня есть первая страница к примеру test_1.htm на которой есть ссылка с классом .uroven1 на вторую страницу test_2.htm.
    Необходимо чтобы при загрузке страницы test_2.htm в новом окне (использование фреймов исключено) скрипт выполнит любое действие (к примеру выбросит сообщение «WELLCOME») — только после того как «поймёт или отследит» что открытие этой страницы произошло по событию «клик» на ссылку с классом .uroven1 что на странице test_1.htm.
    Да и по боьлшей части важней отследить класс ссылки, по которой перешли на новую страницу.
    Сам скрипт вояется в jQuery.

  28. Vii
    18 декабря 2009

    Pastorman, самое простое, что приходит в голову (при условии, что не копаться в window.opener), это при открытии окна добавлять ему в location.hash какой-нибудь флаг, с классом, например #?from=my-class.

    Плюс страницы с одного домена могут смотреть в область глобальных переменных друг-друга, т.е. на test_1 создаем глобальную переменную var sFromClass = ''; и при клике запихиваем в нее что-то $('a').click(function(){ sFromClass = 'blah';window.open(...) });
    Из test_2 должна быть видна window.opener.sFromClass.

  29. 18 декабря 2009

    Проблема то как раз в том, что в моём случае исключено использование window.open(…)

    Работа над скриптом ведётся как раз на том сайте на который ссылается мой ник.

    Там открытие окна по ссылке должно проводиться дву способами:
    1. Вывод через модальное окно -используется избитая тема jquery.fancybox.js (учитывая что в окно подгружается не просто контент а полноценный код html странницы полностью);
    2. Вывод через команду «открыть в новом окне».

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

    Посоветовали следующую схему:

    $(window).load(function() {
    var ref = document.referrer;
    if ref /* ??? */
    then …
    });

    в этом случае как вытащить из referrer — класс ссылки по которой перешли на эту страницу?
    или как именно здесь воспользоваться этой глобальной переменной?

    Как мне кажется решение моей проблемы подразумевает исключительно работу скрипта только на открывшейся странице test_2.htm
    Прошу помощи.

  30. Сергей Чикуенок
    18 декабря 2009

    Попробуйте ифрэйму присвоить атрибут name с вашим классом и проверить его через window.name. Ещё можно писать в куку имя класса при клике, а при загрузке проверять и очищать её.

  31. Alexander
    15 января 2010

    Сергей, я в какой-то момент смотрел на Ваш dataRequest из imobilco и помню, что не понял, зачем там callback зовётся два раза: сразу по приезду ответа от сервера callback не вызывается (потому что b=false), а во второй раз уже вызывается. Почему было сделано именно так?

    Это сделано для того, чтобы пользователь успел увидеть прелоудер на кнопке (то есть понял, что что-то произошло). Если у пользователя очень быстрый интернет, то после нажатия на кнопку он может не понять, отреагировал сайт или нет. Поэтому ставится принудительная задержка на скрытие прелоудера. С другой стороны, интернет может быть очень медленным и ответ придёт позже, чем закончится задержка. С этой целью ставится специальная проверка, которая определяет, в какой именно момент нужно убрать прелоудер с кнопки: после принудительной задержки или после получения ответа.

  32. Илья
    17 января 2010

    Сергей, здравствуйте! Помогите, пожалуйста, решить задачу.
    Есть страница со списком:

    Очень важный текст

    Задача: подгружать содержимое элемента #important-text.
    Я попробовал воспользоваться следующей конструкцией:
    $(«#target»).load(«/some_page #important-text»);
    Но загружается сам элемент #important-text, а мне нужно загружать только его содержимое. Подскажите, пожалуйста, как это сделать?

  33. Alexander
    20 января 2010

    Спасибо.

  34. Владимир
    11 февраля 2010

    Здравствуйте, мне нужно сделать такой эфект на странице, есть логотип на странице сайта и он должен состоять из 3 разных картинок форматом png и как страница загрузилась нужно чтобы эти 3 части логотипа так сказать разьехались в 3 разные стороны и там оставались и чтобы после этого сбоку под появлялось меню в таблице так сказать с задержкой к примеру как страница загрузилась и после 10 сек появилось меню…

  35. Владимир
    11 февраля 2010

    Я нашел пример похожего скрипта вот он

    Как сделать движение HTML-объекта на Javascript

    html, body { height:100%; overflow:hidden; }
    * { font:17px serif; color:black; margin:0; padding:0; overflow:visible; }
    h1 { margin-bottom:15px; }
    input { padding:3px 10px; cursor:pointer; line-height:80%; float:left; margin-right:10px; }

    #rocket { position:absolute; left:50%; top:50%; font-size:100px; margin-top:-12px; line-height:25px; }
    #info { float:left; height:30px; line-height:30px; color:gray; width:500px; margin:0 10px; }

    window.rocketSpeed = 3;

    function rocketLauncher( obj, rocket )
    {
    rocket = (typeof rocket == ‘object’) ? rocket : document.getElementById( rocket );
    rocket.params = {
    direction: { ‘x’: 1, ‘y’: 1},
    borders: {
    ‘x’: document.body.clientWidth — rocket.offsetWidth,
    ‘y’: document.body.clientHeight — rocket.offsetHeight
    }
    }
    obj.flying = !obj.flying ? true : false;
    obj.default_value = ! obj.default_value ? obj.value : obj.default_value ;

    if( obj.flying )
    {
    // устанавливаем первоначальные значения позиции объекта
    if( !rocket.style.left ) rocket.style.left = rocket.offsetLeft + ‘px’;
    if( !rocket.style.top ) rocket.style.top = rocket.offsetTop + ‘px’;

    obj.rocket = setInterval(function()
    {
    // смещение положение объекта
    posX = parseInt( rocket.style.left ) + rocketSpeed * rocket.params.direction.x;
    posY = parseInt( rocket.style.top ) + rocketSpeed * rocket.params.direction.y;
    rocket.style.left = posX + ‘px’;
    rocket.style.top = posY + ‘px’;

    // изменение направления движения при достижении границ окна браузера
    if( posX rocket.params.borders.x ) rocket.params.direction.x *= 1;
    if( posY rocket.params.borders.y ) rocket.params.direction.y *= 0;

    // информационное окно
    document.getElementById(‘info’).innerHTML = ‘Текущая позиция — (X: ‘ + posX +’, Y: ‘+ posY +’), Скорость: ‘ + rocketSpeed;
    }, 10);

    obj.value = ‘Остановить’;
    }
    else {
    // остановка движения
    clearInterval( obj.rocket );
    obj.value = obj.default_value;
    }
    }

    Как сделать движение HTML-объекта на Javascript

    И мне нужно чтобы 3 картинки такие разлетались в отпределенные места окоординаты на странице и там остовались

  36. Владимир
    11 февраля 2010

    ой вот он

    Как сделать движение HTML-объекта на Javascript

    html, body { height:100%; overflow:hidden; }
    * { font:17px serif; color:black; margin:0; padding:0; overflow:visible; }
    h1 { margin-bottom:15px; }
    input { padding:3px 10px; cursor:pointer; line-height:80%; float:left; margin-right:10px; }

    #rocket { position:absolute; left:50%; top:50%; font-size:100px; margin-top:-12px; line-height:25px; }
    #info { float:left; height:30px; line-height:30px; color:gray; width:500px; margin:0 10px; }

    window.rocketSpeed = 3;

    function rocketLauncher( obj, rocket )
    {
    rocket = (typeof rocket == ‘object’) ? rocket : document.getElementById( rocket );
    rocket.params = {
    direction: { ‘x’: 1, ‘y’: 1},
    borders: {
    ‘x’: document.body.clientWidth — rocket.offsetWidth,
    ‘y’: document.body.clientHeight — rocket.offsetHeight
    }
    }
    obj.flying = !obj.flying ? true : false;
    obj.default_value = ! obj.default_value ? obj.value : obj.default_value ;

    if( obj.flying )
    {
    // устанавливаем первоначальные значения позиции объекта
    if( !rocket.style.left ) rocket.style.left = rocket.offsetLeft + ‘px’;
    if( !rocket.style.top ) rocket.style.top = rocket.offsetTop + ‘px’;

    obj.rocket = setInterval(function()
    {
    // смещение положение объекта
    posX = parseInt( rocket.style.left ) + rocketSpeed * rocket.params.direction.x;
    posY = parseInt( rocket.style.top ) + rocketSpeed * rocket.params.direction.y;
    rocket.style.left = posX + ‘px’;
    rocket.style.top = posY + ‘px’;

    // изменение направления движения при достижении границ окна браузера
    if( posX rocket.params.borders.x ) rocket.params.direction.x *= 1;
    if( posY rocket.params.borders.y ) rocket.params.direction.y *= 0;

    // информационное окно
    document.getElementById(‘info’).innerHTML = ‘Текущая позиция — (X: ‘ + posX +’, Y: ‘+ posY +’), Скорость: ‘ + rocketSpeed;
    }, 10);

    obj.value = ‘Остановить’;
    }
    else {
    // остановка движения
    clearInterval( obj.rocket );
    obj.value = obj.default_value;
    }
    }

    Как сделать движение HTML-объекта на Javascript

  37. Стас
    19 февраля 2010

    2Владимир
    Jquery->animate

  38. Alexander
    7 марта 2010

    Сергей, вам попадался флешовый mp3-плейер, который был бы полностью невидим и полностью рулился бы яваскриптом? Я гуглил полдня, но не нашёл 🙁

  39. Артём Поликарпов
    28 марта 2010
  40. Владислав Шкодин
    2 июля 2010

    Сергей, не подскажите, почему ни в хроме, ни в сафари не работает этот код:

    html:
    <img src=»img/round.png» width=»50″ height=»50″ id=»round» alt=»Hello» />
    <canvas id=»first» width=»150px» height=»150px»>Это канвас</canvas>

    js:
    var canvas = document.getElementById(’first’),
    i = document.getElementById(’round’),
    ctx = canvas.getContext(’2d’);
    ctx.drawImage(i,0,0,50,50);

  41. Владислав Шкодин
    2 июля 2010

    Забыл написать, что в Опере и Файерфоксе всё нормально

  42. Сергей Чикуенок
    2 июля 2010

    Владислав Шкодин, проверьте следующее:

    1. у <canvas> атрибуты width и height полжны быть числами (не нужен px)
    2. Картинка должны быть загружена до того, как вы пытаетесь её отрисовать. Лучше всего загружать её принудительно перед отрисовкой:
    	var img = new Image;
    	img.onload = function() {
    		var canvas = document.getElementById(’first’),
    			i = document.getElementById(’round’),
    			ctx = canvas.getContext(’2d’);
    
    		ctx.drawImage(img, 0, 0, 50, 50);
    	}
    
    	img.src = 'img/round.png';
    
  43. Владислав Шкодин
    8 июля 2010

    Да, спасибо, так всё работает. И ещё один вопрос: скажите, у элемента canvas есть z-index? У меня не получилось поставить его ниже других элементов.

  44. Владислав Шкодин
    9 июля 2010

    Ой, видимо я где-то ступил. Всё нормально у него с z-index. Можете потереть этот вопрос.

  45. paska
    22 июля 2010

    Добрый день Сергей. Я совсем недавно начал осваивать анимацию. Использую jQuery и метод .animate() (над свойствами стилей left и opacity). Анимация шустро и плавно отображается в chrome, opera 10.53, ie 6/7. Но в лисе (версия 3.6.6) проблемы — анимаци тупит и не плавная. Здесь пример: http://host.poskachey.com/ex/anim.

    Я также пробовал сделать такую же анимацию на чистом js — и результат тот же. Не подскажите в чем проблема.

  46. Владислав Шкодин
    3 августа 2010

    http://s002.radikal.ru/i199/1008/d9/527b1d0372b4.jpg

    Сергей, скажите, как на канвасе определить координаты синей точки? Мне нужно провести линию из левого верхнего угла квадрата в эту точку.

  47. Сергей Чикуенок
    3 августа 2010

    В смысле определить? Проанализировать изображение или математически высчитать точку пересечения двух линий?

  48. Владислав Шкодин
    3 августа 2010

    Ну, мне нужно, чтобы конечная точка линии перемещалась в зависимости от положения мыши, но не выходила за пределы квадрата. Т.е. исходя из координат курсора нужно как-то высчитывать координаты пересечения этой линии со стороной квадрата. Видимо наверное математически.

  49. Сергей Чикуенок
    3 августа 2010

    Ну значит надо нагуглить алгоритм поиска пересечения двух линий и всё

  50. Владислав Шкодин
    19 августа 2010

    Сергей, скажите пожалуйста, в чём разница между window.getComputedStyle() и document.defaultView.getComputedStyle()? Не могу понять почему иногда одно заменяют другим.

  51. Сергей Чикуенок
    19 августа 2010

    Разницы нет, технически window === document.defaultView. Но возможна ситуация, что document (то есть объект класса HTMLDocument) принадлежит другому документу, а не тому, с которым работаем. Например, загрузили аяксом внешний XML-файл. В этом случае, если захотите получить CSS-свойства элемента из этого внешнего документа через window.getComputedStyle() получите ошибку.

  52. Владислав Шкодин
    19 августа 2010

    Ясно. Спасибо. А в случае с айФреймом тоже ошибку получу?

  53. Сергей Чикуенок
    19 августа 2010

    Да

  54. Андрей
    2 сентября 2010

    Сергей, поясните пожалуйста как работает эта функция, а именно, почему i всегда увеличивается, а не обнуляется?
    function counter() {
    var i = 0;
    counter = function() {
    return i++;
    }
    return counter();
    }

  55. Сергей Чикуенок
    2 сентября 2010

    Это называется «замыкание»: http://javascript.ru/basic/closure

  56. Андрей
    13 октября 2010

    Здравствуйте Сергей. Около года назад один человек побывавший на вашей конференции порекомендовал мне глянуть один ваш продукт, который мог скруглять, обрезать (под разными углами) дивы, картинки и прочее. Это не была библиотека Racon, это было что-то другое. Но спустя время найти это совсем не получается. Называлось оно еще очень заковыристо)
    Буду очень признателен, если напомните. Заранее спасибо

  57. Андрей
    13 октября 2010

    Меня поправили, что это была РИТ 2008 WebHiTech.

  58. 21 ноября 2010

    Андрей, библиотека называется ictinus.

    Ссылка вверху этой страницы, справа.

  59. EzheG
    28 ноября 2010

    Здравствуйте. Делаю меню на jquery. Сергей, подскажите пожалуйста, как сделать чтобы родительские ul скрывались не моментально а через некоторое время и только если на них не наведена мышь? Пробовал использовать setTimeout, не получается.
    Код на данный момент:
    $.fn.submenu = function() {
    $(this).has(«li»).hover(function() {
    if(!lihover) {
    lihover = true;
    $(this).children(«ul»).animate({width:»show»}, «fast», function() {
    lihover = false
    })
    }
    }, function() {
    if(!lihover) {
    $(this).children(«ul»).animate({width:»hide»}, «fast»)
    }
    }).click(function(){return false});
    };

  60. EzheG
    28 ноября 2010

    Лучше так: http://skysail.ru/code.js

  61. EzheG
    29 ноября 2010

    Баг в Zen Coding. В сафари на маке выделение строки CMD+L выделяет всю строку без последнего символа.

  62. Сергей Чикуенок
    29 ноября 2010

    Нужно управлять состоянием меню: после того, как увели мышь выставить какой-нибудь флажок в true и запустить таймер. Если во время срабатывания таймера флажок всё ещё true, то запустить анимацию

  63. Катя
    5 декабря 2010

    Здравствуйте, Сергей.

    В -е с текстом фоном идет полупрозрачный пнг. При срабатывании функции плавного изменения прозрачности fadeTo, ИЕ(7,8) ухудшает качество фонового изображения, теряются полупрозрачные пиксели, и оно становиться похоже на гиф. И у текста вокруг букв появляются неприятные серые артефакты.

    Может вы сталкивались с похожим? Спасибо.

  64. Катя
    5 декабря 2010

    В спане с текстом

  65. Владислав
    8 декабря 2010

    Сергей, у меня следующая проблема: есть меню, довольно большое по ширине. Оно должно быть зафиксировано сверху справа на странице. Проблема в том, что если поставить ему position: fixed, то при сжатии окна оно будет заползать на контент. Тогда я попытался сделать вертикальный псевдо-fixed с помощью события scroll, но в этом случае меню начинает дико дрожать при прокрутке. Вопрос: есть ли какой-то хороший способ решить эту проблему, лучше через css, но можно и через js.

  66. Сергей Чикуенок
    8 декабря 2010

    Катя, посмотрите тут: http://chikuyonok.ru/2009/02/ie-filters/
    Правда, в IE8, скорее всего, не поможет

    Владислав, не понял задачу. На какой контент что заползает?

  67. Владислав
    8 декабря 2010

    Очень просто: контент слева, меню справа. Меню зафиксированно. Если изменять ширину окна (сжимать), то (т.к. position: fixed) в какой-то момент меню начнет заползать на контент. Т.е. по сути мне нужно чтобы меню было fixed по вертикали. Оставалось на месте при вертикальной прокрутке. Я пробовал два способа: эмулировал вертикальный fixed через событие scroll, но в этом случае меню при прокрутке начинает дрожать, и менял скриптом у меню position: fixed, на position: absolute при достижении минимальной ширины. Но оба способа не устраивают: первый из-за дрожания, второй из-за того, что используется событие resize, которое жрёт ресурсы сильно.

  68. Владислав
    8 декабря 2010

    И второе решение опять же не устраивает тем, что при минимальной ширине окна, меню начнет скролиться вместе с контентом.

  69. Сергей Чикуенок
    8 декабря 2010

    Ресайз не жрёт ресурсы, просто в некоторых браузерах он отрабатывает не так быстро, как хотелось бы.

    Задачу всё равно до конца не понимаю, обычно спрашивающие предоставляют макет, чтобы было ясно, что к чему. Но можно попробовать эмулировать position: fixed http://www.artlebedev.ru/tools/technogrette/html/emulate-fixed/

  70. Владислав
    8 декабря 2010

    http://wip.acdstudio.ru/hotshotfilms/ — вот пример. сжимайте окно. меню наползает на контент.

  71. Сергей Чикуенок
    8 декабря 2010

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

  72. Владислав
    8 декабря 2010

    Сергей, я вот только не совсем понимаю, как данный способ эмуляции position: fixed позволит мне ограничить передвижение меню по горизонтали таким образом, чтобы оно не залезало на область контента.

  73. vika
    11 декабря 2010

    Помогите решить задачку… (Написать функцию которая рисует таблицу. Пользователь с клавиатуры вводит количество строк и количество колонок.)

  74. Василий
    20 декабря 2010

    Здравствйте, хотел прикрепить ваш скрипт rocon к скрипту модуля thickbox для друпал. работать его удалось заставить только на опере, что печально. Действовал — добавил после всех append(’див с ид=TB_window ‘) строку rocon.update($(”#TB_window”).get(0)); — что видимо не свовсем верно. можете помочь разобраться в проблеме?

  75. Дмитрий
    12 января 2011

    Здравствуйте. Возможно ли как-то остановить стандартное действие браузера (например сброс фокуса с ссылки) на событие onmousedown на другом оъекте в Ie<=8?

  76. Василий
    31 января 2011

    есть кто живой?

  77. Игорь
    11 февраля 2011

    Здравствуйте Сергей!

    В своей статье в Техногрете «Eclipse: редактирование JavaScript в Spket IDE» был приведён файл документации для jquery в формате jsdoc, но только для jquery версии 1.2.3 — не обновляли ли Вы этот файл в соответствии с изменениями jquery? Если да, то не поделитесь?

    Спасибо.

  78. Karen
    16 февраля 2011

    Хочу заметить, что лучше использовать префикс $, для обозначении объектов jquery.
    var $elem = $(‘.some-item’);

  79. Ruby
    4 апреля 2011

    Привет.

    Как определить, картинка находится в кэше или ее следует загрузить?

    Пытаюсь сделать галерею с загрузкой по клику, алгоритм примерно таков:
    1) показываем лоадер
    2) ждем загрузки картинки через .load(function())
    3) скрываем лоадер

    Хотел бы не показывать лоадер для кэшированных картинок. Как это можно реализовать?

    Заранее спасибо.

  80. Сергей Чикуенок
    4 апреля 2011

    Игорь, я скоро напишу пост про мою обновлённую среду разработки (в частности, про Eclipse JSDT), там будет пара ссылок.

    Ruby, получить информацию о налии картинки в кэше вряд ли получится, но я эту проблему решал так: прелоудер показывал не сразу, а через небольшой таймаут. Если картинка в кэше или интернет быстрый, то прелоудера не будет, а если превышен лимит ожидания, то показываю прелоудер как минимум на секунду, чтобы не было неприятных морганий. Пример: http://federationtower.ru/tower/offices/

  81. Александр
    5 мая 2011

    Сергей,

    сталкивались ли вы с необходимостью вращать блоки с изображениями/текстом/слоями/ссылками и если да, то какой способ использовали?

    Я смог найти svg, canvas и css3 transform: rotate. Для IE фильтр.

  82. Сергей Чикуенок
    10 мая 2011

    Александр, по-моему этих способов вполне достаточно, чтобы сделать вращение текста во всех браузерах. Самый правильный — CSS Transforms, можно ещё глянуть SVG + foreign object,

  83. Виталий
    10 мая 2011

    Здравствуйте Сергей!

    Хочу спросить следующее, про скорость рендеринга страницы используя jQuery селекторы, сначала опишу на примере css, используя селекторы такого плана например ul#menu li a{} которые обрабатываются справа налево.. и можно уменьшить время рендеринга если цеплять классы, на ссылки и css привязывать используя уже классы вместо ul#menu li a{} селектора. Уважаю вашу точку зрения, что если даже элементов около 1000 то особо видимого прироста производительности можно не ждать, даже в ИЕ6.

    Но вопрос мой вот в чем. Если использовать такие селекторы в jQuery(«ul#menu li a»), то как в этой ситуации по производительности, по аналогии со случаем CSS. Как это происходит в jQuery селекторах?

    Заранее спасибо!

  84. 12 августа 2011

    Как правильно реализовать слабое связывание произвольных не DOM объектов? jQuery, как я понял, умеет правильно работать только с DOM элементами, а на остальные bind и trigger по-хорошему привязать не удаётся.

    Студийный способ от 2007го года я знаю и пользуюсь им. Но ведь, наверняка, такой функционал должен быть уже реализован в каком-то фреймворке и использовать самописные модули некрасиво.

    Спасибо!

  85. Сергей Чикуенок
    16 августа 2011

    Виталий, jQuery работает точно так же, как и браузеры: ищет элементы справа налево. То есть в вашем примере сначала найдутся все элементы a, потом отфильтруются те, у которых есть родитель li и т.д. Лучше не писать глубоких селекторов или, как вариант оптимизации, искать вот так: $('#menu').find('li').find('a');. Это должно быстрее работать в старых браузерах.

    Антон, для слабого связывания я использую библиотеку js-signals. Может, она не самая производительная, но для моих проектов вполне хватает.

  86. 28 октября 2011

    Привет Сергей! Подскажи, чем лучше сделать меню «дерево», jquery плагин какой или еще как?

  87. 9 ноября 2011

    Сергей! Скажите, как Вы относитесь к проекту JSLint — оцениваете ли свой собственный код через призму его рекомендаций и насколько на Ваш взгляд применение и ориентация команды разработчиков на следование им может поспособствовать повышению качества их кода с т.з. удобства задач разбора кода, переформатирования кода автоматизированными средствами и т.д.? Случалось ли Вам работать в проектах, где жёстким требованием при commit`е кода было бы выставлено его прохождение через JSLint?

  88. Александр
    14 ноября 2011

    Здравствуйте Сергей. У вас есть замечательная статья «Производительность браузеров в зависимости от верстки», в которой вы использовали счетчик FPS, который прекращал работать после окончания анимации. Возможно ли использовать подобный счетчик постоянно? Просто я посчитал, что это неплохой способ анализировать так сказать «оптимальность» верстки. Чтобы можно было узнать насколько каждый эффект (скрипт, картинка, анимация и т.д.) притормаживат браузер. Или просто скажите, как вы решаете такие проблемы. Очень интересует эта тема. Заранее большое спасибо.

  89. Isaak
    17 ноября 2011

    Подскажите пожалуйста.
    Вопрос связан с библиотекой Raphael

    var paper = Raphael(ph, 600, 600);
    var shapeA = paper.path(«M 300 10 L 400 10 L 600 500 L 500 500 L 400 300 L 350 300 L 250 500 L 150 500 Z»);

    Подскажите пожалуйста, каким способом я погу получить любые 5 координат точек лежащих ВНУТРИ фигуры shapeA ?

  90. Isaak
    15 декабря 2011

    Здравствуйте Сергей.
    Подскажите пожалуйста, как ПРАВИЛЬНЕЕ реализовать.
    Есть земля, в нее попадает снаряд, который разрушает(делает в ней впадину/углубление), все зависит от попавшего в нее снаряда + кроме впадины нужно реализовать осыпание земли.
    Я думаю это реализовать следующим способом:
    Имеем 2 слоя, один под другим. Верхний слой — картинка земли или гор, второй слой — канвас, который и будет разрушаться. Далее я высчитываю координаты конечной точки снаряда. Сам снаряд имеет радиус поражения, после того, как снаряд достиг конечной точки, я стираю первый слой — тот который канвас — имитирую взрыв(не знаю, как правильнее имитировать, гиф-картинку точно не хочу использовать, скорее всего буду спрайтами делать анимацию) и во время этого взрыва подменяю верхнюю картинку на новую с готовой впадиной.
    Физику я уже сделал, больше всего меня интересует реализация впадины в земле. Как правильно это реализовать подскажите пожалуйста?

  91. 12 марта 2012

    Сергей, хотелось бы увидеть цветовую схему которой вы пользуетесь в IDE, можно в скринах, это возможно? 🙂

  92. Сергей Чикуенок
    12 марта 2012

    Никита, сейчас я пользуюсь стандартной в JSDT цветовой схемой. Вряд ли смогу найти старую схему раскраски

  93. Василий
    20 июля 2012

    Сергей, а могли бы вы как-нибудь рассказать про реализацию функционала нестандартных маркеров гуглокарты на bigbuzzy?

  94. 7 августа 2012

    Сергей здравствуйте! если у вас есть интересные уроки и различные решения для веб програмирования …то я с огромным удовольствием прочитаю их — если еще нет то попробуйте их разместить на сайте!

  95. Евгений
    14 сентября 2012

    Здравствуйте Сергей! Я новичок в JS, помогите пожалуйста, не очень понимаю логику рекурсивных функций в JavaScript.

    Вот например, не могли бы вы обьяснить как работает данная функция:

    function power(base, exponent) {
    if (exponent == 0)
    return 1;
    else
    return base * power(base, exponent — 1);
    }

    power(5, 3);

  96. Саша
    6 февраля 2013

    Привет. А скажите как вы замеряете скорость выполнения скриптов? Например, что будет быстрее создать на лету два новых элемента, или один создать, а второй клонировать. Как такие штуки замерять?
    Например, какой код при использовании jQuery будет менее ресурсоемким?

    var $div = $(»);
    var $divInner = $(»).appendTo($div);
    ___________________________________________

    var $div = $(»);
    var $divInner = $div.clone().appendTo($div);

  97. Сергей Чикуенок
    7 февраля 2013

    Для измерения производительности существуют инструменты, встроенные в браузер: http://chikuyonok.ru/2010/11/optimization-story/

    В вашем случае нельзя сказать, какой из методов будет быстрее, так как сильно зависит от браузера и от специфики задачи. Обычно клонирование гораздо быстрее, но в данном конкретном случае вы используете реализацию jQuery, которая, помимо всего прочего, может наследовать содержимое data и события с элемента-донора. Так что всё зависит от конкретной задачи.

  98. 10 февраля 2013

    где можно посмотреть видео урок

Комментировать

Powered by Zen Coding

(Spamcheck Enabled)