diff --git a/js/ajax_view.js b/js/ajax_view.js index e3bc821..edd256e 100644 --- a/js/ajax_view.js +++ b/js/ajax_view.js @@ -3,16 +3,76 @@ * Handles AJAX fetching of views, including filter submission and response. */ (function ($) { - /** * Attaches the AJAX behavior to Views exposed filter forms and key View links. */ + Drupal.behaviors.ViewsAjaxView = {}; Drupal.behaviors.ViewsAjaxView.attach = function() { if (Drupal.settings && Drupal.settings.views && Drupal.settings.views.ajaxViews) { $.each(Drupal.settings.views.ajaxViews, function(i, settings) { Drupal.views.instances[i] = new Drupal.views.ajaxView(settings); }); + + + if (window.location.hash) { + hash = Drupal.Views.getLocationHash(); + + // Do we have a hash that corresponds to an auto-submit form? + $exposed_form_submitted = $('form#views-exposed-form-'+ hash.f); + if ($exposed_form_submitted.hasClass('ctools-auto-submit-full-form') ) { + $lastLinkEvent = location.hash; + $('body').once('views-hash', function() { + if (Drupal.Views.isNumeric(hash.p)) { + var pageValue = $('').val(hash.p) + $exposed_form_submitted.prepend(pageValue); + } + for (v in hash) { + if (hash.hasOwnProperty(v)) { + + // Set the form element to the value from the hash. + $exposed_form_submitted.find(('[name='+ hash[v] +']')).prop('checked', true); + } + } + // @see Drupal.views.ajaxView.prototype.attachExposedFormAjax + $exposed_form_submitted.find('input, select').first().change(); + }); + // Back / Forward click events to handle pager + $(window).bind('hashchange', function() { + hash = Drupal.Views.getLocationHash(); + // Do we have a hash that corresponds to an auto-submit form? + $exposed_form_submitted = $('form#views-exposed-form-'+ hash.f); + var page = ( hash != null ? hash.p : 0); + + if (Drupal.Views.isNumeric(page) && $lastLinkEvent != location.hash ) { + $('ul.pager .pager-item a').each( function() { + var args = Drupal.Views.parseQueryString(this.href); + if (page == args.page || (page == 0 && args.page == null) ) { + $(this).click(); + return false; + } + return true; + }); + + } + }).trigger('hashchange'); + + + } else if (Drupal.Views.isNumeric(hash.p)) { + // No filters, but check for page specified in location hash. + $('body').once('views-hash', function () { + $('ul.pager .pager__item a').each( function() { + var args = Drupal.Views.parseQueryString(this.href); + if (hash.p == args.page) { + $(this).click(); + return false; + } + return true; + }); + }); + } + };// end if hash + } }; @@ -59,6 +119,7 @@ Drupal.views.ajaxView = function(settings) { // Add the ajax to exposed forms. this.$exposed_form = $('form#views-exposed-form-'+ settings.view_name.replace(/_/g, '-') + '-' + settings.view_display_id.replace(/_/g, '-')); this.$exposed_form.once(jQuery.proxy(this.attachExposedFormAjax, this)); + $(document).ajaxComplete(jQuery.proxy(this.ajaxCompleteExposedCallback, this)); // Add the ajax to pagers. this.$view @@ -68,6 +129,30 @@ Drupal.views.ajaxView = function(settings) { .once(jQuery.proxy(this.attachPagerAjax, this)); }; +/** + * Exposed forms use this to append their id as a URL hash so we can + * resubmit the form when the browser's "Back" button is used. + */ +Drupal.views.ajaxView.prototype.ajaxCompleteExposedCallback = function(event, request, options) { + if (options.url === this.element_settings.url) { + var data = Drupal.Views.parseQueryString(options.data); + + var val = {}; + this.$exposed_form.find('select, input').each(function(i, element) { + if ((this.name != "" && this.type == 'select-one') || (this.type == 'checkbox' && this.checked)) { + val[this.name] = (this.type == 'checkbox') ? this.id : this.value; + } + }); + + Drupal.Views.updateLocationHash(val); + + Drupal.Views.updateLocationHash({ f: this.settings.view_name.replace(/_/g, '-') + '-' + this.settings.view_display_id.replace(/_/g, '-'), p: data.page}); + this.$exposed_form.find('input[name=page]').remove(); + } +} + + + Drupal.views.ajaxView.prototype.attachExposedFormAjax = function() { var button = $('input[type=submit], button[type=submit], input[type=image]', this.$exposed_form); button = button[0]; @@ -112,8 +197,20 @@ Drupal.views.ajaxView.prototype.attachPagerLinkAjax = function(id, link) { this.element_settings.submit = viewData; this.pagerAjax = new Drupal.ajax(false, $link, this.element_settings); + + //Attach click handler to update hash + $link.click(this.pagerHandler); }; +/** + * Click handler updates the location hash based on pager. + */ +Drupal.views.ajaxView.prototype.pagerHandler = function(event) { + var args = Drupal.Views.parseQueryString(event.target.href); + if (typeof args.page === "undefined") args.page = 0; + Drupal.Views.updateLocationHash({ p: args.page }); +} + Drupal.ajax.prototype.commands.viewsScrollTop = function (ajax, response, status) { // Scroll to the top of the view. This will allow users // to browse newly loaded content after e.g. clicking a pager diff --git a/js/base.js b/js/base.js index 5855dce..33a34a2 100644 --- a/js/base.js +++ b/js/base.js @@ -107,4 +107,26 @@ Drupal.Views.getPath = function (href) { return href; }; + +/** + * Helper function updates window.location.hash data from a javascript object. + * + * We provide for multiple arbitrary values to be stored in the hash by using a urlencoded string + */ +Drupal.Views.updateLocationHash = function (data) { + hash = Drupal.Views.getLocationHash(); + $.extend(hash, data); + window.location.hash = decodeURIComponent($.param(hash)); +} + +Drupal.Views.getLocationHash = function () { + hashStr = window.location.hash.substr(1); // Strips the # itself + return Drupal.Views.parseQueryString(hashStr); +} + +//This is provided in jQuery 1.7, but we're not there yet. +Drupal.Views.isNumeric = function (n) { + return !isNaN(parseFloat(n)) && isFinite(n); +} + })(jQuery);