Mercurial > defr > drupal > core
diff misc/ahah.js @ 1:c1f4ac30525a 6.0
Drupal 6.0
author | Franck Deroche <webmaster@defr.org> |
---|---|
date | Tue, 23 Dec 2008 14:28:28 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/ahah.js Tue Dec 23 14:28:28 2008 +0100 @@ -0,0 +1,225 @@ +// $Id: ahah.js,v 1.7.2.1 2008/02/11 14:46:27 goba Exp $ + +/** + * Provides AJAX-like page updating via AHAH (Asynchronous HTML and HTTP). + * + * AHAH is a method of making a request via Javascript while viewing an HTML + * 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 + * to provide AHAH capabilities. + */ + +/** + * Attaches the ahah behavior to each ahah form element. + */ +Drupal.behaviors.ahah = function(context) { + for (var base in Drupal.settings.ahah) { + if (!$('#'+ base + '.ahah-processed').size()) { + 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'); + } + } +}; + +/** + * AHAH object. + */ +Drupal.ahah = function(base, element_settings) { + // Set the properties for this object. + this.element = element_settings.element; + this.selector = element_settings.selector; + this.event = element_settings.event; + this.keypress = element_settings.keypress; + this.url = element_settings.url; + this.wrapper = '#'+ element_settings.wrapper; + this.effect = element_settings.effect; + this.method = element_settings.method; + this.progress = element_settings.progress; + this.button = element_settings.button || { }; + + 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'; + } + + // 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, + data: ahah.button, + 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' || status == 'parsererror') { + return ahah.error(response, ahah.url); + } + }, + 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; + }); + // If necessary, enable keyboard submission so that AHAH behaviors + // can be triggered through keyboard input as well as e.g. a mousedown + // action. + if (element_settings.keypress) { + $(element_settings.element).keypress(function(event) { + // Detect enter key. + if (event.keyCode == 13) { + $(element_settings.element).trigger(element_settings.event); + return false; + } + }); + } +}; + +/** + * Handler for the form redirection submission. + */ +Drupal.ahah.prototype.beforeSubmit = function (form_values, element, options) { + // Disable the element that received the change. + $(this.element).addClass('progress-disabled').attr('disabled', true); + + // Insert progressbar or throbber. + if (this.progress.type == 'bar') { + var progressBar = new Drupal.progressBar('ahah-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('ahah-progress ahah-progress-bar'); + this.progress.object = progressBar; + $(this.element).after(this.progress.element); + } + else if (this.progress.type == 'throbber') { + this.progress.element = $('<div class="ahah-progress ahah-progress-throbber"><div class="throbber"> </div></div>'); + if (this.progress.message) { + $('.throbber', this.progress.element).after('<div class="message">' + this.progress.message + '</div>') + } + $(this.element).after(this.progress.element); + } +}; + +/** + * Handler for the form redirection completion. + */ +Drupal.ahah.prototype.success = function (response, status) { + var wrapper = $(this.wrapper); + var form = $(this.element).parents('form'); + // 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); + + // 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. + if (this.progress.element) { + $(this.progress.element).remove(); + } + if (this.progress.object) { + this.progress.object.stopMonitoring(); + } + $(this.element).removeClass('progress-disabled').attr('disabled', false); + + // Add the new content to the page. + Drupal.freezeHeight(); + if (this.method == 'replace') { + wrapper.empty().append(new_content); + } + else { + wrapper[this.method](new_content); + } + + // Immediately hide the new content if we're using any effects. + if (this.showEffect != 'show') { + new_content.hide(); + } + + // 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 (($.browser.safari && $("tr.ahah-new-content", new_content).size() > 0)) { + new_content.show(); + } + else if ($('.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); + } + + Drupal.unfreezeHeight(); +}; + +/** + * Handler for the form redirection error. + */ +Drupal.ahah.prototype.error = function (response, uri) { + alert(Drupal.ahahError(response, uri)); + // Resore the previous action and target to the form. + $(this.element).parent('form').attr( { action: this.form_action, target: this.form_target} ); + // Remove the progress element. + if (this.progress.element) { + $(this.progress.element).remove(); + } + if (this.progress.object) { + this.progress.object.stopMonitoring(); + } + // Undo hide. + $(this.wrapper).show(); + // Re-enable the element. + $(this.element).removeClass('progess-disabled').attr('disabled', false); +};