From 155758f546b435a2cc91b4feb96cb1d34c2a25c0 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Fri, 13 Jul 2012 16:46:23 +0200 Subject: [PATCH] NEW Save and restore tab state upon CMS navigation (fixes #7647) Implemented independently of URL state to ensure that state is retained on every user interaction, rather than having to add it to each URL specifically. Same reasons for not saving it as HTML5 history metadata, as that's only inspected on history events, not normal CMS navigation. --- admin/javascript/LeftAndMain.js | 74 ++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/admin/javascript/LeftAndMain.js b/admin/javascript/LeftAndMain.js index 07f26b076..4b3a05e09 100644 --- a/admin/javascript/LeftAndMain.js +++ b/admin/javascript/LeftAndMain.js @@ -161,6 +161,9 @@ jQuery.noConflict(); if(abort) return; } + + // Save tab selections so we can restore them later + this.saveTabState(); if(window.History.enabled) { // Active menu item is set based on X-Controller ajax header, @@ -208,12 +211,6 @@ jQuery.noConflict(); return false; } - // save tab selections in order to reconstruct them later - var selectedTabs = []; - form.find('.cms-tabset').each(function(i, el) { - if($(el).attr('id')) selectedTabs.push({id:$(el).attr('id'), selected:$(el).tabs('option', 'selected')}); - }); - // get all data from the form var formData = form.serializeArray(); // add button action @@ -223,6 +220,9 @@ jQuery.noConflict(); // as automatic browser ajax response redirects seem to discard the hash/fragment. formData.push({name: 'BackURL', value:History.getPageUrl()}); + // Save tab selections so we can restore them later + this.saveTabState(); + // Standard Pjax behaviour is to replace the submitted form with new content. // The returned view isn't always decided upon when the request // is fired, so the server might decide to change it based on its own logic, @@ -242,23 +242,13 @@ jQuery.noConflict(); var newContentEls = self.handleAjaxResponse(data, status, xhr); if(!newContentEls) return; - var newForm = newContentEls.filter('form'); - - // Re-init tabs (in case the form tag itself is a tabset) - if(newForm.hasClass('cms-tabset')) newForm.removeClass('cms-tabset').addClass('cms-tabset'); - - // re-select previously saved tabs - $.each(selectedTabs, function(i, selectedTab) { - newForm.find('#' + selectedTab.id).tabs('select', selectedTab.selected); - }); - - newForm.trigger('aftersubmitform', {status: status, xhr: xhr, formData: formData}); + newContentEls.filter('form').trigger('aftersubmitform', {status: status, xhr: xhr, formData: formData}); } }, ajaxOptions)); return false; }, - + /** * Handles ajax loading of new panels through the window.History object. * To trigger loading, pass a new URL to window.History.pushState(). @@ -337,7 +327,7 @@ jQuery.noConflict(); * Can be hooked into an ajax 'success' callback. */ handleAjaxResponse: function(data, status, xhr) { - var self = this; + var self = this, url, selectedTabs; // Pseudo-redirects via X-ControllerURL might return empty data, in which // case we'll ignore the response @@ -401,8 +391,14 @@ jQuery.noConflict(); if(origVisible) newContentEl.css('visibility', 'visible'); }); + // Re-init tabs (in case the form tag itself is a tabset) + var newForm = newContentEls.filter('form'); + if(newForm.hasClass('cms-tabset')) newForm.removeClass('cms-tabset').addClass('cms-tabset'); + this.redraw(); + this.restoreTabState(); + return newContentEls; }, @@ -435,6 +431,46 @@ jQuery.noConflict(); $(window).trigger('statechange'); $(this).redraw(); + }, + + /** + * Save tab selections in order to reconstruct them later. + * Requires HTML5 sessionStorage support. + */ + saveTabState: function() { + if(typeof(window.sessionStorage)=="undefined") return; + + var selectedTabs = [], url = this._tabStateUrl(); + this.find('.cms-tabset,.ss-tabset').each(function(i, el) { + var id = $(el).attr('id'); + if(!id) return; // we need a unique reference + selectedTabs.push({id:id, selected:$(el).tabs('option', 'selected')}); + }); + if(selectedTabs) window.sessionStorage.setItem('tabs-' + url, JSON.stringify(selectedTabs)); + }, + + /** + * Re-select previously saved tabs. + * Requires HTML5 sessionStorage support. + */ + restoreTabState: function() { + if(typeof(window.sessionStorage)=="undefined") return; + + var self = this, url = this._tabStateUrl(), + data = window.sessionStorage.getItem('tabs-' + url), + selectedTabs = data ? JSON.parse(data) : false; + if(selectedTabs) { + $.each(selectedTabs, function(i, selectedTab) { + self.find('#' + selectedTab.id).tabs('select', selectedTab.selected); + }); + } + }, + + _tabStateUrl: function() { + return History.getState().url + .replace(/\?.*/, '') + .replace(/#.*/, '') + .replace($('base').attr('href'), ''); } });