Commit 5371104a authored by Dries's avatar Dries

- Patch #316225 by sun et al: allow behaviors to detach from AHAH/AJAX.

parent 068febde
...@@ -15,7 +15,8 @@ ...@@ -15,7 +15,8 @@
/** /**
* Attaches the ahah behavior to each ahah form element. * Attaches the ahah behavior to each ahah form element.
*/ */
Drupal.behaviors.ahah = function(context) { Drupal.behaviors.ahah = {
attach: function(context) {
for (var base in Drupal.settings.ahah) { for (var base in Drupal.settings.ahah) {
if (!$('#'+ base + '.ahah-processed').size()) { if (!$('#'+ base + '.ahah-processed').size()) {
var element_settings = Drupal.settings.ahah[base]; var element_settings = Drupal.settings.ahah[base];
...@@ -28,6 +29,7 @@ Drupal.behaviors.ahah = function(context) { ...@@ -28,6 +29,7 @@ Drupal.behaviors.ahah = function(context) {
$('#'+ base).addClass('ahah-processed'); $('#'+ base).addClass('ahah-processed');
} }
} }
}
}; };
/** /**
......
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
/** /**
* Attaches the autocomplete behavior to all required fields. * Attaches the autocomplete behavior to all required fields.
*/ */
Drupal.behaviors.autocomplete = function (context) { Drupal.behaviors.autocomplete = {
attach: function(context) {
var acdb = []; var acdb = [];
$('input.autocomplete:not(.autocomplete-processed)', context).each(function () { $('input.autocomplete:not(.autocomplete-processed)', context).each(function () {
var uri = this.value; var uri = this.value;
...@@ -16,6 +17,7 @@ Drupal.behaviors.autocomplete = function (context) { ...@@ -16,6 +17,7 @@ Drupal.behaviors.autocomplete = function (context) {
new Drupal.jsAC(input, acdb[uri]); new Drupal.jsAC(input, acdb[uri]);
$(this).addClass('autocomplete-processed'); $(this).addClass('autocomplete-processed');
}); });
}
}; };
/** /**
......
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
/** /**
* Attaches the batch behavior to progress bars. * Attaches the batch behavior to progress bars.
*/ */
Drupal.behaviors.batch = function (context) { Drupal.behaviors.batch = {
attach: function(context) {
// This behavior attaches by ID, so is only valid once on a page. // This behavior attaches by ID, so is only valid once on a page.
if ($('#progress.batch-processed').size()) { if ($('#progress.batch-processed').size()) {
return; return;
...@@ -35,4 +36,5 @@ Drupal.behaviors.batch = function (context) { ...@@ -35,4 +36,5 @@ Drupal.behaviors.batch = function (context) {
$(holder).append(progress.element); $(holder).append(progress.element);
progress.startMonitoring(uri+'&op=do', 10); progress.startMonitoring(uri+'&op=do', 10);
}); });
}
}; };
...@@ -50,7 +50,8 @@ Drupal.collapseScrollIntoView = function (node) { ...@@ -50,7 +50,8 @@ Drupal.collapseScrollIntoView = function (node) {
} }
}; };
Drupal.behaviors.collapse = function (context) { Drupal.behaviors.collapse = {
attach: function(context) {
$('fieldset.collapsible > legend:not(.collapse-processed)', context).each(function() { $('fieldset.collapsible > legend:not(.collapse-processed)', context).each(function() {
var fieldset = $(this.parentNode); var fieldset = $(this.parentNode);
// Expand if there are errors inside // Expand if there are errors inside
...@@ -74,4 +75,5 @@ Drupal.behaviors.collapse = function (context) { ...@@ -74,4 +75,5 @@ Drupal.behaviors.collapse = function (context) {
.append(fieldset.children(':not(legend):not(.action)'))) .append(fieldset.children(':not(legend):not(.action)')))
.addClass('collapse-processed'); .addClass('collapse-processed');
}); });
}
}; };
...@@ -12,10 +12,15 @@ Drupal.jsEnabled = document.getElementsByTagName && document.createElement && do ...@@ -12,10 +12,15 @@ Drupal.jsEnabled = document.getElementsByTagName && document.createElement && do
* *
* Behaviors are event-triggered actions that attach to page elements, enhancing * Behaviors are event-triggered actions that attach to page elements, enhancing
* default non-Javascript UIs. Behaviors are registered in the Drupal.behaviors * default non-Javascript UIs. Behaviors are registered in the Drupal.behaviors
* object as follows: * object using the method 'attach' and optionally also 'detach' as follows:
* @code * @code
* Drupal.behaviors.behaviorName = function () { * Drupal.behaviors.behaviorName = {
* attach: function(context) {
* ... * ...
* },
* detach: function(context) {
* ...
* }
* }; * };
* @endcode * @endcode
* *
...@@ -38,7 +43,38 @@ Drupal.attachBehaviors = function(context) { ...@@ -38,7 +43,38 @@ Drupal.attachBehaviors = function(context) {
context = context || document; context = context || document;
// Execute all of them. // Execute all of them.
jQuery.each(Drupal.behaviors, function() { jQuery.each(Drupal.behaviors, function() {
this(context); if (jQuery.isFunction(this.attach)) {
this.attach(context);
}
});
};
/**
* Detach registered behaviors from a page element.
*
* Developers implementing AHAH/AJAX in their solutions should call this
* function before page content is about to be removed, feeding in an element
* to be processed, in order to allow special behaviors to detach from the
* content.
*
* Such implementations should look for the class name that was added in their
* corresponding Drupal.behaviors.behaviorName.attach implementation, i.e.
* behaviorName-processed, to ensure the behavior is detached only from
* previously processed elements.
*
* @param context
* An element to detach behaviors from. If none is given, the document element
* is used.
*
* @see Drupal.attachBehaviors
*/
Drupal.detachBehaviors = function(context) {
context = context || document;
// Execute all of them.
jQuery.each(Drupal.behaviors, function() {
if (jQuery.isFunction(this.detach)) {
this.detach(context);
}
}); });
}; };
......
// $Id$ // $Id$
Drupal.behaviors.multiselectSelector = function() { Drupal.behaviors.multiselectSelector = {
attach: function(context) {
// Automatically selects the right radio button in a multiselect control. // Automatically selects the right radio button in a multiselect control.
$('.multiselect select:not(.multiselectSelector-processed)') $('.multiselect select:not(.multiselectSelector-processed)', context)
.addClass('multiselectSelector-processed').change(function() { .addClass('multiselectSelector-processed').change(function() {
$('.multiselect input:radio[value="'+ this.id.substr(5) +'"]') $('.multiselect input:radio[value="'+ this.id.substr(5) +'"]')
.attr('checked', true); .attr('checked', true);
}); });
}
}; };
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
* overriding the .onDrag, .onDrop, .row.onSwap, and .row.onIndent methods. * overriding the .onDrag, .onDrop, .row.onSwap, and .row.onIndent methods.
* See blocks.js for an example of adding additional functionality to tableDrag. * See blocks.js for an example of adding additional functionality to tableDrag.
*/ */
Drupal.behaviors.tableDrag = function(context) { Drupal.behaviors.tableDrag = {
attach: function(context) {
for (var base in Drupal.settings.tableDrag) { for (var base in Drupal.settings.tableDrag) {
if (!$('#' + base + '.tabledrag-processed', context).size()) { if (!$('#' + base + '.tabledrag-processed', context).size()) {
var tableSettings = Drupal.settings.tableDrag[base]; var tableSettings = Drupal.settings.tableDrag[base];
...@@ -25,6 +26,7 @@ Drupal.behaviors.tableDrag = function(context) { ...@@ -25,6 +26,7 @@ Drupal.behaviors.tableDrag = function(context) {
$('#' + base).addClass('tabledrag-processed'); $('#' + base).addClass('tabledrag-processed');
} }
} }
}
}; };
/** /**
......
...@@ -6,7 +6,8 @@ Drupal.tableHeaderDoScroll = function() { ...@@ -6,7 +6,8 @@ Drupal.tableHeaderDoScroll = function() {
} }
}; };
Drupal.behaviors.tableHeader = function (context) { Drupal.behaviors.tableHeader = {
attach: function(context) {
// This breaks in anything less than IE 7. Prevent it from running. // This breaks in anything less than IE 7. Prevent it from running.
if (jQuery.browser.msie && parseInt(jQuery.browser.version, 10) < 7) { if (jQuery.browser.msie && parseInt(jQuery.browser.version, 10) < 7) {
return; return;
...@@ -110,4 +111,5 @@ Drupal.behaviors.tableHeader = function (context) { ...@@ -110,4 +111,5 @@ Drupal.behaviors.tableHeader = function (context) {
}, 250); }, 250);
}; };
$(window).resize(resize); $(window).resize(resize);
}
}; };
// $Id$ // $Id$
Drupal.behaviors.tableSelect = function (context) { Drupal.behaviors.tableSelect = {
attach: function(context) {
$('form table:has(th.select-all):not(.tableSelect-processed)', context).each(Drupal.tableSelect); $('form table:has(th.select-all):not(.tableSelect-processed)', context).each(Drupal.tableSelect);
}
}; };
Drupal.tableSelect = function() { Drupal.tableSelect = function() {
......
...@@ -5,7 +5,8 @@ ...@@ -5,7 +5,8 @@
* *
* Note: depends on resizable textareas. * Note: depends on resizable textareas.
*/ */
Drupal.behaviors.teaser = function(context) { Drupal.behaviors.teaser = {
attach: function(context) {
// This breaks in Konqueror. Prevent it from running. // This breaks in Konqueror. Prevent it from running.
if (/KDE/.test(navigator.vendor)) { if (/KDE/.test(navigator.vendor)) {
return; return;
...@@ -85,7 +86,7 @@ Drupal.behaviors.teaser = function(context) { ...@@ -85,7 +86,7 @@ Drupal.behaviors.teaser = function(context) {
// Make sure that textarea.js has done its magic to ensure proper visibility state. // Make sure that textarea.js has done its magic to ensure proper visibility state.
if (Drupal.behaviors.textarea && teaser.is(('.form-textarea:not(.textarea-processed)'))) { if (Drupal.behaviors.textarea && teaser.is(('.form-textarea:not(.textarea-processed)'))) {
Drupal.behaviors.textarea(teaser.parentNode); Drupal.behaviors.textarea.attach(teaser.parentNode);
} }
// Set initial visibility. // Set initial visibility.
if ($(teaser).is('[@disabled]')) { if ($(teaser).is('[@disabled]')) {
...@@ -93,4 +94,5 @@ Drupal.behaviors.teaser = function(context) { ...@@ -93,4 +94,5 @@ Drupal.behaviors.teaser = function(context) {
} }
}); });
}
}; };
// $Id$ // $Id$
Drupal.behaviors.textarea = function(context) { Drupal.behaviors.textarea = {
attach: function(context) {
$('textarea.resizable:not(.textarea-processed)', context).each(function() { $('textarea.resizable:not(.textarea-processed)', context).each(function() {
// Avoid non-processed teasers. // Avoid non-processed teasers.
if ($(this).is(('textarea.teaser:not(.teaser-processed)'))) { if ($(this).is(('textarea.teaser:not(.teaser-processed)'))) {
...@@ -33,4 +34,5 @@ Drupal.behaviors.textarea = function(context) { ...@@ -33,4 +34,5 @@ Drupal.behaviors.textarea = function(context) {
textarea.css('opacity', 1); textarea.css('opacity', 1);
} }
}); });
}
}; };
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
* This behavior is dependent on the tableDrag behavior, since it uses the * This behavior is dependent on the tableDrag behavior, since it uses the
* objects initialized in that behavior to update the row. * objects initialized in that behavior to update the row.
*/ */
Drupal.behaviors.blockDrag = function(context) { Drupal.behaviors.blockDrag = {
attach: function(context) {
var table = $('table#blocks'); var table = $('table#blocks');
var tableDrag = Drupal.tableDrag.blocks; // Get the blocks tableDrag object. var tableDrag = Drupal.tableDrag.blocks; // Get the blocks tableDrag object.
...@@ -92,4 +93,5 @@ Drupal.behaviors.blockDrag = function(context) { ...@@ -92,4 +93,5 @@ Drupal.behaviors.blockDrag = function(context) {
} }
}); });
}; };
}
}; };
// $Id$ // $Id$
Drupal.behaviors.color = function (context) { Drupal.behaviors.color = {
attach: function(context) {
// This behavior attaches by ID, so is only valid once on a page. // This behavior attaches by ID, so is only valid once on a page.
if ($('#color_scheme_form .color-form.color-processed').size()) { if ($('#color_scheme_form .color-form.color-processed').size()) {
return; return;
...@@ -248,4 +249,5 @@ Drupal.behaviors.color = function (context) { ...@@ -248,4 +249,5 @@ Drupal.behaviors.color = function (context) {
// Render preview. // Render preview.
preview(); preview();
}
}; };
// $Id$ // $Id$
Drupal.behaviors.comment = function(context) { Drupal.behaviors.comment = {
attach: function(context) {
var parts = new Array("name", "homepage", "mail"); var parts = new Array("name", "homepage", "mail");
var cookie = ''; var cookie = '';
for (i=0;i<3;i++) { for (i=0;i<3;i++) {
...@@ -11,6 +12,7 @@ Drupal.behaviors.comment = function(context) { ...@@ -11,6 +12,7 @@ Drupal.behaviors.comment = function(context) {
.addClass('comment-processed'); .addClass('comment-processed');
} }
} }
}
}; };
Drupal.comment = {}; Drupal.comment = {};
......
// $Id$ // $Id$
Drupal.behaviors.openid = function (context) { Drupal.behaviors.openid = {
attach: function(context) {
var $loginElements = $("#edit-name-wrapper, #edit-pass-wrapper, li.openid-link"); var $loginElements = $("#edit-name-wrapper, #edit-pass-wrapper, li.openid-link");
var $openidElements = $("#edit-openid-identifier-wrapper, li.user-link"); var $openidElements = $("#edit-openid-identifier-wrapper, li.user-link");
...@@ -35,4 +36,5 @@ Drupal.behaviors.openid = function (context) { ...@@ -35,4 +36,5 @@ Drupal.behaviors.openid = function (context) {
$("#edit-name")[0].focus(); $("#edit-name")[0].focus();
return false; return false;
}); });
}
}; };
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
* objects initialized in that behavior to update the row. It shows and hides * objects initialized in that behavior to update the row. It shows and hides
* a warning message when removing the last field from a profile category. * a warning message when removing the last field from a profile category.
*/ */
Drupal.behaviors.profileDrag = function(context) { Drupal.behaviors.profileDrag = {
attach: function(context) {
var table = $('#profile-fields'); var table = $('#profile-fields');
var tableDrag = Drupal.tableDrag['profile-fields']; // Get the profile tableDrag object. var tableDrag = Drupal.tableDrag['profile-fields']; // Get the profile tableDrag object.
...@@ -51,4 +52,5 @@ Drupal.behaviors.profileDrag = function(context) { ...@@ -51,4 +52,5 @@ Drupal.behaviors.profileDrag = function(context) {
} }
} }
}; };
}
}; };
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
/** /**
* Add the cool table collapsing on the testing overview page. * Add the cool table collapsing on the testing overview page.
*/ */
Drupal.behaviors.simpleTestMenuCollapse = function() { Drupal.behaviors.simpleTestMenuCollapse = {
attach: function() {
// Adds expand-collapse functionality. // Adds expand-collapse functionality.
$('div.simpletest-image').each(function() { $('div.simpletest-image').each(function() {
direction = Drupal.settings.simpleTest[$(this).attr('id')].imageDirection; direction = Drupal.settings.simpleTest[$(this).attr('id')].imageDirection;
...@@ -33,13 +34,15 @@ Drupal.behaviors.simpleTestMenuCollapse = function() { ...@@ -33,13 +34,15 @@ Drupal.behaviors.simpleTestMenuCollapse = function() {
$(this).html(Drupal.settings.simpleTest.images[(direction? 0 : 1)]); $(this).html(Drupal.settings.simpleTest.images[(direction? 0 : 1)]);
} }
}); });
} }
};
/** /**
* Select/deselect all the inner checkboxes when the outer checkboxes are * Select/deselect all the inner checkboxes when the outer checkboxes are
* selected/deselected. * selected/deselected.
*/ */
Drupal.behaviors.simpleTestSelectAll = function() { Drupal.behaviors.simpleTestSelectAll = {
attach: function() {
$('td.simpletest-select-all').each(function() { $('td.simpletest-select-all').each(function() {
var checkboxes = Drupal.settings.simpleTest['simpletest-test-group-'+ $(this).attr('id')].testNames, totalCheckboxes = 0, var checkboxes = Drupal.settings.simpleTest['simpletest-test-group-'+ $(this).attr('id')].testNames, totalCheckboxes = 0,
checkbox = $('<input type="checkbox" class="form-checkbox" id="'+ $(this).attr('id') +'-select-all" />').change(function() { checkbox = $('<input type="checkbox" class="form-checkbox" id="'+ $(this).attr('id') +'-select-all" />').change(function() {
...@@ -72,4 +75,5 @@ Drupal.behaviors.simpleTestSelectAll = function() { ...@@ -72,4 +75,5 @@ Drupal.behaviors.simpleTestSelectAll = function() {
} }
$(this).append(checkbox); $(this).append(checkbox);
}); });
}
}; };
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
* This function is not used to verify whether or not clean URLs * This function is not used to verify whether or not clean URLs
* are currently enabled. * are currently enabled.
*/ */
Drupal.behaviors.cleanURLsSettingsCheck = function(context) { Drupal.behaviors.cleanURLsSettingsCheck = {
attach: function(context) {
// This behavior attaches by ID, so is only valid once on a page. // This behavior attaches by ID, so is only valid once on a page.
// Also skip if we are on an install page, as Drupal.cleanURLsInstallCheck will handle // Also skip if we are on an install page, as Drupal.cleanURLsInstallCheck will handle
// the processing. // the processing.
...@@ -33,6 +34,7 @@ Drupal.behaviors.cleanURLsSettingsCheck = function(context) { ...@@ -33,6 +34,7 @@ Drupal.behaviors.cleanURLsSettingsCheck = function(context) {
} }
}); });
$("#clean-url").addClass('clean-url-processed'); $("#clean-url").addClass('clean-url-processed');
}
}; };
/** /**
...@@ -70,7 +72,8 @@ Drupal.cleanURLsInstallCheck = function() { ...@@ -70,7 +72,8 @@ Drupal.cleanURLsInstallCheck = function() {
* use the same value. In the installer this is used to populate the * use the same value. In the installer this is used to populate the
* administrator e-mail address with the same value as the site e-mail address. * administrator e-mail address with the same value as the site e-mail address.
*/ */
Drupal.behaviors.copyFieldValue = function (context) { Drupal.behaviors.copyFieldValue = {
attach: function(context) {
for (var sourceId in Drupal.settings.copyFieldValue) { for (var sourceId in Drupal.settings.copyFieldValue) {
// Get the list of target fields. // Get the list of target fields.
targetIds = Drupal.settings.copyFieldValue[sourceId]; targetIds = Drupal.settings.copyFieldValue[sourceId];
...@@ -88,12 +91,14 @@ Drupal.behaviors.copyFieldValue = function (context) { ...@@ -88,12 +91,14 @@ Drupal.behaviors.copyFieldValue = function (context) {
sourceField.addClass('copy-field-values-processed'); sourceField.addClass('copy-field-values-processed');
} }
} }
}
}; };
/** /**
* Show/hide custom format sections on the date-time settings page. * Show/hide custom format sections on the date-time settings page.
*/ */
Drupal.behaviors.dateTime = function(context) { Drupal.behaviors.dateTime = {
attach: function(context) {
// Show/hide custom format depending on the select's value. // Show/hide custom format depending on the select's value.
$('select.date-format:not(.date-time-processed)', context).change(function() { $('select.date-format:not(.date-time-processed)', context).change(function() {
$(this).addClass('date-time-processed').parents("div.date-container").children("div.custom-container")[$(this).val() == "custom" ? "show" : "hide"](); $(this).addClass('date-time-processed').parents("div.date-container").children("div.custom-container")[$(this).val() == "custom" ? "show" : "hide"]();
...@@ -110,4 +115,5 @@ Drupal.behaviors.dateTime = function(context) { ...@@ -110,4 +115,5 @@ Drupal.behaviors.dateTime = function(context) {
// Trigger the event handler to show the form input if necessary. // Trigger the event handler to show the form input if necessary.
$('select.date-format', context).trigger('change'); $('select.date-format', context).trigger('change');
}
}; };
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
* This behavior is dependent on the tableDrag behavior, since it uses the * This behavior is dependent on the tableDrag behavior, since it uses the
* objects initialized in that behavior to update the row. * objects initialized in that behavior to update the row.
*/ */
Drupal.behaviors.termDrag = function(context) { Drupal.behaviors.termDrag = {
attach: function(context) {
var table = $('#taxonomy', context); var table = $('#taxonomy', context);
var tableDrag = Drupal.tableDrag.taxonomy; // Get the blocks tableDrag object. var tableDrag = Drupal.tableDrag.taxonomy; // Get the blocks tableDrag object.
var rows = $('tr', table).size(); var rows = $('tr', table).size();
...@@ -33,4 +34,5 @@ Drupal.behaviors.termDrag = function(context) { ...@@ -33,4 +34,5 @@ Drupal.behaviors.termDrag = function(context) {
$(table[0].tBodies[0].rows[rows - Drupal.settings.taxonomy.forwardPeddle - 1]).addClass('taxonomy-term-divider-bottom'); $(table[0].tBodies[0].rows[rows - Drupal.settings.taxonomy.forwardPeddle - 1]).addClass('taxonomy-term-divider-bottom');
} }
}; };
}
}; };
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
* Attach handlers to evaluate the strength of any password fields and to check * Attach handlers to evaluate the strength of any password fields and to check
* that its confirmation is correct. * that its confirmation is correct.
*/ */
Drupal.behaviors.password = function(context) { Drupal.behaviors.password = {
attach: function(context) {
var translate = Drupal.settings.password; var translate = Drupal.settings.password;
$("input.password-field:not(.password-processed)", context).each(function() { $("input.password-field:not(.password-processed)", context).each(function() {
var passwordInput = $(this).addClass('password-processed'); var passwordInput = $(this).addClass('password-processed');
...@@ -83,6 +83,7 @@ Drupal.behaviors.password = function(context) { ...@@ -83,6 +83,7 @@ Drupal.behaviors.password = function(context) {
passwordInput.keyup(passwordCheck).focus(passwordCheck).blur(passwordCheck); passwordInput.keyup(passwordCheck).focus(passwordCheck).blur(passwordCheck);
confirmInput.keyup(passwordCheckMatch).blur(passwordCheckMatch); confirmInput.keyup(passwordCheckMatch).blur(passwordCheckMatch);
}); });
}
}; };
/** /**
...@@ -171,9 +172,10 @@ Drupal.setDefaultTimezone = function() { ...@@ -171,9 +172,10 @@ Drupal.setDefaultTimezone = function() {
* picture-related form elements depending on the current value of the * picture-related form elements depending on the current value of the
* "Picture support" radio buttons. * "Picture support" radio buttons.
*/ */
Drupal.behaviors.userSettings = function (context) { Drupal.behaviors.userSettings = {
attach: function(context) {
$('div.user-admin-picture-radios input[type=radio]:not(.userSettings-processed)', context).addClass('userSettings-processed').click(function () { $('div.user-admin-picture-radios input[type=radio]:not(.userSettings-processed)', context).addClass('userSettings-processed').click(function () {
$('div.user-admin-picture-settings', context)[['hide', 'show'][this.value]](); $('div.user-admin-picture-settings', context)[['hide', 'show'][this.value]]();
}); });
}
}; };
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment