TemKa_SD 9 03/02/19 07:21 (изменено) Здравствуйте, необходимо реализовать функцию, которая, переносит HTML в новое место, точнее, это старая логика, сейчас нужно придумать более сложный способ. И так, вот старая функция: var row = this.scope.find('[data-gamename="'+ data.gamename +'"] > .ipsDataItem_main > ul.ipsDataItem_subList'); var currentPlayer = row.find('[data-player="'+ data.name +'"]'); var currentSID = currentPlayer.parent(); var newSID = row.find('> li.usercolor.usercolor-'+ data.sid +''); var newPlayer = newSID.innerHTML; currentSID.html(newPlayer); newSID.html(currentPlayer); Она переносила пользователя на новый SID, например, с 0 на 5, а 5 на 0, там уже была структура li элементов, сейчас её нет, li нужно создавать через JS, поэтому, прошлый способ не подходит. Я вот начал, но этого мало, оно переносит на новый SID но старый class остается: this.scope.find('[data-gamename="'+ data.gamename +'"] > .ipsDataItem_main > ul.ipsDataItem_subList').find('[data-player="'+ data.name +'"]').removeClass('').addClass('usercolor usercolor-'+ data.sid +''); Это функция входа игрока, в принципе в ней реализовано всё что нужно, нужно модифицировать под новые потребности и всё, сейчас буду пробовать, напишу что получилось или нет. // Вход игрока var rowElem = this.scope.find('[data-gamename="'+ data.gamename+ '"] > .ipsDataItem_main > ul.ipsDataItem_subList'); var playerElement = '<li class="usercolor usercolor-'+ data.sid +'" data-player="'+ data.name +'"><a href="#" data-ipsHover data-ipsHover-width="225" data-ipsHover-target="'+ ips.getSetting('baseURL') +'index.php?app=wc3&module=activegames&controller=ActiveGames&player='+ data.name +'&server='+ data.realm +'&ping='+ data.ping +'&do=hovercard" data-ipsHover-timeout="0">'+ data.name +'</a></li>'; var insertAfter, insertBefore, uColor; var sid = data.sid; rowElem.find('.usercolor').each(function( i ) { uColor = parseInt($(this).attr('class').replace('usercolor usercolor-', '')); if (uColor > sid && !insertBefore) { insertBefore = $(this); } if (uColor < sid) { insertAfter = $(this); } }); if (insertAfter) { insertAfter.after(playerElement); } else if (insertBefore) { insertBefore.before(playerElement); } else { rowElem.html(playerElement); } Как я примерно это вижу, у нас известен только новый SID, сначала необходимо спарсить старый. Затем, старый заменить на новый и наоборот, при этом, нужно сохранить последовательность li элементов. Изменено 2 марта 2019 пользователем TemKa_SD Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 03/02/19 07:53 (изменено) Парсит норм: http://prntscr.com/ms5xke var currentSID = this.scope.find('[data-gamename="'+ data.gamename+ '"] > .ipsDataItem_main > ul.ipsDataItem_subList').find('[data-player="'+ data.name +'"]'); var uColor = parseInt(currentSID.attr('class').replace('usercolor usercolor-', '')); var newSID = data.sid; Debug.log("Старый SID: " + uColor + " Новый SID: " + newSID); Он парсится, почему ошибка? TypeError: Cannot read property 'replace' of undefined Наверно, лучше всего будет удалить старый li и добавить новый. Изменено 2 марта 2019 пользователем TemKa_SD Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 04/06/19 07:51 Здравствуйте. Вернулся к разработке данного приложения, последний вопрос актуален. Я реализовал функцию замены данных при переходе игрока на другой слот, должен меняться li элемент на новый, в итоге получилось следующее (специально перед этим сообщением добавил комментарии в код): handlePlayerChangedSID: function (data) { // Определяем строку (игру) в которой нужно произвести замену. var rowElem = this.scope.find('[data-gamename="'+ data.gamename+ '"] > .ipsDataItem_main > ul.ipsDataItem_subList'); // Определяем на каком слоте сейчас находится нужный игрок. var currentColor = parseInt(this.scope.find('[data-gamename="'+ data.gamename+ '"] > .ipsDataItem_main > ul.ipsDataItem_subList').find('[data-player="'+ data.name +'"]').attr('class').replace('usercolor usercolor-', '')); // Данные для замены (полностью li, нужно будет вывести эти данные в общую переменную, так как они используются в нескольких местах) var playerElement = '<li class="usercolor usercolor-'+ data.sid +'" data-player="'+ data.name +'"><a href="#" data-ipsHover data-ipsHover-width="225" data-ipsHover-target="'+ ips.getSetting('baseURL') +'index.php?app=wc3&module=activegames&controller=ActiveGames&player='+ data.name +'&server='+ data.realm +'&ping='+ data.ping +'&do=hovercard" data-ipsHover-timeout="0">'+ data.name +'</a></li>'; var insertAfter, insertBefore, uColor; rowElem.find('.usercolor').each(function( i ) { // Парсим старый sid слота, с которого ушел данный игрок. uColor = parseInt($(this).attr('class').replace('usercolor usercolor-', '')); // Если старый слот больше нового, вставить данные до старого слота. if (uColor > data.sid && !insertBefore) { insertBefore = $(this); } // Если старый слот меньше нового, вставить данные после старого слота. if (uColor < data.sid) { insertAfter = $(this); } }); if (insertAfter) { // Если вставить после, выполняем функцию after и удаляем старый li. insertAfter.after(playerElement); this.scope.find('[data-gamename="'+ data.gamename +'"] > .ipsDataItem_main > ul.ipsDataItem_subList').find('li.usercolor.usercolor-'+ currentColor +'').remove(); } else if (insertBefore) { // Если вставить до, выполняем функцию before и удаляем старый li. insertBefore.before(playerElement); this.scope.find('[data-gamename="'+ data.gamename +'"] > .ipsDataItem_main > ul.ipsDataItem_subList').find('li.usercolor.usercolor-'+ currentColor +'').remove(); } else { // Если ни то ни то, вставляем просто html. rowElem.html(playerElement); } } Здесь мне не понятно, зачем тут && !insertBefore: // Если старый слот больше нового, вставить данные до старого слота. if (uColor > data.sid && !insertBefore) { insertBefore = $(this); } И ошибка в консоли: ypeError: Cannot read property 'replace' of undefined На строку: var currentColor = parseInt(this.scope.find('[data-gamename="'+ data.gamename+ '"] > .ipsDataItem_main > ul.ipsDataItem_subList').find('[data-player="'+ data.name +'"]').attr('class').replace('usercolor usercolor-', '')); Поделиться сообщением Ссылка на сообщение
siv1987 2627 04/06/19 08:44 Здесь мне не понятно, зачем тут && !insertBefore: Очевидно для того, чтобы присвоить первый найденный элемент а не последний. Нам откуда знать зачем вы его там добавили. Даже если бы я был автором этого кода, я бы не разобрался в нем без полноценной рабочей версии где можно в "живую" увидеть логику работы скрипта. Проблема то в чем? И ошибка в консоли: ypeError: Cannot read property 'replace' of undefinedСкорее всего один из найденных элементов не имеет атрибута class. Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 04/07/19 05:03 1. Плохой код?2. Проблем в ошибке Error: Cannot read property 'replace' of undefined, оно всё работает, но ошибок не должно быть в консоли. class есть у всех, на демо нужно самому прыгать по слотам, чтобы увидеть логику, попробую скринами: Вот я только зашел в игру и попал на 0 слот: http://prntscr.com/n8jwkb http://prntscr.com/n8jwnqВот я в игре перешел на другой слот (начинает работать выше указанная функция): http://prntscr.com/n8jwuq http://prntscr.com/n8jwxb т.е удалился старый li с usercolor-0 и добавился новый с usercolor-1, возможно не может найти class после удаления usercolor-0 хотя врятли, он удаляется в конце функции, в этот момент уже usercolor-1 существует. 3. Вопрос на засыпку, часа два копаюсь уже, не могу решить. У меня есть два ol с разными data-role: http://prntscr.com/n8jxlk мне нужно найти data-gamename именно в data-role="lobbyRows", уже по разному пробовал, и через this.scop.find и через find и через this.scop.find.leight, не получается. Я вроде правильно всё делаю, но чего-то не хватает. if (this.scope.find('[data-role="lobbyRows"] > [data-gamename="'+ data.gamename +'"]')) { Debug.log("ЛОББИ"); } if (this.scope.find('[data-role="gameRows"] > [data-gamename="'+ data.gamename +'"]')) { Debug.log("GAME"); } if ($('[data-role="lobbyRows"]').find('[data-gamename="'+ data.gamename +'"]')) { Debug.log("ЛОББИ"); } if ($('[data-role="gameRows"]').find('[data-gamename="'+ data.gamename +'"]')) { Debug.log("GAME"); } Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 04/07/19 06:33 (изменено) Блин, разобрался. У меня это действие стояло в начале функции: this.scope.find('[data-gamename="'+ data.gamename +'"]').remove(); И когда выполнялись следующие условия, на странице уже не было игры, надо перенести в самый конец. Хоть в JS начал понимать немного, осталось функции выучить и синтаксис ))) ----------------- Еще у меня такой вопрос созрел, в правильности кода. Ситуация следующая: у меня один и тот же JS файл обновляет контент на странице в нескольких виджетах: игры, фильтр, статистика. Стоит ли делать условие на проверку существования виджетов? По идее, да, но на практике может это и будет лишним. Т.е JS: если на странице найден ID виджета со статистикой, выполняем условие. В условии код. По логике, если условие такое НЕ делать, при синтаксическом анализе браузер будет постоянно читать код всей функции. Если условие сделать, браузер остановит чтение ну или анализ на условии и дальше читать не будет. или я бред говорю? Ага, вот я похоже с этим столкнулся: Если условие в if: if (this.scope.find('[data-role="lobbyRows"] [data-gamename="'+ data.gamename +'"]').length) { var lobbiesBefore = parseInt(this.scope.find('[data-countType="currentLobbies"]').attr('data-currentCount')); Debug.log("Значение: " + lobbiesBefore); } js ищет данные именно в этом блоке: http://prntscr.com/n8klrh так как [data-gamename='+ data.gamename +'] находится в другом виджете совсем, он не может спарсить, при этом, одно соединение только читается. Вот без if: http://prntscr.com/n8kmo8 var lobbiesBefore = parseInt(this.scope.find('[data-countType="currentLobbies"]').attr('data-currentCount')); Debug.log("Значение: " + lobbiesBefore); Изменено 7 апреля 2019 пользователем TemKa_SD Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 04/07/19 17:02 Так, ладно, мне очень понравилась идея поиска виджета, работает всё супер. Выше указанный код тоже изменил, много лишнего было, но ошибка осталась, прошу помочь.Чтобы не вставлять весь код, вот его часть, на которую ругается: // Определяем строку (игру) в которой нужно произвести замену. var rowElem = this.scope.find('[data-gamename="'+ data.gamename+ '"]'); // Определяем на каком слоте сейчас находится нужный игрок. var currentColor = parseInt(rowElem.find('[data-player="'+ data.name +'@'+ data.realm +'"]').attr('class').replace('usercolor usercolor-', '')); rowElem.find('li.usercolor.usercolor-'+ currentColor +'').remove(); Структура html: http://prntscr.com/n8pu70 http://prntscr.com/n8pujh я вот думаю, может потому что data-player находится после usercolor usercolor-. Поделиться сообщением Ссылка на сообщение
newbie 1722 04/08/19 05:18 Опять скриншоты. Вам же написали я бы не разобрался в нем без полноценной рабочей версии где можно в "живую" увидеть логику работы скрипта. я вот думаю, может потому что data-player находится после usercolor usercolor-. Без разницы. Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 04/14/19 12:06 Хорошо, просто хост бот тестовый, на нем игроков может не быть. https://dev.wc3.info/wc3/ActiveGames/ Поделиться сообщением Ссылка на сообщение
newbie 1722 04/15/19 11:54 Хорошо, просто хост бот тестовый, на нем игроков может не быть. https://dev.wc3.info/wc3/ActiveGames/ Страница умерла. Проверяйте элемент перед .replace() или используйте try/catch Поделиться сообщением Ссылка на сообщение
siv1987 2627 04/15/19 12:07 ТС, я же вам указал по поводу ошибки. У одного из элементов отсутсвует аттрибут класс, поэтому возвращается null, ну и соотвественно при вызове replace у null получаете ошибку. В гугле легко ищется пояснение этой ошибки. Вам нужно добавить условие на hasAttr("class") Поделиться сообщением Ссылка на сообщение