/** * @file * Extends methods from core/misc/ajax.js. */ (function ($, window, Drupal, drupalSettings) { /** * Attempts to find the closest glyphicon progress indicator. * * @param {jQuery|Element} element * A DOM element. * * @returns {jQuery} * A jQuery object. */ Drupal.Ajax.prototype.findGlyphicon = function (element) { return $(element).closest('.form-item').find('.ajax-progress.glyphicon') }; /** * Starts the spinning of the glyphicon progress indicator. * * @param {jQuery|Element} element * A DOM element. * @param {string} [message] * An optional message to display (tooltip) for the progress. * * @returns {jQuery} * A jQuery object. */ Drupal.Ajax.prototype.glyphiconStart = function (element, message) { var $glyphicon = this.findGlyphicon(element); if ($glyphicon[0]) { $glyphicon.addClass('glyphicon-spin'); // Add any message as a tooltip to the glyphicon. if ($.fn.tooltip && drupalSettings.bootstrap.tooltip_enabled) { $glyphicon .removeAttr('data-toggle') .removeAttr('data-original-title') .removeAttr('title') .tooltip('destroy') ; if (message) { $glyphicon.attr('data-toggle', 'tooltip').attr('title', message).tooltip(); } } // Append a message for screen readers. if (message) { $glyphicon.parent().append('
' + message + '
'); } } return $glyphicon; }; /** * Stop the spinning of a glyphicon progress indicator. * * @param {jQuery|Element} element * A DOM element. */ Drupal.Ajax.prototype.glyphiconStop = function (element) { var $glyphicon = this.findGlyphicon(element); if ($glyphicon[0]) { $glyphicon.removeClass('glyphicon-spin'); if ($.fn.tooltip && drupalSettings.bootstrap.tooltip_enabled) { $glyphicon .removeAttr('data-toggle') .removeAttr('data-original-title') .removeAttr('title') .tooltip('destroy') ; } } }; /** * Sets the throbber progress indicator. */ Drupal.Ajax.prototype.setProgressIndicatorThrobber = function () { var $element = $(this.element); // Find an existing glyphicon progress indicator. var $glyphicon = this.glyphiconStart($element, this.progress.message); if ($glyphicon[0]) { this.progress.element = $glyphicon.parent(); this.progress.glyphicon = true; return; } // Otherwise, add a glyphicon throbber after the element. if (!this.progress.element) { this.progress.element = $(Drupal.theme('ajaxThrobber')); } if (this.progress.message) { this.progress.element.after('
' + this.progress.message + '
'); } // If element is an input DOM element type (not :input), append after. if ($element.is('input')) { $element.after(this.progress.element); } // Otherwise append the throbber inside the element. else { $element.append(this.progress.element); } }; /** * Handler for the form redirection completion. * * @param {Array.} response * @param {number} status */ Drupal.Ajax.prototype.success = function (response, status) { if (this.progress.element) { // Stop a glyphicon throbber. if (this.progress.glyphicon) { this.glyphiconStop(this.progress.element); } // Remove the progress element. else { this.progress.element.remove(); } // Remove any message set. this.progress.element.parent().find('.message').remove(); } // -------------------------------------------------------- // Everything below is from core/misc/ajax.js. // -------------------------------------------------------- if (this.progress.object) { this.progress.object.stopMonitoring(); } $(this.element).prop('disabled', false); // Save element's ancestors tree so if the element is removed from the dom // we can try to refocus one of its parents. Using addBack reverse the // result array, meaning that index 0 is the highest parent in the hierarchy // in this situation it is usually a
element. var elementParents = $(this.element).parents('[data-drupal-selector]').addBack().toArray(); // Track if any command is altering the focus so we can avoid changing the // focus set by the Ajax command. var focusChanged = false; for (var i in response) { if (response.hasOwnProperty(i) && response[i].command && this.commands[response[i].command]) { this.commands[response[i].command](this, response[i], status); if (response[i].command === 'invoke' && response[i].method === 'focus') { focusChanged = true; } } } // If the focus hasn't be changed by the ajax commands, try to refocus the // triggering element or one of its parents if that element does not exist // anymore. if (!focusChanged && this.element && !$(this.element).data('disable-refocus')) { var target = false; for (var n = elementParents.length - 1; !target && n > 0; n--) { target = document.querySelector('[data-drupal-selector="' + elementParents[n].getAttribute('data-drupal-selector') + '"]'); } if (target) { $(target).trigger('focus'); } } // Reattach behaviors, if they were detached in beforeSerialize(). The // attachBehaviors() called on the new content from processing the response // commands is not sufficient, because behaviors from the entire form need // to be reattached. if (this.$form) { var settings = this.settings || drupalSettings; Drupal.attachBehaviors(this.$form.get(0), settings); } // Remove any response-specific settings so they don't get used on the next // call by mistake. this.settings = null; }; })(jQuery, this, Drupal, drupalSettings);