1/** 2 * @file 3 * Adds default classes to buttons for styling purposes. 4 */ 5 6(function ($, { tabbable, isTabbable }) { 7 $.widget('ui.dialog', $.ui.dialog, { 8 options: { 9 buttonClass: 'button', 10 buttonPrimaryClass: 'button--primary', 11 }, 12 _createButtons() { 13 const opts = this.options; 14 let primaryIndex; 15 let index; 16 const il = opts.buttons.length; 17 for (index = 0; index < il; index++) { 18 if ( 19 opts.buttons[index].primary && 20 opts.buttons[index].primary === true 21 ) { 22 primaryIndex = index; 23 delete opts.buttons[index].primary; 24 break; 25 } 26 } 27 this._super(); 28 const $buttons = this.uiButtonSet.children().addClass(opts.buttonClass); 29 if (typeof primaryIndex !== 'undefined') { 30 $buttons.eq(index).addClass(opts.buttonPrimaryClass); 31 } 32 }, 33 _createWrapper() { 34 this.uiDialog = $('<div>') 35 .hide() 36 .attr({ 37 // Setting tabIndex makes the div focusable 38 tabIndex: -1, 39 role: 'dialog',
40 'aria-modal': this.options.modal ? 'true' : null, 41 }) 42 .appendTo(this._appendTo()); 43 44 this._addClass( 45 this.uiDialog, 46 'ui-dialog', 47 'ui-widget ui-widget-content ui-front', 48 ); 49 this._on(this.uiDialog, { 50 keydown(event) { 51 if ( 52 this.options.closeOnEscape && 53 !event.isDefaultPrevented() && 54 event.keyCode && 55 event.keyCode === $.ui.keyCode.ESCAPE 56 ) { 57 event.preventDefault(); 58 this.close(event); 59 return; 60 } 61 62 // Prevent tabbing out of dialogs 63 if ( 64 event.keyCode !== $.ui.keyCode.TAB || 65 event.isDefaultPrevented() 66 ) { 67 return; 68 } 69 70 const tabbableElements = tabbable(this.uiDialog[0]); 71 if (tabbableElements.length) { 72 const first = tabbableElements[0]; 73 const last = tabbableElements[tabbableElements.length - 1]; 74 75 if ( 76 (event.target === last || event.target === this.uiDialog[0]) && 77 !event.shiftKey 78 ) { 79 this._delay(function () { 80 $(first).trigger('focus'); 81 }); 82 event.preventDefault(); 83 } else if ( 84 (event.target === first || event.target === this.uiDialog[0]) && 85 event.shiftKey 86 ) { 87 this._delay(function () { 88 $(last).trigger('focus'); 89 }); 90 event.preventDefault(); 91 } 92 } 93 }, 94 mousedown(event) { 95 if (this._moveToTop(event)) { 96 this._focusTabbable(); 97 } 98 }, 99 }); 100 101 // We assume that any existing aria-describedby attribute means 102 // that the dialog content is marked up properly 103 // otherwise we brute force the content as the description 104 if (!this.element.find('[aria-describedby]').length) { 105 this.uiDialog.attr({ 106 'aria-describedby': this.element.uniqueId().attr('id'), 107 }); 108 } 109 }, 110 // Override jQuery UI's `_focusTabbable()` so finding tabbable elements uses 111 // the core/tabbable library instead of jQuery UI's `:tabbable` selector. 112 _focusTabbable() { 113 // Set focus to the first match: 114 115 // 1. An element that was focused previously. 116 let hasFocus = this._focusedElement ? this._focusedElement.get(0) : null; 117 118 // 2. First element inside the dialog matching [autofocus]. 119 if (!hasFocus) { 120 hasFocus = this.element.find('[autofocus]').get(0); 121 } 122 123 // 3. Tabbable element inside the content element. 124 // 4. Tabbable element inside the buttonpane. 125 if (!hasFocus) { 126 const $elements = [this.element, this.uiDialogButtonPane]; 127 for (let i = 0; i < $elements.length; i++) { 128 const element = $elements[i].get(0); 129 if (element) { 130 const elementTabbable = tabbable(element); 131 hasFocus = elementTabbable.length ? elementTabbable[0] : null; 132 } 133 if (hasFocus) { 134 break; 135 } 136 } 137 } 138 139 // 5. The close button. 140 if (!hasFocus) { 141 const closeBtn = this.uiDialogTitlebarClose.get(0); 142 hasFocus = closeBtn && isTabbable(closeBtn) ? closeBtn : null; 143 } 144 145 // 6. The dialog itself. 146 if (!hasFocus) { 147 hasFocus = this.uiDialog.get(0); 148 } 149 $(hasFocus).eq(0).trigger('focus'); 150 }, 151 }); 152})(jQuery, window.tabbable);
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.