diff --git a/js/views_ajax_history.js b/js/views_ajax_history.js index cd30224..d72b8d1 100644 --- a/js/views_ajax_history.js +++ b/js/views_ajax_history.js @@ -41,6 +41,7 @@ // not have loadable history and will not work the back button. if (once('body', 'views-ajax-history-first-page-load').length) { drupalSettings.viewsAjaxHistory.onloadPageItem = drupalSettings.viewsAjaxHistory.renderPageItem; + $(window).bind('popstate', loadView); } } }; @@ -66,6 +67,15 @@ if (pair[0] != 'q' && pair[1]) { key = decodeURIComponent(pair[0].replace(/\+/g, ' ')); value = decodeURIComponent(pair[1].replace(/\+/g, ' ')); + var element_type = $('[name="' + key + '"]').attr('type'); + + // It may happen that field name ends with [] with text between them e.g. + // [0], [1]. Let's convert them to []. One example is when we build URL query + // with URL query builder. We don't want to do this for radios or checkbox types, + // since this will break the detection between values and url. + if (/\[(.+)\]/.test(key) && (element_type !== 'checkbox' && element_type !== 'radio')) { + key = key.replace(/\[(.+)\]/, '[]'); + } // Field name ends with [], it's multivalues. if (/\[\]$/.test(key)) { if (!(key in args)) { @@ -172,22 +182,23 @@ // The data in the history state must be serializable. var historyOptions = $.extend({}, options); - // Store the actual view's dom id. - drupalSettings.viewsAjaxHistory.lastViewDomID = options.data.view_dom_id; - $(window).unbind('popstate', loadView); - history.pushState(cleanStateForHistory(historyOptions), document.title, cleanURL(url, options.data)); - $(window).bind('popstate', loadView); + if (options.data.view_dom_id === getViewDomId()) { + $(window).unbind('popstate', loadView); + history.pushState(cleanStateForHistory(historyOptions), document.title, cleanURL(url, options.data)); + $(window).bind('popstate', loadView); + } }; /** * Make an AJAX request to update the view when navigating back and forth. */ var loadView = function () { + var view_dom_id = getViewDomId(); var options; // This should be the first loaded page, so init the options object. if (history.state === null) { - var viewsAjaxSettingsKey = 'views_dom_id:' + drupalSettings.viewsAjaxHistory.lastViewDomID; + var viewsAjaxSettingsKey = 'views_dom_id:' + view_dom_id; if (drupalSettings.views.ajaxViews.hasOwnProperty(viewsAjaxSettingsKey)) { var viewsAjaxSettings = drupalSettings.views.ajaxViews[viewsAjaxSettingsKey]; var initialExposedInput = drupalSettings.viewsAjaxHistory.initialExposedInput[viewsAjaxSettingsKey]; @@ -197,12 +208,25 @@ data: viewsAjaxSettings, url: drupalSettings.views.ajax_path }; + // On first loaded page, url can have filters passed in query. They are + // present in window.location.search. Let's add them to initial filters, + // when getting back to first loaded page. + $.each(parseQueryString(window.location.search), function(filter_name) { + if (!options.data.hasOwnProperty(filter_name)) { + options.data[filter_name] = this; + } + }); } } else { options = history.state; } + // When page was reloaded, view_dom_id stored in history might be outdated + // (it's refreshed on every page reload). Make sure, that current dom_id is + // used. + options.data.view_dom_id = view_dom_id; + // Drupal's AJAX options. var settings = $.extend({ submit: options.data, @@ -217,6 +241,33 @@ viewsAjaxSubmit.execute(); }; + /** + * Get current dom_id for the view, based on its name and display ID. + * + * When doing AJAX calls, dom_id don't change. But on page refresh or + * getting back to view from other pages dom_id changes. And browser history + * contains old dom_id. We can update it and get current dom_id, based on + * view_name and view_display_id. + * + * @return string|null + * Current view dom_id. + */ + var getViewDomId = function () { + var view_dom_id = null; + + var views_ajax_history = drupalSettings.viewsAjaxHistory; + // Get list of available views and look for view matching current view name + // and display id. Get dom_id of it. + $.each(drupalSettings.views.ajaxViews, function() { + if (views_ajax_history.viewName === this.view_name && views_ajax_history.viewDisplayId === this.view_display_id) { + view_dom_id = this.view_dom_id; + return false; + } + }); + + return view_dom_id; + }; + /** * Check to see if facets are enabled for the view. * diff --git a/views_ajax_history.module b/views_ajax_history.module index 50a8abf..648bbb1 100644 --- a/views_ajax_history.module +++ b/views_ajax_history.module @@ -37,7 +37,11 @@ function views_ajax_history_views_pre_render(ViewExecutable $view) { if (($view->ajaxEnabled() && (isset($display_extenders_options['ajax_history']['enable_history']) && $display_extenders_options['ajax_history']['enable_history'] == TRUE)) && empty($view->is_attachment) && empty($view->live_preview)) { // @TODO add option to views form for html4+html5 or html5 only $view->element['#attached']['library'][] = 'views_ajax_history/history'; - $view->element['#attached']['drupalSettings']['viewsAjaxHistory'] = ['renderPageItem' => \Drupal::service('pager.parameters')->findPage()]; + $view->element['#attached']['drupalSettings']['viewsAjaxHistory'] = [ + 'renderPageItem' => \Drupal::service('pager.parameters')->findPage(), + 'viewName' => $view->id(), + 'viewDisplayId' => $view->current_display, + ]; $view->element['#cache']['contexts'][] = 'url.query_args.pagers'; // Save the initial exposed input on first page load