search_api_ajax.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. (function($) {
  2. var history;
  3. Drupal.search_api_ajax = {};
  4. if (Drupal.settings.search_api_ajax) {
  5. var blocks = Drupal.settings.search_api_ajax.blocks;
  6. var content = Drupal.settings.search_api_ajax.content;
  7. var regions = Drupal.settings.search_api_ajax.regions;
  8. var spinner = Drupal.settings.search_api_ajax.spinner;
  9. var target = Drupal.settings.search_api_ajax.scrolltarget;
  10. var fade = Drupal.settings.search_api_ajax.fade;
  11. var opacity = Drupal.settings.search_api_ajax.opacity;
  12. var speed = Drupal.settings.search_api_ajax.scrollspeed;
  13. // notice the "search_api_ajax_path" instead of
  14. // "search_api_ajax.path" for magic reasons
  15. var ajaxPath = Drupal.settings.search_api_ajax_path;
  16. var qPath = Drupal.settings.search_api_ajax_qpath;
  17. var isView = Drupal.settings.search_api_ajax.view;
  18. // initialize listeners
  19. Drupal.search_api_ajax.initialize = function() {
  20. if (content) {
  21. Drupal.search_api_ajax.ajax(content);
  22. }
  23. if (blocks) {
  24. for (var block in blocks) {
  25. Drupal.search_api_ajax.ajax(blocks[block]);
  26. }
  27. }
  28. };
  29. // extract url for ajax history
  30. Drupal.search_api_ajax.url_to_state = function(url) {
  31. var state = '';
  32. if (isView) {
  33. var query = Drupal.search_api_ajax.get_url_state(url)["query"];
  34. }
  35. state = url.replace(new RegExp('^.*' + Drupal.settings.basePath + ajaxPath + '/' + '?'), '');
  36. if (query) {
  37. state = query + state.replace('?query=' + query, '');
  38. }
  39. else {
  40. state = state.replace('?query=', '');
  41. state = state.replace('?', '&');
  42. }
  43. return state;
  44. };
  45. Drupal.search_api_ajax.get_url_state = function(url) {
  46. var vars = [], hash;
  47. var hashes = url.slice(url.indexOf('?') + 1).split('&');
  48. for (var i = 0; i < hashes.length; i++) {
  49. hash = hashes[i].split('=');
  50. vars.push(hash[0]);
  51. vars[hash[0]] = hash[1];
  52. }
  53. return vars;
  54. }
  55. // prepare and perform ajax search request
  56. Drupal.search_api_ajax.request_callback = function(state) {
  57. if (content) {
  58. if (fade) {
  59. $(content + ':first').fadeTo('fast', opacity);
  60. }
  61. if (spinner) {
  62. $('#content').append('<div id="search-api-ajax-spinner"><img class="spinner" src="' + Drupal.settings.basePath + spinner + '" /></div>')
  63. }
  64. }
  65. // Scroll back to top, when top is out of view. Inspired by views module.
  66. if (target) {
  67. var offset = $(target).offset();
  68. var scrollTarget = target;
  69. while ($(scrollTarget).scrollTop() == 0 && $(scrollTarget).parent()) {
  70. scrollTarget = $(scrollTarget).parent()
  71. }
  72. if (offset.top - 10 < $(scrollTarget).scrollTop()) {
  73. $(scrollTarget).animate({
  74. scrollTop: (offset.top - 10)
  75. }, speed);
  76. }
  77. }
  78. // post ajax, read json
  79. var keysPath = '/' + state;
  80. if (isView) {
  81. keysPath = '?query=' + state;
  82. }
  83. $.post(Drupal.settings.basePath + 'search_api_ajax/' + ajaxPath + keysPath, {
  84. js: 1
  85. }, Drupal.search_api_ajax.response_callback, 'json');
  86. };
  87. // update search page with ajax, based on the json we read
  88. Drupal.search_api_ajax.response_callback = function(data) {
  89. if (content) {
  90. if (fade) {
  91. $(content + ':first').fadeTo('fast', 1);
  92. }
  93. if (spinner) {
  94. $('#search-api-ajax-spinner').remove();
  95. }
  96. }
  97. for (var setting in data.settings) {
  98. Drupal.settings[setting] = data.settings[setting];
  99. }
  100. var list = [];
  101. // we have to add the new blocks, that have come into existence
  102. // @see search_api_ajax.pages.inc where we add this blocks variable
  103. if (data.blocks) {
  104. for (var new_block in data.blocks) {
  105. blocks[new_block] = data.blocks[new_block];
  106. }
  107. }
  108. // schedule items for removal to reduce page jumpiness.
  109. if (blocks) {
  110. for (var block in blocks) {
  111. list.push($(blocks[block]));
  112. }
  113. for (var i = 0, l = list.length; i < l; i++) {
  114. list[i].remove();
  115. }
  116. }
  117. for (var region in data.regions) {
  118. if (region == 'search_api_ajax') {
  119. if (content) {
  120. $(content + ':first').html(data.regions[region]);
  121. }
  122. }
  123. else {
  124. for (var block in data.regions[region]) {
  125. if (regions[region] && blocks[block]) {
  126. $(regions[region]).append(data.regions[region][block]);
  127. }
  128. }
  129. }
  130. }
  131. // re-attach Drupal behaviors for whole document
  132. Drupal.attachBehaviors('body');
  133. };
  134. Drupal.search_api_ajax.navigate = function(url) {
  135. if (url !== undefined) {
  136. YUI().use('history', function(Y) {
  137. history.add({
  138. q: Drupal.search_api_ajax.url_to_state(url)
  139. });
  140. });
  141. }
  142. return false;
  143. };
  144. Drupal.search_api_ajax.ajax = function(selector) {
  145. // observe regular facet and sorts links ^ starts with * contains
  146. // check two paths: ^basePath/ajaxPath OR ^search_api_ajax/basePath/ajaxPath
  147. // @see http://api.jquery.com/category/selectors/attribute-selectors/
  148. // Create an array of selectors for readability.
  149. var selectors = [selector + ' a[href^="' + Drupal.settings.basePath + ajaxPath + '"]', selector + ' a[href^="' + Drupal.settings.basePath + 'search_api_ajax/' + ajaxPath + '"]'];
  150. $(selectors.join(', ')).livequery('click', function() {
  151. return Drupal.search_api_ajax.navigate($(this).attr('href'));
  152. });
  153. // Add support for facetapi checkboxes widget.
  154. // Unbind facetapi click event.
  155. $(selector + ' .facetapi-checkbox').unbind('click');
  156. $(selector + ' .facetapi-checkbox').livequery('click', function() {
  157. return Drupal.search_api_ajax.navigate($(this).next('a').attr('href'));
  158. })
  159. // observe search keys forms (or views input forms, must be custom set)
  160. $(selector + ' form[action^="' + Drupal.settings.basePath + ajaxPath + '"], ' + selector + ' form[action^="' + Drupal.settings.basePath + 'search_api_ajax/' + ajaxPath + '"]').livequery('submit', function() {
  161. return Drupal.search_api_ajax.navigate($(this).find('input[name*="keys"]').val());
  162. });
  163. // observe facet range sliders
  164. $(selector + ' .search-api-ranges-widget form[action^="' + Drupal.settings.basePath + ajaxPath + '"], ' + selector + ' .search-api-ranges-widget form[action^="' + Drupal.settings.basePath + 'search_api_ajax/' + ajaxPath + '"]').livequery('submit', function() {
  165. var separator = '?';
  166. if ($(this).find('input[name="range-ajax-target"]').val().indexOf("?") !== -1) {
  167. separator = '&';
  168. }
  169. // add a filter in the form of &f[n]=field_name:[A B]
  170. // instead of actually knowing what "n" is, we just f[]
  171. // @todo Facet API can have different 'f', how to know which?
  172. var addFilter = 'f[]=' + $(this).find('input[name="range-field"]').val() + ':' + '[' + $(this).find('input[name="range-from"]').val() + ' TO ' + $(this).find('input[name="range-to"]').val() + ']';
  173. return Drupal.search_api_ajax.navigate($(this).find('input[name="range-ajax-target"]').val() + separator + addFilter);
  174. });
  175. };
  176. }
  177. // we initiate YUI3's History extension
  178. YUI().use('history', function(Y) {
  179. // initialize
  180. history = new Y.HistoryHash();
  181. if (history.get('q')) {
  182. Drupal.search_api_ajax.request_callback(history.get('q'));
  183. }
  184. // listen to changes
  185. // @todo when going from /page#q= to /page it should also trigger
  186. Y.on('history:change', function(e) {
  187. var changed = e.changed;
  188. if (changed.q) {
  189. Drupal.search_api_ajax.request_callback(history.get('q'));
  190. }
  191. });
  192. });
  193. Drupal.behaviors.search_api_ajax = {
  194. attach: function(context, settings) {
  195. // initialize livequery() event only if there is an active search
  196. // only needed for search api pages, not for views paths
  197. if (Drupal.search_api_ajax.url_to_state(window.location.href) != '' || isView === 1) {
  198. Drupal.search_api_ajax.initialize();
  199. }
  200. }
  201. };
  202. })(jQuery);