Browse Source

Multiple select dropdown now uses a sizer element to determine current text width, instead of estimating based on character count

pull/3975/head
Jack Lukic 9 years ago
parent
commit
664a9d9032
4 changed files with 49 additions and 19 deletions
  1. 1
      RELEASE-NOTES.md
  2. 47
      src/definitions/modules/dropdown.js
  3. 8
      src/definitions/modules/dropdown.less
  4. 12
      src/themes/default/modules/dropdown.variables

1
RELEASE-NOTES.md

@ -5,6 +5,7 @@
**Major Enhancements**
- **Webpack** - Modified all relative paths in project to prefix with `./` to make them webpack friendly (wont be misinterpreted as module)
- **Popup** - Added new settings `autoRemove`, which is enabled by default. This will add special event listeners to auto hide a popup if the triggering element is removed from the DOM. This is useful in controlled DOM environments like Meteor/Ember/React to ensure a popup auto-hides itself when a page navigation or other DOM change occurs that may not trigger `mouseout`.
- **Dropdown** - Multiple select dropdown now sizes current dropdown input based on rendered width of a hidden element, not using an estimate based on character count. This means search will never break to a second line earlier than would normally fit in current line.
- **Dropdown** - Added new setting for search selection `hideAdditions` this will remove showing user additions inside the menu, making for a more intuitive adding process. Dropdowns now have a new state `empty` which will format an active dropdown with empty results. #3791
- **All UI** - All UI now include _all_ sizing variations, `mini`, `tiny`, `small`, `large`, `big`, `huge`, `massive`. Headers remain with only 5 sizes `small-huge` to match `H1-H5`
- **Icons** - Icons now use the latest Font Awesome `4.5.0` Icons. 50+ new icons+ are included. Thanks @BreadMaker for the PR and @davegandy for the font!

47
src/definitions/modules/dropdown.js

@ -62,6 +62,7 @@ $.fn.dropdown = function(parameters) {
$context = $(settings.context),
$text = $module.find(selector.text),
$search = $module.find(selector.search),
$sizer = $module.find(selector.sizer),
$input = $module.find(selector.input),
$icon = $module.find(selector.icon),
@ -227,6 +228,12 @@ $.fn.dropdown = function(parameters) {
.addClass(className.menu)
.appendTo($module)
;
},
sizer: function() {
$sizer = $('<span />')
.addClass(className.sizer)
.insertAfter($search)
;
}
},
@ -306,6 +313,9 @@ $.fn.dropdown = function(parameters) {
.insertBefore($text)
;
}
if( module.is.multiple() && module.is.searchSelection() && !module.has.sizer()) {
module.create.sizer();
}
if(settings.allowTab) {
module.set.tabbable();
}
@ -1406,11 +1416,11 @@ $.fn.dropdown = function(parameters) {
module.verbose('Determining action', settings.action);
if( $.isFunction( module.action[settings.action] ) ) {
module.verbose('Triggering preset action', settings.action, text, value);
module.action[ settings.action ].call(this, text, value);
module.action[ settings.action ].call(element, text, value, this);
}
else if( $.isFunction(settings.action) ) {
module.verbose('Triggering user action', settings.action, text, value);
settings.action.call(this, text, value);
settings.action.call(element, text, value, this);
}
else {
module.error(error.action, settings.action);
@ -1464,13 +1474,13 @@ $.fn.dropdown = function(parameters) {
nothing: function() {},
activate: function(text, value) {
activate: function(text, value, element) {
value = (value !== undefined)
? value
: text
;
if( module.can.activate( $(this) ) ) {
module.set.selected(value, $(this));
if( module.can.activate( $(element) ) ) {
module.set.selected(value, $(element));
if(module.is.multiple() && !module.is.allFiltered()) {
return;
}
@ -1480,21 +1490,21 @@ $.fn.dropdown = function(parameters) {
}
},
select: function(text, value) {
select: function(text, value, element) {
// mimics action.activate but does not select text
module.action.activate.call(this);
module.action.activate.call(element);
},
combo: function(text, value) {
combo: function(text, value, element) {
value = (value !== undefined)
? value
: text
;
module.set.selected(value, $(this));
module.set.selected(value, $(element));
module.hideAndClear();
},
hide: function(text, value) {
hide: function(text, value, element) {
module.set.value(value, text);
module.hideAndClear();
}
@ -1520,8 +1530,14 @@ $.fn.dropdown = function(parameters) {
query: function() {
return $.trim($search.val());
},
searchWidth: function(characterCount) {
return (characterCount * settings.glyphWidth) + 'em';
searchWidth: function(value) {
value = (value !== undefined)
? value
: $search.val()
;
$sizer.text(value);
// prevent rounding issues
return Math.ceil( $sizer.width() + 1);
},
selectionCount: function() {
var
@ -2062,7 +2078,7 @@ $.fn.dropdown = function(parameters) {
? module.get.query()
: '',
hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0),
searchWidth = module.get.searchWidth(searchValue.length),
searchWidth = module.get.searchWidth(),
valueIsSet = searchValue !== ''
;
if(isMultiple && hasSearchValue) {
@ -2802,6 +2818,9 @@ $.fn.dropdown = function(parameters) {
search: function() {
return ($search.length > 0);
},
sizer: function() {
return ($sizer.length > 0);
},
selectInput: function() {
return ( $input.is('select') );
},
@ -3508,6 +3527,7 @@ $.fn.dropdown.settings = {
message : '.message',
menuIcon : '.dropdown.icon',
search : 'input.search, .menu > .search > input',
sizer : '> input.sizer',
text : '> .text:not(.icon)',
unselectable : '.disabled, .filtered'
},
@ -3528,6 +3548,7 @@ $.fn.dropdown.settings = {
message : 'message',
multiple : 'multiple',
placeholder : 'default',
sizer : 'sizer',
search : 'search',
selected : 'selected',
selection : 'selection',

8
src/definitions/modules/dropdown.less

@ -575,6 +575,14 @@ select.ui.dropdown {
padding: @searchSelectionInputPadding;
}
/* Used to size multi select input to character width */
.ui.search.selection.dropdown > span.sizer {
line-height: @searchSelectionLineHeight;
padding: @searchSelectionInputPadding;
display: none;
white-space: pre;
}
/* Active/Visible Search */
.ui.search.dropdown.active > input.search,
.ui.search.dropdown.visible > input.search {

12
src/themes/default/modules/dropdown.variables

@ -132,7 +132,7 @@
@selectionMinHeight: @inputLineHeight + (@selectionVerticalPadding * 2) - @selectionBorderEmWidth;
@selectionBackground: @inputBackground;
@selectionDisplay: inline-block;
@selectionIconDistance: @inputHorizontalPadding + @glyphWidth + 0.5em;
@selectionIconDistance: @inputHorizontalPadding + @glyphWidth;
@selectionPadding: @selectionVerticalPadding @selectionIconDistance @selectionVerticalPadding @selectionHorizontalPadding;
@selectionZIndex: 10;
@ -231,10 +231,10 @@
@searchWidescreenMaxMenuHeight: @selectionWidescreenMaxMenuHeight;
/* Inline */
@inlineIconMargin: 0em 0.5em 0em 0.25em;
@inlineIconMargin: 0em @relative7px 0em @relative3px;
@inlineTextColor: inherit;
@inlineTextFontWeight: bold;
@inlineMenuDistance: 0.25em;
@inlineMenuDistance: @relative3px;
@inlineMenuBorderRadius: @borderRadius;
@ -244,7 +244,7 @@
/* Split Actual Padding Between Child and Parent (allows for label spacing) */
@multipleSelectionVerticalPadding: (@searchSelectionVerticalPadding * (1/3));
@multipleSelectionLeftPadding: (@selectionHorizontalPadding - @labelHorizontalPadding);
@multipleSelectionLeftPadding: @relative5px;
@multipleSelectionRightPadding: @selectionIconDistance;
@multipleSelectionPadding: @multipleSelectionVerticalPadding @multipleSelectionRightPadding @multipleSelectionVerticalPadding @multipleSelectionLeftPadding;
@ -256,7 +256,7 @@
@multipleSelectionSearchStartWidth: (@glyphWidth * 2);
/* Dropdown Icon */
@multipleSelectionDropdownIconMargin: -@searchSelectionVerticalPadding -@labelHorizontalPadding 0em 0em;
@multipleSelectionDropdownIconMargin: '';
@multipleSelectionDropdownIconPadding: '';
@multipleSelectionSearchAfterLabelDistance: @relative2px;
@ -264,7 +264,7 @@
/* Selection Label */
@labelSize: @relativeMedium;
@labelHorizontalMargin: @4px;
@labelVerticalMargin: (@relative6px / 2);
@labelVerticalMargin: @2px;
@labelMargin: @labelVerticalMargin @labelHorizontalMargin @labelVerticalMargin 0em;
@labelBorderWidth: 1px;
@labelBoxShadow: 0px 0px 0px @labelBorderWidth @borderColor inset;

Loading…
Cancel
Save