1/** 2 * @file 3 * Handles AJAX fetching of views, including filter submission and response. 4 */ 5(function ($) { 6 7 /** 8 * Attaches the AJAX behavior to exposed filter forms and key views links. 9 */ 10 Drupal.behaviors.ViewsAjaxView = {}; 11 Drupal.behaviors.ViewsAjaxView.attach = function() { 12 if (Drupal.settings && Drupal.settings.views && Drupal.settings.views.ajaxViews) { 13 $.each(Drupal.settings.views.ajaxViews, function(i, settings) { 14 Drupal.views.instances[i] = new Drupal.views.ajaxView(settings); 15 }); 16 } 17 }; 18 19 Drupal.views = {}; 20 Drupal.views.instances = {}; 21 22 /** 23 * JavaScript object for a certain view. 24 */ 25 Drupal.views.ajaxView = function(settings) { 26 var selector = '.view-dom-id-' + settings.view_dom_id; 27 this.$view = $(selector); 28 29 // If view is not present return to prevent errors. 30 if (!this.$view.length) { 31 return; 32 } 33 34 // Retrieve the path to use for views' ajax. 35 var ajax_path = Drupal.settings.views.ajax_path; 36 37 // If there are multiple views this might've ended up showing up multiple 38 // times. 39 if (ajax_path.constructor.toString().indexOf("Array") != -1) { 40 ajax_path = ajax_path[0]; 41 } 42 43 // Check if there are any GET parameters to send to views. 44 var queryString = window.location.search || ''; 45 if (queryString !== '') { 46 // Remove the question mark and Drupal path component if any. 47 var queryString = queryString.slice(1).replace(/q=[^&]+&?|&?render=[^&]+/, ''); 48 if (queryString !== '') { 49 // If there is a '?' in ajax_path, clean url are on and & should be 50 // used to add parameters. 51 queryString = ((/\?/.test(ajax_path)) ? '&' : '?') + queryString; 52 } 53 } 54 55 this.element_settings = { 56 url: ajax_path + queryString, 57 submit: settings, 58 setClick: true, 59 event: 'click', 60 selector: selector, 61 progress: { 62 type: 'throbber' 63 } 64 }; 65 66 this.settings = settings; 67 68 // Add the ajax to exposed forms. 69 this.$exposed_form = $('#views-exposed-form-' + settings.view_name.replace(/_/g, '-') + '-' + settings.view_display_id.replace(/_/g, '-')); 70 this.$exposed_form.once(jQuery.proxy(this.attachExposedFormAjax, this)); 71 72 // Store Drupal.ajax objects here for all pager links. 73 this.links = []; 74 75 // Add the ajax to pagers. 76 this.$view 77 .once(jQuery.proxy(this.attachPagerAjax, this)); 78 79 // Add a trigger to update this view specifically. In order to trigger a 80 // refresh use the following code. 81 // 82 // @code 83 // jQuery('.view-name').trigger('RefreshView'); 84 // @endcode 85 // Add a trigger to update this view specifically. 86 var self_settings = this.element_settings; 87 self_settings.event = 'RefreshView'; 88 var self = this; 89 this.$view.once('refresh', function () { 90 self.refreshViewAjax = new Drupal.ajax(self.selector, self.$view, self_settings); 91 }); 92 }; 93 94 Drupal.views.ajaxView.prototype.attachExposedFormAjax = function() { 95 var button = $('input[type=submit], button[type=submit], input[type=image]', this.$exposed_form); 96 button = button[0]; 97 98 // Call the autocomplete submit before doing AJAX. 99 $(button).click(function () { 100 if (Drupal.autocompleteSubmit) { 101 Drupal.autocompleteSubmit(); 102 } 103 }); 104 105 this.exposedFormAjax = new Drupal.ajax($(button).attr('id'), button, this.element_settings); 106 }; 107 108 /** 109 * Attach the ajax behavior to each link. 110 */ 111 Drupal.views.ajaxView.prototype.attachPagerAjax = function() { 112 this.$view.find('ul.pager > li > a, ol.pager > li > a, th.views-field a, .attachment .views-summary a') 113 .each(jQuery.proxy(this.attachPagerLinkAjax, this)); 114 }; 115 116 /** 117 * Attach the ajax behavior to a single link. 118 */ 119 Drupal.views.ajaxView.prototype.attachPagerLinkAjax = function(id, link) { 120 var $link = $(link); 121 var viewData = {}; 122 var href = $link.attr('href'); 123 // Don't attach to pagers inside nested views. 124 if ($link.closest('.view')[0] !== this.$view[0] && 125 $link.closest('.view').parent().hasClass('attachment') === false) { 126 return; 127 } 128 129 // Provide a default page if none has been set. This must be done 130 // prior to merging with settings to avoid accidentally using the 131 // page landed on instead of page 1. 132 if (typeof(viewData.page) === 'undefined') { 133 viewData.page = 0; 134 } 135 136 // Construct an object using the settings defaults and then overriding 137 // with data specific to the link. 138 $.extend( 139 viewData, 140 this.settings, 141 Drupal.Views.parseQueryString(href), 142 // Extract argument data from the URL. 143 Drupal.Views.parseViewArgs(href, this.settings.view_base_path) 144 ); 145
146 // For anchor tags, these will go to the target of the anchor rather 147 // than the usual location. 148 $.extend(viewData, Drupal.Views.parseViewArgs(href, this.settings.view_base_path)); 149 150 // Construct an object using the element settings defaults, 151 // then overriding submit with viewData. 152 var pager_settings = $.extend({}, this.element_settings); 153 pager_settings.submit = viewData; 154 this.pagerAjax = new Drupal.ajax(false, $link, pager_settings); 155 this.links.push(this.pagerAjax); 156 }; 157 158 Drupal.ajax.prototype.commands.viewsScrollTop = function (ajax, response, status) { 159 // Scroll to the top of the view. This will allow users 160 // to browse newly loaded content after e.g. clicking a pager 161 // link. 162 var offset = $(response.selector).offset(); 163 // We can't guarantee that the scrollable object should be 164 // the body, as the view could be embedded in something 165 // more complex such as a modal popup. Recurse up the DOM 166 // and scroll the first element that has a non-zero top. 167 var scrollTarget = response.selector; 168 while ($(scrollTarget).scrollTop() == 0 && $(scrollTarget).parent()) { 169 scrollTarget = $(scrollTarget).parent(); 170 } 171 // Only scroll upward. 172 if (offset.top - 10 < $(scrollTarget).scrollTop()) { 173 $(scrollTarget).animate({scrollTop: (offset.top - 10)}, 500); 174 } 175 }; 176 177})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.