mirror of
https://github.com/Choices-js/Choices.git
synced 2024-05-23 16:02:21 +02:00
Split mousedown function into onClick & onMouseDown - maintaining default select actions
This commit is contained in:
parent
8cfa698746
commit
4ff68b60dc
4
assets/scripts/dist/choices.min.js
vendored
4
assets/scripts/dist/choices.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -118,6 +118,7 @@ export class Choices {
|
|||
this._onBlur = this._onBlur.bind(this);
|
||||
this._onKeyUp = this._onKeyUp.bind(this);
|
||||
this._onKeyDown = this._onKeyDown.bind(this);
|
||||
this._onClick = this._onClick.bind(this);
|
||||
this._onTouchMove = this._onTouchMove.bind(this);
|
||||
this._onTouchEnd = this._onTouchEnd.bind(this);
|
||||
this._onMouseDown = this._onMouseDown.bind(this);
|
||||
|
@ -396,7 +397,8 @@ export class Choices {
|
|||
* @public
|
||||
*/
|
||||
toggleDropdown() {
|
||||
if(this.dropdown.classList.contains(this.config.classNames.activeState)) {
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.config.classNames.activeState);
|
||||
if(hasActiveDropdown) {
|
||||
this.hideDropdown()
|
||||
} else {
|
||||
this.showDropdown();
|
||||
|
@ -743,7 +745,7 @@ export class Choices {
|
|||
const currentValue = isType('String', this.currentValue) ? this.currentValue.trim() : this.currentValue;
|
||||
|
||||
if(newValue.length >= 1 && newValue !== currentValue + ' ') {
|
||||
const haystack = this.store.getChoicesFiltedBySelectable();
|
||||
const haystack = this.store.getChoicesFilteredBySelectable();
|
||||
const needle = newValue;
|
||||
|
||||
const keys = isType('Array', this.config.sortFields) ? this.config.sortFields : [this.config.sortFields];
|
||||
|
@ -981,15 +983,16 @@ export class Choices {
|
|||
} else {
|
||||
// If user has removed value...
|
||||
if((e.keyCode === backKey || e.keyCode === deleteKey) && !e.target.value) {
|
||||
// ...and it is a multiple select input, activate choices
|
||||
if(this.passedElement.type === 'select-multiple') {
|
||||
// ...and it is a multiple select input, activate choices (if searching)
|
||||
if(this.passedElement.type !== 'text' && this.isSearching) {
|
||||
this.isSearching = false;
|
||||
this.store.dispatch(activateChoices(true));
|
||||
}
|
||||
}
|
||||
// If we have enabled text search
|
||||
if(this.canSearch) {
|
||||
this._searchChoices(this.input.value);
|
||||
} else {
|
||||
// If we have enabled text search
|
||||
if(this.canSearch) {
|
||||
this._searchChoices(this.input.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1004,9 +1007,9 @@ export class Choices {
|
|||
if(this.passedElement.type !== 'select-one') {
|
||||
if (this.config.placeholder && (this.config.placeholderValue || this.passedElement.getAttribute('placeholder'))) {
|
||||
// If there is a placeholder, we only want to set the width of the input when it is a greater
|
||||
// length than the placeholder. This stops the input jumping around.
|
||||
// length than 75% of the placeholder. This stops the input jumping around.
|
||||
const placeholder = this.config.placeholderValue || this.passedElement.getAttribute('placeholder');
|
||||
if(this.input.value && this.input.value.length > placeholder.length) {
|
||||
if(this.input.value && this.input.value.length >= (placeholder.length / 1.25)) {
|
||||
this.input.style.width = getWidthOfInput(this.input);
|
||||
}
|
||||
} else {
|
||||
|
@ -1064,37 +1067,21 @@ export class Choices {
|
|||
}
|
||||
|
||||
/**
|
||||
* Click event
|
||||
* Mouse down event
|
||||
* @param {Object} e Event
|
||||
* @return
|
||||
* @private
|
||||
*/
|
||||
_onMouseDown(e) {
|
||||
const activeItems = this.store.getItemsFilteredByActive();
|
||||
const target = e.target;
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.config.classNames.activeState);
|
||||
|
||||
// If click is affecting a child node of our element
|
||||
if(this.containerOuter.contains(target)) {
|
||||
if(this.containerOuter.contains(target) && target !== this.input) {
|
||||
|
||||
const activeItems = this.store.getItemsFilteredByActive();
|
||||
const hasShiftKey = e.shiftKey ? true : false;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
// If dropdown is not active...
|
||||
if(!hasActiveDropdown) {
|
||||
if(this.passedElement.type === 'text') {
|
||||
if(document.activeElement !== this.input) {
|
||||
this.input.focus();
|
||||
}
|
||||
} else {
|
||||
this.showDropdown();
|
||||
if(this.canSearch && document.activeElement !== this.input) {
|
||||
this.input.focus();
|
||||
}
|
||||
}
|
||||
} else if(this.passedElement.type === 'select-one' && hasActiveDropdown) {
|
||||
this.hideDropdown();
|
||||
if(target !== this.input) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
if(target.hasAttribute('data-button')) {
|
||||
|
@ -1106,8 +1093,6 @@ export class Choices {
|
|||
// Remove item associated with button
|
||||
this._removeItem(itemToRemove);
|
||||
this._triggerChange(itemToRemove.value);
|
||||
|
||||
e.preventDefault();
|
||||
}
|
||||
} else if(target.hasAttribute('data-item')) {
|
||||
// If we are clicking on an item
|
||||
|
@ -1126,16 +1111,13 @@ export class Choices {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
e.preventDefault();
|
||||
}
|
||||
} else if(target.hasAttribute('data-choice')) {
|
||||
// If we are clicking on an option
|
||||
const id = target.getAttribute('data-id');
|
||||
const choices = this.store.getChoicesFilteredByActive();
|
||||
const choice = choices.find((choice) => choice.id === parseInt(id));
|
||||
const choice = this.store.getChoiceById(id);
|
||||
|
||||
if(!choice.selected && !choice.disabled) {
|
||||
if(choice && !choice.selected && !choice.disabled) {
|
||||
this._addItem(choice.value, choice.label, choice.id);
|
||||
this._triggerChange(choice.value);
|
||||
if(this.passedElement.type === 'select-one') {
|
||||
|
@ -1146,14 +1128,52 @@ export class Choices {
|
|||
this.store.dispatch(activateChoices(true));
|
||||
this.hideDropdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
/**
|
||||
* Click event
|
||||
* @param {Object} e Event
|
||||
* @return
|
||||
* @private
|
||||
*/
|
||||
_onClick(e) {
|
||||
const target = e.target;
|
||||
const activeItems = this.store.getItemsFilteredByActive();
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.config.classNames.activeState);
|
||||
|
||||
if(this.containerOuter.contains(target)) {
|
||||
// If click is affecting a child node of our element
|
||||
|
||||
const hasShiftKey = e.shiftKey ? true : false;
|
||||
|
||||
// If dropdown is not active...
|
||||
if(!hasActiveDropdown) {
|
||||
if(this.passedElement.type === 'text') {
|
||||
if(document.activeElement !== this.input) {
|
||||
this.input.focus();
|
||||
}
|
||||
} else {
|
||||
this.showDropdown();
|
||||
if(this.canSearch && document.activeElement !== this.input) {
|
||||
this.input.focus();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(this.passedElement.type === 'select-one' && hasActiveDropdown) {
|
||||
if(target !== this.input) {
|
||||
this.hideDropdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Click is outside of our element so close dropdown and de-select items
|
||||
const hasHighlightedItems = activeItems.some((item) => item.highlighted === true);
|
||||
|
||||
const hasHighlightedItems = activeItems.some((item) => item.highlighted === true);
|
||||
|
||||
// De-select any highlighted items
|
||||
if(hasHighlightedItems) {
|
||||
|
@ -1229,7 +1249,6 @@ export class Choices {
|
|||
this.input.focus();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1893,6 +1912,7 @@ export class Choices {
|
|||
_addEventListeners() {
|
||||
document.addEventListener('keyup', this._onKeyUp);
|
||||
document.addEventListener('keydown', this._onKeyDown);
|
||||
document.addEventListener('click', this._onClick);
|
||||
document.addEventListener('touchmove', this._onTouchMove);
|
||||
document.addEventListener('touchend', this._onTouchEnd);
|
||||
document.addEventListener('mousedown', this._onMouseDown);
|
||||
|
@ -1917,6 +1937,7 @@ export class Choices {
|
|||
_removeEventListeners() {
|
||||
document.removeEventListener('keyup', this._onKeyUp);
|
||||
document.removeEventListener('keydown', this._onKeyDown);
|
||||
document.removeEventListener('click', this._onClick);
|
||||
document.removeEventListener('touchmove', this._onTouchMove);
|
||||
document.removeEventListener('touchend', this._onTouchEnd);
|
||||
document.removeEventListener('mousedown', this._onMouseDown);
|
||||
|
|
|
@ -102,7 +102,7 @@ export class Store {
|
|||
* Get selectable choices from store
|
||||
* @return {Array} Option objects
|
||||
*/
|
||||
getChoicesFiltedBySelectable() {
|
||||
getChoicesFilteredBySelectable() {
|
||||
const choices = this.getChoices();
|
||||
const values = choices.filter((choice) => {
|
||||
return choice.disabled !== true;
|
||||
|
@ -111,6 +111,18 @@ export class Store {
|
|||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single choice by it's ID
|
||||
* @return {Object} Found choice
|
||||
*/
|
||||
getChoiceById(id) {
|
||||
if(!id) return;
|
||||
const choices = this.getChoicesFilteredByActive();
|
||||
const foundChoice = choices.find((choice) => choice.id === parseInt(id));
|
||||
|
||||
return foundChoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get groups from store
|
||||
* @return {Array} Group objects
|
||||
|
|
|
@ -26,7 +26,8 @@ label {
|
|||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500; }
|
||||
font-weight: 500;
|
||||
cursor: pointer; }
|
||||
|
||||
hr {
|
||||
display: block;
|
||||
|
@ -46,6 +47,19 @@ a, a:visited, a:focus {
|
|||
text-decoration: none;
|
||||
font-weight: 600; }
|
||||
|
||||
.form-control {
|
||||
display: block;
|
||||
width: 100%;
|
||||
background-color: #f9f9f9;
|
||||
padding: 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 2.5px;
|
||||
font-size: 14px;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
margin-bottom: 24px; }
|
||||
|
||||
h1, .h1 {
|
||||
font-size: 32px; }
|
||||
|
||||
|
|
2
assets/styles/css/base.min.css
vendored
2
assets/styles/css/base.min.css
vendored
|
@ -1 +1 @@
|
|||
*{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,:after,:before{box-sizing:border-box}body,html{position:relative;margin:0;width:100%;height:100%}body{font-family:"Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;font-size:16px;line-height:1.4;color:#fff;background-color:#333;overflow-x:hidden}hr,label{display:block}label{margin-bottom:8px;font-size:14px;font-weight:500}hr{margin:36px 0;border:0;border-bottom:1px solid #eaeaea;height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:12px;font-weight:400;line-height:1.2}a,a:focus,a:visited{color:#fff;text-decoration:none;font-weight:600}.h1,h1{font-size:32px}.h2,h2{font-size:24px}.h3,h3{font-size:20px}.h4,h4{font-size:18px}.h5,h5{font-size:16px}.h6,h6{font-size:14px}.container{display:block;margin:auto;max-width:40em;padding:48px}@media (max-width:620px){.container{padding:0}}.section{background-color:#fff;padding:24px;color:#333}.section a,.section a:focus,.section a:visited{color:#00bcd4}.logo{width:100%;height:auto;display:inline-block;max-width:100%;vertical-align:top;padding:6px 0}.visible-ie{display:none}
|
||||
*{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,:after,:before{box-sizing:border-box}body,html{position:relative;margin:0;width:100%;height:100%}body{font-family:"Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;font-size:16px;line-height:1.4;color:#fff;background-color:#333;overflow-x:hidden}hr,label{display:block}label{margin-bottom:8px;font-size:14px;font-weight:500;cursor:pointer}hr{margin:36px 0;border:0;border-bottom:1px solid #eaeaea;height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:12px;font-weight:400;line-height:1.2}a,a:focus,a:visited{color:#fff;text-decoration:none;font-weight:600}.form-control{display:block;width:100%;background-color:#f9f9f9;padding:12px;border:1px solid #ddd;border-radius:2.5px;font-size:14px;-webkit-appearance:none;-moz-appearance:none;appearance:none;margin-bottom:24px}.h1,h1{font-size:32px}.h2,h2{font-size:24px}.h3,h3{font-size:20px}.h4,h4{font-size:18px}.h5,h5{font-size:16px}.h6,h6{font-size:14px}.container{display:block;margin:auto;max-width:40em;padding:48px}@media (max-width:620px){.container{padding:0}}.section{background-color:#fff;padding:24px;color:#333}.section a,.section a:focus,.section a:visited{color:#00bcd4}.logo{width:100%;height:auto;display:inline-block;max-width:100%;vertical-align:top;padding:6px 0}.visible-ie{display:none}
|
|
@ -42,6 +42,7 @@ label {
|
|||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
hr {
|
||||
|
@ -65,6 +66,19 @@ a, a:visited, a:focus {
|
|||
font-weight: 600;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
display: block;
|
||||
width: 100%;
|
||||
background-color: #f9f9f9;
|
||||
padding: 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 2.5px;
|
||||
font-size: 14px;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
margin-bottom: $global-guttering;
|
||||
}
|
||||
|
||||
h1, .h1 { font-size: $global-font-size-h1; }
|
||||
h2, .h2 { font-size: $global-font-size-h2; }
|
||||
h3, .h3 { font-size: $global-font-size-h3; }
|
||||
|
|
38
index.html
38
index.html
|
@ -31,28 +31,28 @@
|
|||
<hr>
|
||||
<h2>Text inputs</h2>
|
||||
<label for="choices-1">Limited to 5 values</label>
|
||||
<input id="choices-1" type="text" value="preset-1,preset-2" placeholder="Enter something">
|
||||
<input class="form-control" id="choices-1" type="text" value="preset-1,preset-2" placeholder="Enter something">
|
||||
|
||||
<label for="choices-2">Unique values only, no pasting</label>
|
||||
<input id="choices-2" type="text" value="preset-1, preset-2" placeholder="This is a placeholder" class="custom class">
|
||||
<input class="form-control" id="choices-2" type="text" value="preset-1, preset-2" placeholder="This is a placeholder" class="custom class">
|
||||
|
||||
<label for="choices-3">Email addresses only</label>
|
||||
<input id="choices-3" type="text" placeholder="This is a placeholder">
|
||||
<input class="form-control" id="choices-3" type="text" placeholder="This is a placeholder">
|
||||
|
||||
<label for="choices-4">Disabled</label>
|
||||
<input id="choices-4" type="text" value="josh@joshuajohnson.co.uk, joe@bloggs.co.uk" placeholder="This is a placeholder">
|
||||
<input class="form-control" id="choices-4" type="text" value="josh@joshuajohnson.co.uk, joe@bloggs.co.uk" placeholder="This is a placeholder">
|
||||
|
||||
<label for="choices-5">Prepends and appends a value to each items return value</label>
|
||||
<input id="choices-5" type="text" value="preset-1, preset-2" placeholder="This is a placeholder">
|
||||
<input class="form-control" id="choices-5" type="text" value="preset-1, preset-2" placeholder="This is a placeholder">
|
||||
|
||||
<label for="choices-6">Preset values passed through options</label>
|
||||
<input id="choices-6" type="text" value="olivia@benson.com" placeholder="This is a placeholder">
|
||||
<input class="form-control" id="choices-6" type="text" value="olivia@benson.com" placeholder="This is a placeholder">
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Multiple select input</h2>
|
||||
<label for="choices-7">Default</label>
|
||||
<select data-choice name="choices-7" id="choices-7" placeholder="This is a placeholder" multiple>
|
||||
<select class="form-control" data-choice name="choices-7" id="choices-7" placeholder="This is a placeholder" multiple>
|
||||
<option value="Dropdown item 1">Dropdown item 1</option>
|
||||
<option value="Dropdown item 2">Dropdown item 2</option>
|
||||
<option value="Dropdown item 3" selected>Dropdown item 3</option>
|
||||
|
@ -60,14 +60,14 @@
|
|||
</select>
|
||||
|
||||
<label for="choices-8">With pre-selected option</label>
|
||||
<select data-choice name="choices-8" id="choices-8" placeholder="Choose an option" multiple>
|
||||
<select class="form-control" data-choice name="choices-8" id="choices-8" placeholder="Choose an option" multiple>
|
||||
<option value="Dropdown item 1">Dropdown item 1</option>
|
||||
<option value="Dropdown item 2" selected>Dropdown item 2</option>
|
||||
<option value="Dropdown item 3">Dropdown item 3</option>
|
||||
</select>
|
||||
|
||||
<label for="choices-9">Option groups</label>
|
||||
<select data-choice name="choices-9" id="choices-9" placeholder="This is a placeholder" multiple>
|
||||
<select class="form-control" data-choice name="choices-9" id="choices-9" placeholder="This is a placeholder" multiple>
|
||||
<optgroup label="UK">
|
||||
<option value="London">London</option>
|
||||
<option value="Manchester">Manchester</option>
|
||||
|
@ -101,26 +101,26 @@
|
|||
</select>
|
||||
|
||||
<label for="choices-10">Options from remote source (Fetch API)</label>
|
||||
<select name="choices-10" id="choices-10" placeholder="Pick an Arctic Monkeys record" multiple></select>
|
||||
<select class="form-control" name="choices-10" id="choices-10" placeholder="Pick an Arctic Monkeys record" multiple></select>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Single select input</h2>
|
||||
<label for="choices-11">Default</label>
|
||||
<select data-choice name="choices-11" id="choices-11" placeholder="This is a placeholder">
|
||||
<select class="form-control" data-choice name="choices-11" id="choices-11" placeholder="This is a placeholder">
|
||||
<option value="Dropdown item 1">Dropdown item 1</option>
|
||||
<option value="Dropdown item 2">Dropdown item 2</option>
|
||||
<option value="Dropdown item 3">Dropdown item 3</option>
|
||||
</select>
|
||||
|
||||
<label for="choices-12">Options from remote source (Fetch API)</label>
|
||||
<select name="choices-12" id="choices-12" placeholder="Pick an Arctic Monkeys record"></select>
|
||||
<select class="form-control" name="choices-12" id="choices-12" placeholder="Pick an Arctic Monkeys record"></select>
|
||||
|
||||
<label for="choices-14">Options from remote source (XHR)</label>
|
||||
<select name="choices-14" id="choices-14" placeholder="Pick a Smiths record"></select>
|
||||
<select class="form-control" name="choices-14" id="choices-14" placeholder="Pick a Smiths record"></select>
|
||||
|
||||
<label for="choices-13">Option groups</label>
|
||||
<select data-choice name="choices-13" id="choices-13" placeholder="This is a placeholder">
|
||||
<select class="form-control" data-choice name="choices-13" id="choices-13" placeholder="This is a placeholder">
|
||||
<optgroup label="UK">
|
||||
<option value="London">London</option>
|
||||
<option value="Manchester">Manchester</option>
|
||||
|
@ -154,19 +154,19 @@
|
|||
</select>
|
||||
|
||||
<label for="choices-15">Options added via config with no search</label>
|
||||
<select name="choices-15" id="choices-15" placeholder="This is a placeholder">
|
||||
<select class="form-control" name="choices-15" id="choices-15" placeholder="This is a placeholder">
|
||||
<option value="0">Zero</option>
|
||||
</select>
|
||||
|
||||
<label for="choices-16">Option and option groups added via config</label>
|
||||
<select name="choices-16" id="choices-16" placeholder="This is a placeholder"></select>
|
||||
<select class="form-control" name="choices-16" id="choices-16" placeholder="This is a placeholder"></select>
|
||||
|
||||
<label for="choices-17">Option selected via config</label>
|
||||
<select name="choices-17" id="choices-17" placeholder="This is a placeholder"></select>
|
||||
<select class="form-control" name="choices-17" id="choices-17" placeholder="This is a placeholder"></select>
|
||||
|
||||
<p>Below is an example of how you could have two select inputs depend on eachother. 'Boroughs' will only be enabled if the value of 'States' is 'New York'</p>
|
||||
<label for="cities">States</label>
|
||||
<select name="cities" id="cities" placeholder="Choose a state">
|
||||
<select class="form-control" name="cities" id="cities" placeholder="Choose a state">
|
||||
<option value="Texas">Texas</option>
|
||||
<option value="Chicago">Chicago</option>
|
||||
<option value="New York">New York</option>
|
||||
|
@ -175,7 +175,7 @@
|
|||
</select>
|
||||
|
||||
<label for="boroughs">Boroughs</label>
|
||||
<select name="boroughs" id="boroughs" placeholder="Choose a borough">
|
||||
<select class="form-control" name="boroughs" id="boroughs" placeholder="Choose a borough">
|
||||
<option value="The Bronx">The Bronx</option>
|
||||
<option value="Brooklyn">Brooklyn</option>
|
||||
<option value="Manhatten">Manhatten</option>
|
||||
|
|
Loading…
Reference in a new issue