diff options
author | Gábor Hojtsy <gabor@hojtsy.hu> | 2007-10-05 09:35:09 +0000 |
---|---|---|
committer | Gábor Hojtsy <gabor@hojtsy.hu> | 2007-10-05 09:35:09 +0000 |
commit | 31b73898af536da873e12cc0cf6f3a4ee7b7d9cc (patch) | |
tree | dd33ce8708f6b929a11b79ae90a2a6957afbe54f /misc | |
parent | 5fc06cec4c440ac21b3913c0c9b0c892a6091bb9 (diff) | |
download | brdo-31b73898af536da873e12cc0cf6f3a4ee7b7d9cc.tar.gz brdo-31b73898af536da873e12cc0cf6f3a4ee7b7d9cc.tar.bz2 |
#157752 by quicksketch: extend AHAH functionality to most types of form elements, without writing JavaScript. Also AHAH enable the blocks admin page.
Diffstat (limited to 'misc')
-rw-r--r-- | misc/ahah.js | 136 | ||||
-rw-r--r-- | misc/drupal.js | 102 |
2 files changed, 104 insertions, 134 deletions
diff --git a/misc/ahah.js b/misc/ahah.js index 87ab19404..af226ced4 100644 --- a/misc/ahah.js +++ b/misc/ahah.js @@ -7,8 +7,8 @@ * page. The request returns a small chunk of HTML, which is then directly * injected into the page. * - * Drupal uses this file to enhance form elements with #ahah_path and - * #ahah_wrapper properties. If set, this file will automatically be included + * Drupal uses this file to enhance form elements with #ahah[path] and + * #ahah[wrapper] properties. If set, this file will automatically be included * to provide AHAH capabilities. */ @@ -18,8 +18,13 @@ Drupal.behaviors.ahah = function(context) { for (var base in Drupal.settings.ahah) { if (!$('#'+ base + '.ahah-processed').size()) { - var element = Drupal.settings.ahah[base]; - var ahah = new Drupal.ahah(base, element); + var element_settings = Drupal.settings.ahah[base]; + + $(element_settings.selector).each(function() { + element_settings.element = this; + var ahah = new Drupal.ahah(base, element_settings); + }); + $('#'+ base).addClass('ahah-processed'); } } @@ -28,95 +33,148 @@ Drupal.behaviors.ahah = function(context) { /** * AHAH object. */ -Drupal.ahah = function(base, element) { +Drupal.ahah = function(base, element_settings) { // Set the properties for this object. - this.id = '#' + base; - this.event = element.event; - this.uri = element.uri; - this.wrapper = '#'+ element.wrapper; - this.effect = element.effect; - this.method = element.method; + this.element = element_settings.element; + this.selector = element_settings.selector; + this.event = element_settings.event; + this.url = element_settings.url; + this.wrapper = '#'+ element_settings.wrapper; + this.effect = element_settings.effect; + this.method = element_settings.method; if (this.effect == 'none') { this.showEffect = 'show'; this.hideEffect = 'hide'; + this.showSpeed = ''; } else if (this.effect == 'fade') { this.showEffect = 'fadeIn'; this.hideEffect = 'fadeOut'; + this.showSpeed = 'slow'; } else { this.showEffect = this.effect + 'Toggle'; this.hideEffect = this.effect + 'Toggle'; + this.showSpeed = 'slow'; } - Drupal.redirectFormButton(this.uri, $(this.id).get(0), this); + + // Record the form action and target, needed for iFrame file uploads. + var form = $(this.element).parents('form'); + this.form_action = form.attr('action'); + this.form_target = form.attr('target'); + this.form_encattr = form.attr('encattr'); + + // Set the options for the ajaxSubmit function. + // The 'this' variable will not persist inside of the options object. + var ahah = this; + var options = { + url: ahah.url, + beforeSubmit: function(form_values, element_settings, options) { + return ahah.beforeSubmit(form_values, element_settings, options); + }, + success: function(response, status) { + // Sanity check for browser support (object expected). + // When using iFrame uploads, responses must be returned as a string. + if (typeof(response) == 'string') { + response = Drupal.parseJson(response); + } + return ahah.success(response, status); + }, + complete: function(response, status) { + if (status == 'error') { + return ahah.error(response.responseText); + } + }, + dataType: 'json', + type: 'POST' + }; + + // Bind the ajaxSubmit function to the element event. + $(element_settings.element).bind(element_settings.event, function() { + $(element_settings.element).parents('form').ajaxSubmit(options); + return false; + }); }; /** * Handler for the form redirection submission. */ -Drupal.ahah.prototype.onsubmit = function () { +Drupal.ahah.prototype.beforeSubmit = function (form_values, element, options) { // Insert progressbar and stretch to take the same space. this.progress = new Drupal.progressBar('ahah_progress'); this.progress.setProgress(-1, Drupal.t('Please wait...')); - var wrapper = $(this.wrapper); - var button = $(this.id); - var progress_element = $(this.progress.element); - - progress_element.css('float', 'left').css({ - display: 'none', - width: '10em', - margin: '0 0 0 20px' - }); - button.css('float', 'left').attr('disabled', true).after(progress_element); - if (progress_element[this.showEffect]) { - progress_element[this.showEffect](); - } + var progress_element = $(this.progress.element).addClass('ahah-progress'); + $(this.element).addClass('progress-disabled').attr('disabled', true).after(progress_element); }; /** * Handler for the form redirection completion. */ -Drupal.ahah.prototype.oncomplete = function (data) { +Drupal.ahah.prototype.success = function (response, status) { var wrapper = $(this.wrapper); - var button = $(this.id); + var form = $(this.element).parents('form'); var progress_element = $(this.progress.element); - var new_content = $('<div>' + data + '</div>'); + // Manually insert HTML into the jQuery object, using $() directly crashes + // Safari with long string lengths. http://dev.jquery.com/ticket/1152 + var new_content = $('<div></div>').html(response.data); - Drupal.freezeHeight(); + // Restore the previous action and target to the form. + form.attr('action', this.form_action); + this.form_target ? form.attr('target', this.form_target) : form.removeAttr('target'); + this.form_encattr ? form.attr('target', this.form_encattr) : form.removeAttr('encattr'); // Remove the progress element. progress_element.remove(); + $(this.element).removeClass('progess-disabled').attr('disabled', false); // Hide the new content before adding to page. - new_content.hide(); + if (this.showEffect != 'show') { + new_content.hide(); + } - // Add the form and re-attach behavior. + // Add the new content to the page. + Drupal.freezeHeight(); if (this.method == 'replace') { wrapper.empty().append(new_content); } - else if (wrapper[this.method]) { + else { wrapper[this.method](new_content); } - if (new_content[this.showEffect]) { - new_content[this.showEffect](); + + // Determine what effect use and what content will receive the effect, then + // show the new content. For browser compatibility, Safari is excluded from + // using effects on table rows. + if ($('.ahah-new-content', new_content).size() > 0 && !($.browser.safari && $("tr.ahah-new-content", new_content).size() > 0)) { + $('.ahah-new-content', new_content).hide(); + new_content.show(); + $(".ahah-new-content", new_content)[this.showEffect](this.showSpeed); + } + else if (this.showEffect != 'show') { + new_content[this.showEffect](this.showSpeed); + } + + // Attach all javascript behaviors to the new content, if it was successfully + // added to the page, this if statement allows #ahah[wrapper] to be optional. + if (new_content.parents('html').length > 0) { + Drupal.attachBehaviors(new_content); } - button.css('float', 'none').attr('disabled', false); - Drupal.attachBehaviors(new_content); Drupal.unfreezeHeight(); }; /** * Handler for the form redirection error. */ -Drupal.ahah.prototype.onerror = function (error) { +Drupal.ahah.prototype.error = function (error) { alert(Drupal.t('An error occurred:\n\n@error', { '@error': error })); + // Resore the previous action and target to the form. + element.parent('form').attr( { action: this.form_action, target: this.form_target} ); // Remove progressbar. $(this.progress.element).remove(); this.progress = null; // Undo hide. $(this.wrapper).show(); // Re-enable the element. - $(this.id).css('float', 'none').attr('disabled', false); + $(this.element).removeClass('progess-disabled').attr('disabled', false); }; diff --git a/misc/drupal.js b/misc/drupal.js index c7e955aae..edf621101 100644 --- a/misc/drupal.js +++ b/misc/drupal.js @@ -181,103 +181,15 @@ Drupal.theme = function(func) { }; /** - * Redirects a button's form submission to a hidden iframe and displays the result - * in a given wrapper. The iframe should contain a call to - * window.parent.iframeHandler() after submission. - */ -Drupal.redirectFormButton = function (uri, button, handler) { - // Trap the button - button.onmouseover = button.onfocus = function() { - button.onclick = function() { - // Create target iframe - Drupal.deleteIframe(); - Drupal.createIframe(); - - // Prepare variables for use in anonymous function. - var button = this; - var action = button.form.action; - var target = button.form.target; - - // Redirect form submission to iframe - this.form.action = uri; - this.form.target = 'redirect-target'; - this.form.submit(); - - handler.onsubmit(); - - // Set iframe handler for later - window.iframeHandler = function () { - var iframe = $('#redirect-target').get(0); - // Restore form submission - button.form.action = action; - button.form.target = target; - - // Get response from iframe body - try { - response = (iframe.contentWindow || iframe.contentDocument || iframe).document.body.innerHTML; - // Firefox 1.0.x hack: Remove (corrupted) control characters - response = response.replace(/[\f\n\r\t]/g, ' '); - if (window.opera) { - // Opera-hack: it returns innerHTML sanitized. - response = response.replace(/"/g, '"'); - } - } - catch (e) { - response = null; - } - - response = eval('('+ response +');'); - // Check response code - if (!response || response.status == 0) { - handler.onerror(response.data || Drupal.t('Error parsing response')); - return; - } - handler.oncomplete(response.data); - - return true; - }; - - return true; - }; - }; - button.onmouseout = button.onblur = function() { - button.onclick = null; - }; -}; - -/** - * Create an invisible iframe for form submissions. + * Parse a JSON response. + * + * The result is either the JSON object, or an object with 'status' 0 and 'data' an error message. */ -Drupal.createIframe = function () { - if ($('#redirect-holder').size()) { - return; +Drupal.parseJson = function (data) { + if ((data.substring(0, 1) != '{') && (data.substring(0, 1) != '[')) { + return { status: 0, data: data.length ? data : Drupal.t('Unspecified error') }; } - // Note: some browsers require the literal name/id attributes on the tag, - // some want them set through JS. We do both. - window.iframeHandler = function () {}; - var div = document.createElement('div'); - div.id = 'redirect-holder'; - $(div).html('<iframe name="redirect-target" id="redirect-target" class="redirect" onload="window.iframeHandler();"></iframe>'); - var iframe = div.firstChild; - $(iframe) - .attr({ - name: 'redirect-target', - id: 'redirect-target' - }) - .css({ - position: 'absolute', - height: '1px', - width: '1px', - visibility: 'hidden' - }); - $('body').append(div); -}; - -/** - * Delete the invisible iframe - */ -Drupal.deleteIframe = function () { - $('#redirect-holder').remove(); + return eval('(' + data + ');'); }; /** |