annotate misc/ahah.js @ 20:e3d20ebd63d1 tip

Added tag 6.9 for changeset 3edae6ecd6c6
author Franck Deroche <franck@defr.org>
date Thu, 15 Jan 2009 10:16:10 +0100
parents c1f4ac30525a
children
rev   line source
webmaster@1 1 // $Id: ahah.js,v 1.7.2.1 2008/02/11 14:46:27 goba Exp $
webmaster@1 2
webmaster@1 3 /**
webmaster@1 4 * Provides AJAX-like page updating via AHAH (Asynchronous HTML and HTTP).
webmaster@1 5 *
webmaster@1 6 * AHAH is a method of making a request via Javascript while viewing an HTML
webmaster@1 7 * page. The request returns a small chunk of HTML, which is then directly
webmaster@1 8 * injected into the page.
webmaster@1 9 *
webmaster@1 10 * Drupal uses this file to enhance form elements with #ahah[path] and
webmaster@1 11 * #ahah[wrapper] properties. If set, this file will automatically be included
webmaster@1 12 * to provide AHAH capabilities.
webmaster@1 13 */
webmaster@1 14
webmaster@1 15 /**
webmaster@1 16 * Attaches the ahah behavior to each ahah form element.
webmaster@1 17 */
webmaster@1 18 Drupal.behaviors.ahah = function(context) {
webmaster@1 19 for (var base in Drupal.settings.ahah) {
webmaster@1 20 if (!$('#'+ base + '.ahah-processed').size()) {
webmaster@1 21 var element_settings = Drupal.settings.ahah[base];
webmaster@1 22
webmaster@1 23 $(element_settings.selector).each(function() {
webmaster@1 24 element_settings.element = this;
webmaster@1 25 var ahah = new Drupal.ahah(base, element_settings);
webmaster@1 26 });
webmaster@1 27
webmaster@1 28 $('#'+ base).addClass('ahah-processed');
webmaster@1 29 }
webmaster@1 30 }
webmaster@1 31 };
webmaster@1 32
webmaster@1 33 /**
webmaster@1 34 * AHAH object.
webmaster@1 35 */
webmaster@1 36 Drupal.ahah = function(base, element_settings) {
webmaster@1 37 // Set the properties for this object.
webmaster@1 38 this.element = element_settings.element;
webmaster@1 39 this.selector = element_settings.selector;
webmaster@1 40 this.event = element_settings.event;
webmaster@1 41 this.keypress = element_settings.keypress;
webmaster@1 42 this.url = element_settings.url;
webmaster@1 43 this.wrapper = '#'+ element_settings.wrapper;
webmaster@1 44 this.effect = element_settings.effect;
webmaster@1 45 this.method = element_settings.method;
webmaster@1 46 this.progress = element_settings.progress;
webmaster@1 47 this.button = element_settings.button || { };
webmaster@1 48
webmaster@1 49 if (this.effect == 'none') {
webmaster@1 50 this.showEffect = 'show';
webmaster@1 51 this.hideEffect = 'hide';
webmaster@1 52 this.showSpeed = '';
webmaster@1 53 }
webmaster@1 54 else if (this.effect == 'fade') {
webmaster@1 55 this.showEffect = 'fadeIn';
webmaster@1 56 this.hideEffect = 'fadeOut';
webmaster@1 57 this.showSpeed = 'slow';
webmaster@1 58 }
webmaster@1 59 else {
webmaster@1 60 this.showEffect = this.effect + 'Toggle';
webmaster@1 61 this.hideEffect = this.effect + 'Toggle';
webmaster@1 62 this.showSpeed = 'slow';
webmaster@1 63 }
webmaster@1 64
webmaster@1 65 // Record the form action and target, needed for iFrame file uploads.
webmaster@1 66 var form = $(this.element).parents('form');
webmaster@1 67 this.form_action = form.attr('action');
webmaster@1 68 this.form_target = form.attr('target');
webmaster@1 69 this.form_encattr = form.attr('encattr');
webmaster@1 70
webmaster@1 71 // Set the options for the ajaxSubmit function.
webmaster@1 72 // The 'this' variable will not persist inside of the options object.
webmaster@1 73 var ahah = this;
webmaster@1 74 var options = {
webmaster@1 75 url: ahah.url,
webmaster@1 76 data: ahah.button,
webmaster@1 77 beforeSubmit: function(form_values, element_settings, options) {
webmaster@1 78 return ahah.beforeSubmit(form_values, element_settings, options);
webmaster@1 79 },
webmaster@1 80 success: function(response, status) {
webmaster@1 81 // Sanity check for browser support (object expected).
webmaster@1 82 // When using iFrame uploads, responses must be returned as a string.
webmaster@1 83 if (typeof(response) == 'string') {
webmaster@1 84 response = Drupal.parseJson(response);
webmaster@1 85 }
webmaster@1 86 return ahah.success(response, status);
webmaster@1 87 },
webmaster@1 88 complete: function(response, status) {
webmaster@1 89 if (status == 'error' || status == 'parsererror') {
webmaster@1 90 return ahah.error(response, ahah.url);
webmaster@1 91 }
webmaster@1 92 },
webmaster@1 93 dataType: 'json',
webmaster@1 94 type: 'POST'
webmaster@1 95 };
webmaster@1 96
webmaster@1 97 // Bind the ajaxSubmit function to the element event.
webmaster@1 98 $(element_settings.element).bind(element_settings.event, function() {
webmaster@1 99 $(element_settings.element).parents('form').ajaxSubmit(options);
webmaster@1 100 return false;
webmaster@1 101 });
webmaster@1 102 // If necessary, enable keyboard submission so that AHAH behaviors
webmaster@1 103 // can be triggered through keyboard input as well as e.g. a mousedown
webmaster@1 104 // action.
webmaster@1 105 if (element_settings.keypress) {
webmaster@1 106 $(element_settings.element).keypress(function(event) {
webmaster@1 107 // Detect enter key.
webmaster@1 108 if (event.keyCode == 13) {
webmaster@1 109 $(element_settings.element).trigger(element_settings.event);
webmaster@1 110 return false;
webmaster@1 111 }
webmaster@1 112 });
webmaster@1 113 }
webmaster@1 114 };
webmaster@1 115
webmaster@1 116 /**
webmaster@1 117 * Handler for the form redirection submission.
webmaster@1 118 */
webmaster@1 119 Drupal.ahah.prototype.beforeSubmit = function (form_values, element, options) {
webmaster@1 120 // Disable the element that received the change.
webmaster@1 121 $(this.element).addClass('progress-disabled').attr('disabled', true);
webmaster@1 122
webmaster@1 123 // Insert progressbar or throbber.
webmaster@1 124 if (this.progress.type == 'bar') {
webmaster@1 125 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 126 if (this.progress.message) {
webmaster@1 127 progressBar.setProgress(-1, this.progress.message);
webmaster@1 128 }
webmaster@1 129 if (this.progress.url) {
webmaster@1 130 progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500);
webmaster@1 131 }
webmaster@1 132 this.progress.element = $(progressBar.element).addClass('ahah-progress ahah-progress-bar');
webmaster@1 133 this.progress.object = progressBar;
webmaster@1 134 $(this.element).after(this.progress.element);
webmaster@1 135 }
webmaster@1 136 else if (this.progress.type == 'throbber') {
webmaster@1 137 this.progress.element = $('<div class="ahah-progress ahah-progress-throbber"><div class="throbber">&nbsp;</div></div>');
webmaster@1 138 if (this.progress.message) {
webmaster@1 139 $('.throbber', this.progress.element).after('<div class="message">' + this.progress.message + '</div>')
webmaster@1 140 }
webmaster@1 141 $(this.element).after(this.progress.element);
webmaster@1 142 }
webmaster@1 143 };
webmaster@1 144
webmaster@1 145 /**
webmaster@1 146 * Handler for the form redirection completion.
webmaster@1 147 */
webmaster@1 148 Drupal.ahah.prototype.success = function (response, status) {
webmaster@1 149 var wrapper = $(this.wrapper);
webmaster@1 150 var form = $(this.element).parents('form');
webmaster@1 151 // Manually insert HTML into the jQuery object, using $() directly crashes
webmaster@1 152 // Safari with long string lengths. http://dev.jquery.com/ticket/1152
webmaster@1 153 var new_content = $('<div></div>').html(response.data);
webmaster@1 154
webmaster@1 155 // Restore the previous action and target to the form.
webmaster@1 156 form.attr('action', this.form_action);
webmaster@1 157 this.form_target ? form.attr('target', this.form_target) : form.removeAttr('target');
webmaster@1 158 this.form_encattr ? form.attr('target', this.form_encattr) : form.removeAttr('encattr');
webmaster@1 159
webmaster@1 160 // Remove the progress element.
webmaster@1 161 if (this.progress.element) {
webmaster@1 162 $(this.progress.element).remove();
webmaster@1 163 }
webmaster@1 164 if (this.progress.object) {
webmaster@1 165 this.progress.object.stopMonitoring();
webmaster@1 166 }
webmaster@1 167 $(this.element).removeClass('progress-disabled').attr('disabled', false);
webmaster@1 168
webmaster@1 169 // Add the new content to the page.
webmaster@1 170 Drupal.freezeHeight();
webmaster@1 171 if (this.method == 'replace') {
webmaster@1 172 wrapper.empty().append(new_content);
webmaster@1 173 }
webmaster@1 174 else {
webmaster@1 175 wrapper[this.method](new_content);
webmaster@1 176 }
webmaster@1 177
webmaster@1 178 // Immediately hide the new content if we're using any effects.
webmaster@1 179 if (this.showEffect != 'show') {
webmaster@1 180 new_content.hide();
webmaster@1 181 }
webmaster@1 182
webmaster@1 183 // Determine what effect use and what content will receive the effect, then
webmaster@1 184 // show the new content. For browser compatibility, Safari is excluded from
webmaster@1 185 // using effects on table rows.
webmaster@1 186 if (($.browser.safari && $("tr.ahah-new-content", new_content).size() > 0)) {
webmaster@1 187 new_content.show();
webmaster@1 188 }
webmaster@1 189 else if ($('.ahah-new-content', new_content).size() > 0) {
webmaster@1 190 $('.ahah-new-content', new_content).hide();
webmaster@1 191 new_content.show();
webmaster@1 192 $(".ahah-new-content", new_content)[this.showEffect](this.showSpeed);
webmaster@1 193 }
webmaster@1 194 else if (this.showEffect != 'show') {
webmaster@1 195 new_content[this.showEffect](this.showSpeed);
webmaster@1 196 }
webmaster@1 197
webmaster@1 198 // Attach all javascript behaviors to the new content, if it was successfully
webmaster@1 199 // added to the page, this if statement allows #ahah[wrapper] to be optional.
webmaster@1 200 if (new_content.parents('html').length > 0) {
webmaster@1 201 Drupal.attachBehaviors(new_content);
webmaster@1 202 }
webmaster@1 203
webmaster@1 204 Drupal.unfreezeHeight();
webmaster@1 205 };
webmaster@1 206
webmaster@1 207 /**
webmaster@1 208 * Handler for the form redirection error.
webmaster@1 209 */
webmaster@1 210 Drupal.ahah.prototype.error = function (response, uri) {
webmaster@1 211 alert(Drupal.ahahError(response, uri));
webmaster@1 212 // Resore the previous action and target to the form.
webmaster@1 213 $(this.element).parent('form').attr( { action: this.form_action, target: this.form_target} );
webmaster@1 214 // Remove the progress element.
webmaster@1 215 if (this.progress.element) {
webmaster@1 216 $(this.progress.element).remove();
webmaster@1 217 }
webmaster@1 218 if (this.progress.object) {
webmaster@1 219 this.progress.object.stopMonitoring();
webmaster@1 220 }
webmaster@1 221 // Undo hide.
webmaster@1 222 $(this.wrapper).show();
webmaster@1 223 // Re-enable the element.
webmaster@1 224 $(this.element).removeClass('progess-disabled').attr('disabled', false);
webmaster@1 225 };