1/** 2 * @file 3 * dialog.js 4 */ 5(function ($, Drupal, Bootstrap, Attributes) { 6 7 Bootstrap.Dialog = Bootstrap.Dialog || {}; 8 9 /** 10 * A collection of Drupal dialog handlers. 11 * 12 * @type {Object<String, Drupal.bootstrap.Dialog.Handler>} 13 */ 14 Bootstrap.Dialog.handlers = {}; 15 16 /** 17 * @class Drupal.bootstrap.Dialog.Handler 18 * 19 * @param type 20 * @param data 21 */ 22 Bootstrap.Dialog.Handler = function (type, data) { 23 this.ctor = $.fn.modal; 24 this.extend = null; 25 this.plugin = 'modal'; 26 this.prefix = 'modal'; 27 this.themeHooks = { 28 modal: 'bootstrapModal', 29 dialog: 'bootstrapModalDialog', 30 header: 'bootstrapModalHeader', 31 title: 'bootstrapModalTitle', 32 close: 'bootstrapModalClose', 33 content: 'bootstrapModalContent', 34 body: 'bootstrapModalBody', 35 footer: 'bootstrapModalFooter', 36 }; 37 this.type = type; 38 this.selectors = { 39 dialog: '.modal-dialog', 40 header: '.modal-header', 41 title: '.modal-title', 42 close: '.close', 43 content: '.modal-content', 44 body: '.modal-body', 45 footer: '.modal-footer', 46 buttons: '.modal-buttons' 47 }; 48 49 // Extend the object with subclassed data. 50 $.extend(this, data); 51 52 // Extend the jQuery plugin. 53 if (this.extend) { 54 Bootstrap.extend(this.plugin, this.extend); 55 } 56 }; 57 58 /** 59 * Retrieves a Drupal dialog type handler. 60 * 61 * @param {String|HTMLElement|jQuery} type 62 * The dialog type to retrieve. 63 * 64 * @return {Drupal.bootstrap.Dialog.Handler} 65 * A Bootstrap.Dialog.Handler instance. 66 */ 67 Bootstrap.Dialog.Handler.get = function (type) { 68 if (type instanceof $) { 69 type = type[0]; 70 } 71 if (type instanceof HTMLElement) { 72 type = type.dialogType; 73 } 74 if (!type) { 75 type = 'modal'; 76 } 77 if (!Bootstrap.Dialog.handlers[type]) { 78 Bootstrap.Dialog.handlers[type] = new Bootstrap.Dialog.Handler(); 79 } 80 return Bootstrap.Dialog.handlers[type]; 81 }; 82 83 /** 84 * Registers a Drupal dialog type handler. 85 * 86 * @param {String} type 87 * The dialog type to 88 * @param {Object} [data] 89 * Optional. Additional data to use to create the dialog handler. By 90 * default, this assumes values relative to the Bootstrap Modal plugin. 91 */ 92 Bootstrap.Dialog.Handler.register = function (type, data) { 93 Bootstrap.Dialog.handlers[type] = new Bootstrap.Dialog.Handler(type, data); 94 }; 95 96 Bootstrap.Dialog.Handler.prototype.invoke = function (context) { 97 var args = Array.prototype.slice.call(arguments); 98 return this.ctor.apply(context, args.slice(1)); 99 }; 100 101 Bootstrap.Dialog.Handler.prototype.theme = function (hook) { 102 var args = Array.prototype.slice.call(arguments); 103 return $(Drupal.theme.apply(Drupal.theme, [this.themeHooks[hook]].concat(args.slice(1)))); 104 }; 105 106 /** 107 * Ensures a DOM element has the appropriate structure for a modal. 108 * 109 * Note: this can get a little tricky. Core potentially already 110 * semi-processes a "dialog" if was created using an Ajax command 111 * (i.e. prepareDialogButtons in drupal.ajax.js). Because of this, the 112 * contents (HTML) of the existing element cannot simply be dumped into a 113 * newly created modal. This would destroy any existing event bindings. 114 * Instead, the contents must be "moved" (appended) to the new modal and 115 * then "moved" again back to the to the existing container as needed. 116 * 117 * @param {HTMLElement|jQuery} element 118 * The element to ensure is a modal structure. 119 * @param {Object} options 120 * THe dialog options to use to construct the modal. 121 */ 122 Bootstrap.Dialog.Handler.prototype.ensureModalStructure = function (element, options) { 123 var $element = $(element); 124 125 // Immediately return if the modal was already converted into a proper modal. 126 if ($element.is('[data-drupal-theme="' + this.themeHooks.modal + '"]')) { 127 return; 128 } 129 130 var attributes = Attributes.create(element).remove('style').set('data-drupal-theme', this.themeHooks.modal); 131 132 // Merge in trigger data attributes. 133 if (options.$trigger && options.$trigger[0]) { 134 /** @var {HTMLElement} trigger */ 135 var trigger = options.$trigger[0]; 136 var data = {}; 137 for (var i = 0, l = trigger.attributes.length; i < l; i++) { 138 var name = trigger.attributes[i].name; 139 if (name && name.substring(0, 5) === 'data-') { 140 data[name] = trigger.getAttribute(name); 141 } 142 } 143 attributes.merge(data); 144 } 145 146 options = $.extend(true, {}, options, { 147 attributes: attributes, 148 }); 149 150 // Create a new modal. 151 var $modal = this.theme('modal', options); 152 153 // Store a reference to the content inside the existing element container. 154 // This references the actual DOM node elements which will allow 155 // jQuery to "move" then when appending below. Using $.fn.children() 156 // does not return any text nodes present and $.fn.html() only returns 157 // a string representation of the content, which effectively destroys 158 // any prior event bindings or processing. 159 var $body = $element.find(this.selectors.body); 160 var $existing = $body[0] ? $body.contents() : $element.contents(); 161 162 // Set the attributes of the dialog to that of the newly created modal. 163 $element.attr(Attributes.create($modal).toPlainObject()); 164 165 // Append the newly created modal markup. 166 $element.append($modal.html()); 167 168 // Move the existing HTML into the modal markup that was just appended. 169 $element.find(this.selectors.body).append($existing); 170 }; 171 172})(jQuery, Drupal, Drupal.bootstrap, Attributes);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.