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