summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Carver2013-05-06 17:50:54 (GMT)
committer Mark Carver2013-05-06 17:50:54 (GMT)
commit05daacc4fa9f09706638c814f4986c18b12b119e (patch)
treed6ce3f2bb0dfef5e0e60bc709141c45cd5b1468f
parente426a14c1617361532d48ad669f3fda22f51dd38 (diff)
Issue #1907472 by lupus78, Adam Wood, Mark Carver: Pager in views with ajax
-rw-r--r--css/style.css10
-rw-r--r--includes/pager.inc4
-rw-r--r--includes/theme.inc17
-rw-r--r--js/bootstrap_ajax.js74
-rw-r--r--js/bootstrap_ajax_view.js12
5 files changed, 114 insertions, 3 deletions
diff --git a/css/style.css b/css/style.css
index fa7d054..a13e664 100644
--- a/css/style.css
+++ b/css/style.css
@@ -243,3 +243,13 @@ e.g. multipage*/
border: 0 none;
margin: 0;
}
+
+/* Views AJAX pagination support */
+.pagination ul > li > a.progress-disabled {
+ float: left;
+}
+.pagination ul > li a .throbber {
+ margin: 0 -0.25em 0 0.5em;
+ position: relative;
+ top: 1px;
+}
diff --git a/includes/pager.inc b/includes/pager.inc
index cab241f..f9c0d79 100644
--- a/includes/pager.inc
+++ b/includes/pager.inc
@@ -80,7 +80,7 @@ function bootstrap_pager($variables) {
if ($i > 1) {
$items[] = array(
'class' => array('pager-ellipsis', 'disabled'),
- 'data' => '<a>…</a>',
+ 'data' => '<span>…</span>',
);
}
// Now generate the actual pager piece.
@@ -107,7 +107,7 @@ function bootstrap_pager($variables) {
if ($i < $pager_max) {
$items[] = array(
'class' => array('pager-ellipsis', 'disabled'),
- 'data' => '<a>…</a>',
+ 'data' => '<span>…</span>',
);
}
}
diff --git a/includes/theme.inc b/includes/theme.inc
index f5c511f..f44e4b9 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -298,13 +298,28 @@ function bootstrap_js_alter(&$js) {
libraries_load('bootstrap', 'minified');
}
+ $theme_path = drupal_get_path('theme', 'bootstrap');
+
// Replace core progress bar JS with the Bootstrap equivilent.
if (isset($js['misc/progress.js']) && !empty($js['misc/progress.js'])) {
unset($js['misc/progress.js']);
- $progress = drupal_get_path('theme', 'bootstrap') . '/js/progress.js';
+ $progress = $theme_path . '/js/progress.js';
$js[$progress] = drupal_js_defaults($progress);
}
+ // Fix broken Views AJAX pagers.
+ if (module_exists('views') && !empty($js[drupal_get_path('module', 'views') . '/js/ajax_view.js'])) {
+ // Override core ajax prototype function to append throbber inside links,
+ // instead of after it (floating issues).
+ $ajax = $theme_path . '/js/bootstrap_ajax.js';
+ $js[$ajax] = drupal_js_defaults($ajax);
+ $js[$ajax]['group'] = JS_THEME;
+ // Override views prototype function to bind to Bootstrap pagination.
+ $ajax_view = $theme_path . '/js/bootstrap_ajax_view.js';
+ $js[$ajax_view] = drupal_js_defaults($ajax_view);
+ $js[$ajax_view]['group'] = JS_THEME;
+ }
+
$js = array_diff_key($js, $excludes);
if (theme_get_setting('cdn_bootstrap')) {
$files[] = '//netdna.bootstrapcdn.com/twitter-bootstrap/'. theme_get_setting('cdn_bootstrap_version') .'/js/bootstrap.min.js';
diff --git a/js/bootstrap_ajax.js b/js/bootstrap_ajax.js
new file mode 100644
index 0000000..141c152
--- /dev/null
+++ b/js/bootstrap_ajax.js
@@ -0,0 +1,74 @@
+(function ($) {
+
+/**
+ * Override Drupal's AJAX prototype beforeSend function so it can append the
+ * throbber inside the pager links.
+ */
+Drupal.ajax.prototype.beforeSend = function (xmlhttprequest, options) {
+ // For forms without file inputs, the jQuery Form plugin serializes the form
+ // values, and then calls jQuery's $.ajax() function, which invokes this
+ // handler. In this circumstance, options.extraData is never used. For forms
+ // with file inputs, the jQuery Form plugin uses the browser's normal form
+ // submission mechanism, but captures the response in a hidden IFRAME. In this
+ // circumstance, it calls this handler first, and then appends hidden fields
+ // to the form to submit the values in options.extraData. There is no simple
+ // way to know which submission mechanism will be used, so we add to extraData
+ // regardless, and allow it to be ignored in the former case.
+ if (this.form) {
+ options.extraData = options.extraData || {};
+
+ // Let the server know when the IFRAME submission mechanism is used. The
+ // server can use this information to wrap the JSON response in a TEXTAREA,
+ // as per http://jquery.malsup.com/form/#file-upload.
+ options.extraData.ajax_iframe_upload = '1';
+
+ // The triggering element is about to be disabled (see below), but if it
+ // contains a value (e.g., a checkbox, textfield, select, etc.), ensure that
+ // value is included in the submission. As per above, submissions that use
+ // $.ajax() are already serialized prior to the element being disabled, so
+ // this is only needed for IFRAME submissions.
+ var v = $.fieldValue(this.element);
+ if (v !== null) {
+ options.extraData[this.element.name] = v;
+ }
+ }
+
+ // Disable the element that received the change to prevent user interface
+ // interaction while the Ajax request is in progress. ajax.ajaxing prevents
+ // the element from triggering a new request, but does not prevent the user
+ // from changing its value.
+ $(this.element).addClass('progress-disabled').attr('disabled', true);
+
+ // Insert progressbar or throbber.
+ if (this.progress.type == 'bar') {
+ var progressBar = new Drupal.progressBar('ajax-progress-' + this.element.id, eval(this.progress.update_callback), this.progress.method, eval(this.progress.error_callback));
+ if (this.progress.message) {
+ progressBar.setProgress(-1, this.progress.message);
+ }
+ if (this.progress.url) {
+ progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500);
+ }
+ this.progress.element = $(progressBar.element).addClass('ajax-progress ajax-progress-bar');
+ this.progress.object = progressBar;
+ $(this.element).after(this.progress.element);
+ }
+ else if (this.progress.type == 'throbber') {
+ this.progress.element = $('<div class="ajax-progress ajax-progress-throbber"><div class="throbber">&nbsp;</div></div>');
+ // If progress type has the Bootstrap pagination parent, then append the
+ // throbber instead of attaching it after the link.
+ if ($(this.element).parents('.pagination')) {
+ if (this.progress.message) {
+ $('.throbber', this.progress.element).append('<div class="message">' + this.progress.message + '</div>');
+ }
+ $(this.element).append(this.progress.element);
+ }
+ else {
+ if (this.progress.message) {
+ $('.throbber', this.progress.element).after('<div class="message">' + this.progress.message + '</div>');
+ }
+ $(this.element).after(this.progress.element);
+ }
+ }
+};
+
+})(jQuery);
diff --git a/js/bootstrap_ajax_view.js b/js/bootstrap_ajax_view.js
new file mode 100644
index 0000000..ec6b55d
--- /dev/null
+++ b/js/bootstrap_ajax_view.js
@@ -0,0 +1,12 @@
+(function ($) {
+
+/**
+ * Override Views prototype function so it can recognize Bootstrap AJAX pagers.
+ * Attach the ajax behavior to each link.
+ */
+Drupal.views.ajaxView.prototype.attachPagerAjax = function() {
+ this.$view.find('ul.pager > li > a, th.views-field a, .attachment .views-summary a, .pagination ul li a')
+ .each(jQuery.proxy(this.attachPagerLinkAjax, this));
+};
+
+})(jQuery);