Опубликован: 28.02.2016 | Уровень: для всех | Доступ: платный
Лекция 4:

События

< Лекция 3 || Лекция 4: 12 || Лекция 5 >

"Живые" события

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

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

"У нас есть HTML страница, на которой все внутренние ссылки будут подгружаться AJAX’ом, данное утверждение справедливо и для подгружаемого HTML’а тоже"

Первое условие решается просто:

$('a[href^=\\/]').on('click', function() {
var url = $(this).attr('href');
$('body').load(url + ' body > *');
return false;
});

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

Со вторым условием чуть-чуть посложнее ситуация, но тоже вполне решаема:

$('body').on('click', 'a[href^=\\/]', function() {
var url = $(this).attr('href');
$('body').load(url + ' body > *');
return false;
});

Отличий не так уж и много, проясню происходящее:

  • первым делом на элемент <body> будет повешен обработчик события "click"
  • данный обработчик будет срабатывать только в том случае, когда событие будет относится к элементу <a>

Работа данной схемы базируется на "всплытии" событий, так что используя метод "event.stopPropagation()" вы сможете предотвратить выполнение "живых" обработчиков

Лирическое отступление к истории: жил да был когда-то плагин для jQuery, назывался "live()", позволял он вешать обработчики на элементы DOM дерева которых ещё нет (подгружаемые AJAX’ом или ещё как), а потом он умер его внесли в само ядро. Метод "live()" к тому времени работал лишь с "document". Затем появился метод "delegate()" который научился вешать обработчик на произвольный элемент, а затем и он был поглощён методом "on()". Так что не пугайтесь сильно, если встретите старый метод "live()", адаптировать под новые версии jQuery его будет не так уж и сложно (ну я на это надеюсь)

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

Случай первый, банальный – представьте себе таблицу на тысячу строк да десяток столбцов, а теперь попытайтесь подсчитать, сколько памяти скушают обработчики события "click" для каждой ячейки? Вот-вот, стоит это переписать в один обработчик:

$('table').on('click', 'td', function() { /* ... */ }

Случай второй, надуманный – необходимо записывать действия пользователя на странице, т.е. отслеживать клики по бессчётному количеству объектов:

$('body').on('click', '*', function() {
console.info("Click on "+this.tagName);
});

Пример работы данного "надуманного" варианта

<!DOCTYPE html>
<html dir="ltr" lang="en-US">
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Оптимизация в обработке событий</title>
    <link rel="profile" href="http://gmpg.org/xfn/11"/>
    <link rel="shortcut icon" href="http://anton.shevchuk.name/favicon.ico"/>
    <link rel="stylesheet" href="css/styles.css"/>
    <style>
        #content {
            padding: 2px;
        }
        #content:before {
            color:#777;
            font-size: 14px;
            content: '<div id="content" class="wrapper box">'
        }
        #content:after {
            color:#777;
            font-size: 14px;
            content: '</div>'
        }
        header {
            background: #fff;
            padding: 2px;
            margin: 20px;
            border-left: 1px solid #ddd;
        }
        header:before {
            color:#777;
            font-size: 12px;
            content: "<header>"
        }
        header:after {
            color:#777;
            font-size: 12px;
            content: "</header>"
        }
        article {
            background: #fff;
            padding: 2px;
            margin: 20px;
            border-left: 1px solid #ddd;
        }
        article:before{
            color:#777;
            font-size: 12px;
            content: "<article>"
        }
        article#stick:before{
            content: '<article id="stick" class="box">'
        }
        article:after{
            color:#777;
            font-size: 12px;
            content: "</article>"
        }
        footer {
            background: #fff;
            margin: 12px 8px;
        }
        footer:before{
            color:#777;
            font-size: 12px;
            content: "<footer>"
        }
        footer:after{
            color:#777;
            font-size: 12px;
            content: "</footer>"
        }
        p {
            background: #fff;
            margin: 12px 8px;
        }
        p:before{
            color:#777;
            font-size: 12px;
            content: "<p>"
        }
        p:after{
            color:#777;
            font-size: 12px;
            content: "</p>"
        }
        h1 {
            background: #fff;
        }
        h1:before{
            color:#777;
            font-size: 12px;
            content: "<h1>"
        }
        h1:after{
            color:#777;
            font-size: 12px;
            content: "</h1>"
        }
        h2 {
            background: #fff;
            border: 0 !important;
        }
        h2:before{
            color:#777;
            font-size: 12px;
            content: "<h2>"
        }
        h2:after{
            color:#777;
            font-size: 12px;
            content: "</h2>"
        }
    </style>
    <script type="text/javascript" src="js/jquery.js"></script>
    <script type="text/javascript" src="js/code.js"></script>
    <script type="text/javascript">
        $(function(){
            $('body').on('click', '*', function(e) {
                var targ;
                if (e.target) targ = e.target;
                else if (e.srcElement) targ = e.srcElement;
                if (targ.nodeType == 3) // defeat Safari bug
                    targ = targ.parentNode;
                if (targ == this) {
                    appendOut("Click on "+this.tagName + "\n");
                } else {
                    appendOut(" > "+this.tagName + "\n");
                }
            });
        });
    </script>
</head>
<body>
    <div id="content" class="wrapper box">
        <menu label="Try...">
            <a href="index.html" title="go prev" class="button alignleft" rel="prev">← Back </a>
            <a href="#" title="reload" class="button alignleft" onclick="window.location.reload();return false">Reload ¤</a>
            <hr/>
            <h3>Покликайте по элементам</h3>
            <h3>Объясните, что за дополнительная информация выводится на экран</h3>
        </menu>
        <div id="output">
            <h3>Output</h3>
            <pre></pre>
        </div>
        <header>
            <h1><a href="#">Events optimization</a></h1>
            <h2>Page Description</h2>
        </header>
        <article id="stick" class="box">
            <h2>Article</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus rutrum,
            lectus eu varius consectetur, libero velit hendrerit augue, ut posuere enim neque
            in libero. Donec eget sagittis nibh. Suspendisse sed tincidunt urna. Cras quis
            euismod neque. Maecenas auctor ultricies posuere. Pellentesque luctus pulvinar dui
            eget semper. Donec sodales odio eu sapien varius luctus. Donec dictum feugiat diam
            at malesuada. Sed nec massa in augue condimentum faucibus quis ut diam. Quisque
            nisl sem, semper nec vulputate vel, mattis sit amet justo. Aliquam purus felis,
            tempor at scelerisque quis, tincidunt in neque. Etiam ut risus diam. Pellentesque
            fermentum risus id elit feugiat cursus. Ut fringilla dictum diam, sed iaculis
            lorem pulvinar ut. Cras vel elit id velit commodo viverra sit amet vel orci.</p>
        </article>
        <article>
            <h2>Article</h2>
            <p>Duis in vestibulum sem. Cras euismod tincidunt dui, et scelerisque tellus condimentum vel.
            Maecenas et urna sit amet risus fermentum rhoncus nec porttitor ligula. Maecenas sit amet
            turpis enim, ut iaculis est. Duis feugiat, lacus id placerat porttitor, lorem augue gravida
            nisi, eu porta eros risus et lectus. Maecenas vestibulum nunc vel ipsum tincidunt sit amet
            blandit sapien bibendum. Proin vel vulputate nisl. Duis tempor imperdiet placerat. Pellentesque
            faucibus consequat magna, et bibendum nisl egestas non. Pellentesque sit amet mattis augue.
            Aenean at diam tincidunt purus sollicitudin gravida non in nisi. Fusce bibendum, magna in
            adipiscing mattis, sem risus fringilla mi, nec gravida lectus lectus at nibh. Suspendisse
            adipiscing elementum laoreet. Suspendisse sem erat, varius quis aliquet vitae, dapibus sed
            nibh. Nullam iaculis sem at mauris faucibus in vestibulum libero pretium. Aliquam eu turpis
            libero. Fusce et ultrices lectus.</p>
        </article>
        <footer>
            ©copyright 2014 Anton Shevchuk — <a href="http://anton.shevchuk.name/jquery-book/">jQuery Book</a>
        </footer>
        <script type="text/javascript">
            var _gaq = _gaq || [];
            _gaq.push(['_setAccount', 'UA-1669896-2']);
            _gaq.push(['_trackPageview']);
            (function() {
             var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
             ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
             var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
            })();
         </script>
	</div>
</body>
</html>

Touch события

Смартфоны с большим сенсорным экраном — это уже норма жизни, и любому web-разработчику рано или поздно потребуется разрабатывать интерфейсы с поддержкой "touch" событий. На этот случай в JavaScript'е предусмотрены следующие события:

touchstart — событие схоже с "mousedown", происходит при касании пальцем экрана

touchend — убираем палец с экрана, ака "mouseup"

touchmove — водим пальцем по экрану — "mousemove"

touchcancel — странное событие, отмена "touch" до того, как палец был убран

О том как с ними работать, можно подчерпнуть из статьи Touching and Gesturing on iPhone, Android, and More [http://www.sitepen.com/blog/?p=3425] (хоть рассказ там и о Dojo Toolkit).

В jQuery Mobile работа с touch событиями идёт "из коробки". Чтобы jQuery UI заставить работать с touch событиями следует использовать библиотеку jQuery UI Touch Punch [http://touchpunch.furf.com/] Пробуйте, но учтите, без touch устройства разработка интерфейсов для подобных устройств – нонсенс (англ. nonsense).

< Лекция 3 || Лекция 4: 12 || Лекция 5 >
Наталья Маркова
Наталья Маркова
Ярослав Гаевой
Ярослав Гаевой

10 марта 2016 c 20:13 до 22:39 я сдавал экзамен. Однако, за два месяца статус не изменился: "Задание не проверено"

Когда ожидать проверки?

Руслан Жанбосынов
Руслан Жанбосынов
Россия
Дмитрий Молокоедов
Дмитрий Молокоедов
Россия, Новосибирск, НГПУ, 2009