From ce1e9672f95b6e8a5c46ac98ac5a4d38889076c5 Mon Sep 17 00:00:00 2001 From: Sebastian Castro Date: Tue, 14 Apr 2020 09:27:13 +0200 Subject: [PATCH] css: style select with nice-select library --- src/static/css/pad.css | 11 +- src/static/css/pad/form.css | 174 +++++++++++++++ src/static/js/pad.js | 1 + src/static/js/pad_editbar.js | 3 + src/static/js/vendors/nice-select.js | 209 ++++++++++++++++++ .../skins/colibris/src/components/form.css | 21 +- .../skins/colibris/src/components/popup.css | 2 +- .../colibris/src/components/scrollbars.css | 14 ++ src/templates/pad.html | 2 +- 9 files changed, 422 insertions(+), 15 deletions(-) create mode 100644 src/static/css/pad/form.css create mode 100644 src/static/js/vendors/nice-select.js diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 0a66bc8cf..bbec1b016 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -11,6 +11,7 @@ @import url("pad/chat.css"); @import url("pad/gritter.css"); @import url("pad/loadingbox.css"); +@import url("pad/form.css"); html { font-size: 14px; @@ -23,16 +24,6 @@ html, font-family: Cantarell, Roboto, "Open Sans", "Helvetica Neue", Arial, sans-serif; } -select { - padding: 3px; - border-radius: 3px; - border: 1px solid #ccc; - outline: none; - width: 120px; - cursor: pointer; - background-color: white; -} - .clear { clear: both } diff --git a/src/static/css/pad/form.css b/src/static/css/pad/form.css new file mode 100644 index 000000000..5b42290a5 --- /dev/null +++ b/src/static/css/pad/form.css @@ -0,0 +1,174 @@ +select, .nice-select { + -webkit-tap-highlight-color: transparent; + background-color: #fff; + border-radius: 3px; + border: 1px solid #ccc; + box-sizing: border-box; + clear: both; + cursor: pointer; + display: inline-block; + font-family: inherit; + font-weight: normal; + height: 28px; + line-height: 28px; + outline: none; + padding-left: 8px; + padding-right: 24px; + position: relative; + text-align: left !important; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + white-space: nowrap; + width: 120px; + text-transform: capitalize; +} +.popup .nice-select { + padding: 4px 24px 4px 8px; +} +.nice-select:hover { + border-color: #dbdbdb; +} +.nice-select:active,.nice-select.open,.nice-select:focus { + /*border-color: #999;*/ +} +.nice-select:after { + border-bottom: 2px solid #999; + border-right: 2px solid #999; + content: ''; + display: block; + height: 5px; + margin-top: -3px; + pointer-events: none; + position: absolute; + right: 10px; + top: 50%; + -webkit-transform-origin: 66% 66%; + -ms-transform-origin: 66% 66%; + transform-origin: 66% 66%; + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + -webkit-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; + width: 5px; +} +.nice-select.open:after { + -webkit-transform: rotate(-135deg); + -ms-transform: rotate(-135deg); + transform: rotate(-135deg); +} +.nice-select.open .list { + opacity: 1; + pointer-events: auto; + -webkit-transform: scale(1) translateY(0); + -ms-transform: scale(1) translateY(0); + transform: scale(1) translateY(0); +} +.nice-select.disabled { + border-color: #ededed; + color: #999; + pointer-events: none; +} +.nice-select.disabled:after { + border-color: #cccccc; +} +.nice-select.wide { + width: 100%; +} +.nice-select.wide .list { + left: 0 !important; + right: 0 !important; +} +.nice-select.right { + float: right; +} +.nice-select.right .list { + left: auto; + right: 0; +} +.nice-select.small { + font-size: 12px; + height: 36px; + line-height: 34px; +} +.nice-select.small:after { + height: 4px; + width: 4px; +} +.nice-select.small .option { + line-height: 34px; + min-height: 34px; +} +.nice-select .list { + display: block; + background-color: #fff; + border-radius: 3px; + box-shadow: 0 0 0 1px rgba(68, 68, 68, 0.11); + box-sizing: border-box; + margin-top: 4px; + opacity: 0; + overflow: auto; + padding: 0; + pointer-events: none; + position: absolute; + top: 100%; + left: 0; + max-height: 10px; + -webkit-transform-origin: 50% 0; + -ms-transform-origin: 50% 0; + transform-origin: 50% 0; + -webkit-transform: scale(0.75) translateY(-21px); + -ms-transform: scale(0.75) translateY(-21px); + transform: scale(0.75) translateY(-21px); + -webkit-transition: all 0.2s cubic-bezier(0.5, 0, 0, 1.25), opacity 0.15s ease-out; + transition: all 0.2s cubic-bezier(0.5, 0, 0.08, 1.10), opacity 0.15s ease-out; + z-index: 9; +} +.nice-select.reverse .list { + bottom: calc(100% + 5px); + top: auto; +} +.toolbar .nice-select .list { + position: fixed; + top: auto; + left: auto; +} +.nice-select .list:hover .option:not(:hover) { + background-color: transparent !important; +} +.nice-select .option { + cursor: pointer; + font-weight: 400; + line-height: 35px; + list-style: none; + min-height: 35px; + outline: none; + margin: 0; + padding-left: 8px; + padding-right: 8px; + text-align: left; + -webkit-transition: all 0.2s; + transition: all 0.2s; + text-transform: capitalize; +} +.nice-select .option:hover,.nice-select .option.focus,.nice-select .option.selected.focus { + background-color: #f6f6f6; +} +.nice-select .option.selected { + font-weight: bold; +} +.nice-select .option.disabled { + background-color: transparent; + color: #999; + cursor: default; +} + .no-csspointerevents.nice-select .list { + display: none; +} + .no-csspointerevents.nice-select.open .list { + display: block; +} diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 2732f3492..673a6aa1d 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -555,6 +555,7 @@ var pad = { pad.changeViewOption('rtlIsTrue', true); } pad.changeViewOption('padFontFamily', padcookie.getPref("padFontFamily")); + $('#viewfontmenu').val(padcookie.getPref("padFontFamily")).niceSelect('update'); hooks.aCallAll("postAceInit", {ace: padeditor.ace, pad: pad}); } diff --git a/src/static/js/pad_editbar.js b/src/static/js/pad_editbar.js index 21e2d4f87..c400387bd 100644 --- a/src/static/js/pad_editbar.js +++ b/src/static/js/pad_editbar.js @@ -25,6 +25,7 @@ var padutils = require('./pad_utils').padutils; var padeditor = require('./pad_editor').padeditor; var padsavedrevs = require('./pad_savedrevs'); var _ = require('ep_etherpad-lite/static/js/underscore'); +require('ep_etherpad-lite/static/js/vendors/nice-select'); var ToolbarItem = function (element) { this.$el = element; @@ -168,6 +169,8 @@ var padeditbar = (function() toolbar: self, ace: padeditor.ace }); + + $('select').niceSelect(); }, isEnabled: function() { diff --git a/src/static/js/vendors/nice-select.js b/src/static/js/vendors/nice-select.js new file mode 100644 index 000000000..cbd978ac7 --- /dev/null +++ b/src/static/js/vendors/nice-select.js @@ -0,0 +1,209 @@ +/* jQuery Nice Select - v1.1.0 + https://github.com/hernansartorio/jquery-nice-select + Made by Hernán Sartorio */ + +(function($) { + + $.fn.niceSelect = function(method) { + + // Methods + if (typeof method == 'string') { + if (method == 'update') { + this.each(function() { + var $select = $(this); + var $dropdown = $(this).next('.nice-select'); + var open = $dropdown.hasClass('open'); + + if ($dropdown.length) { + $dropdown.remove(); + create_nice_select($select); + + if (open) { + $select.next().trigger('click'); + } + } + }); + } else if (method == 'destroy') { + this.each(function() { + var $select = $(this); + var $dropdown = $(this).next('.nice-select'); + + if ($dropdown.length) { + $dropdown.remove(); + $select.css('display', ''); + } + }); + if ($('.nice-select').length == 0) { + $(document).off('.nice_select'); + } + } else { + console.log('Method "' + method + '" does not exist.') + } + return this; + } + + // Hide native select + this.hide(); + + // Create custom markup + this.each(function() { + var $select = $(this); + + if (!$select.next().hasClass('nice-select')) { + create_nice_select($select); + } + }); + + function create_nice_select($select) { + $select.after($('
') + .addClass('nice-select') + .addClass($select.attr('class') || '') + .addClass($select.attr('disabled') ? 'disabled' : '') + .attr('tabindex', $select.attr('disabled') ? null : '0') + .html('') + ); + + var $dropdown = $select.next(); + var $options = $select.find('option'); + var $selected = $select.find('option:selected'); + + $dropdown.find('.current').html($selected.data('display') || $selected.text()); + + $options.each(function(i) { + var $option = $(this); + var display = $option.data('display'); + + $dropdown.find('ul').append($('
  • ') + .attr('data-value', $option.val()) + .attr('data-display', (display || null)) + .addClass('option' + + ($option.is(':selected') ? ' selected' : '') + + ($option.is(':disabled') ? ' disabled' : '')) + .html($option.text()) + ); + }); + } + + /* Event listeners */ + + // Unbind existing events in case that the plugin has been initialized before + $(document).off('.nice_select'); + + // Open/close + $(document).on('click.nice_select', '.nice-select', function(event) { + var $dropdown = $(this); + + $('.nice-select').not($dropdown).removeClass('open'); + + $dropdown.toggleClass('open'); + + if ($dropdown.hasClass('open')) { + $dropdown.find('.option'); + $dropdown.find('.focus').removeClass('focus'); + $dropdown.find('.selected').addClass('focus'); + if ($dropdown.closest('.toolbar').length > 0) { + $dropdown.find('.list').css('left', $dropdown.offset().left); + $dropdown.find('.list').css('top', $dropdown.offset().top + $dropdown.outerHeight()); + $dropdown.find('.list').css('min-width', $dropdown.outerWidth() + 'px'); + } + + $listHeight = $dropdown.find('.list').outerHeight(); + $top = $dropdown.parent().offset().top; + $bottom = $('body').height() - $top; + $maxListHeight = $bottom - $dropdown.outerHeight() - 20; + if ($maxListHeight < 200) { + $dropdown.addClass('reverse'); + $maxListHeight = 250; + } else { + $dropdown.removeClass('reverse') + } + $dropdown.find('.list').css('max-height', $maxListHeight + 'px'); + + } else { + $dropdown.focus(); + } + }); + + // Close when clicking outside + $(document).on('click.nice_select', function(event) { + if ($(event.target).closest('.nice-select').length === 0) { + $('.nice-select').removeClass('open').find('.option'); + } + }); + + // Option click + $(document).on('click.nice_select', '.nice-select .option:not(.disabled)', function(event) { + var $option = $(this); + var $dropdown = $option.closest('.nice-select'); + + $dropdown.find('.selected').removeClass('selected'); + $option.addClass('selected'); + + var text = $option.data('display') || $option.text(); + $dropdown.find('.current').text(text); + + $dropdown.prev('select').val($option.data('value')).trigger('change'); + }); + + // Keyboard events + $(document).on('keydown.nice_select', '.nice-select', function(event) { + var $dropdown = $(this); + var $focused_option = $($dropdown.find('.focus') || $dropdown.find('.list .option.selected')); + + // Space or Enter + if (event.keyCode == 32 || event.keyCode == 13) { + if ($dropdown.hasClass('open')) { + $focused_option.trigger('click'); + } else { + $dropdown.trigger('click'); + } + return false; + // Down + } else if (event.keyCode == 40) { + if (!$dropdown.hasClass('open')) { + $dropdown.trigger('click'); + } else { + var $next = $focused_option.nextAll('.option:not(.disabled)').first(); + if ($next.length > 0) { + $dropdown.find('.focus').removeClass('focus'); + $next.addClass('focus'); + } + } + return false; + // Up + } else if (event.keyCode == 38) { + if (!$dropdown.hasClass('open')) { + $dropdown.trigger('click'); + } else { + var $prev = $focused_option.prevAll('.option:not(.disabled)').first(); + if ($prev.length > 0) { + $dropdown.find('.focus').removeClass('focus'); + $prev.addClass('focus'); + } + } + return false; + // Esc + } else if (event.keyCode == 27) { + if ($dropdown.hasClass('open')) { + $dropdown.trigger('click'); + } + // Tab + } else if (event.keyCode == 9) { + if ($dropdown.hasClass('open')) { + return false; + } + } + }); + + // Detect CSS pointer-events support, for IE <= 10. From Modernizr. + var style = document.createElement('a').style; + style.cssText = 'pointer-events:auto'; + if (style.pointerEvents !== 'auto') { + $('html').addClass('no-csspointerevents'); + } + + return this; + + }; + +}(jQuery)); \ No newline at end of file diff --git a/src/static/skins/colibris/src/components/form.css b/src/static/skins/colibris/src/components/form.css index 03504999f..9cb021cd0 100644 --- a/src/static/skins/colibris/src/components/form.css +++ b/src/static/skins/colibris/src/components/form.css @@ -1,20 +1,35 @@ -input[type="text"], select { +input[type="text"], select, textarea, .nice-select { border-radius: 3px; box-shadow: none; border: none; outline: 0; } -input[type="text"] { +input[type="text"], textarea { padding: 8px 10px; background-color: var(--bg-color); border: 1px solid var(--border-color); } -select { +select, .nice-select { background-color: var(--bg-soft-color); border: none; padding: 4px 10px; + padding-right: 25px; font-weight: bold; + line-height: inherit; +} +.nice-select .list { + background-color: var(--bg-soft-color); +} +.nice-select .option:hover,.nice-select .option.focus,.nice-select .option.selected.focus { + background-color: var(--bg-color); +} +.nice-select .option { + padding: 0 15px; +} +.popup .nice-select .list { + right: 0; + left: auto; } diff --git a/src/static/skins/colibris/src/components/popup.css b/src/static/skins/colibris/src/components/popup.css index c34dee37c..f4d25c27c 100644 --- a/src/static/skins/colibris/src/components/popup.css +++ b/src/static/skins/colibris/src/components/popup.css @@ -34,7 +34,7 @@ width: 120px; display: inline-block; } -.popup .dropdowns-container select { +.popup .dropdowns-container .nice-select { min-width: 180px; } diff --git a/src/static/skins/colibris/src/components/scrollbars.css b/src/static/skins/colibris/src/components/scrollbars.css index 128d878d6..202d49dc5 100644 --- a/src/static/skins/colibris/src/components/scrollbars.css +++ b/src/static/skins/colibris/src/components/scrollbars.css @@ -30,4 +30,18 @@ border-radius: 7px; background-color: var(--scrollbar-thumb); border: 5px solid var(--scrollbar-bg); +} + +.nice-select .list::-webkit-scrollbar-track { + background-color: var(--bg-soft-color); + border: 0px solid var(--bg-soft-color); +} + +.nice-select .list::-webkit-scrollbar { + width: 6px; +} + +.nice-select .list::-webkit-scrollbar-thumb { + background-color: var(--text-soft-color); + border: 0px solid var(--bg-soft-color); } \ No newline at end of file diff --git a/src/templates/pad.html b/src/templates/pad.html index c7a5aed8d..d84a69aab 100644 --- a/src/templates/pad.html +++ b/src/templates/pad.html @@ -62,7 +62,7 @@ -
    +