reverted: --- b/ajax_facets.info +++ a/ajax_facets.info @@ -3,7 +3,6 @@ dependencies[] = facetapi dependencies[] = search_api dependencies[] = views -dependencies[] = libraries package = Search Toolkit core = 7.x diff -u b/ajax_facets.install b/ajax_facets.install --- b/ajax_facets.install +++ b/ajax_facets.install @@ -14,18 +14,26 @@ switch ($phase) { case 'runtime': - if (!libraries_get_path('history.js')) { - $requirements['ajax_facets_error'] = array( - 'title' => $t('Ajax Facets'), - 'description' => $t('Please download and unpack "history.js" library to libraries directory.'), - 'value' => l($t('Download'), 'https://github.com/browserstate/history.js/', array( - 'attributes' => array( - 'target' => '_blank', - ), - )), - 'severity' => REQUIREMENT_ERROR, - ); + $description = $t('For now browser ajax history feature works only in HTML5 browsers. If you want to get this feature on HTML4 browsers you need to install libraries module and download history.js library.'); + $value = $t('Libraries module not installed.'); + + if (module_exists('libraries')) { + if (!libraries_get_path('history.js')) { + $description = $t('For now browser ajax history feature works only in HTML5 browsers. If you want to get this feature on HTML4 browsers you need to download history.js library.'); + $value = $t('Library history.js not found.'); + } + else { + $description = $t('For now browser ajax history feature works both in HTML4 and HTML5 browsers.'); + $value = $t('Works with history.js library'); + } } + + $requirements['ajax_facets_message'] = array( + 'title' => $t('Ajax Facets'), + 'description' => $description, + 'value' => $value, + 'severity' => REQUIREMENT_INFO, + ); break; } diff -u b/ajax_facets.module b/ajax_facets.module --- b/ajax_facets.module +++ b/ajax_facets.module @@ -93,9 +93,9 @@ static $included = FALSE; if (!$included) { $included = TRUE; + $history_js_exists = FALSE; $module_path = drupal_get_path('module', 'ajax_facets'); drupal_add_js($module_path . '/misc/ajax_facets.js'); - drupal_add_js(libraries_get_path('history.js') . '/scripts/bundled/html4+html5/jquery.history.js', array('group' => JS_LIBRARY)); drupal_add_css($module_path . '/misc/ajax_facets.css'); $search_path = $facet->getAdapter()->getSearchPath(); $filter_key = $facet->getAdapter()->getUrlProcessor()->getFilterKey(); @@ -105,6 +105,16 @@ $view_name = ''; $display_name = ''; + // Add history.js file if exists. + if (module_exists('libraries')) { + $history_js_path = libraries_get_path('history.js'); + + if ($history_js_path) { + $history_js_exists = TRUE; + drupal_add_js($history_js_path . '/scripts/bundled/html4+html5/jquery.history.js', array('group' => JS_LIBRARY)); + } + } + if (!empty($views)) { // Get display from current search. if (empty($view_name) || empty($display_name)) { @@ -126,6 +136,7 @@ 'display_name' => $display_name, 'facet_field' => $facet['map options']['field']['key'], 'applyPath' => url($search_path, array('query' => $query)), + 'isHistoryJsExists' => $history_js_exists, ); drupal_add_js($setting, 'setting'); drupal_add_library('system', 'drupal.ajax'); diff -u b/misc/ajax_facets.js b/misc/ajax_facets.js --- b/misc/ajax_facets.js +++ b/misc/ajax_facets.js @@ -358,7 +358,7 @@ ajax.success = function(response, status) { // Push new state only on successful ajax response. if (pushStateNeeded) { - var stateUrl = Drupal.settings.basePath + Drupal.settings.pathPrefix + Drupal.settings.facetapi.searchPath + '?' + Drupal.ajax_facets.getFacetsQuery(), + var stateUrl = Drupal.ajax_facets.getFacetsQueryUrl(Drupal.settings.basePath + Drupal.settings.pathPrefix + Drupal.settings.facetapi.searchPath), state = { current_id: Drupal.ajax_facets.current_id, current_facet_name: Drupal.ajax_facets.current_facet_name, @@ -496,7 +496,7 @@ /** * Returns query string with selected facets. */ - Drupal.ajax_facets.getFacetsQuery = function() { + Drupal.ajax_facets.getFacetsQueryUrl = function(baseUrl) { var query = { 'f': Drupal.ajax_facets.queryState.f }; @@ -514,7 +514,12 @@ query.pages = Drupal.ajax_facets.queryState.pages; } - return decodeURIComponent($.param(query)); + // Add query string to base url. + if (!$.isEmptyObject(query)) { + baseUrl += '?' + decodeURIComponent($.param(query)); + } + + return baseUrl; }; /** @@ -523,15 +528,28 @@ * need to communicate which one is being "deactivated" for our ajax success * handler. */ - Drupal.ajax_facets.initHistoryState = function ($facet) { + Drupal.ajax_facets.initHistoryState = function($facet) { // Set the initial state only initial page load. if (Drupal.ajax_facets.firstLoad) { - History.replaceState({ - current_id: $facet.attr('id'), - current_facet_name: $facet.data('facet'), - facets: Drupal.ajax_facets.queryState['f'] - }, null, null); Drupal.ajax_facets.firstLoad = false; + + // If history.js available - use it. + if (Drupal.settings.facetapi.isHistoryJsExists) { + History.replaceState({ + current_id: $facet.attr('id'), + current_facet_name: $facet.data('facet'), + facets: Drupal.ajax_facets.queryState['f'] + }, null, null); + } else { + // Fallback to HTML5 history object. + if (typeof history.replaceState != 'undefined') { + history.replaceState({ + current_id: $facet.attr('id'), + current_facet_name: $facet.data('facet'), + facets: Drupal.ajax_facets.queryState['f'] + }, null, null); + } + } } }; @@ -541,30 +559,66 @@ * History.js library fires "statechange" event even on API push/replace calls. - * So before pushing new state to history we should unbind from this event and after bin again. + * So before pushing new state to history we should unbind from this event and after bind again. */ Drupal.ajax_facets.pushState = function (state, title, stateUrl) { - var $window = $(window); - - $window.unbind('statechange', Drupal.ajax_facets.reactOnStateChange); - History.pushState(state, title, stateUrl); - $window.bind('statechange', Drupal.ajax_facets.reactOnStateChange); + // If history.js available - use it. + if (Drupal.settings.facetapi.isHistoryJsExists) { + var $window = $(window); + + $window.unbind('statechange', Drupal.ajax_facets.reactOnStateChange); + History.pushState(state, title, stateUrl); + $window.bind('statechange', Drupal.ajax_facets.reactOnStateChange); + } else { + // Fallback to HTML5 history object. + if (typeof history.pushState != 'undefined') { + history.pushState(state, title, stateUrl); + } + } }; /** * Callback for back/forward browser buttons. */ Drupal.ajax_facets.reactOnStateChange = function () { - var state = History.getState(); + var state = null, + facets = [], + current_id = ''; + + // If history.js available - use it. + if (Drupal.settings.facetapi.isHistoryJsExists) { + state = History.getState(); + + facets = state.data.facets; + current_id = state.data.current_id; + } else { + // Fallback to HTML5 history object. + if (typeof history.pushState != 'undefined') { + state = history.state; - Drupal.ajax_facets.queryState['f'] = state.data.facets; - Drupal.ajax_facets.sendAjaxQuery($('#' + state.data.current_id), false); + facets = state.facets; + current_id = state.current_id; + } + } + + Drupal.ajax_facets.queryState['f'] = facets; + Drupal.ajax_facets.sendAjaxQuery($('#' + current_id), false); }; - /** - * Initial bind to statechange event. - */ - History.Adapter.bind(window, 'statechange', function () { - if (Drupal.ajax_facets.firstLoad) { - Drupal.ajax_facets.reactOnStateChange(); - } - }); + // If user opened new page and then clicked browser's back button then would not be fired "statechange" event. + // So we need to bind on 'statechange' event and react only once. All farther work does + // Drupal.ajax_facets.pushState() function. + // If history.js Adapter available - use it to bind "statechange" event. + if (typeof History.Adapter != 'undefined') { + History.Adapter.bind(window, 'statechange', function () { + if (Drupal.ajax_facets.firstLoad) { + Drupal.ajax_facets.reactOnStateChange(); + } + }); + } else { + // Fallback to default HTML5 event. + window.onpopstate = function () { + if (Drupal.ajax_facets.firstLoad) { + Drupal.ajax_facets.reactOnStateChange(); + } + }; + } })(jQuery);