Improved ARIA support, use native drop-down menus inside Redactor
authorAlexander Ebert <ebert@woltlab.com>
Mon, 11 Mar 2019 16:58:56 +0000 (17:58 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 11 Mar 2019 16:58:56 +0000 (17:58 +0100)
wcfsetup/install/files/js/3rdParty/redactor2/plugins/WoltLabButton.js
wcfsetup/install/files/js/3rdParty/redactor2/plugins/WoltLabDropdown.js
wcfsetup/install/files/js/3rdParty/redactor2/plugins/WoltLabObserve.js
wcfsetup/install/files/js/3rdParty/redactor2/redactor.js
wcfsetup/install/files/style/ui/redactor.scss

index aa245a25489192da5d68fac5bf68bf4b0fa7f06d..7d9b4f9bece62686ce0eb8a2a0ad0c05d4f675ba 100644 (file)
@@ -157,6 +157,9 @@ $.Redactor.prototype.WoltLabButton = function() {
                        this.$toolbar[0].addEventListener('dragstart', function (event) {
                                event.preventDefault();
                        });
+                       
+                       // Set the tabindex of the HTML button to `0` to support tab navigation (ARIA).
+                       elAttr(elBySel('.re-html', toolbar), 'tabindex', 0);
                },
                
                _handleCustomButton: function (bbcode) {
index 009bae4e0187ed65738bfe8b85cfeb3924b12c5b..4cd1823258216c5dcc68dd565144f64947352f79 100644 (file)
@@ -16,56 +16,9 @@ $.Redactor.prototype.WoltLabDropdown = function() {
                        
                        // the original implementation didn't perform that well (especially with multiple
                        // instance being launched at start) and suffered from too many live DOM manipulations
-                       this.dropdown.build = (function(name, $dropdown, dropdownObject) {
-                               dropdownObject = this.dropdown.buildFormatting(name, dropdownObject);
-                               
-                               var btnObject, fragment = document.createDocumentFragment();
-                               for (var btnName in dropdownObject) {
-                                       if (dropdownObject.hasOwnProperty(btnName)) {
-                                               btnObject = dropdownObject[btnName];
-                                               
-                                               var item = this.dropdown.buildItem(btnName, btnObject);
-                                               
-                                               this.observe.addDropdown($(item), btnName, btnObject);
-                                               fragment.appendChild(item);
-                                       }
-                               }
-                               
-                               var hasItems = false;
-                               for (var i = 0, length = fragment.childNodes.length; i < length; i++) {
-                                       if (fragment.childNodes[i].nodeType === Node.ELEMENT_NODE) {
-                                               hasItems = true;
-                                               break;
-                                       }
-                               }
-                               
-                               if (hasItems) {
-                                       $dropdown[0].rel = name;
-                                       $dropdown[0].appendChild(fragment);
-                               }
-                       }).bind(this);
-                       
-                       this.dropdown.buildItem = (function(btnName, btnObject) {
-                               var itemContainer = elCreate('li');
-                               if (typeof btnObject.classname !== 'undefined') {
-                                       itemContainer.classList.add(btnObject.classname);
-                               }
-                               
-                               if (btnName.toLowerCase().indexOf('divider') === 0) {
-                                       itemContainer.classList.add('redactor-dropdown-divider');
-                                       
-                                       return itemContainer;
-                               }
-                               
-                               itemContainer.innerHTML = '<a href="#" class="redactor-dropdown-' + btnName + '" role="button"><span>' + btnObject.title + '</span></a>';
-                               itemContainer.children[0].addEventListener('mousedown', (function(event) {
-                                       event.preventDefault();
-                                       
-                                       this.dropdown.buildClick(event, btnName, btnObject);
-                               }).bind(this));
-                               
-                               return itemContainer;
-                       }).bind(this);
+                       // Integrated into Redactor itself in WoltLab Suite 5.2:
+                       //  * this.dropdown.build
+                       //  * this.dropdown.buildItem
                },
                
                _hideAll: function() {
@@ -78,24 +31,12 @@ $.Redactor.prototype.WoltLabDropdown = function() {
                },
                
                _show: function() {
+                       return;
                        var show = this.dropdown.show;
                        this.dropdown.show = (function(e, key) {
                                var $button = this.button.get(key);
                                var $dropdown = $button.data('dropdown');
                                
-                               if (!elDataBool($dropdown[0], 'woltlab')) {
-                                       var list = elCreate('ul');
-                                       list.className = 'dropdownMenu';
-                                       
-                                       while ($dropdown[0].childElementCount) {
-                                               list.appendChild($dropdown[0].children[0]);
-                                       }
-                                       
-                                       $dropdown[0].appendChild(list);
-                                       
-                                       elData($dropdown[0], 'woltlab', true);
-                               }
-                               
                                var isActive = $button.hasClass('dropact');
                                
                                show.call(this, e, key);
index b8bc9e167c3a7ac1a98491dd19df617eabba4bfa..00a2b1dbfdc244ba4365e5a598082deda29f5a5a 100644 (file)
@@ -22,6 +22,8 @@ $.Redactor.prototype.WoltLabObserve = function() {
                                        }
                                        
                                        button.classList.remove('redactor-act');
+                                       if (button.rel !== 'html') elAttr(button, 'tabindex', -1);
+                                       elAttr(button, 'aria-pressed', false);
                                }
                        }).bind(this);
                        
index 4a59b55ec4f767fd58eef6edb7ecce87a3be8371..aa06c0aaea45da11f850350c36d6b68b42848168 100644 (file)
                                                        true
                                                );
                                                
-                                               var $dropdown = $('<ul class="redactor-dropdown redactor-dropdown-' + this.uuid + ' redactor-dropdown-box-' + btnName + '" style="display: none;">');
+                                               var $dropdown = $('<ul class="dropdownMenu redactor-dropdown-menu redactor-dropdown-menu-' + $button[0].rel + '" data-dropdown-allow-flip="horizontal" data-dropdown-ignore-page-scroll="true" />');
                                                $button.data('dropdown', $dropdown);
                                                this.dropdown.build(btnName, $dropdown, btnObject.dropdown);
+                                               
+                                               this.button.setupDropdown($button[0], $dropdown[0]);
                                        }
                                        
                                        this.button.buttons.push($button);
                                        
                                        return $button;
                                },
+                               setupDropdown: function(button, dropdown) {
+                                       require(['Ui/SimpleDropdown'], (function (UiSimpleDropdown) {
+                                               UiSimpleDropdown.initFragment(button, dropdown);
+                                               UiSimpleDropdown.registerCallback(button.id, (function(containerId, action) {
+                                                       if (action === 'close') {
+                                                               this.dropdown.hideOut();
+                                                       }
+                                               }).bind(this));
+                                               
+                                               elData(button, 'a11y-mouse-event', 'mousedown');
+                                               
+                                               button.addEventListener('click', function (event) {
+                                                       event.preventDefault();
+                                                       event.stopPropagation();
+                                               });
+                                       }).bind(this));
+                               },
                                getButtons: function () {
                                        return this.button.toolbar().find('a.re-button');
                                },
                                        var key = $btn.attr('rel');
                                        this.button.addCallback($btn, 'dropdown');
                                        
-                                       var $dropdown = $('<div class="redactor-dropdown redactor-dropdown-' + this.uuid + ' redactor-dropdown-box-' + key + '" style="display: none;">');
+                                       var $dropdown = $('<ul class="dropdownMenu redactor-dropdown-menu redactor-dropdown-menu-' + key + '" data-dropdown-allow-flip="horizontal" data-dropdown-ignore-page-scroll="true" />');
                                        $btn.data('dropdown', $dropdown);
                                        
                                        // build dropdown
                                        if (dropdown) {
                                                this.dropdown.build(key, $dropdown, dropdown);
+                                               
+                                               this.button.setupDropdown($btn[0], $dropdown[0]);
                                        }
                                        
                                        return $dropdown;
                                },
                                setActive: function (key) {
-                                       this.button.get(key).addClass('redactor-act');
+                                       this.button.get(key).addClass('redactor-act').attr({
+                                               'aria-pressed': true,
+                                               tabindex: 0
+                                       });
                                },
                                setInactive: function (key) {
-                                       this.button.get(key).removeClass('redactor-act');
+                                       this.button.get(key).removeClass('redactor-act').attr({
+                                               'aria-pressed': false,
+                                               tabindex: (key === 'html') ? 0 : -1
+                                       });
                                },
                                setInactiveAll: function (key) {
                                        var $btns = this.button.toolbar().find('a.re-button');
                                        this.$element.off('.redactor').removeData('redactor');
                                        this.core.editor().off('.redactor');
                                        
-                                       $(document).off('.redactor-dropdown');
                                        $(document).off('.redactor-air.' + this.uuid);
                                        $(document).off('mousedown.redactor-blur.' + this.uuid);
                                        $(document).off('mousedown.redactor.' + this.uuid);
                                        return this.dropdown.active;
                                },
                                build: function (name, $dropdown, dropdownObject) {
-                                       dropdownObject = this.dropdown.buildFormatting(name, dropdownObject);
-                                       
-                                       $.each(dropdownObject, $.proxy(function (btnName, btnObject) {
-                                               var $item = this.dropdown.buildItem(btnName, btnObject);
-                                               
-                                               this.observe.addDropdown($item, btnName, btnObject);
-                                               $dropdown.attr('rel', name).append($item);
-                                               
-                                       }, this));
-                               },
-                               buildFormatting: function (name, dropdownObject) {
-                                       if (name !== 'format' || this.opts.formattingAdd === false) {
-                                               return dropdownObject;
+                                       var btnObject, fragment = document.createDocumentFragment();
+                                       for (var btnName in dropdownObject) {
+                                               if (dropdownObject.hasOwnProperty(btnName)) {
+                                                       btnObject = dropdownObject[btnName];
+                                                       
+                                                       var item = this.dropdown.buildItem(btnName, btnObject);
+                                                       
+                                                       this.observe.addDropdown($(item), btnName, btnObject);
+                                                       fragment.appendChild(item);
+                                               }
                                        }
                                        
-                                       $.each(this.opts.formattingAdd, $.proxy(function (i, s) {
-                                               var type = (this.utils.isBlockTag(s.args[0])) ? 'block' : 'inline';
-                                               
-                                               dropdownObject[i] = {
-                                                       func: (type === 'block') ? 'block.format' : 'inline.format',
-                                                       args: s.args,
-                                                       title: s.title
-                                               };
-                                               
-                                       }, this));
+                                       var hasItems = false;
+                                       for (var i = 0, length = fragment.childNodes.length; i < length; i++) {
+                                               if (fragment.childNodes[i].nodeType === Node.ELEMENT_NODE) {
+                                                       hasItems = true;
+                                                       break;
+                                               }
+                                       }
                                        
-                                       return dropdownObject;
+                                       if (hasItems) {
+                                               $dropdown[0].rel = name;
+                                               $dropdown[0].appendChild(fragment);
+                                       }
                                },
+                               buildFormatting: function () {},
                                buildItem: function (btnName, btnObject) {
-                                       var $itemContainer = $('<li />');
+                                       var itemContainer = elCreate('li');
                                        if (typeof btnObject.classname !== 'undefined') {
-                                               $itemContainer.addClass(btnObject.classname);
+                                               itemContainer.classList.add(btnObject.classname);
                                        }
                                        
-                                       if (btnName.search(/^divider/i) !== -1) {
-                                               $itemContainer.addClass('redactor-dropdown-divider');
+                                       if (btnName.toLowerCase().indexOf('divider') === 0) {
+                                               itemContainer.classList.add('redactor-dropdown-divider');
                                                
-                                               return $itemContainer;
+                                               return itemContainer;
                                        }
                                        
-                                       var $item = $('<a href="#" class="redactor-dropdown-' + btnName + '" role="button" />');
-                                       var $itemSpan = $('<span />').html(btnObject.title);
-                                       
-                                       $item.append($itemSpan);
-                                       $item.on('mousedown', $.proxy(function (e) {
-                                               e.preventDefault();
-                                               
-                                               this.dropdown.buildClick(e, btnName, btnObject);
+                                       itemContainer.innerHTML = '<a href="#" class="redactor-dropdown-' + btnName + '" role="button"><span>' + btnObject.title + '</span></a>';
+                                       itemContainer.children[0].addEventListener('mousedown', (function(event) {
+                                               event.preventDefault();
                                                
-                                       }, this));
-                                       
-                                       $itemContainer.append($item);
-                                       
-                                       return $itemContainer;
+                                               this.dropdown.buildClick(event, btnName, btnObject);
+                                       }).bind(this));
                                        
+                                       return itemContainer;
                                },
                                buildClick: function (e, btnName, btnObject) {
                                        if ($(e.target).hasClass('redactor-dropdown-link-inactive')) {
                                        this.dropdown.key = key;
                                        this.dropdown.button = this.button.get(this.dropdown.key);
                                        
-                                       if (this.dropdown.button.hasClass('dropact')) {
-                                               this.dropdown.hide();
-                                               return;
-                                       }
-                                       
-                                       // re append
-                                       this.dropdown.active = this.dropdown.button.data('dropdown').appendTo(document.body);
-                                       
-                                       // callback
-                                       this.core.callback('dropdownShow', {
-                                               dropdown: this.dropdown.active,
-                                               key: this.dropdown.key,
-                                               button: this.dropdown.button
-                                       });
-                                       
-                                       // set button
-                                       this.button.setActive(this.dropdown.key);
-                                       this.dropdown.button.addClass('dropact');
-                                       
-                                       // position
-                                       this.dropdown.getButtonPosition();
-                                       
-                                       // show
-                                       if (this.button.toolbar().hasClass('toolbar-fixed-box') && this.detect.isDesktop()) {
-                                               this.dropdown.showIsFixedToolbar();
-                                       }
-                                       else {
-                                               this.dropdown.showIsUnFixedToolbar();
-                                       }
-                                       
-                                       // disable scroll whan dropdown scroll
-                                       if (this.detect.isDesktop() && !this.detect.isFirefox()) {
-                                               this.dropdown.active.on('mouseover.redactor-dropdown',
-                                                       $.proxy(this.utils.disableBodyScroll, this)
-                                               );
-                                               this.dropdown.active.on(
-                                                       'mouseout.redactor-dropdown mousedown.redactor-dropdown',
-                                                       $.proxy(this.utils.enableBodyScroll, this)
-                                               );
-                                       }
-                                       
-                                       e.stopPropagation();
-                                       
-                               },
-                               showIsFixedToolbar: function () {
-                                       var top = this.dropdown.button.position().top + this.dropdown.button.innerHeight() + this.opts.toolbarFixedTopOffset;
-                                       
-                                       var position = 'fixed';
-                                       if (this.opts.toolbarFixedTarget !== document) {
-                                               top = (this.dropdown.button.innerHeight() + this.$toolbar.offset().top) + this.opts.toolbarFixedTopOffset;
-                                               position = 'absolute';
-                                       }
-                                       
-                                       this.dropdown.active.css({
-                                               
-                                               position: position,
-                                               left: this.dropdown.position.left + 'px',
-                                               top: top + 'px'
+                                       require(['Ui/SimpleDropdown'], (function(UiSimpleDropdown) {
+                                               var dropdownId = this.dropdown.button[0].id;
                                                
-                                       }).show();
-                                       
-                                       // animate
-                                       this.dropdown.active.redactorAnimation('slideDown',
-                                               {duration: 0.2},
-                                               $.proxy(function () {
-                                                       this.dropdown.enableCallback();
-                                                       this.dropdown.enableEvents();
+                                               UiSimpleDropdown.toggleDropdown(dropdownId);
+                                               if (UiSimpleDropdown.isOpen(dropdownId)) {
+                                                       this.dropdown.active = $(UiSimpleDropdown.getDropdownMenu(dropdownId));
                                                        
-                                               }, this)
-                                       );
-                               },
-                               showIsUnFixedToolbar: function () {
-                                       this.dropdown.active.css({
-                                               
-                                               position: 'absolute',
-                                               left: this.dropdown.position.left + 'px',
-                                               top: (this.dropdown.button.innerHeight() + this.dropdown.position.top) + 'px'
-                                               
-                                       }).show();
-                                       
-                                       // animate
-                                       this.dropdown.active.redactorAnimation(((this.opts.animation) ? 'slideDown' : 'show'),
-                                               {duration: 0.2},
-                                               $.proxy(function () {
-                                                       this.dropdown.enableCallback();
-                                                       this.dropdown.enableEvents();
+                                                       this.core.callback('dropdownShow', {
+                                                               dropdown: this.dropdown.active,
+                                                               key: this.dropdown.key,
+                                                               button: this.dropdown.button
+                                                       });
                                                        
-                                               }, this)
-                                       );
-                               },
-                               enableEvents: function () {
-                                       $(document).on('mousedown.redactor-dropdown',
-                                               $.proxy(this.dropdown.hideAll, this)
-                                       );
-                                       this.core.editor().on('touchstart.redactor-dropdown',
-                                               $.proxy(this.dropdown.hideAll, this)
-                                       );
-                                       $(document).on('keyup.redactor-dropdown',
-                                               $.proxy(this.dropdown.closeHandler, this)
-                                       );
+                                                       this.button.setActive(this.dropdown.key);
+                                                       this.dropdown.button.addClass('dropact');
+                                                       
+                                                       this.dropdown.enableCallback();
+                                               }
+                                               else {
+                                                       this.dropdown.hide();
+                                               }
+                                       }).bind(this));
+                                       
+                                       e.preventDefault();
                                },
+                               showIsFixedToolbar: function () {},
+                               showIsUnFixedToolbar: function () {},
+                               enableEvents: function () {},
                                enableCallback: function () {
                                        this.core.callback('dropdownShown', {
                                                dropdown: this.dropdown.active,
                                                button: this.dropdown.button
                                        });
                                },
-                               getButtonPosition: function () {
-                                       this.dropdown.position = this.dropdown.button.offset();
-                                       
-                                       // fix right placement
-                                       var dropdownWidth = this.dropdown.active.width();
-                                       if ((this.dropdown.position.left + dropdownWidth) > $(document).width()) {
-                                               this.dropdown.position.left = Math.max(0,
-                                                       this.dropdown.position.left - dropdownWidth + parseInt(this.dropdown.button.innerWidth())
-                                               );
-                                       }
-                                       
-                               },
-                               closeHandler: function (e) {
-                                       if (e.which !== this.keyCode.ESC) {
-                                               return;
-                                       }
-                                       
-                                       this.dropdown.hideAll(e);
-                                       this.core.editor().focus();
-                               },
-                               hideAll: function (e, key) {
-                                       if (this.detect.isDesktop()) {
-                                               this.utils.enableBodyScroll();
-                                       }
-                                       
-                                       if (e !== false && $(e.target).closest('.redactor-dropdown').length !== 0) {
-                                               return;
-                                       }
-                                       
-                                       var $buttons = (typeof key === 'undefined') ? this.button.toolbar().find(
-                                               'a.dropact') : this.button.toolbar().find('a.dropact').not('.re-' + key);
-                                       var $elements = (typeof key === 'undefined') ? $('.redactor-dropdown-' + this.uuid) : $(
-                                               '.redactor-dropdown-' + this.uuid).not('.redactor-dropdown-box-' + key);
-                                       
-                                       if ($elements.length !== 0) {
-                                               $(document).off('.redactor-dropdown');
-                                               this.core.editor().off('.redactor-dropdown');
-                                               
-                                               $.each($elements, $.proxy(function (i, s) {
-                                                       var $el = $(s);
-                                                       
-                                                       this.core.callback('dropdownHide', $el);
-                                                       
-                                                       $el.hide();
-                                                       $el.off('mouseover mouseout').off('.redactor-dropdown');
-                                                       
-                                               }, this));
-                                               
-                                               $buttons.removeClass('redactor-act dropact');
-                                       }
-                                       
-                               },
-                               hide: function () {
+                               getButtonPosition: function () {},
+                               closeHandler: function () {},
+                               hideAll: function (e, key) { this.dropdown.hideOut(key); },
+                               hide: function () { this.dropdown.hideOut(); },
+                               hideOut: function (key) {
                                        if (this.dropdown.active === false) {
                                                return;
                                        }
                                        
-                                       if (this.detect.isDesktop()) {
-                                               this.utils.enableBodyScroll();
+                                       if (this.dropdown.button[0].rel === key) {
+                                               return;
                                        }
                                        
-                                       this.dropdown.active.redactorAnimation(((this.opts.animation) ? 'slideUp' : 'hide'),
-                                               {duration: 0.2},
-                                               $.proxy(function () {
-                                                       $(document).off('.redactor-dropdown');
-                                                       this.core.editor().off('.redactor-dropdown');
-                                                       
-                                                       this.dropdown.hideOut();
-                                                       
-                                               }, this)
-                                       );
-                               },
-                               hideOut: function () {
                                        this.core.callback('dropdownHide', this.dropdown.active);
                                        
+                                       var id = this.dropdown.button[0].id;
+                                       require(['Ui/SimpleDropdown'], function(UiSimpleDropdown) {
+                                               UiSimpleDropdown.close(id);
+                                       });
+                                       
                                        this.dropdown.button.removeClass('redactor-act dropact');
-                                       this.dropdown.active.off('mouseover mouseout').off('.redactor-dropdown');
                                        this.dropdown.button = false;
                                        this.dropdown.key = false;
                                        this.dropdown.active = false;
                                        this.button.$toolbar = this.$toolbar;
                                        this.button.setFormatting();
                                        this.button.load(this.$toolbar);
+                                       
+                                       require(['Core'], (function(Core) {
+                                               this.$toolbar[0].addEventListener('keydown', this.toolbar.keydown.bind(this, Core));
+                                       }).bind(this));
                                },
                                createContainer: function () {},
                                append: function () {},
                                observeScrollDisable: function () {},
                                setDropdownsFixed: function () {},
                                unsetDropdownsFixed: function () {},
-                               setDropdownPosition: function () {}
+                               setDropdownPosition: function () {},
+                               /**
+                                * @param {object} Core
+                                * @param {KeyboardEvent} event
+                                */
+                               keydown: function(Core, event) {
+                                       var activeButton = document.activeElement;
+                                       if (!activeButton.classList.contains('re-button')) {
+                                               return;
+                                       }
+                                       
+                                       // Enter, Space, End, Home, ArrowLeft, ArrowRight, ArrowDown
+                                       // Remarks: ArrowUp is not considered, because we do not support radio groups at the top level.
+                                       var keyboardCodes = [13, 32, 35, 36, 37, 39, 40];
+                                       if (keyboardCodes.indexOf(event.which) === -1) {
+                                               return;
+                                       }
+                                       
+                                       // [Enter] || [Space]
+                                       if (event.which === 13 || event.which === 32) {
+                                               event.preventDefault();
+                                               
+                                               require(['Core'], function(Core) {
+                                                       Core.triggerEvent(activeButton, 'mousedown');
+                                               });
+                                               
+                                               return;
+                                       }
+                                       
+                                       // [ArrowDown] opens drop-down menus, but does nothing on "regular" buttons.
+                                       if (event.which === 40) {
+                                               if (elAttr(activeButton, 'aria-haspopup') !== 'true') {
+                                                       return;
+                                               }
+                                               
+                                               event.preventDefault();
+                                               Core.triggerEvent(activeButton, 'mousedown');
+                                               
+                                               var dropdown = $(activeButton).data('dropdown');
+                                               var firstItem = elBySel('li', dropdown[0]);
+                                               if (firstItem) firstItem.focus();
+                                               return;
+                                       }
+                                       
+                                       event.preventDefault();
+                                       
+                                       var buttons = Array.prototype.slice.call(elBySelAll('.re-button', this.$toolbar[0]));
+                                       var newActiveButton = null;
+                                       // [End]
+                                       if (event.which === 35) {
+                                               newActiveButton = buttons[buttons.length - 1];
+                                       }
+                                       // [Home]
+                                       else if (event.which === 36) {
+                                               newActiveButton = buttons[0];
+                                       }
+                                       else {
+                                               var index = buttons.indexOf(activeButton);
+                                               
+                                               // [ArrowLeft]
+                                               if (event.which === 37) {
+                                                       index--;
+                                                       
+                                                       if (index === -1) {
+                                                               index = buttons.length - 1;
+                                                       }
+                                               }
+                                               // [ArrowRight]
+                                               else if (event.which === 39) {
+                                                       index++;
+                                                       
+                                                       if (index === buttons.length) {
+                                                               index = 0;
+                                                       }
+                                               }
+                                               
+                                               newActiveButton = buttons[index];
+                                       }
+                                       
+                                       if (newActiveButton !== null) {
+                                               newActiveButton.focus();
+                                       }
+                               }
                        };
                },
                
                                disableSelectAll: function () {
                                        this.selectAll = false;
                                },
-                               disableBodyScroll: function () {
-                                       var $body = $('html');
-                                       var windowWidth = window.innerWidth;
-                                       if (!windowWidth) {
-                                               var documentElementRect = document.documentElement.getBoundingClientRect();
-                                               windowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
-                                       }
-                                       
-                                       var isOverflowing = document.body.clientWidth < windowWidth;
-                                       var scrollbarWidth = this.utils.measureScrollbar();
-                                       
-                                       $body.css('overflow', 'hidden');
-                                       if (isOverflowing) {
-                                               $body.css('padding-right', scrollbarWidth);
-                                       }
-                               },
+                               disableBodyScroll: function () {},
                                measureScrollbar: function () {
                                        var $body = $('body');
                                        var scrollDiv = document.createElement('div');
                                        $body[0].removeChild(scrollDiv);
                                        return scrollbarWidth;
                                },
-                               enableBodyScroll: function () {
-                                       $('html').css({
-                                               'overflow': '',
-                                               'padding-right': ''
-                                       });
-                                       $('body').remove('redactor-scrollbar-measure');
-                               },
+                               enableBodyScroll: function () {},
                                appendFields: function (appendFields, data) {
                                        if (!appendFields) {
                                                return data;
index ebad4252364f02692f071973eccc2a32b3ae9fff..e83c33805f381d92be2e875fc04a946df45ff4dd 100644 (file)
        }
 }
 
-.redactor-dropdown {
-       > .dropdownMenu {
-               display: block;
-               position: relative;
-               visibility: visible;
-               
-               @include screen-lg {
-                       top: 1px;
-               }
+.redactor-dropdown-menu {
+       @include screen-lg {
                
-               > li:hover {
-                       background-color: transparent !important;
-               }
-               
-               a:hover {
-                       background-color: $wcfDropdownBackgroundActive;
-               }
+       }
+       
+       > li:hover {
+               background-color: transparent !important;
+       }
+       
+       a:hover {
+               background-color: $wcfDropdownBackgroundActive;
        }
        
        .redactor-dropdown-link-inactive {
                                        color: $wcfHeaderMenuLinkActive;
                                }
                        }
+                       
+                       &:focus {
+                               background-color: $wcfHeaderMenuLinkBackgroundActive;
+                               color: $wcfHeaderMenuLinkActive;
+                       }
                }
                
                @include screen-sm-up {
        padding: 7px 14px 7px;
 }
 
-.redactor-dropdown-box-fontcolor {
+.redactor-dropdown-menu-fontcolor {
        width: 200px;
        
        > li.redactorColorPallet {
 }
 
 /* text color selection */
-.redactor-dropdown-box-woltlabColor {
-       > ul {
-               display: flex !important;
-               flex-wrap: wrap;
-               width: 272px;
-               
-               > .dropdownDivider,
-               > .dropdownDivider + li {
-                       flex: 0 0 100%;
-               }
+.redactor-dropdown-menu-woltlabColor {
+       display: flex !important;
+       flex-wrap: wrap;
+       width: 272px;
+       
+       > .dropdownDivider,
+       > .dropdownDivider + li {
+               flex: 0 0 100%;
        }
        
        .woltlab-color-selection {