Index: misc/autocomplete.js =================================================================== RCS file: /cvs/drupal/drupal/misc/autocomplete.js,v retrieving revision 1.19 diff -u -r1.19 autocomplete.js --- misc/autocomplete.js 8 Jun 2007 12:51:59 -0000 1.19 +++ misc/autocomplete.js 25 Jun 2007 19:28:22 -0000 @@ -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 @@ .attr('autocomplete', 'OFF')[0]; $(input.form).submit(Drupal.autocompleteSubmit); new Drupal.jsAC(input, acdb[uri]); + $(this).addClass('autocomplete-processed'); }); }; @@ -296,8 +297,3 @@ if (this.timer) clearTimeout(this.timer); this.searchString = ''; }; - -// Global Killswitch -if (Drupal.jsEnabled) { - $(document).ready(Drupal.autocompleteAutoAttach); -} Index: misc/batch.js =================================================================== RCS file: /cvs/drupal/drupal/misc/batch.js,v retrieving revision 1.2 diff -u -r1.2 batch.js --- misc/batch.js 1 Jun 2007 09:05:45 -0000 1.2 +++ misc/batch.js 26 Jun 2007 23:02:52 -0000 @@ -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); }); -} +}; Index: misc/collapse.js =================================================================== RCS file: /cvs/drupal/drupal/misc/collapse.js,v retrieving revision 1.13 diff -u -r1.13 collapse.js --- misc/collapse.js 4 Jun 2007 10:36:42 -0000 1.13 +++ misc/collapse.js 26 Jun 2007 20:10:19 -0000 @@ -20,10 +20,6 @@ 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 @@ } }; -// 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($(''+ text +'').click(function() { var fieldset = $(this).parents('fieldset:first')[0]; // Don't animate multiple times @@ -71,7 +65,9 @@ Drupal.toggleFieldset(fieldset); } return false; - })).after($('
').append(fieldset.children(':not(legend)'))); - }); + })) + .after($('') + .append(fieldset.children(':not(legend)'))) + .addClass('collapse-processed'); }); -} +}; Index: misc/drupal.js =================================================================== RCS file: /cvs/drupal/drupal/misc/drupal.js,v retrieving revision 1.34 diff -u -r1.34 drupal.js --- misc/drupal.js 8 Jun 2007 12:51:59 -0000 1.34 +++ misc/drupal.js 30 Jun 2007 22:48:20 -0000 @@ -1,6 +1,6 @@ // $Id: drupal.js,v 1.34 2007/06/08 12:51:59 goba Exp $ -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 @@ }; /** + * 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 @@ document.documentElement.className = 'js'; // 'js enabled' cookie document.cookie = 'has_js=1'; + // Attach all behaviors. + $(document).ready(Drupal.attachBehaviors); } /** Index: misc/tableheader.js =================================================================== RCS file: /cvs/drupal/drupal/misc/tableheader.js,v retrieving revision 1.3 diff -u -r1.3 tableheader.js --- misc/tableheader.js 1 Jun 2007 09:05:45 -0000 1.3 +++ misc/tableheader.js 25 Jun 2007 19:28:26 -0000 @@ -1,60 +1,57 @@ // $Id: tableheader.js,v 1.3 2007/06/01 09:05:45 unconed Exp $ -// 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; - - // Find all header cells. - $('th', this).each(function () { - - // Ensure each cell has an element in it. - var html = $(this).html(); - if (html == ' ') { - html = ' '; - } - if ($(this).children().size() == 0) { - html = ''+ html +''; - } + 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 () { + + // Ensure each cell has an element in it. + var html = $(this).html(); + if (html == ' ') { + html = ' '; + } + if ($(this).children().size() == 0) { + html = ''+ html +''; + } - // Clone and wrap cell contents in sticky wrapper that overlaps the cell's padding. - $('').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'); + // Clone and wrap cell contents in sticky wrapper that overlaps the cell's padding. + $('').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'); - // 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 @@ }, 250); }; $(window).resize(resize); -} +}; Index: misc/tableselect.js =================================================================== RCS file: /cvs/drupal/drupal/misc/tableselect.js,v retrieving revision 1.3 diff -u -r1.3 tableselect.js --- misc/tableselect.js 8 Jun 2007 12:51:59 -0000 1.3 +++ misc/tableselect.js 25 Jun 2007 19:28:15 -0000 @@ -1,5 +1,9 @@ // $Id: tableselect.js,v 1.3 2007/06/08 12:51:59 goba Exp $ +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 @@ // Keep track of the last checked checkbox. lastChecked = e.target; }); + $(this).addClass('tableSelect-processed'); }; Drupal.tableSelectRange = function(from, to, state) { @@ -67,10 +72,3 @@ } }; - -// Global Killswitch -if (Drupal.jsEnabled) { - $(document).ready(function() { - $('form table[th.select-all]').each(Drupal.tableSelect); - }); -} Index: misc/teaser.js =================================================================== RCS file: /cvs/drupal/drupal/misc/teaser.js,v retrieving revision 1.6 diff -u -r1.6 teaser.js --- misc/teaser.js 22 Jun 2007 06:30:11 -0000 1.6 +++ misc/teaser.js 25 Jun 2007 19:28:10 -0000 @@ -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 @@ }); }; - -if (Drupal.jsEnabled) { - $(document).ready(Drupal.teaserAttach); -} Index: misc/textarea.js =================================================================== RCS file: /cvs/drupal/drupal/misc/textarea.js,v retrieving revision 1.15 diff -u -r1.15 textarea.js --- misc/textarea.js 1 Jun 2007 09:05:45 -0000 1.15 +++ misc/textarea.js 25 Jun 2007 19:28:35 -0000 @@ -1,8 +1,8 @@ // $Id: textarea.js,v 1.15 2007/06/01 09:05:45 unconed Exp $ -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 @@ } }); }; - -if (Drupal.jsEnabled) { - $(document).ready(Drupal.textareaAttach); -} Index: misc/upload.js =================================================================== RCS file: /cvs/drupal/drupal/misc/upload.js,v retrieving revision 1.13 diff -u -r1.13 upload.js --- misc/upload.js 8 Jun 2007 12:51:59 -0000 1.13 +++ misc/upload.js 30 Jun 2007 20:53:06 -0000 @@ -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 @@ 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 @@ // 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 @@ $(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 @@ left: '0px' }); }; - - -// Global killswitch -if (Drupal.jsEnabled) { - $(document).ready(Drupal.uploadAutoAttach); -} Index: modules/color/color.js =================================================================== RCS file: /cvs/drupal/drupal/modules/color/color.js,v retrieving revision 1.4 diff -u -r1.4 color.js --- modules/color/color.js 4 Jun 2007 10:36:42 -0000 1.4 +++ modules/color/color.js 25 Jun 2007 19:39:04 -0000 @@ -1,247 +1,251 @@ // $Id: color.js,v 1.4 2007/06/04 10:36:42 goba Exp $ -if (Drupal.jsEnabled) { - $(document).ready(function () { - var form = $('#color_scheme_form .color-form'); - var inputs = []; - var hooks = []; - var locks = []; - var focused = null; - - // Add Farbtastic - $(form).prepend(''); - var farb = $.farbtastic('#placeholder'); - - // Decode reference colors to HSL - var reference = Drupal.settings.color.reference; - for (i in reference) { - reference[i] = farb.RGBToHSL(farb.unpack(reference[i])); - } - - // Build preview - $('#preview').append(''); - var gradient = $('#preview #gradient'); - var h = parseInt(gradient.css('height')) / 10; - for (i = 0; i < h; ++i) { - gradient.append(''); - } - - // Fix preview background in IE6 - if (navigator.appVersion.match(/MSIE [0-6]\./)) { - var e = $('#preview #img')[0]; - var image = e.currentStyle.backgroundImage; - e.style.backgroundImage = 'none'; - e.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image.substring(5, image.length - 2) + "')"; - } - - // Set up colorscheme selector - $('#edit-scheme', form).change(function () { - var colors = this.options[this.selectedIndex].value; - if (colors != '') { - colors = colors.split(','); - for (i in colors) { - callback(inputs[i], colors[i], false, true); - } - preview(); +Drupal.behaviors.color = function (context) { + // This behavior attaches by ID, so is only valid once on a page. + if ($('#color_scheme_form .color-form.color-processed').size()) { + return; + } + var form = $('#color_scheme_form .color-form', context); + var inputs = []; + var hooks = []; + var locks = []; + var focused = null; + + // Add Farbtastic + $(form).prepend('').addClass('color-processed'); + var farb = $.farbtastic('#placeholder'); + + // Decode reference colors to HSL + var reference = Drupal.settings.color.reference; + for (i in reference) { + reference[i] = farb.RGBToHSL(farb.unpack(reference[i])); + } + + // Build preview + $('#preview:not(.color-processed)') + .append('') + .addClass('color-processed'); + var gradient = $('#preview #gradient'); + var h = parseInt(gradient.css('height')) / 10; + for (i = 0; i < h; ++i) { + gradient.append(''); + } + + // Fix preview background in IE6 + if (navigator.appVersion.match(/MSIE [0-6]\./)) { + var e = $('#preview #img')[0]; + var image = e.currentStyle.backgroundImage; + e.style.backgroundImage = 'none'; + e.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image.substring(5, image.length - 2) + "')"; + } + + // Set up colorscheme selector + $('#edit-scheme', form).change(function () { + var colors = this.options[this.selectedIndex].value; + if (colors != '') { + colors = colors.split(','); + for (i in colors) { + callback(inputs[i], colors[i], false, true); } - }); + preview(); + } + }); - /** - * Render the preview. - */ - function preview() { - // Solid background - $('#preview', form).css('backgroundColor', inputs[0].value); - - // Text preview - $('#text', form).css('color', inputs[4].value); - $('#text a, #text h2', form).css('color', inputs[1].value); - - // Set up gradient - var top = farb.unpack(inputs[2].value); - var bottom = farb.unpack(inputs[3].value); - if (top && bottom) { - var delta = []; - for (i in top) { - delta[i] = (bottom[i] - top[i]) / h; + /** + * Render the preview. + */ + function preview() { + // Solid background + $('#preview', form).css('backgroundColor', inputs[0].value); + + // Text preview + $('#text', form).css('color', inputs[4].value); + $('#text a, #text h2', form).css('color', inputs[1].value); + + // Set up gradient + var top = farb.unpack(inputs[2].value); + var bottom = farb.unpack(inputs[3].value); + if (top && bottom) { + var delta = []; + for (i in top) { + delta[i] = (bottom[i] - top[i]) / h; + } + var accum = top; + + // Render gradient lines + $('#gradient > div', form).each(function () { + for (i in accum) { + accum[i] += delta[i]; } - var accum = top; - - // Render gradient lines - $('#gradient > div', form).each(function () { - for (i in accum) { - accum[i] += delta[i]; - } - this.style.backgroundColor = farb.pack(accum); - }); - } + this.style.backgroundColor = farb.pack(accum); + }); } + } - /** - * Shift a given color, using a reference pair (ref in HSL). - * - * This algorithm ensures relative ordering on the saturation and luminance - * axes is preserved, and performs a simple hue shift. - * - * It is also symmetrical. If: shift_color(c, a, b) == d, - * then shift_color(d, b, a) == c. - */ - function shift_color(given, ref1, ref2) { - // Convert to HSL - given = farb.RGBToHSL(farb.unpack(given)); - - // Hue: apply delta - given[0] += ref2[0] - ref1[0]; - - // Saturation: interpolate - if (ref1[1] == 0 || ref2[1] == 0) { - given[1] = ref2[1]; + /** + * Shift a given color, using a reference pair (ref in HSL). + * + * This algorithm ensures relative ordering on the saturation and luminance + * axes is preserved, and performs a simple hue shift. + * + * It is also symmetrical. If: shift_color(c, a, b) == d, + * then shift_color(d, b, a) == c. + */ + function shift_color(given, ref1, ref2) { + // Convert to HSL + given = farb.RGBToHSL(farb.unpack(given)); + + // Hue: apply delta + given[0] += ref2[0] - ref1[0]; + + // Saturation: interpolate + if (ref1[1] == 0 || ref2[1] == 0) { + given[1] = ref2[1]; + } + else { + var d = ref1[1] / ref2[1]; + if (d > 1) { + given[1] /= d; } else { - var d = ref1[1] / ref2[1]; - if (d > 1) { - given[1] /= d; - } - else { - given[1] = 1 - (1 - given[1]) * d; - } + given[1] = 1 - (1 - given[1]) * d; } + } - // Luminance: interpolate - if (ref1[2] == 0 || ref2[2] == 0) { - given[2] = ref2[2]; + // Luminance: interpolate + if (ref1[2] == 0 || ref2[2] == 0) { + given[2] = ref2[2]; + } + else { + var d = ref1[2] / ref2[2]; + if (d > 1) { + given[2] /= d; } else { - var d = ref1[2] / ref2[2]; - if (d > 1) { - given[2] /= d; - } - else { - given[2] = 1 - (1 - given[2]) * d; - } + given[2] = 1 - (1 - given[2]) * d; } - - return farb.pack(farb.HSLToRGB(given)); } - /** - * Callback for Farbtastic when a new color is chosen. - */ - function callback(input, color, propagate, colorscheme) { - // Set background/foreground color - $(input).css({ - backgroundColor: color, - 'color': farb.RGBToHSL(farb.unpack(color))[2] > 0.5 ? '#000' : '#fff' - }); + return farb.pack(farb.HSLToRGB(given)); + } - // Change input value - if (input.value && input.value != color) { - input.value = color; - - // Update locked values - if (propagate) { - var i = input.i; - for (j = i + 1; ; ++j) { - if (!locks[j - 1] || $(locks[j - 1]).is('.unlocked')) break; - var matched = shift_color(color, reference[input.key], reference[inputs[j].key]); - callback(inputs[j], matched, false); - } - for (j = i - 1; ; --j) { - if (!locks[j] || $(locks[j]).is('.unlocked')) break; - var matched = shift_color(color, reference[input.key], reference[inputs[j].key]); - callback(inputs[j], matched, false); - } + /** + * Callback for Farbtastic when a new color is chosen. + */ + function callback(input, color, propagate, colorscheme) { + // Set background/foreground color + $(input).css({ + backgroundColor: color, + 'color': farb.RGBToHSL(farb.unpack(color))[2] > 0.5 ? '#000' : '#fff' + }); - // Update preview - preview(); + // Change input value + if (input.value && input.value != color) { + input.value = color; + + // Update locked values + if (propagate) { + var i = input.i; + for (j = i + 1; ; ++j) { + if (!locks[j - 1] || $(locks[j - 1]).is('.unlocked')) break; + var matched = shift_color(color, reference[input.key], reference[inputs[j].key]); + callback(inputs[j], matched, false); + } + for (j = i - 1; ; --j) { + if (!locks[j] || $(locks[j]).is('.unlocked')) break; + var matched = shift_color(color, reference[input.key], reference[inputs[j].key]); + callback(inputs[j], matched, false); } - // Reset colorscheme selector - if (!colorscheme) { - resetScheme(); - } + // Update preview + preview(); } + // Reset colorscheme selector + if (!colorscheme) { + resetScheme(); + } } - /** - * Reset the color scheme selector. - */ - function resetScheme() { - $('#edit-scheme', form).each(function () { - this.selectedIndex = this.options.length - 1; - }); - } - - // Focus the Farbtastic on a particular field. - function focus() { - var input = this; - // Remove old bindings - focused && $(focused).unbind('keyup', farb.updateValue) - .unbind('keyup', preview).unbind('keyup', resetScheme) - .parent().removeClass('item-selected'); - - // Add new bindings - focused = this; - farb.linkTo(function (color) { callback(input, color, true, false) }); - farb.setColor(this.value); - $(focused).keyup(farb.updateValue).keyup(preview).keyup(resetScheme) - .parent().addClass('item-selected'); - } - - // Initialize color fields - $('#palette input.form-text', form) - .each(function () { - // Extract palette field name - this.key = this.id.substring(13); - - // Link to color picker temporarily to initialize. - farb.linkTo(function () {}).setColor('#000').linkTo(this); - - // Add lock - var i = inputs.length; - if (inputs.length) { - var lock = $('').toggle( - function () { - $(this).addClass('unlocked'); - $(hooks[i - 1]).attr('class', - locks[i - 2] && $(locks[i - 2]).is(':not(.unlocked)') ? 'hook up' : 'hook' - ); - $(hooks[i]).attr('class', - locks[i] && $(locks[i]).is(':not(.unlocked)') ? 'hook down' : 'hook' - ); - }, - function () { - $(this).removeClass('unlocked'); - $(hooks[i - 1]).attr('class', - locks[i - 2] && $(locks[i - 2]).is(':not(.unlocked)') ? 'hook both' : 'hook down' - ); - $(hooks[i]).attr('class', - locks[i] && $(locks[i]).is(':not(.unlocked)') ? 'hook both' : 'hook up' - ); - } - ); - $(this).after(lock); - locks.push(lock); - }; - - // Add hook - var hook = $(''); - $(this).after(hook); - hooks.push(hook); - - $(this).parent().find('.lock').click(); - this.i = i; - inputs.push(this); - }) - .focus(focus); + } - $('#palette label', form); - - // Focus first color - focus.call(inputs[0]); + /** + * Reset the color scheme selector. + */ + function resetScheme() { + $('#edit-scheme', form).each(function () { + this.selectedIndex = this.options.length - 1; + }); + } - // Render preview - preview(); - }); -} + // Focus the Farbtastic on a particular field. + function focus() { + var input = this; + // Remove old bindings + focused && $(focused).unbind('keyup', farb.updateValue) + .unbind('keyup', preview).unbind('keyup', resetScheme) + .parent().removeClass('item-selected'); + + // Add new bindings + focused = this; + farb.linkTo(function (color) { callback(input, color, true, false) }); + farb.setColor(this.value); + $(focused).keyup(farb.updateValue).keyup(preview).keyup(resetScheme) + .parent().addClass('item-selected'); + } + + // Initialize color fields + $('#palette input.form-text', form) + .each(function () { + // Extract palette field name + this.key = this.id.substring(13); + + // Link to color picker temporarily to initialize. + farb.linkTo(function () {}).setColor('#000').linkTo(this); + + // Add lock + var i = inputs.length; + if (inputs.length) { + var lock = $('').toggle( + function () { + $(this).addClass('unlocked'); + $(hooks[i - 1]).attr('class', + locks[i - 2] && $(locks[i - 2]).is(':not(.unlocked)') ? 'hook up' : 'hook' + ); + $(hooks[i]).attr('class', + locks[i] && $(locks[i]).is(':not(.unlocked)') ? 'hook down' : 'hook' + ); + }, + function () { + $(this).removeClass('unlocked'); + $(hooks[i - 1]).attr('class', + locks[i - 2] && $(locks[i - 2]).is(':not(.unlocked)') ? 'hook both' : 'hook down' + ); + $(hooks[i]).attr('class', + locks[i] && $(locks[i]).is(':not(.unlocked)') ? 'hook both' : 'hook up' + ); + } + ); + $(this).after(lock); + locks.push(lock); + }; + + // Add hook + var hook = $(''); + $(this).after(hook); + hooks.push(hook); + + $(this).parent().find('.lock').click(); + this.i = i; + inputs.push(this); + }) + .focus(focus); + + $('#palette label', form); + + // Focus first color + focus.call(inputs[0]); + + // Render preview + preview(); +}; Index: modules/comment/comment.js =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.js,v retrieving revision 1.2 diff -u -r1.2 comment.js --- modules/comment/comment.js 20 May 2007 12:34:47 -0000 1.2 +++ modules/comment/comment.js 25 Jun 2007 19:30:31 -0000 @@ -1,15 +1,16 @@ // $Id: comment.js,v 1.2 2007/05/20 12:34:47 dries Exp $ -if (Drupal.jsEnabled) { - $(document).ready(function() { - var parts = new Array("name", "homepage", "mail"); - var cookie = ''; - for (i=0;i<3;i++) { - cookie = Drupal.comment.getCookie('comment_info_' + parts[i]); - if (cookie != '') { - $("#comment-form input[@name=" + parts[i] + "]").val(cookie); - } + +Drupal.behaviors.comment = function (context) { + var parts = new Array("name", "homepage", "mail"); + var cookie = ''; + for (i=0;i<3;i++) { + cookie = Drupal.comment.getCookie('comment_info_' + parts[i]); + if (cookie != '') { + $("#comment-form input[@name=" + parts[i] + "]:not(.comment-processed)", context) + .val(cookie) + .addClass('comment-processed'); } - }); + } }; Drupal.comment = {}; Index: modules/openid/openid.js =================================================================== RCS file: /cvs/drupal/drupal/modules/openid/openid.js,v retrieving revision 1.1 diff -u -r1.1 openid.js --- modules/openid/openid.js 18 Jun 2007 16:09:39 -0000 1.1 +++ modules/openid/openid.js 25 Jun 2007 20:04:34 -0000 @@ -1,14 +1,17 @@ // $Id: openid.js,v 1.1 2007/06/18 16:09:39 dries Exp $ -$(document).ready( - function() { - if ($("#edit-openid-url").val()) { - $("#edit-name-wrapper").hide(); - $("#edit-pass-wrapper").hide(); - $("#edit-openid-url-wrapper").show(); - $("a.openid-link").hide(); - } - $("a.openid-link").click( function() { +Drupal.behaviors.openid = function (context) { + // This behavior attaches by ID, so is only valid once on a page. + if (!$("#edit-openid-url.openid-processed").size() && $("#edit-openid-url").val()) { + $("#edit-openid-url").addClass('openid-processed'); + $("#edit-name-wrapper").hide(); + $("#edit-pass-wrapper").hide(); + $("#edit-openid-url-wrapper").show(); + $("a.openid-link").hide(); + } + $("a.openid-link:not(.openid-processed)", context) + .addClass('openid-processed') + .click( function() { $("#edit-pass-wrapper").hide(); $("#edit-name-wrapper").fadeOut('medium', function() { $("#edit-openid-url-wrapper").fadeIn('medium'); @@ -17,7 +20,9 @@ $("a.user-link").show(); return false; }); - $("a.user-link").click( function() { + $("a.user-link:not(.openid-processed)", context) + .addClass('openid-processed') + .click(function() { $("#edit-openid-url-wrapper").hide(); $("#edit-pass-wrapper").show(); $("#edit-name-wrapper").show(); @@ -25,5 +30,5 @@ $("a.openid-link").show(); return false; }); - }); +}; Index: modules/system/system.js =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.js,v retrieving revision 1.8 diff -u -r1.8 system.js --- modules/system/system.js 8 Jun 2007 12:51:59 -0000 1.8 +++ modules/system/system.js 26 Jun 2007 21:02:48 -0000 @@ -7,7 +7,13 @@ * This function is not used to verify whether or not clean URLs * are currently enabled. */ -Drupal.cleanURLsSettingsCheck = function() { +Drupal.behaviors.cleanURLsSettingsCheck = function(context) { + // 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 + // the processing. + if ($("#clean-url.clean-url-processed, #clean-url.install").size()) { + return; + } var url = location.pathname +"admin/settings/clean-urls"; $("#clean-url .description span").html('