newbie 1723 11/22/18 12:22 Вы же уже делали что-то подобное. Или сейчас ajax/cookie не нужны? Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 11/22/18 12:28 Нужны, просто я переделываю приложение с нуля и решил сделать более грамотно его. Сейчас дошел до фильтра и подумал, что у этих функций более правильное решение. AJAX планирую сделать через файл, который обновляет ЛС, на его основе точнее. Ну куки работают сейчас и тут, с этим всё норм. На этом эта мне надо сделать, чтобы контент обновлялся при нажатии на фильтр, потом уже буду ковырять AJAX. Сейчас файл такой: Чуть позже уберу всё лишнее тут. /** * Invision Community * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * * ips.forum.flow.js - Flow filter controller * * Author: Matt Mecham, certainly not Rikki Tissier (yet) */ ;( function($, _, undefined){ "use strict"; ips.controller.register('wc3.front.games.runningGamesFilter', { _ids: [], _button: null, initialize: function () { this.on( 'click', '[data-node-id]', this.toggleFilters ); this.setup(); }, /** * Um, set up... */ setup: function () { /* Populate forum IDs */ var _ids = ips.utils.url.getParam( 'botId' ); var self = this; if ( ! _.isUndefined( _ids ) ) { /* Check URL */ this._ids = decodeURIComponent( _ids ).split(','); } else if( ! _.isUndefined( ips.utils.cookie.get('runningGames_botIds') ) ) { /* Check local storage */ this._ids = ips.utils.cookie.get('runningGames_botIds').split(','); } if( _.isObject( this._ids ) && _.size( this._ids ) ){ _.each( this._ids, function (val, key) { if ( val ) { self.childSelect( val, true ); } }); } this._button = $('body').find('[data-role="fluidForumMobileDesc"]'); this._updateButtonText(); }, /** * Event handler for toggling a filter * * @param {event} e Event object * @returns {void} */ toggleFilters: function (e) { e.preventDefault(); var link = $( e.currentTarget ); var id = link.attr('data-node-id'); var parentId = link.attr('data-parent-id'); var hasChildren = link.attr('data-has-children'); if ( _.indexOf( this._ids, id ) == -1 ) { /* Does not exist, so add it */ this.childSelect( id, false ); } else { /* Exists, so remove it */ this.childUnselect( id ); } this._updateButtonText(); $( document ).trigger( 'updateTableURL', { botId: _.uniq( _.values( this._ids ) ).join(',') } ); }, /** * Is item selected * */ isSelected: function(id) { return this.scope.find('[data-node-id="' + id + '"]').hasClass('cForumMiniList_selected') ? true : false; }, /** * Select a child * */ childSelect: function(id, skipChildren) { Debug.log("Select child: " + id ); this._ids.push( id ); var node = this.scope.find('[data-node-id="' + id + '"]'); node.addClass('cForumMiniList_selected'); var parentId = node.attr('data-parent-id'); /* Mark any children, but we do not need to keep individual row markings */ if ( skipChildren === false && ( node.attr('data-has-children') || id == parentId ) ) { var self = this; _.each( this.scope.find('[data-parent-id="' + id + '"]'), function( v, k ) { var _cId = $(v).attr('data-node-id'); if ( _cId != id ) { self.childSelect( _cId, false ); } } ); } this.updateCookie(); }, /** * Unselect a child * */ childUnselect: function(id) { Debug.log("UNselect child: " + id ); /* Remove marking */ this.scope.find('[data-node-id="' + id + '"]').removeClass('cForumMiniList_selected'); /* Remove from local storage and id stack */ this._ids = _.without( this._ids, id ); this.updateCookie(); /* Check for children of this and unselect those too */ var self = this; _.each( this.scope.find('[data-parent-id="' + id + '"]'), function( v, k ) { var _cId = $(v).attr('data-node-id'); if ( _cId != id ) { self.childUnselect( _cId ); } } ); /* And we always need to unselect the category */ this.parentUnselect( this.scope.find('[data-node-id="' + id + '"]').closest('[data-category]').find('[data-node-id]').first().attr('data-node-id') ); }, /** * Select a parent * */ parentSelect: function(parentId) { Debug.log("Select parent: " + parentId ); /* Mark category and children as selected */ this.scope.find('[data-node-id="' + parentId + '"]').addClass('cForumMiniList_selected'); /* Remove children from the arrays as PHP handles this */ var self = this; _.each( this.scope.find('[data-parent-id="' + parentId + '"]'), function( v, k ) { var _cId = $(v).attr('data-node-id'); if ( _cId != parentId ) { self.childUnselect( _cId ); } } ); }, /** * Unselect a parent * */ parentUnselect: function(parentId) { Debug.log("UNselect parent: " + parentId ); /* Unselect parent as marked */ var node = this.scope.find('[data-node-id="' + parentId + '"]'); node.removeClass('cForumMiniList_selected'); this._ids = _.without( this._ids, parentId ); this.updateCookie(); /* Off up the tree we go */ Debug.log( "Looking for parent ID " + node.attr('data-parent-id') ); var self = this; _.each( this.scope.find('[data-node-id="' + node.attr('data-parent-id') + '"]'), function( v, k ) { var _cId = $(v).attr('data-node-id'); if ( _cId != parentId ) { Debug.log( "Found " + _cId ); self.parentUnselect( _cId ); } } ); }, /** * Update the cookie */ updateCookie: function(id) { var cookie = _.uniq( _.values( this._ids ) ).join(','); Debug.log("Updating cookie: " + cookie ); ips.utils.cookie.set('runningGames_botIds', cookie, true); }, /** * Updates the mobile button text based on selected forums * * @param {event} e The submit event * @param {element} elem The element this widget is being created on * @returns {void} */ _updateButtonText: function () { var blobs = this.scope.find('.cForumMiniList_blob'); var selectedBlobRows = blobs.filter( function () { if( $( this ).closest('.cForumMiniList_selected').length ){ return true; } return false; }); var text = ''; // If the counts are the same, we know we've selected all of them if( blobs.length == selectedBlobRows.length || selectedBlobRows.length === 0 ){ text = ips.getString('topicsFromAllForums'); } else { text = ips.pluralize( ips.getString( 'topicsFromXForums' ), selectedBlobRows.length ); } this._button.text( text ); } }); }(jQuery, _)); Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 11/22/18 12:35 Еще хочу спросить, модуль который сейчас делаю, активные игры можно передавать с помощью вебсокета, я мало про него знаю, знаю что он с JS работает ну и у меня есть готовый код в принципе. В чем разница между вебсокетом и обычными данными ? Поделиться сообщением Ссылка на сообщение
siv1987 2628 11/22/18 17:35 Правильно вывел кол-во игр?Мне кажется тут еще можно использовать группировку сразу в запросе по botid. За одно и приплюсовать там totalplayers и получить готовый результат. ->select( 'botid, gamename, SUM(totalplayers) as players, COUNT(*) as games', 'stats_gamelist', NULL, 'botid ASC', NULL, 'botid' ) 1 Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 11/22/18 19:04 @siv1987 Спасибо, позже рассмотрю эту инфу, башка не варит уже ))) @newbie Я разобрался, правда пол движка пришлось перекопать, ну ладно... Этим параметром обновляются результаты, у меня не получилось только за счет HTML структуры превратить это в рабочий вариант, нужна всё равно форма от Table. $( document ).trigger( 'updateTableURL', { botId: _.uniq( _.values( this._ids ) ).join(',') } ); Нужно реализовать что-то вроде: $( document ).trigger( 'contentChange', [ this.scope ] ); где this.scope - функция html обновления, помогите плиз. Поделиться сообщением Ссылка на сообщение
siv1987 2628 11/22/18 19:13 Спасибо, позже рассмотрю эту инфу, башка не варит уже ))) foreach( \IPS\Db::i('wc3')->select( 'botid, gamename, SUM(totalplayers) as players, COUNT(*) as games', 'stats_gamelist', NULL, 'botid ASC', NULL, 'botid' ) as $bot ) { $bot['gamename'] = trim( current( explode('#', $bot['gamename']) ) ); static::$cachedBotlist[ $bot['botid'] ] = $bot; } Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 11/22/18 19:58 Ура, у меня получилось обновить страничку при нажатии, осталось сделать обновление только таблицы )))) var rows = this.scope.find('[data-role="tableRows"]'); if( !rows.length ){ window.location = this._baseURL; return; } $( document ).trigger( 'contentChange', [ this.scope ] ); Поделиться сообщением Ссылка на сообщение
siv1987 2628 11/22/18 20:26 window.location/reload это вообще топор. А почему не использовать ajax запрос? В ипс есть удобный апи для работы с ним если муторно разбиратся с таблицами форума. Поделиться сообщением Ссылка на сообщение
newbie 1723 11/23/18 05:59 foreach( \IPS\Db::i('wc3')->select( 'botid, gamename, SUM(totalplayers) as players, COUNT(*) as games', 'stats_gamelist', NULL, 'botid ASC', NULL, 'botid' ) as $bot ) { $bot['gamename'] = trim( current( explode('#', $bot['gamename']) ) ); static::$cachedBotlist[ $bot['botid'] ] = $bot; }Забыл предложить вариант с GROUP BYПредложенный код может не работать из-за ONLY_FULL_GROUP_BY (в mysql 5.7 включен по умолчанию)Можно сделать так->select( 'botid, MIN(gamename) as gamename, SUM(totalplayers) as players, COUNT(*) as games' Поделиться сообщением Ссылка на сообщение
newbie 1723 11/23/18 06:34 Зачем Вам такая js-портянка нужна.Если у Вас не таблица, то смысл переделывать под таблицу только из-за того, что есть какой-то js-код Повторюсь. У Вас же был js-код для подобного. Возьмите и перепишите его. Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 11/23/18 06:55 У меня не было обновления при клике. Сейчас мне нужно только это сделать, под таблицы не обязательно, просто нужно вот эту функцию правильно изменить: http://ipbskins.ru/forum/topic15808.html/page__view__findpost__p__105904 код небольшой и простой, там ничего лишнего сейчас нет, просто он более правильный и другой. Т.е тут выбор чекбоксов, обновление их из куков и URL, запись в куки, немного для мобилок, с этим всё норм. Мне нудно вот по ссылке выше в коде сделать обновление моей таблице ПО НАЖАТИЮ на фильтр. /** * * ips.games.runningGamesFilter.js - Bot filter controller * */ ;( function($, _, undefined){ "use strict"; ips.controller.register('wc3.front.games.runningGamesFilter', { _ids: [], _button: null, initialize: function () { this.on( 'click', '[data-bot-id]', this.toggleFilters ); this.setup(); }, /** * Um, set up... */ setup: function () { /* Populate forum IDs */ var _ids = ips.utils.url.getParam( 'botId' ); var self = this; /* BotId */ if ( ! _.isUndefined( _ids ) ) { /* Проверка айди в строке URL */ this._ids = decodeURIComponent( _ids ).split(','); } else if( ! _.isUndefined( ips.utils.cookie.get('runningGames_botIds') ) ) { /* Проверка айди в куках */ this._ids = ips.utils.cookie.get('runningGames_botIds').split(','); } if( _.isObject( this._ids ) && _.size( this._ids ) ){ _.each( this._ids, function (val, key) { if ( val ) { self.botSelect( val, true ); } }); } this._button = $('body').find('[data-role="fluidForumMobileDesc"]'); this._updateButtonText(); }, /** * Event handler for toggling a filter * * @param {event} e Event object * @returns {void} */ toggleFilters: function (e) { e.preventDefault(); var link = $( e.currentTarget ); var id = link.attr('data-bot-id'); if ( _.indexOf( this._ids, id ) == -1 ) { /* Does not exist, so add it */ this.botSelect( id, false ); } else { /* Exists, so remove it */ this.botUnselect( id ); } this._updateButtonText(); $( document ).trigger( 'updateTableURL', { botId: _.uniq( _.values( this._ids ) ).join(',') } ); }, /** * Is item selected * */ isSelected: function(id) { return this.scope.find('[data-bot-id="' + id + '"]').hasClass('cForumMiniList_selected') ? true : false; }, /** * Select a child * */ botSelect: function(id) { Debug.log("Выбран бот: " + id ); this._ids.push( id ); var node = this.scope.find('[data-bot-id="' + id + '"]'); node.addClass('cForumMiniList_selected'); this.updateCookie(); }, /** * Unselect a child * */ botUnselect: function(id) { Debug.log("Удален бот: " + id ); /* Remove marking */ this.scope.find('[data-bot-id="' + id + '"]').removeClass('cForumMiniList_selected'); /* Remove from local storage and id stack */ this._ids = _.without( this._ids, id ); this.updateCookie(); }, /** * Обновление куков */ updateCookie: function(id) { var cookie = _.uniq( _.values( this._ids ) ).join(','); Debug.log("Обновление куков: " + cookie ); ips.utils.cookie.set('runningGames_botIds', cookie, true); }, /** * Updates the mobile button text based on selected forums * * @param {event} e The submit event * @param {element} elem The element this widget is being created on * @returns {void} */ _updateButtonText: function () { var blobs = this.scope.find('.cForumMiniList_blob'); var selectedBlobRows = blobs.filter( function () { if( $( this ).closest('.cForumMiniList_selected').length ){ return true; } return false; }); var text = ''; // If the counts are the same, we know we've selected all of them if( blobs.length == selectedBlobRows.length || selectedBlobRows.length === 0 ){ text = ips.getString('topicsFromAllForums'); } else { text = ips.pluralize( ips.getString( 'topicsFromXForums' ), selectedBlobRows.length ); } this._button.text( text ); } }); }(jQuery, _)); Поделиться сообщением Ссылка на сообщение
newbie 1723 11/23/18 07:12 Мне нудно вот по ссылке выше в коде сделать обновление моей таблице ПО НАЖАТИЮ на фильтр.Делайте ajax-запрос и обновляйте html Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 11/23/18 09:18 Так, помогите заменить содержимое при автоматическом обновлении, что-то не получается. http://prntscr.com/lly1r4 /** * Processes an ajax response * * @param {object} response Server response * @returns {void} */ _handleResponse: function (response) { try { // If auto-polling is now disabled, stop everything if( response.error && response.error == 'auto_polling_disabled' ){ this._stopPolling( true ); return; } $('#gamelistTable').find('ol').html( response['html'] ); } catch (err) { this._stopPolling( true ); return; } }, Поделиться сообщением Ссылка на сообщение
newbie 1723 11/23/18 09:45 И где тут ajax-запрос? Тут уже какой-то ответ разбирается. Поделиться сообщением Ссылка на сообщение
TemKa_SD 9 11/23/18 09:48 response выводит шаблон который нужно из модуля > ajax, с этим всё в порядке, шаблон в логах выводится, но не заменяется в таблице. /** * The main method to check notification status * Checks in localstorage to see if the last poll was < 20s ago * * @returns {void} */ _checkNotifications: function () { // If our window is inactive, increase the count if( document[ ips.utils.events.getVisibilityProp() ] ){ if( this._windowInactivePoll >= 3 && this._pollMultiplier === 1 ){ // 0-3 minutes @ 60s poll if( this._debugPolling ){ Debug.log( "runningGames: Polled over 3 minutes, increasing multiplier to 2"); } this._pollMultiplier = 2; this._setInterval( this._pollTimeout * this._pollMultiplier ); } else if( this._windowInactivePoll >= 7 && this._pollMultiplier === 2 ) { // 4-11 minutes @ 120s poll if( this._debugPolling ){ Debug.log( "runningGames: Polled over 10 minutes, increasing multiplier to 3"); } this._pollMultiplier = 3; this._setInterval( this._pollTimeout * this._pollMultiplier ); } else if( this._windowInactivePoll >= 25 && this._pollMultiplier === 3 ) { // > 60 mins stop if( this._debugPolling ){ Debug.log( "runningGames: Polled over 60 mins, stopping polling"); } this._stopPolling(); return; } this._windowInactivePoll++; } // We send our currently-displayed bubble count to the backend // to find out if there's any change in number var dataToSend = { dataToSend }; this._doAjaxRequest( dataToSend ); }, /** * Calls the backend to get new notification data * * @param {object} dataToSend Object containing current message and notification counts * @returns {void} */ _doAjaxRequest: function (dataToSend) { var self = this; var url = ips.getSetting( 'baseURL' ) + '?app=wc3&module=games&controller=runningGames&do=ajax'; if( this._debugPolling ){ Debug.log("runningGames: sending ajax request"); } // We'll update the timestamp before polling so that other windows // don't start polling before this one is finished //this._updateTimestamp(); // We do need to poll, it's been more than 20s this._ajaxObj = ips.getAjax()( url, { data: dataToSend }) .done( _.bind( this._handleResponse, this ) ) .fail( function () { self._stopPolling(true); Debug.error("Problem polling for new notifications; stopping."); }); }, /** * Processes an ajax response * * @param {object} response Server response * @returns {void} */ _handleResponse: function (response) { try { // If auto-polling is now disabled, stop everything if( response.error && response.error == 'auto_polling_disabled' ){ this._stopPolling( true ); return; } var html = ''; var table = $('#gamelistTable'); var tableBody = table.find('ol'); if( this._debugPolling ){ tableBody.replaceWith(response); Debug.log("Update"); } } catch (err) { this._stopPolling( true ); return; } }, Поделиться сообщением Ссылка на сообщение