Updated the Bootstrap theme.
[yaffs-website] / web / themes / contrib / bootstrap / js / modal.jquery.ui.bridge.js
index 88d5ce480be5298a7c60f4c249f1f394202635f2..cd9509251baa9c321cd8951d900ff510e50ad44d 100644 (file)
            */
           createButtons: function () {
             this.$footer.find('.modal-buttons').remove();
+
+            // jQuery UI supports both objects and arrays. Unfortunately
+            // developers have misunderstood and abused this by simply placing
+            // the objects that should be in an array inside an object with
+            // arbitrary keys (likely to target specific buttons as a hack).
             var buttons = this.options.dialogOptions && this.options.dialogOptions.buttons || [];
+            if (!Array.isArray(buttons)) {
+              var array = [];
+              for (var k in buttons) {
+                // Support the proper object values: label => click callback.
+                if (typeof buttons[k] === 'function') {
+                  array.push({
+                    label: k,
+                    click: buttons[k],
+                  });
+                }
+                // Support nested objects, but log a warning.
+                else if (buttons[k].text || buttons[k].label) {
+                  Bootstrap.warn('Malformed jQuery UI dialog button: @key. The button object should be inside an array.', {
+                    '@key': k
+                  });
+                  array.push(buttons[k]);
+                }
+                else {
+                  Bootstrap.unsupported('button', k, buttons[k]);
+                }
+              }
+              buttons = array;
+            }
+
             if (buttons.length) {
               var $buttons = $('<div class="modal-buttons"/>').appendTo(this.$footer);
               for (var i = 0, l = buttons.length; i < l; i++) {
                 var button = buttons[i];
                 var $button = $(Drupal.theme('bootstrapModalDialogButton', button));
+
+                // Invoke the "create" method for jQuery UI buttons.
+                if (typeof button.create === 'function') {
+                  button.create.call($button[0]);
+                }
+
+                // Bind the "click" method for jQuery UI buttons to the modal.
                 if (typeof button.click === 'function') {
-                  $button.on('click', button.click);
+                  $button.on('click', button.click.bind(this.$element));
                 }
+
                 $buttons.append($button);
               }
             }
+
+            // Toggle footer visibility based on whether it has child elements.
+            this.$footer[this.$footer.children()[0] ? 'show' : 'hide']();
           },
 
           /**
               this.$footer = $(Drupal.theme('bootstrapModalFooter', {}, true)).insertAfter(this.$dialogBody);
             }
 
-            // Create buttons.
-            this.createButtons();
-
-            // Hide the footer if there are no children.
-            if (!this.$footer.children()[0]) {
-              this.$footer.hide();
-            }
-
             // Now call the parent init method.
             this.super();
 
                 if (value) {
                   dialogOptions[prop] = value;
                   styles[prop] = value;
+
+                  // If there's a defined height of some kind, enforce the modal
+                  // to use flex (on modern browsers). This will ensure that
+                  // the core autoResize calculations don't cause the content
+                  // to overflow.
+                  if (options.autoResize && (prop === 'height' || prop === 'maxHeight')) {
+                    styles.display = 'flex';
+                    styles.flexDirection = 'column';
+                    this.$dialogBody.css('overflow', 'scroll');
+                  }
                 }
               }
             }
               delete options.dialogClass;
             }
 
+            // Add jQuery UI classes to elements in case developers target them
+            // in callbacks.
+            for (var k in classesMap) {
+              this.$element.find('.' + classesMap[k]).addClass(k);
+            }
 
             // Bind events.
             var events = [
               this.$element.on('dialog' + event, options[event]);
             }
 
+            // Support title attribute on the modal.
+            var title;
+            if ((options.title === null || options.title === void 0) && (title = this.$element.attr('title'))) {
+              options.title = title;
+            }
+
             // Handle the reset of the options.
             for (var name in options) {
               if (!options.hasOwnProperty(name) || options[name] === void 0) continue;
 
             // Merge in the cloned mapped options.
             $.extend(true, this.options, this.mapDialogOptions(clone.options));
+
+            // Update buttons.
+            this.createButtons();
           },
 
           position: function(position) {
         var icon = '';
         var iconPosition = button.iconPosition || 'beginning';
         iconPosition = (iconPosition === 'end' && !rtl) || (iconPosition === 'beginning' && rtl) ? 'after' : 'before';
-        if (button.icon) {
+
+        // Handle Bootstrap icons differently.
+        if (button.bootstrapIcon) {
+          icon = Drupal.theme('icon', 'bootstrap', button.icon);
+        }
+        // Otherwise, assume it's a jQuery UI icon.
+        // @todo Map jQuery UI icons to Bootstrap icons?
+        else if (button.icon) {
           var iconAttributes = Attributes.create()
             .addClass(['ui-icon', button.icon])
             .set('aria-hidden', 'true');
           icon = '<span' + iconAttributes + '></span>';
         }
 
-        // Value.
-        var value = button.text;
+        // Label. Note: jQuery UI dialog has an inconsistency where it uses
+        // "text" instead of "label", so both need to be supported.
+        var value = button.label || button.text;
+
+        // Show/hide label.
+        if (icon && ((button.showLabel !== void 0 && !button.showLabel) || (button.text !== void 0 && !button.text))) {
+          value = '<span' + Attributes.create().addClass('sr-only') + '>' + value + '</span>';
+        }
         attributes.set('value', iconPosition === 'before' ? icon + value : value + icon);
 
         // Handle disabled.
         if (button['class']) {
           attributes.addClass(button['class']);
         }
+        if (button.primary) {
+          attributes.addClass('btn-primary');
+        }
 
         return Drupal.theme('button', attributes);
       }