Введение в jQuery

Манипуляции с DOM

Показывать лекцию целиком

А теперь я буду долго и нудно рассказывать о том, как с помощью jQuery можно изменять DOM дерево на странице, т.е. добавлять и удалять элементы, но чего это я, глава в действительности не будет объёмной :)

Начнём с создания элементов для последующей работы с ними, документация нам заботливо сообщает, что тут всё просто:

var $myDiv = $('<div id="my" class="some"></div>')

Этот пример вполне рабочий, да вот только производительностью он блистать не будет, ведь внутри будет всё это разбираться с помощью метода "jQuery.parseHTML()", который совсем не быстрый. Но мы можем помочь парсеру если атрибуты элемента будем передавать вторым параметром:

var $myDiv = $('<div>', {'id':'my', 'class':'some'})

Можем сделать ещё проще:

var $myDiv = $('<div>').attr({'id':'my', 'class':'some'});

И этот способ будет работать даже быстрее (ну совсем капельку), но почему? Для того, чтобы ответить на данный вопрос – загляните в код jQuery, в самую главную функцию "init()", в её коде можно найти алгоритм разбора предыдущего примера:

  • Парсим строку, и создаём DOM элемент в jQuery обёртке
  • Заходим в цикл обработки переданных параметров:
  • Проверяем, а нет ли функции у нашего элемента с таким названием
  • Если нет, то устанавливаем атрибут элемента используя метод attr()
  • Выводы делайте сами, гдe мы тут время потеряли :)

    Ну и на последок опишу самый быстрый способ, который я часто использую:

    var myDiv = document.createElement('div'); 
    myDiv.id = 'my';
    myDiv.className = 'some';
    

    Да, это и есть "чистый" JavaScript, но как по мне – в данном случае он не менее удобен любых фреймворков. И вот вам домашнее задание – оптимизируйте такой скрипт:

    $('<div id="my"><div 
    id="precious">Ring</div></div>')

    Выполняйте тут, бумага стерпит:

    Все необходимые нам методы собраны в одном разделе документации – Manipulation, с некоторыми из них мы уже познакомились, и осталось совсем чуть-чуть:

    after(content) — вставляет контент после каждого элемента из выборки, т.е. если вы встречаете строку "$("p").after("<hr/>")", читайте её как "после каждого параграфа будет вставлена линия"

    insertAfter(element) — вставляет элементы из выборки после каждого элемента переданного в качестве аргумента, т.е. если вы встречаете строку "$("<hr/>").insertAfter("p")" – читайте её как "линия будет вставлена после каждого параграфа"

    — Хм, а я разницы не увидел! — тут всё легко, присмотритесь:

    $("после чего добавляем").after("что добавляем")
    $("что добавляем").insertAfter("после чего добавляем")

    before(content) — вставляет контент перед каждым выбранным элементом

    insertBefore(element) — вставляет элементы из выборки перед каждым элементом переданным в качестве аргумента

    append(content) — вставляет контент в конец каждого элемента из выборки, т.е. строку кода "$("p").append("<hr/>")", следует читать как "в конец каждого параграфа будет добавлена линия"

    appendTo(element) — вставляет выбранный контент в конец каждого элемента переданного в качестве аргумента: "$("<hr/>").appendTo("p")" — "линия будет добавлена в конец каждого параграфа"

    Опять про разницу:

    $("куда добавляем").append("что добавляем")
    $("что добавляем").appendTo("куда добавляем")

    prepend(content) — вставляет контент в начало каждого элемента из выборки

    prependTo(element) — вставляет выбранный контент в начало каждого элемента переданного в качестве аргумента

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

    replaceWith(content) – заменяет найденные элементы новым

    replaceAll(target) – вставляет контент в замен найденному

    $("что-то находим").replaceWith("на что меняем")
    $("что вставляем").replaceAll("вместо чего")

    wrap(element) – оборачиваем каждый найденный элемент новым элементом, т.е. мы конфеты из коробки заворачиваем в фантики

    wrapAll(element) – оборачивает найденные элементы новым элементом, мы берём все конфеты, и заворачиваем в один большой фантик

    wrapInner(element) – оборачивает контент каждого найденного элемента новым элементом, берём конфеты, убираем фантики, заворачиваем в свой фантик, и сверху заворачиваем в родной фантик

    unwrap() – удаляет родительский элемент у найденных элементов, фантики вон

    clone(withDataAndEvents) – клонирует выбранные элементы, для дальнейшей вставки копий назад в DOM, позволяет так же копировать и обработчики событий

    detach() – удаляет элемент из DOM, но при этом сохраняет все данные о нём в jQuery, следует использовать, если надо удалить элемент, а потом вернуть его обратно

    empty() – удаляет текст и дочерние DOM элементы

    remove() – удаляет элемент из DOM, насовсем

    html() – вернёт HTML заданного элемента

    html(newHtml) – заменит HTML в заданном элементе

    text() – вернёт текст заданного элемента, если внутри элемента будут другие HTML тэги, то вернётся сборная солянка из текста всех элементов

    text(newText) – заменит текст внутри выбранных элементов, при попытке вставить таким образом HTML, будет получен текст, где тэги будут приведены к HTML entities:

    $("div").text("Some <strong>text</strong>") >> Some <strong>text</strong>

    Переварили? Хорошо, теперь настал черёд методов, которые работают с размерами, и знают координаты элементов:

    Но прежде чем продолжить, хотелось бы освежить в памяти информацию о вычислении высоты и ширины блочных элементов ;)

    offset() – вернёт позицию DOM элемента относительно document'а, данные будут получены в виде объекта: "{ top: 10, left: 30 }"

    offset({ top: 10, left: 30 }) – устанавливаем расположение DOM элемента по указанным координатам

    position() – вернёт позицию DOM элемента относительно родительского элемента

    height() – возвращает высоту элемента за вычетом отступов и границ; если у нас несколько элементов в выборке, вернётся первый; значение, в отличии от метода "css('height')", возвращается без указания единиц измерения

    height(height) — устанавливает высоту всех элементов в выборке, если значение высоты передано без указания единиц измерения, то это будут "px"

    // в качестве памятки, взято из мануала
    $(window).height(); // высота окна
    $(document).height(); // высота HTML документа

    width() и width(width) – ведут себя аналогично методу "height()", но работают с шириной элемента

    Методы "height()" и "width()" не изменяют своего поведения в зависимости от выбранной блочной модели, т.е. они всегда возвращают параметры области внутри margin, padding и border'а элемента.

    innerHeight() и innerWidth() – вернут соответственно высоту и ширину элемента, включая "padding"

    outerHeight() и outerWidth() – вернут высоту и ширину элемента, включая "padding" и "border"

    outerHeight(true) и outerWidth(true) – высота и ширина, включая "padding", "border" и "margin"

    Для наглядности различий между методами "height()", "innerHeight()" и "outerHeight()" я создал страничку, а ещё переделал несколько картинок из официальной документации в одну полноценную иллюстрацию:

    <!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"/>
    	<script type="text/javascript" src="js/jquery.js"></script>
    	<script type="text/javascript" src="js/code.js"></script>
        <style>
            article {
                border: 1px solid #000;
            }
            #block {
                width:400px;
                height:40px;
                margin:40px;
                padding:40px;
                border:40px solid #777;
                background: #ddd;
            }
            #text {
                background: #fff;
                font-size: 20px;
                line-height: 40px;
                text-indent: 8px;
            }
            .contentBox {
                box-sizing: content-box;
                -moz-box-sizing: content-box;
                -webkit-box-sizing: content-box;
            }
            .borderBox {
                box-sizing: content-box;
                -moz-box-sizing: content-box;
                -webkit-box-sizing: content-box;
            }
            @media screen and (max-width: 480px) {
                article {
                    border: 0;
                }
                #block {
                    width:auto;
                }
                #text {
                    font-size: 16px;
                }
            }
        </style>
    </head>
    <body>
        <div id="content" class="wrapper box">
            <menu>
                <a href="property.html" title="go prev" class="button alignleft" rel="prev">← Prev </a>
                <a href="index.html" title="back to Index" class="button alignleft" rel="index">Index §</a>
                <a href="#" title="reload" class="button alignleft" onclick="window.location.reload();return false">Reload ¤</a>
                <a href="form.html" title="go next" class="button alignright" rel="next">Next →</a>
                <hr/>
                <h3>Style</h3>
                <pre><code>#block {
        height:40px;
        margin:40px;
        padding:40px;
        border:40px solid #777;
    }</code></pre>
                <!--<h3>Switch <em>box-sizing</em></h3>-->
                <!--<pre><code contenteditable="true">$(<span>'#block'</span>).addClass(<span>'borderBox'</span>)</code></pre>-->
                <!--<button type="button" class="code">Run Code</button>-->
                <!--<pre><code contenteditable="true">$(<span>'#block'</span>).addClass(<span>'contentBox'</span>)</code></pre>-->
                <!--<button type="button" class="code">Run Code</button>-->
                <h3>Получаем высоту</h3>
                <p>Лишь значение height</p>
                <pre data-out="1"><code>$(<span>'#block'</span>).height()</code></pre>
                <button type="button" class="code">Run Code</button>
                <p>Значение height + padding</p>
                <pre data-out="1"><code>$(<span>'#block'</span>).innerHeight()</code></pre>
                <button type="button" class="code">Run Code</button>
                <p>Значение height + padding + border</p>
                <pre data-out="1"><code>$(<span>'#block'</span>).outerHeight()</code></pre>
                <button type="button" class="code">Run Code</button>
                <p>Значение height + padding + border + margin</p>
                <pre data-out="1"><code>$(<span>'#block'</span>).outerHeight(true)</code></pre>
                <button type="button" class="code">Run Code</button>
            </menu>
            <header>
                <h1>Пример вычисление «высот»</h1>
            </header>
            <div id="output">
                <h3>Output</h3>
                <pre></pre>
            </div>
            <article>
                <div id="block">
                    <div id="text">Content</div>
                </div>
            </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>
    
    (рис 6.1) блочная модель

    Ну и последняя пара методов:

    scrollLeft() – возвращает значение "проскроленности" по горизонтали первого элемента из выборки

    scrollLeft(value) – устанавливает значение горизонтального скрола для каждого элемента из выборки

    scrollTop() – возвращает значение "проскроленности" по вертикали первого элемента из выборки

    scrollTop(value) – устанавливает значение вертикального скрола для каждого элемента из выборки

    Значение "scrollTop" и "scrollLeft" поддаются анимации и не работают для спрятанных элементов DOM

    Методов реально много, я и сам не всегда помню что и для чего (особенно это касается wrap-семейства), так что не утруждайте себя запоминанием всего перечисленного, главное помнить что таковые имеются и держать под рукой документацию

    Вернуться к учебному плану