Модераторы: Sardar, Aliance

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> как узнать порядковый номер дочернего элемента ? 
V
    Опции темы
macdack
Дата 2.9.2014, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 15.4.2010

Репутация: нет
Всего: нет



допустим в документе есть список элементов

как при клике по элементу узнать его порядковый номер в списке дочерних элементов ?
PM MAIL   Вверх
Aliance
Дата 2.9.2014, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


I ♥ <script>
****


Профиль
Группа: Модератор
Сообщений: 6418
Регистрация: 2.8.2004
Где: spb

Репутация: 17
Всего: 137



Если через jQuery, то там есть метод $.index()
Демо: http://jsfiddle.net/Aliance/en653sza/
PM MAIL WWW ICQ Skype   Вверх
macdack
Дата 2.9.2014, 14:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 15.4.2010

Репутация: нет
Всего: нет



спасибо
но мне нужно без сторонних библиотек
только хардкор ))

PM MAIL   Вверх
Aliance
Дата 2.9.2014, 14:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


I ♥ <script>
****


Профиль
Группа: Модератор
Сообщений: 6418
Регистрация: 2.8.2004
Где: spb

Репутация: 17
Всего: 137



Ну как бы можно посмотреть как в этой библиотеки оно реализовано и скопировать.
С ходу могу предложить минимум два решения:
1) Нужно найти parentNode у искомого элемента, далее найти массив дочерних элементов (childNodes) этой родительской ноды, и пройтись циклом  по этому массиву, чтобы узнать на какой итерации мы дойдем до искомой. Номер итерации и будет равен её положению.
http://jsfiddle.net/Aliance/en653sza/1/
2) Нужно подсчитать кол-во предшествующих соседних элементов ДО искомой ноды. Это количество плюс один и будет равно ее положению.
подробнее
PM MAIL WWW ICQ Skype   Вверх
macdack
Дата 2.9.2014, 14:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 15.4.2010

Репутация: нет
Всего: нет



вопрос еще так стоит - не проще ли просто добавлять в каждый элемент нужные данные data-
если в модели DOM нет простого решения

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


PM MAIL   Вверх
ksnk
Дата 2.9.2014, 16:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 48
Всего: 386



macdack, Ну и добавляй в элементы дополнительные атрибуты, если это возможно, какие проблемы? Добавлять их можно в атрибуты data-XXX="YYY". 
Тогда переход когда-нибудь на jQuery окажется еще более безболезненным. В принципе, если используется валидатор html, могут обнаружится проблемы с некорректными именами атрибутов, но на это разумно плевать или использовать правильный доктайп.


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
macdack
Дата 2.9.2014, 17:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 15.4.2010

Репутация: нет
Всего: нет



ksnk,  проблем нет датасет годится

просто хотел узнать нет ли чегото в ДОМе готового и быстрого

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

jQuery вообще не рассматривается по причине того что проекты планируются не энтерпрайзные, а чисто для себя и чисто на вебките без микрософтов, а потом может и на асме, когда подрасту ))

например оч интересно синтезатор на веб-аудио-апи сделать



Это сообщение отредактировал(а) macdack - 2.9.2014, 17:20
PM MAIL   Вверх
Aliance
Дата 3.9.2014, 08:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


I ♥ <script>
****


Профиль
Группа: Модератор
Сообщений: 6418
Регистрация: 2.8.2004
Где: spb

Репутация: 17
Всего: 137



Я сравнил 4 метода: jQuery.index() / jQuery.data() / native js parentNode.childNodes / native js previousElementSibling, самым производительным оказался второй. Мог где-то ошибиться конечно, но в целом вроде адекватно.
PM MAIL WWW ICQ Skype   Вверх
Aliance
Дата 3.9.2014, 08:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


I ♥ <script>
****


Профиль
Группа: Модератор
Сообщений: 6418
Регистрация: 2.8.2004
Где: spb

Репутация: 17
Всего: 137



Если с data-* все понятно, то можно подсмотреть как в jQuery реализован метод $.index():
Код

    index: function( elem ) {
        // No argument, return index in parent
        if ( !elem ) {
            return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
        }
        // ...
    }

// метод .first() просто выбирает из коллекции первый подходящий элемент, его опустим.
// рассмотрим сразу метод prevAll(). По логике, он должен вернуть коллекцию previousElementSibling
// подсчитая ее количество (.length) мы поймем какая позиция у текущего элемента

    prevAll: function( elem ) {
        return jQuery.dir( elem, "previousSibling" );
    }

// рассмотрим метод jQuery.dir

    dir: function( elem, dir, until ) {
        var matched = [],
            cur = elem[ dir ];

        while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
            if ( cur.nodeType === 1 ) {
                matched.push( cur );
            }
            cur = cur[dir];
        }
        return matched;
    }


Ага, теперь видим разницу. Я предложил использовать previousElementSibling (IE > 8), которое выдает, видимо, только ноды тегов (тип 1), а в jQuery используется previousSibling, которые выдает вообще все ноды, в совокупности с фильтрацией по типу 1. Это и оказалось быстрее (вариант 5 по ссылке ранее), чем jQuery.index() (вариант 1). Но все же jQuery.data еще быстрее, можно подсмотреть ее реализацию и сделать на нативном JS и получить наиболее быстрое решение. Если интересно, в jQuery метод, отвечающий за это, выглядит вот так:
Код

function dataAttr( elem, key, data ) {
    // If nothing was found internally, try to fetch any
    // data from the HTML5 data-* attribute
    if ( data === undefined && elem.nodeType === 1 ) {

        var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();

        data = elem.getAttribute( name );

        if ( typeof data === "string" ) {
            try {
                data = data === "true" ? true :
                    data === "false" ? false :
                    data === "null" ? null :
                    // Only convert to a number if it doesn't change the string
                    +data + "" === data ? +data :
                    rbrace.test( data ) ? jQuery.parseJSON( data ) :
                    data;
            } catch( e ) {}

            // Make sure we set the data so it isn't changed later
            jQuery.data( elem, key, data );

        } else {
            data = undefined;
        }
    }

    return data;
}

Добавил его в тестовое сравнение как пункт №6, но в итоге несмотря на ожидания он не победил. Почему - точно сказать не могу, но явно я что-то упустил. Внутри jQuery.data есть кеширование, видимо из-за этого.

Кому лень смотреть тесты, итог таков:
jQuery.index() - 9,869 операций в секунду
jQuery.data() - 16,558
native js parentNode.childNodes - 3,860
native js previousElementSibling - 7,014
native js previousSibling - 11,525
native js data-* - 11,852
PM MAIL WWW ICQ Skype   Вверх
macdack
Дата 3.9.2014, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 15.4.2010

Репутация: нет
Всего: нет



списибо Aliance, но мне пока трудно читать чужой код
я пока делаю первую практическую работу - простейший редактор текста

пожста попроще поясни почему нативная и жикверская data- различаются у тебя по скорости
PM MAIL   Вверх
Aliance
Дата 3.9.2014, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


I ♥ <script>
****


Профиль
Группа: Модератор
Сообщений: 6418
Регистрация: 2.8.2004
Где: spb

Репутация: 17
Всего: 137



Цитата(Aliance @  3.9.2014,  09:51 Найти цитируемый пост)
Почему - точно сказать не могу, но явно я что-то упустил. Внутри jQuery.data есть кеширование, видимо из-за этого.

скорее всего потому, что jQuery сперва проверяет наличие значения во внутреннем статик-кеше, и если его там нет - только тогда лезет в аттрибут к ноде, а затем его записывает в статик-кеш, чтобы при следующем обращении получить от туда быстрее. Получается, при одной итерации - jQuery вариант должен быть медленнее, из-за лишних операций. Но на дистанции оказывается быстрее за счет того, что вычисляет значение единожды. Думаю перевес связан с этим. А jsperf прогоняет тесты многократно, соответственно кеш срабатывает. Если бы сравнивалась скорость одной итерации - нативный вариант должен был победить.
PM MAIL WWW ICQ Skype   Вверх
Aliance
Дата 3.9.2014, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


I ♥ <script>
****


Профиль
Группа: Модератор
Сообщений: 6418
Регистрация: 2.8.2004
Где: spb

Репутация: 17
Всего: 137



Ну да, так оно и есть. Исправил 6 пример с нативным data-* (см. ссылку на jsperf выше), итог получился следующим:
jQuery.data() - 16,155
native js data-* - 20,731

Добавлено через 1 минуту и 14 секунд
Соответственно, самый быстрый способ - №6:
Код

<div class="container">
    <p id="p6" data-index="1">one</p>
    <p id="p7" data-index="2">two</p>
    <p id="p8" data-index="3">three</p>
</div>
<div class="container">
    <p id="p1" data-index="1">one</p>
    <p id="p2" data-index="2">two</p>
    <p id="p3" data-index="3">three</p>
    <p id="p4" data-index="4">four</p>
    <p id="p5" data-index="5">five</p>
</div>

Код

var data = {},
    elements = document.getElementsByTagName('p');
for (var i = 0; i < elements.length; i++) {
    var index = getIndex(elements[i]);
    elements[i].innerHTML += ' [' + index + ']';
}

function getIndex(node) {
    if (typeof data[node.id] === 'undefined') {
        data[node.id] = node && node.nodeType === 1 ? node.getAttribute('data-index') : -1;
    }

    return data[node.id];
}

PM MAIL WWW ICQ Skype   Вверх
macdack
Дата 3.9.2014, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 15.4.2010

Репутация: нет
Всего: нет



Aliance, спасибо

пойду делать нативный data-
PM MAIL   Вверх
Aliance
Дата 3.9.2014, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


I ♥ <script>
****


Профиль
Группа: Модератор
Сообщений: 6418
Регистрация: 2.8.2004
Где: spb

Репутация: 17
Всего: 137



Не за что. В Вашем случае скорее всего хватит варианта без статик-кеширования, сомневаюсь что вы многократно будете высчитывать позицию какого-либо элемента. Кроме того наличие статик-кеша требует некого идентификатора, я в своем кода для примера ввел ID (в коде обращаясь через node.id), но в реальности скорее всего с этим будут проблемы, еще один мотив не писать статик кеша просто так.
Как-нибудь руки доберутся посмотреть как реализован механизм идентификации нод в jQuery...

Если ответ на ваш вопрос дан - вверху есть ссылка "Пометить как решённый", желательно не забывать ее нажимать.
PM MAIL WWW ICQ Skype   Вверх
macdack
Дата 5.9.2014, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 15.4.2010

Репутация: нет
Всего: нет



оказывается почтишто что я придумал в этой теме реализовано в этой библиотеке - http://habrahabr.ru/post/235675/

Если кратко (на самом деле, очень кратко, но идею уловите, а подробности придут с кодом) и по сути: Ractive.js до ужаса прост и состоит из двух половинок:

Темплейты (читай «вьюшка»), в которых вы очень декларативно описываете, как ваша программа\компонент должна выглядеть.
Данные — собственно данные, которые нужно представить во вьюшке и то, как на них влияет внешний мир (взаимодействие пользователя и\или сетевых запросов).


Соответственно, после того, как вы описали темплейт, данные и куда это все это рендарить (обычно id DOM элемента на страничке),
Ractive.js обеспечивает (причем абсолютно бескорыстно и без вашего участия) двухстороннюю связь между этими данными и темплейтом.
Т.е., как только данные меняются, тут же реактивненько меняется ваша вьюшка, которая соответствует этим данным, добовляются нужные и удаляются устаревшие DOM елементы. Ну и в обратную сторону:
как только пользователь чем-то в ваше приложение потыкал — меняются данные.
И так по кругу. И все очень реактивненько.

Вы спросите: «А в чем же радость?»

А радость в том, что вы пишите короткий, понятный, декларативный код без миллионов ивентов (которые как обычно летают взад и вперед, а мы пытаемся их обсервить, биндить и т.д.).
А главное — нет никаких манипуляций с DOM! Мы не создаем новые элементы… мы не удаляем их из DOM…
мы фактически никогда не ищем какой-то элемент при помощи $(selector) — всё всегда под рукой.
Ractive выстраивает паралельный DOM точно так же как это делает React и производит только точечные манипуляции с DOM.
Никаких лишних движений, и поэтому работает очень быстро. Кстати чем Ractive лучше\хуже React — тема для отдельной статьи.

Всё просто: поменяли данные — поменялось отображение. Это общая идея библиотечки.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0940 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.