summaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2007-07-01 15:37:10 +0000
committerDries Buytaert <dries@buytaert.net>2007-07-01 15:37:10 +0000
commitc11cb4ec24479e801076c094f043f2084b344d0c (patch)
tree5248d25917032a394ec350b65ebde88259168ffe /misc
parenta3d75e547f62174fe9fa2b5c3f9684b620612b00 (diff)
downloadbrdo-c11cb4ec24479e801076c094f043f2084b344d0c.tar.gz
brdo-c11cb4ec24479e801076c094f043f2084b344d0c.tar.bz2
- Patch #120360 by nedjo: enable AJAX by making all behaviours reattachable.
Diffstat (limited to 'misc')
-rw-r--r--misc/autocomplete.js10
-rw-r--r--misc/batch.js61
-rw-r--r--misc/collapse.js34
-rw-r--r--misc/drupal.js41
-rw-r--r--misc/tableheader.js91
-rw-r--r--misc/tableselect.js12
-rw-r--r--misc/teaser.js10
-rw-r--r--misc/textarea.js10
-rw-r--r--misc/upload.js16
9 files changed, 152 insertions, 133 deletions
diff --git a/misc/autocomplete.js b/misc/autocomplete.js
index 2431d37e4..844b628cc 100644
--- a/misc/autocomplete.js
+++ b/misc/autocomplete.js
@@ -3,9 +3,9 @@
/**
* Attaches the autocomplete behaviour to all required fields
*/
-Drupal.autocompleteAutoAttach = function () {
+Drupal.behaviors.autocomplete = function (context) {
var acdb = [];
- $('input.autocomplete').each(function () {
+ $('input.autocomplete:not(.autocomplete-processed)', context).each(function () {
var uri = this.value;
if (!acdb[uri]) {
acdb[uri] = new Drupal.ACDB(uri);
@@ -14,6 +14,7 @@ Drupal.autocompleteAutoAttach = function () {
.attr('autocomplete', 'OFF')[0];
$(input.form).submit(Drupal.autocompleteSubmit);
new Drupal.jsAC(input, acdb[uri]);
+ $(this).addClass('autocomplete-processed');
});
};
@@ -296,8 +297,3 @@ Drupal.ACDB.prototype.cancel = function() {
if (this.timer) clearTimeout(this.timer);
this.searchString = '';
};
-
-// Global Killswitch
-if (Drupal.jsEnabled) {
- $(document).ready(Drupal.autocompleteAutoAttach);
-}
diff --git a/misc/batch.js b/misc/batch.js
index 8cf1f910f..51b1e8b59 100644
--- a/misc/batch.js
+++ b/misc/batch.js
@@ -1,31 +1,38 @@
-if (Drupal.jsEnabled) {
- $(document).ready(function() {
- $('#progress').each(function () {
- var holder = this;
- var uri = Drupal.settings.batch.uri;
- var initMessage = Drupal.settings.batch.initMessage;
- var errorMessage = Drupal.settings.batch.errorMessage;
+// $Id$
- // Success: redirect to the summary.
- var updateCallback = function (progress, status, pb) {
- if (progress == 100) {
- pb.stopMonitoring();
- window.location = uri+'&op=finished';
- }
- };
+/**
+ * Attaches the batch behaviour to progress bars.
+ */
+Drupal.behaviors.batch = function (context) {
+ // This behavior attaches by ID, so is only valid once on a page.
+ if ($('#progress.batch-processed').size()) {
+ return;
+ }
+ $('#progress', context).addClass('batch-processed').each(function () {
+ var holder = this;
+ var uri = Drupal.settings.batch.uri;
+ var initMessage = Drupal.settings.batch.initMessage;
+ var errorMessage = Drupal.settings.batch.errorMessage;
- var errorCallback = function (pb) {
- var div = document.createElement('p');
- div.className = 'error';
- $(div).html(errorMessage);
- $(holder).prepend(div);
- $('#wait').hide();
- };
+ // Success: redirect to the summary.
+ var updateCallback = function (progress, status, pb) {
+ if (progress == 100) {
+ pb.stopMonitoring();
+ window.location = uri+'&op=finished';
+ }
+ };
- var progress = new Drupal.progressBar('updateprogress', updateCallback, "POST", errorCallback);
- progress.setProgress(-1, initMessage);
- $(holder).append(progress.element);
- progress.startMonitoring(uri+'&op=do', 10);
- });
+ var errorCallback = function (pb) {
+ var div = document.createElement('p');
+ div.className = 'error';
+ $(div).html(errorMessage);
+ $(holder).prepend(div);
+ $('#wait').hide();
+ };
+
+ var progress = new Drupal.progressBar('updateprogress', updateCallback, "POST", errorCallback);
+ progress.setProgress(-1, initMessage);
+ $(holder).append(progress.element);
+ progress.startMonitoring(uri+'&op=do', 10);
});
-}
+};
diff --git a/misc/collapse.js b/misc/collapse.js
index c1fd3d4c3..7bff25397 100644
--- a/misc/collapse.js
+++ b/misc/collapse.js
@@ -20,10 +20,6 @@ Drupal.toggleFieldset = function(fieldset) {
Drupal.collapseScrollIntoView(this.parentNode);
}
});
- if (typeof(Drupal.textareaAttach) != 'undefined') {
- // Initialize resizable textareas that are now revealed
- Drupal.textareaAttach(null, fieldset);
- }
}
else {
var content = $('> div', fieldset).slideUp('medium', function() {
@@ -50,19 +46,17 @@ Drupal.collapseScrollIntoView = function (node) {
}
};
-// Global Killswitch
-if (Drupal.jsEnabled) {
- $(document).ready(function() {
- $('fieldset.collapsible > legend').each(function() {
- var fieldset = $(this.parentNode);
- // Expand if there are errors inside
- if ($('input.error, textarea.error, select.error', fieldset).size() > 0) {
- fieldset.removeClass('collapsed');
- }
+Drupal.behaviors.collapse = function (context) {
+ $('fieldset.collapsible > legend:not(.collapse-processed)', context).each(function() {
+ var fieldset = $(this.parentNode);
+ // Expand if there are errors inside
+ if ($('input.error, textarea.error, select.error', fieldset).size() > 0) {
+ fieldset.removeClass('collapsed');
+ }
- // Turn the legend into a clickable link and wrap the contents of the fieldset
- // in a div for easier animation
- var text = this.innerHTML;
+ // Turn the legend into a clickable link and wrap the contents of the fieldset
+ // in a div for easier animation
+ var text = this.innerHTML;
$(this).empty().append($('<a href="#">'+ text +'</a>').click(function() {
var fieldset = $(this).parents('fieldset:first')[0];
// Don't animate multiple times
@@ -71,7 +65,9 @@ if (Drupal.jsEnabled) {
Drupal.toggleFieldset(fieldset);
}
return false;
- })).after($('<div class="fieldset-wrapper"></div>').append(fieldset.children(':not(legend)')));
- });
+ }))
+ .after($('<div class="fieldset-wrapper"></div>')
+ .append(fieldset.children(':not(legend)')))
+ .addClass('collapse-processed');
});
-}
+};
diff --git a/misc/drupal.js b/misc/drupal.js
index 98441c7ec..0c155f7d6 100644
--- a/misc/drupal.js
+++ b/misc/drupal.js
@@ -1,6 +1,6 @@
// $Id$
-var Drupal = Drupal || { 'settings': {}, 'themes': {}, 'locale': {} };
+var Drupal = Drupal || { 'settings': {}, 'behaviors': {}, 'themes': {}, 'locale': {} };
/**
* Set the variable that indicates if JavaScript behaviors should be applied
@@ -22,6 +22,43 @@ Drupal.extend = function(obj) {
};
/**
+ * Attach all registered behaviors to a page element.
+ *
+ * Behaviors are event-triggered actions that attach to page elements, enhancing
+ * default non-Javascript UIs. Behaviors are registered in the Drupal.behaviors
+ * object as follows:
+ * @code
+ * Drupal.behaviors.behaviorName = function () {
+ * ...
+ * };
+ * @endcode
+ *
+ * Drupal.attachBehaviors is added below to the jQuery ready event and so
+ * runs on initial page load. Developers implementing AHAH/AJAX in their
+ * solutions should also call this function after new page content has been
+ * loaded, feeding in an element to be processed, in order to attach all
+ * behaviors to the new content.
+ *
+ * Behaviors should use a class in the form behaviorName-processed to ensure
+ * the behavior is attached only once to a given element. (Doing so enables
+ * the reprocessing of given elements, which may be needed on occasion despite
+ * the ability to limit behavior attachment to a particular element.)
+ *
+ * @param context
+ * An element to attach behaviors to. If none is given, the document element
+ * is used.
+ */
+Drupal.attachBehaviors = function(context) {
+ context = context || document;
+ if (Drupal.jsEnabled) {
+ // Execute all of them.
+ jQuery.each(Drupal.behaviors, function() {
+ this(context);
+ });
+ }
+};
+
+/**
* Encode special characters in a plain-text string for display as HTML.
*/
Drupal.checkPlain = function(str) {
@@ -362,6 +399,8 @@ if (Drupal.jsEnabled) {
document.documentElement.className = 'js';
// 'js enabled' cookie
document.cookie = 'has_js=1';
+ // Attach all behaviors.
+ $(document).ready(Drupal.attachBehaviors);
}
/**
diff --git a/misc/tableheader.js b/misc/tableheader.js
index 5b84126ca..80d1fbdde 100644
--- a/misc/tableheader.js
+++ b/misc/tableheader.js
@@ -1,60 +1,57 @@
// $Id$
-// Global Killswitch
-if (Drupal.jsEnabled) {
+Drupal.behaviors.tableHeader = function (context) {
// Keep track of all header cells.
var cells = [];
- // Attach to all headers.
- $(document).ready(function() {
- var z = 0;
- $('table thead').each(function () {
- // Find table height.
- var table = $(this).parent('table')[0];
- var height = $(table).addClass('sticky-table').height();
- var i = 0;
+ var z = 0;
+ $('table thead:not(.tableHeader-processed)', context).each(function () {
+ // Find table height.
+ var table = $(this).parent('table')[0];
+ var height = $(table).addClass('sticky-table').height();
+ var i = 0;
- // Find all header cells.
- $('th', this).each(function () {
+ // Find all header cells.
+ $('th', this).each(function () {
- // Ensure each cell has an element in it.
- var html = $(this).html();
- if (html == ' ') {
- html = '&nbsp;';
- }
- if ($(this).children().size() == 0) {
- html = '<span>'+ html +'</span>';
- }
+ // Ensure each cell has an element in it.
+ var html = $(this).html();
+ if (html == ' ') {
+ html = '&nbsp;';
+ }
+ if ($(this).children().size() == 0) {
+ html = '<span>'+ html +'</span>';
+ }
- // Clone and wrap cell contents in sticky wrapper that overlaps the cell's padding.
- $('<div class="sticky-header" style="position: fixed; visibility: hidden; top: 0px;">'+ html +'</div>').prependTo(this);
- var div = $('div.sticky-header', this).css({
- 'marginLeft': '-'+ $(this).css('paddingLeft'),
- 'marginRight': '-'+ $(this).css('paddingRight'),
- 'paddingLeft': $(this).css('paddingLeft'),
- 'paddingTop': $(this).css('paddingTop'),
- 'paddingBottom': $(this).css('paddingBottom'),
- 'z-index': ++z
- })[0];
- cells.push(div);
+ // Clone and wrap cell contents in sticky wrapper that overlaps the cell's padding.
+ $('<div class="sticky-header" style="position: fixed; visibility: hidden; top: 0px;">'+ html +'</div>').prependTo(this);
+ var div = $('div.sticky-header', this).css({
+ 'marginLeft': '-'+ $(this).css('paddingLeft'),
+ 'marginRight': '-'+ $(this).css('paddingRight'),
+ 'paddingLeft': $(this).css('paddingLeft'),
+ 'paddingTop': $(this).css('paddingTop'),
+ 'paddingBottom': $(this).css('paddingBottom'),
+ 'z-index': ++z
+ })[0];
+ cells.push(div);
- // Adjust width to fit cell/table.
- var ref = this;
- if (!i++) {
- // The first cell is as wide as the table to prevent gaps.
- ref = table;
- div.wide = true;
- }
- $(div).css('width', parseInt($(ref).width())
- - parseInt($(div).css('paddingLeft')) +'px');
+ // Adjust width to fit cell/table.
+ var ref = this;
+ if (!i++) {
+ // The first cell is as wide as the table to prevent gaps.
+ ref = table;
+ div.wide = true;
+ }
+ $(div).css('width', parseInt($(ref).width())
+ - parseInt($(div).css('paddingLeft')) +'px');
- // Get position and store.
- div.cell = this;
- div.table = table;
- div.stickyMax = height;
- div.stickyPosition = Drupal.absolutePosition(this).y;
- });
+ // Get position and store.
+ div.cell = this;
+ div.table = table;
+ div.stickyMax = height;
+ div.stickyPosition = Drupal.absolutePosition(this).y;
});
+ $(this).addClass('tableHeader-processed');
});
// Track scrolling.
@@ -108,4 +105,4 @@ if (Drupal.jsEnabled) {
}, 250);
};
$(window).resize(resize);
-}
+};
diff --git a/misc/tableselect.js b/misc/tableselect.js
index 5c0cfbb32..978cff7c2 100644
--- a/misc/tableselect.js
+++ b/misc/tableselect.js
@@ -1,5 +1,9 @@
// $Id$
+Drupal.behaviors.tableSelect = function (context) {
+ $('form table[th.select-all]:not(.tableSelect-processed)', context).each(Drupal.tableSelect);
+}
+
Drupal.tableSelect = function() {
// Keep track of the table, which checkbox is checked and alias the settings.
var table = this, selectAll, checkboxes, lastChecked;
@@ -41,6 +45,7 @@ Drupal.tableSelect = function() {
// Keep track of the last checked checkbox.
lastChecked = e.target;
});
+ $(this).addClass('tableSelect-processed');
};
Drupal.tableSelectRange = function(from, to, state) {
@@ -67,10 +72,3 @@ Drupal.tableSelectRange = function(from, to, state) {
}
};
-
-// Global Killswitch
-if (Drupal.jsEnabled) {
- $(document).ready(function() {
- $('form table[th.select-all]').each(Drupal.tableSelect);
- });
-}
diff --git a/misc/teaser.js b/misc/teaser.js
index c59a92e55..0aa512901 100644
--- a/misc/teaser.js
+++ b/misc/teaser.js
@@ -5,9 +5,9 @@
*
* Note: depends on resizable textareas.
*/
-Drupal.teaserAttach = function() {
- $('textarea.teaser:not(.joined)').each(function() {
- var teaser = $(this).addClass('joined');
+Drupal.behaviors.teaser = function(context) {
+ $('textarea.teaser:not(.teaser-processed)', context).each(function() {
+ var teaser = $(this).addClass('teaser-processed');
// Move teaser textarea before body, and remove its form-item wrapper.
var body = $('#'+ Drupal.settings.teaser[this.id]);
@@ -75,7 +75,3 @@ Drupal.teaserAttach = function() {
});
};
-
-if (Drupal.jsEnabled) {
- $(document).ready(Drupal.teaserAttach);
-}
diff --git a/misc/textarea.js b/misc/textarea.js
index 9cd5a1c84..65b8d3cca 100644
--- a/misc/textarea.js
+++ b/misc/textarea.js
@@ -1,8 +1,8 @@
// $Id$
-Drupal.textareaAttach = function() {
- $('textarea.resizable:not(.processed)').each(function() {
- var textarea = $(this).addClass('processed'), staticOffset = null;
+Drupal.behaviors.textarea = function(context) {
+ $('textarea.resizable:not(.textarea-processed)', context).each(function() {
+ var textarea = $(this).addClass('textarea-processed'), staticOffset = null;
// When wrapping the text area, work around an IE margin bug. See:
// http://jaspan.com/ie-inherited-margin-bug-form-elements-and-haslayout
@@ -37,7 +37,3 @@ Drupal.textareaAttach = function() {
}
});
};
-
-if (Drupal.jsEnabled) {
- $(document).ready(Drupal.textareaAttach);
-}
diff --git a/misc/upload.js b/misc/upload.js
index 900d979ec..d69f3b765 100644
--- a/misc/upload.js
+++ b/misc/upload.js
@@ -3,8 +3,8 @@
/**
* Attaches the upload behaviour to the upload form.
*/
-Drupal.uploadAutoAttach = function() {
- $('input.upload').each(function () {
+Drupal.behaviors.upload = function(context) {
+ $('input.upload:not(.upload-processed)', context).addClass('upload-processed').each(function () {
var uri = this.value;
// Extract the base name from the id (edit-attach-url -> attach).
var base = this.id.substring(5, this.id.length - 4);
@@ -12,6 +12,7 @@ Drupal.uploadAutoAttach = function() {
var wrapper = base + '-wrapper';
var hide = base + '-hide';
var upload = new Drupal.jsUpload(uri, button, wrapper, hide);
+ $(this).addClass('upload-processed');
});
};
@@ -65,11 +66,10 @@ Drupal.jsUpload.prototype.oncomplete = function (data) {
// If uploading the first attachment fade in everything
if ($('tr', div).size() == 2) {
- // Replace form and re-attach behaviour
+ // Replace form and re-attach behaviours
$(div).hide();
$(this.wrapper).append(div);
$(div).fadeIn('slow');
- Drupal.uploadAutoAttach();
}
// Else fade in only the last table row
else {
@@ -89,8 +89,8 @@ Drupal.jsUpload.prototype.oncomplete = function (data) {
$(this.wrapper).append(div);
$('table tr:last-of-type td', div).fadeIn('slow');
$(this.hide, div).fadeIn('slow');
- Drupal.uploadAutoAttach();
}
+ Drupal.attachBehaviors(div);
Drupal.unfreezeHeight();
};
@@ -108,9 +108,3 @@ Drupal.jsUpload.prototype.onerror = function (error) {
left: '0px'
});
};
-
-
-// Global killswitch
-if (Drupal.jsEnabled) {
- $(document).ready(Drupal.uploadAutoAttach);
-}