first commit
[step2_drupal.git] / views / js / ajax_view.js
blob8470058844682fe27fe82c17b19a1d84074831be
1 // $Id: ajax_view.js,v 1.17 2009/03/25 00:11:25 merlinofchaos Exp $
3 /**
4  * @file ajaxView.js
5  *
6  * Handles AJAX fetching of views, including filter submission and response.
7  */
9 Drupal.Views.Ajax = Drupal.Views.Ajax || {};
11 /**
12  * An ajax responder that accepts a packet of JSON data and acts appropriately.
13  *
14  * The following fields control behavior.
15  * - 'display': Display the associated data in the view area.
16  */
17 Drupal.Views.Ajax.ajaxViewResponse = function(target, response) {
19   if (response.debug) {
20     alert(response.debug);
21   }
23   var $view = $(target);
25   // Check the 'display' for data.
26   if (response.status && response.display) {
27     var $newView = $(response.display);
28     $view.replaceWith($newView);
29     $view = $newView;
30     Drupal.attachBehaviors($view.parent());
31   }
33   if (response.messages) {
34     // Show any messages (but first remove old ones, if there are any).
35     $view.find('.views-messages').remove().end().prepend(response.messages);
36   }
39 /**
40  * Ajax behavior for views. 
41  */
42 Drupal.behaviors.ViewsAjaxView = function() {
43   if (Drupal.settings && Drupal.settings.views && Drupal.settings.views.ajaxViews) {
44     var ajax_path = Drupal.settings.views.ajax_path;
45     // If there are multiple views this might've ended up showing up multiple times.
46     if (ajax_path.constructor.toString().indexOf("Array") != -1) {
47       ajax_path = ajax_path[0];
48     }
49     $.each(Drupal.settings.views.ajaxViews, function(i, settings) {
50       var view = '.view-dom-id-' + settings.view_dom_id;
51       if (!$(view).size()) {
52         // Backward compatibility: if 'views-view.tpl.php' is old and doesn't
53         // contain the 'view-dom-id-#' class, we fall back to the old way of
54         // locating the view:
55         view = '.view-id-' + settings.view_name + '.view-display-id-' + settings.view_display_id;
56       }
59       // Process exposed filter forms.
60       $('form#views-exposed-form-' + settings.view_name.replace(/_/g, '-') + '-' + settings.view_display_id.replace(/_/g, '-'))
61       .filter(':not(.views-processed)')
62       .each(function () {
63         // remove 'q' from the form; it's there for clean URLs
64         // so that it submits to the right place with regular submit
65         // but this method is submitting elsewhere.
66         $('input[name=q]', this).remove();
67         var form = this;
68         // ajaxSubmit doesn't accept a data argument, so we have to
69         // pass additional fields this way.
70         $.each(settings, function(key, setting) {
71           $(form).append('<input type="hidden" name="'+ key + '" value="'+ setting +'"/>');
72         });
73       })
74       .addClass('views-processed')
75       .submit(function () {
76         $('input[type=submit]', this).after('<span class="views-throbbing">&nbsp</span>');
77         var object = this;
78         $(this).ajaxSubmit({
79           url: ajax_path,
80           type: 'GET',
81           success: function(response) {
82             // Call all callbacks.
83             if (response.__callbacks) {
84               $.each(response.__callbacks, function(i, callback) {
85                 eval(callback)(view, response);
86               });
87               $('.views-throbbing', object).remove();
88             }
89           },
90           error: function() { alert(Drupal.t("An error occurred at @path.", {'@path': ajax_path})); $('.views-throbbing', object).remove(); },
91           dataType: 'json'
92         });
94         return false;
95       });
97       $(view).filter(':not(.views-processed)')
98         // Don't attach to nested views. Doing so would attach multiple behaviors
99         // to a given element.
100         .filter(function() {
101           // If there is at least one parent with a view class, this view
102           // is nested (e.g., an attachment). Bail.
103           return !$(this).parents('.view').size();
104         })
105         .each(function() {
106           // Set a reference that will work in subsequent calls.
107           var target = this;
108           $(this)
109             .addClass('views-processed')
110             // Process pager, tablesort, and summary links.
111             .find('ul.pager > li > a, th.views-field a, .views-summary a')
112             .each(function () {
113               var viewData = {};
114               // Construct an object using the settings defaults and then overriding
115               // with data specific to the link.
116               $.extend(
117                 viewData,
118                 settings,
119                 Drupal.Views.parseQueryString($(this).attr('href')),
120                 // Extract argument data from the URL.
121                 Drupal.Views.parseViewArgs($(this).attr('href'), settings.view_base_path)
122               );
123               $(this).click(function () {
124                 $(this).addClass('views-throbbing');
125                 $.ajax({
126                   url: ajax_path,
127                   type: 'GET',
128                   data: viewData,
129                   success: function(response) {
130                     $(this).removeClass('views-throbbing');
131                     // Scroll to the top of the view. This will allow users
132                     // to browse newly loaded content after e.g. clicking a pager
133                     // link.
134                     var offset = $(target).offset();
135                     // Only scroll upward
136                     if (offset.top - 10 < $(window).scrollTop()) {
137                       $('html,body').animate({scrollTop: (offset.top - 10)}, 500);
138                     }
139                     // Call all callbacks.
140                     if (response.__callbacks) {
141                       $.each(response.__callbacks, function(i, callback) {
142                         eval(callback)(target, response);
143                       });
144                     }
145                   },
146                   error: function() { $(this).removeClass('views-throbbing'); alert(Drupal.t("An error occurred at @path.", {'@path': ajax_path})); },
147                   dataType: 'json'
148                 });
150                 return false;
151               });
152             }); // .each function () {
153       }); // $view.filter().each
154     }); // .each Drupal.settings.views.ajaxViews
155   } // if