173 lines
5.5 KiB
JavaScript
173 lines
5.5 KiB
JavaScript
/**
|
|
* @file
|
|
* dialog.js
|
|
*/
|
|
(function ($, Drupal, Bootstrap, Attributes) {
|
|
|
|
Bootstrap.Dialog = Bootstrap.Dialog || {};
|
|
|
|
/**
|
|
* A collection of Drupal dialog handlers.
|
|
*
|
|
* @type {Object<String, Drupal.bootstrap.Dialog.Handler>}
|
|
*/
|
|
Bootstrap.Dialog.handlers = {};
|
|
|
|
/**
|
|
* @class Drupal.bootstrap.Dialog.Handler
|
|
*
|
|
* @param type
|
|
* @param data
|
|
*/
|
|
Bootstrap.Dialog.Handler = function (type, data) {
|
|
this.ctor = $.fn.modal;
|
|
this.extend = null;
|
|
this.plugin = 'modal';
|
|
this.prefix = 'modal';
|
|
this.themeHooks = {
|
|
modal: 'bootstrapModal',
|
|
dialog: 'bootstrapModalDialog',
|
|
header: 'bootstrapModalHeader',
|
|
title: 'bootstrapModalTitle',
|
|
close: 'bootstrapModalClose',
|
|
content: 'bootstrapModalContent',
|
|
body: 'bootstrapModalBody',
|
|
footer: 'bootstrapModalFooter',
|
|
};
|
|
this.type = type;
|
|
this.selectors = {
|
|
dialog: '.modal-dialog',
|
|
header: '.modal-header',
|
|
title: '.modal-title',
|
|
close: '.close',
|
|
content: '.modal-content',
|
|
body: '.modal-body',
|
|
footer: '.modal-footer',
|
|
buttons: '.modal-buttons'
|
|
};
|
|
|
|
// Extend the object with subclassed data.
|
|
$.extend(this, data);
|
|
|
|
// Extend the jQuery plugin.
|
|
if (this.extend) {
|
|
Bootstrap.extend(this.plugin, this.extend);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Retrieves a Drupal dialog type handler.
|
|
*
|
|
* @param {String|HTMLElement|jQuery} type
|
|
* The dialog type to retrieve.
|
|
*
|
|
* @return {Drupal.bootstrap.Dialog.Handler}
|
|
* A Bootstrap.Dialog.Handler instance.
|
|
*/
|
|
Bootstrap.Dialog.Handler.get = function (type) {
|
|
if (type instanceof $) {
|
|
type = type[0];
|
|
}
|
|
if (type instanceof HTMLElement) {
|
|
type = type.dialogType;
|
|
}
|
|
if (!type) {
|
|
type = 'modal';
|
|
}
|
|
if (!Bootstrap.Dialog.handlers[type]) {
|
|
Bootstrap.Dialog.handlers[type] = new Bootstrap.Dialog.Handler();
|
|
}
|
|
return Bootstrap.Dialog.handlers[type];
|
|
};
|
|
|
|
/**
|
|
* Registers a Drupal dialog type handler.
|
|
*
|
|
* @param {String} type
|
|
* The dialog type to
|
|
* @param {Object} [data]
|
|
* Optional. Additional data to use to create the dialog handler. By
|
|
* default, this assumes values relative to the Bootstrap Modal plugin.
|
|
*/
|
|
Bootstrap.Dialog.Handler.register = function (type, data) {
|
|
Bootstrap.Dialog.handlers[type] = new Bootstrap.Dialog.Handler(type, data);
|
|
};
|
|
|
|
Bootstrap.Dialog.Handler.prototype.invoke = function (context) {
|
|
var args = Array.prototype.slice.call(arguments);
|
|
return this.ctor.apply(context, args.slice(1));
|
|
};
|
|
|
|
Bootstrap.Dialog.Handler.prototype.theme = function (hook) {
|
|
var args = Array.prototype.slice.call(arguments);
|
|
return $(Drupal.theme.apply(Drupal.theme, [this.themeHooks[hook]].concat(args.slice(1))));
|
|
};
|
|
|
|
/**
|
|
* Ensures a DOM element has the appropriate structure for a modal.
|
|
*
|
|
* Note: this can get a little tricky. Core potentially already
|
|
* semi-processes a "dialog" if was created using an Ajax command
|
|
* (i.e. prepareDialogButtons in drupal.ajax.js). Because of this, the
|
|
* contents (HTML) of the existing element cannot simply be dumped into a
|
|
* newly created modal. This would destroy any existing event bindings.
|
|
* Instead, the contents must be "moved" (appended) to the new modal and
|
|
* then "moved" again back to the to the existing container as needed.
|
|
*
|
|
* @param {HTMLElement|jQuery} element
|
|
* The element to ensure is a modal structure.
|
|
* @param {Object} options
|
|
* THe dialog options to use to construct the modal.
|
|
*/
|
|
Bootstrap.Dialog.Handler.prototype.ensureModalStructure = function (element, options) {
|
|
var $element = $(element);
|
|
|
|
// Immediately return if the modal was already converted into a proper modal.
|
|
if ($element.is('[data-drupal-theme="' + this.themeHooks.modal + '"]')) {
|
|
return;
|
|
}
|
|
|
|
var attributes = Attributes.create(element).remove('style').set('data-drupal-theme', this.themeHooks.modal);
|
|
|
|
// Merge in trigger data attributes.
|
|
if (options.$trigger && options.$trigger[0]) {
|
|
/** @var {HTMLElement} trigger */
|
|
var trigger = options.$trigger[0];
|
|
var data = {};
|
|
for (var i = 0, l = trigger.attributes.length; i < l; i++) {
|
|
var name = trigger.attributes[i].name;
|
|
if (name && name.substring(0, 5) === 'data-') {
|
|
data[name] = trigger.getAttribute(name);
|
|
}
|
|
}
|
|
attributes.merge(data);
|
|
}
|
|
|
|
options = $.extend(true, {}, options, {
|
|
attributes: attributes,
|
|
});
|
|
|
|
// Create a new modal.
|
|
var $modal = this.theme('modal', options);
|
|
|
|
// Store a reference to the content inside the existing element container.
|
|
// This references the actual DOM node elements which will allow
|
|
// jQuery to "move" then when appending below. Using $.fn.children()
|
|
// does not return any text nodes present and $.fn.html() only returns
|
|
// a string representation of the content, which effectively destroys
|
|
// any prior event bindings or processing.
|
|
var $body = $element.find(this.selectors.body);
|
|
var $existing = $body[0] ? $body.contents() : $element.contents();
|
|
|
|
// Set the attributes of the dialog to that of the newly created modal.
|
|
$element.attr(Attributes.create($modal).toPlainObject());
|
|
|
|
// Append the newly created modal markup.
|
|
$element.append($modal.html());
|
|
|
|
// Move the existing HTML into the modal markup that was just appended.
|
|
$element.find(this.selectors.body).append($existing);
|
|
};
|
|
|
|
})(jQuery, Drupal, Drupal.bootstrap, Attributes);
|