webmaster@1: // $Id: ahah.js,v 1.7.2.1 2008/02/11 14:46:27 goba Exp $ webmaster@1: webmaster@1: /** webmaster@1: * Provides AJAX-like page updating via AHAH (Asynchronous HTML and HTTP). webmaster@1: * webmaster@1: * AHAH is a method of making a request via Javascript while viewing an HTML webmaster@1: * page. The request returns a small chunk of HTML, which is then directly webmaster@1: * injected into the page. webmaster@1: * webmaster@1: * Drupal uses this file to enhance form elements with #ahah[path] and webmaster@1: * #ahah[wrapper] properties. If set, this file will automatically be included webmaster@1: * to provide AHAH capabilities. webmaster@1: */ webmaster@1: webmaster@1: /** webmaster@1: * Attaches the ahah behavior to each ahah form element. webmaster@1: */ webmaster@1: Drupal.behaviors.ahah = function(context) { webmaster@1: for (var base in Drupal.settings.ahah) { webmaster@1: if (!$('#'+ base + '.ahah-processed').size()) { webmaster@1: var element_settings = Drupal.settings.ahah[base]; webmaster@1: webmaster@1: $(element_settings.selector).each(function() { webmaster@1: element_settings.element = this; webmaster@1: var ahah = new Drupal.ahah(base, element_settings); webmaster@1: }); webmaster@1: webmaster@1: $('#'+ base).addClass('ahah-processed'); webmaster@1: } webmaster@1: } webmaster@1: }; webmaster@1: webmaster@1: /** webmaster@1: * AHAH object. webmaster@1: */ webmaster@1: Drupal.ahah = function(base, element_settings) { webmaster@1: // Set the properties for this object. webmaster@1: this.element = element_settings.element; webmaster@1: this.selector = element_settings.selector; webmaster@1: this.event = element_settings.event; webmaster@1: this.keypress = element_settings.keypress; webmaster@1: this.url = element_settings.url; webmaster@1: this.wrapper = '#'+ element_settings.wrapper; webmaster@1: this.effect = element_settings.effect; webmaster@1: this.method = element_settings.method; webmaster@1: this.progress = element_settings.progress; webmaster@1: this.button = element_settings.button || { }; webmaster@1: webmaster@1: if (this.effect == 'none') { webmaster@1: this.showEffect = 'show'; webmaster@1: this.hideEffect = 'hide'; webmaster@1: this.showSpeed = ''; webmaster@1: } webmaster@1: else if (this.effect == 'fade') { webmaster@1: this.showEffect = 'fadeIn'; webmaster@1: this.hideEffect = 'fadeOut'; webmaster@1: this.showSpeed = 'slow'; webmaster@1: } webmaster@1: else { webmaster@1: this.showEffect = this.effect + 'Toggle'; webmaster@1: this.hideEffect = this.effect + 'Toggle'; webmaster@1: this.showSpeed = 'slow'; webmaster@1: } webmaster@1: webmaster@1: // Record the form action and target, needed for iFrame file uploads. webmaster@1: var form = $(this.element).parents('form'); webmaster@1: this.form_action = form.attr('action'); webmaster@1: this.form_target = form.attr('target'); webmaster@1: this.form_encattr = form.attr('encattr'); webmaster@1: webmaster@1: // Set the options for the ajaxSubmit function. webmaster@1: // The 'this' variable will not persist inside of the options object. webmaster@1: var ahah = this; webmaster@1: var options = { webmaster@1: url: ahah.url, webmaster@1: data: ahah.button, webmaster@1: beforeSubmit: function(form_values, element_settings, options) { webmaster@1: return ahah.beforeSubmit(form_values, element_settings, options); webmaster@1: }, webmaster@1: success: function(response, status) { webmaster@1: // Sanity check for browser support (object expected). webmaster@1: // When using iFrame uploads, responses must be returned as a string. webmaster@1: if (typeof(response) == 'string') { webmaster@1: response = Drupal.parseJson(response); webmaster@1: } webmaster@1: return ahah.success(response, status); webmaster@1: }, webmaster@1: complete: function(response, status) { webmaster@1: if (status == 'error' || status == 'parsererror') { webmaster@1: return ahah.error(response, ahah.url); webmaster@1: } webmaster@1: }, webmaster@1: dataType: 'json', webmaster@1: type: 'POST' webmaster@1: }; webmaster@1: webmaster@1: // Bind the ajaxSubmit function to the element event. webmaster@1: $(element_settings.element).bind(element_settings.event, function() { webmaster@1: $(element_settings.element).parents('form').ajaxSubmit(options); webmaster@1: return false; webmaster@1: }); webmaster@1: // If necessary, enable keyboard submission so that AHAH behaviors webmaster@1: // can be triggered through keyboard input as well as e.g. a mousedown webmaster@1: // action. webmaster@1: if (element_settings.keypress) { webmaster@1: $(element_settings.element).keypress(function(event) { webmaster@1: // Detect enter key. webmaster@1: if (event.keyCode == 13) { webmaster@1: $(element_settings.element).trigger(element_settings.event); webmaster@1: return false; webmaster@1: } webmaster@1: }); webmaster@1: } webmaster@1: }; webmaster@1: webmaster@1: /** webmaster@1: * Handler for the form redirection submission. webmaster@1: */ webmaster@1: Drupal.ahah.prototype.beforeSubmit = function (form_values, element, options) { webmaster@1: // Disable the element that received the change. webmaster@1: $(this.element).addClass('progress-disabled').attr('disabled', true); webmaster@1: webmaster@1: // Insert progressbar or throbber. webmaster@1: if (this.progress.type == 'bar') { webmaster@1: var progressBar = new Drupal.progressBar('ahah-progress-' + this.element.id, eval(this.progress.update_callback), this.progress.method, eval(this.progress.error_callback)); webmaster@1: if (this.progress.message) { webmaster@1: progressBar.setProgress(-1, this.progress.message); webmaster@1: } webmaster@1: if (this.progress.url) { webmaster@1: progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500); webmaster@1: } webmaster@1: this.progress.element = $(progressBar.element).addClass('ahah-progress ahah-progress-bar'); webmaster@1: this.progress.object = progressBar; webmaster@1: $(this.element).after(this.progress.element); webmaster@1: } webmaster@1: else if (this.progress.type == 'throbber') { webmaster@1: this.progress.element = $('
 
'); webmaster@1: if (this.progress.message) { webmaster@1: $('.throbber', this.progress.element).after('
' + this.progress.message + '
') webmaster@1: } webmaster@1: $(this.element).after(this.progress.element); webmaster@1: } webmaster@1: }; webmaster@1: webmaster@1: /** webmaster@1: * Handler for the form redirection completion. webmaster@1: */ webmaster@1: Drupal.ahah.prototype.success = function (response, status) { webmaster@1: var wrapper = $(this.wrapper); webmaster@1: var form = $(this.element).parents('form'); webmaster@1: // Manually insert HTML into the jQuery object, using $() directly crashes webmaster@1: // Safari with long string lengths. http://dev.jquery.com/ticket/1152 webmaster@1: var new_content = $('
').html(response.data); webmaster@1: webmaster@1: // Restore the previous action and target to the form. webmaster@1: form.attr('action', this.form_action); webmaster@1: this.form_target ? form.attr('target', this.form_target) : form.removeAttr('target'); webmaster@1: this.form_encattr ? form.attr('target', this.form_encattr) : form.removeAttr('encattr'); webmaster@1: webmaster@1: // Remove the progress element. webmaster@1: if (this.progress.element) { webmaster@1: $(this.progress.element).remove(); webmaster@1: } webmaster@1: if (this.progress.object) { webmaster@1: this.progress.object.stopMonitoring(); webmaster@1: } webmaster@1: $(this.element).removeClass('progress-disabled').attr('disabled', false); webmaster@1: webmaster@1: // Add the new content to the page. webmaster@1: Drupal.freezeHeight(); webmaster@1: if (this.method == 'replace') { webmaster@1: wrapper.empty().append(new_content); webmaster@1: } webmaster@1: else { webmaster@1: wrapper[this.method](new_content); webmaster@1: } webmaster@1: webmaster@1: // Immediately hide the new content if we're using any effects. webmaster@1: if (this.showEffect != 'show') { webmaster@1: new_content.hide(); webmaster@1: } webmaster@1: webmaster@1: // Determine what effect use and what content will receive the effect, then webmaster@1: // show the new content. For browser compatibility, Safari is excluded from webmaster@1: // using effects on table rows. webmaster@1: if (($.browser.safari && $("tr.ahah-new-content", new_content).size() > 0)) { webmaster@1: new_content.show(); webmaster@1: } webmaster@1: else if ($('.ahah-new-content', new_content).size() > 0) { webmaster@1: $('.ahah-new-content', new_content).hide(); webmaster@1: new_content.show(); webmaster@1: $(".ahah-new-content", new_content)[this.showEffect](this.showSpeed); webmaster@1: } webmaster@1: else if (this.showEffect != 'show') { webmaster@1: new_content[this.showEffect](this.showSpeed); webmaster@1: } webmaster@1: webmaster@1: // Attach all javascript behaviors to the new content, if it was successfully webmaster@1: // added to the page, this if statement allows #ahah[wrapper] to be optional. webmaster@1: if (new_content.parents('html').length > 0) { webmaster@1: Drupal.attachBehaviors(new_content); webmaster@1: } webmaster@1: webmaster@1: Drupal.unfreezeHeight(); webmaster@1: }; webmaster@1: webmaster@1: /** webmaster@1: * Handler for the form redirection error. webmaster@1: */ webmaster@1: Drupal.ahah.prototype.error = function (response, uri) { webmaster@1: alert(Drupal.ahahError(response, uri)); webmaster@1: // Resore the previous action and target to the form. webmaster@1: $(this.element).parent('form').attr( { action: this.form_action, target: this.form_target} ); webmaster@1: // Remove the progress element. webmaster@1: if (this.progress.element) { webmaster@1: $(this.progress.element).remove(); webmaster@1: } webmaster@1: if (this.progress.object) { webmaster@1: this.progress.object.stopMonitoring(); webmaster@1: } webmaster@1: // Undo hide. webmaster@1: $(this.wrapper).show(); webmaster@1: // Re-enable the element. webmaster@1: $(this.element).removeClass('progess-disabled').attr('disabled', false); webmaster@1: };