react-super-select
Advanced tools
Comparing version 0.1.18 to 0.1.19
@@ -28,2 +28,5 @@ // © Scotland Stephenson 2015 | ||
// **clearable** *optional* - (default - true) whether or not to show a button to clear selected options | ||
clearable: React.PropTypes.bool, | ||
// **multiple** (Boolean) *optional* - Whether or not the control supports multi-selection. When using the **tags** display option, this option is redundant | ||
@@ -138,2 +141,8 @@ multiple: React.PropTypes.bool, | ||
// **clearSearchLabelString** (String) *optional* - (Used in conjunction with the **clearable** option) This string will be used as an aria-label for the clear selection button | ||
clearSelectionLabelString: React.PropTypes.string, | ||
// **clearSelectionsLabelString** (String) *optional* - (Used in conjunction with the **searchable** option) This string will be used as an aria-label for the clear search button | ||
clearSearchLabelString: React.PropTypes.string, | ||
// **noResultsString** (String) *optional* - A string value which will be displayed when your dropdown shows no results. (i.e. dataSource is an empty collection, or ajaxDataFetch returns an empty collection) | ||
@@ -164,2 +173,4 @@ noResultsString: React.PropTypes.string, | ||
ajaxErrorString: 'An Error occured while fetching options', | ||
clearSelectionLabelString: 'Clear Selection', | ||
clearSearchLabelString: 'Clear Search Field', | ||
noResultsString: 'No Results Available', | ||
@@ -270,3 +281,5 @@ placeholder: 'Select an Option', | ||
render: function render() { | ||
var dropdownContent = this._getDropdownContent(), | ||
var clearSelectionButton = null, | ||
clearSelectionLabelString = this.props.clearSelectionLabelString ? this.props.clearSelectionLabelString : this.DEFAULT_LOCALIZATIONS.clearSelectionLabelString, | ||
dropdownContent = this._getDropdownContent(), | ||
placeholderString, | ||
@@ -281,3 +294,3 @@ triggerDisplayContent, | ||
wrapClasses = classNames('r-ss-wrap', this.props.customClass, { | ||
wrapClasses = classNames("r-ss-wrap", this.props.customClass, { | ||
'r-ss-expanded': this.state.isOpen | ||
@@ -294,2 +307,10 @@ }); | ||
if (!_.isEmpty(this.state.value) && this.props.clearable !== false) { | ||
clearSelectionButton = React.createElement( | ||
'button', | ||
{ 'aria-label': clearSelectionLabelString, ref: 'selectionClear', name: 'clearSelection', type: 'button', className: 'r-ss-selection-clear', onClick: this._clearSelection, onKeyDown: this._clearSelection }, | ||
React.createElement('span', null) | ||
); | ||
} | ||
return React.createElement( | ||
@@ -312,2 +333,3 @@ 'div', | ||
triggerDisplayContent, | ||
clearSelectionButton, | ||
React.createElement( | ||
@@ -350,2 +372,8 @@ 'span', | ||
// helper for stopping event propagation | ||
_arrestEvent: function _arrestEvent(event) { | ||
event.stopPropagation(); | ||
event.preventDefault(); | ||
}, | ||
// calculate the initial value for the control from props, componentWillReceiveProps will call passing nextProps | ||
@@ -367,2 +395,21 @@ _buildInitialValue: function _buildInitialValue(props) { | ||
// clear the searchString value | ||
// for **searchable** controls | ||
_clearSearchString: function _clearSearchString() { | ||
this.setState({ | ||
searchString: undefined | ||
}, this._setFocusIdToSearch); | ||
}, | ||
// clear the selected options | ||
// for **clearable** controls | ||
_clearSelection: function _clearSelection(event) { | ||
if (event.which === this.keymap.enter || event.which === this.keymap.space || event.type === "click") { | ||
event.stopPropagation(); | ||
this.setState({ | ||
value: [] | ||
}, this._focusTrigger); | ||
} | ||
}, | ||
// close the dropdown | ||
@@ -499,2 +546,30 @@ // resets focus to the main control trigger | ||
// shift focus from dropdown trigger to any removal/clear buttons | ||
// for keyboard navigation and accessibility | ||
_focusRemovalButtons: function _focusRemovalButtons(event) { | ||
var triggerContainer = this.refs.triggerDiv.getDOMNode(), | ||
buttons = triggerContainer.getElementsByTagName('button'), | ||
currentlyFocusedRemoveButtonIndex, | ||
nextButtonIndexToFocus; | ||
if (buttons.length) { | ||
for (var i = 0; i < buttons.length; i++) { | ||
if (buttons[i] === document.activeElement) { | ||
currentlyFocusedRemoveButtonIndex = i; | ||
nextButtonIndexToFocus = event.shiftKey ? i - 1 : i + 1; | ||
} | ||
} | ||
} | ||
if (buttons[nextButtonIndexToFocus]) { | ||
this._arrestEvent(event); | ||
buttons[nextButtonIndexToFocus].focus(); | ||
} else if (nextButtonIndexToFocus && nextButtonIndexToFocus < 0) { | ||
this._focusTrigger(); | ||
} else if (buttons[0] && !_.isNumber(currentlyFocusedRemoveButtonIndex)) { | ||
this._arrestEvent(event); | ||
buttons[0].focus(); | ||
} | ||
}, | ||
// focus the main trigger element of the control | ||
@@ -592,4 +667,4 @@ _focusTrigger: function _focusTrigger() { | ||
var headingClasses = classNames('r-ss-option-group-heading', this.props.customGroupHeadingClass), | ||
headingKey = 'heading_' + heading, | ||
var headingClasses = classNames("r-ss-option-group-heading", this.props.customGroupHeadingClass), | ||
headingKey = "heading_" + heading, | ||
headingMarkup = this.props.customGroupHeadingTemplateFunction ? this.props.customGroupHeadingTemplateFunction(heading) : heading; | ||
@@ -624,3 +699,3 @@ | ||
return _.map(this.state.value, function (value) { | ||
var selectedKey = 'r_ss_selected_' + value[this.state.labelKey]; | ||
var selectedKey = "r_ss_selected_" + value[this.state.labelKey]; | ||
if (this.props.customOptionTemplateFunction) { | ||
@@ -640,3 +715,3 @@ return this.props.customOptionTemplateFunction(value); | ||
_getLoadingMarkup: function _getLoadingMarkup() { | ||
var loaderClasses = this.props.customLoaderClass ? 'r-ss-loader ' + this.props.customLoaderClass : 'r-ss-loader'; | ||
var loaderClasses = this.props.customLoaderClass ? "r-ss-loader " + this.props.customLoaderClass : "r-ss-loader"; | ||
return React.createElement('span', { ref: 'loader', className: loaderClasses }); | ||
@@ -701,3 +776,5 @@ }, | ||
var magnifierClass = this.props.customSearchIconClass ? this.props.customSearchIconClass : 'r-ss-magnifier', | ||
var clearSearch = null, | ||
clearSearchLabelString = this.props.clearSearchLabelString ? this.props.clearSearchLabelString : this.DEFAULT_LOCALIZATIONS.clearSearchLabelString, | ||
magnifierClass = this.props.customSearchIconClass ? this.props.customSearchIconClass : "r-ss-magnifier", | ||
searchPlaceholderString = this.props.searchPlaceholder ? this.props.searchPlaceholder : this.DEFAULT_LOCALIZATIONS.searchPlaceholder, | ||
@@ -707,2 +784,10 @@ searchAriaId = this.state.controlId + '_search', | ||
if (_.isString(this.state.searchString)) { | ||
clearSearch = React.createElement( | ||
'button', | ||
{ 'aria-label': clearSearchLabelString, ref: 'searchClear', name: 'clearSearch', type: 'button', className: 'r-ss-search-clear', onClick: this._clearSearchString, onKeyDown: this._clearSearchString }, | ||
React.createElement('span', null) | ||
); | ||
} | ||
return React.createElement( | ||
@@ -723,3 +808,3 @@ 'div', | ||
onChange: this._handleSearch, | ||
defaultValue: this.state.searchString, | ||
value: this.state.searchString, | ||
name: searchAriaId, | ||
@@ -729,2 +814,3 @@ id: searchAriaId, | ||
'aria-autocomplete': 'list' }), | ||
clearSearch, | ||
React.createElement( | ||
@@ -752,8 +838,8 @@ 'i', | ||
tagKey = 'tag_' + displayValue, | ||
buttonName = 'RemoveTag_' + displayValue, | ||
buttonName = "RemoveTag_" + displayValue, | ||
tagRemoveIndex = this._getTagRemoveIndex(displayValue), | ||
tagRemoveButtonLabelString = this.props.tagRemoveLabelString ? this.props.tagRemoveLabelString : this.DEFAULT_LOCALIZATIONS.tagRemoveLabelString, | ||
tagWrapClass = this.props.customTagClass ? 'r-ss-tag ' + this.props.customTagClass : 'r-ss-tag'; | ||
tagWrapClass = this.props.customTagClass ? "r-ss-tag " + this.props.customTagClass : "r-ss-tag"; | ||
tagRemoveButtonLabelString = tagRemoveButtonLabelString + ' ' + label; | ||
tagRemoveButtonLabelString = tagRemoveButtonLabelString + " " + label; | ||
@@ -778,3 +864,3 @@ return React.createElement( | ||
_getTagRemoveIndex: function _getTagRemoveIndex(identifier) { | ||
return 'tag_remove_' + identifier; | ||
return "tag_remove_" + identifier; | ||
}, | ||
@@ -802,4 +888,3 @@ | ||
if (this.state.isOpen || event.which !== this.keymap.tab) { | ||
event.stopPropagation(); | ||
event.preventDefault(); | ||
this._arrestEvent(event); | ||
} | ||
@@ -830,2 +915,4 @@ | ||
this._onEnterKey(event); | ||
} else { | ||
this._focusRemovalButtons(event); | ||
} | ||
@@ -841,4 +928,3 @@ break; | ||
_handleSearch: function _handleSearch(event) { | ||
event.stopPropagation(); | ||
event.preventDefault(); | ||
this._arrestEvent(event); | ||
var searchString = event.target.value; | ||
@@ -883,3 +969,3 @@ this._handleSearchDebounced.call(this, searchString); | ||
var isCurrentlySelected = this._isCurrentlySelected(dataOption), | ||
itemKey = 'drop_li_' + dataOption[this.state.valueKey], | ||
itemKey = "drop_li_" + dataOption[this.state.valueKey], | ||
indexRef = 'option_' + index, | ||
@@ -985,13 +1071,5 @@ ariaDescendantId = this.state.controlId + '_aria_' + indexRef, | ||
var keepControlOpen = this._isMultiSelect() && (event.ctrlKey || event.metaKey), | ||
alreadySelected = this.SELECTED_OPTION_REGEX.test(event.target.getAttribute('class')); | ||
var keepControlOpen = this._isMultiSelect() && (event.ctrlKey || event.metaKey); | ||
if (keepControlOpen && alreadySelected) { | ||
var optionData = _.first(this._findArrayOfOptionDataObjectsByValue(event.target.getAttribute('data-option-value'))); | ||
this._removeSelectedOptionByValue(optionData); | ||
} else { | ||
if (!alreadySelected) { | ||
this._selectFocusedOption(event.target, keepControlOpen); | ||
} | ||
} | ||
this._selectFocusedOption(event.target, keepControlOpen); | ||
}, | ||
@@ -1070,4 +1148,4 @@ | ||
var remainingSelected = _.reject(this.state.value, function (option) { | ||
return _.includes(valuePropsToReject, option[this.state.valueKey]); | ||
var remainingSelected = _.reject(this.state.value, function (opt) { | ||
return _.includes(valuePropsToReject, opt[this.state.valueKey]); | ||
}, this); | ||
@@ -1109,4 +1187,3 @@ | ||
if (isEnterKey || isSpaceKey) { | ||
event.preventDefault(); | ||
event.stopPropagation(); | ||
this._arrestEvent(event); | ||
this._removeSelectedOptionByValue(value, this._setFocusToTagRemovalIfPresent); // delegate to removal handler | ||
@@ -1118,4 +1195,3 @@ } | ||
_removeTagClick: function _removeTagClick(value, event) { | ||
event.preventDefault(); | ||
event.stopPropagation(); | ||
this._arrestEvent(event); | ||
@@ -1139,5 +1215,5 @@ this._removeSelectedOptionByValue(value); | ||
var optionsToSelect = _.reduce(this.state.data, function (memo, option) { | ||
if (_.includes(valuePropsToSelect, option[this.state.valueKey])) { | ||
memo.push(option); | ||
var optionsToSelect = _.reduce(this.state.data, function (memo, opt) { | ||
if (_.includes(valuePropsToSelect, opt[this.state.valueKey])) { | ||
memo.push(opt); | ||
} | ||
@@ -1175,3 +1251,2 @@ return memo; | ||
_selectFocusedOption: function _selectFocusedOption(eventTargetLi, keepControlOpen) { | ||
keepControlOpen = keepControlOpen || false; | ||
@@ -1185,6 +1260,7 @@ var focusedOptionKey = this._getFocusedOptionKey(); | ||
if (keepControlOpen && this.SELECTED_OPTION_REGEX.test(this.refs[focusedOptionKey].props.className)) { | ||
if (this.SELECTED_OPTION_REGEX.test(this.refs[focusedOptionKey].props.className)) { | ||
var optionFullFromValueProp = _.first(this._findArrayOfOptionDataObjectsByValue(optionValue)); | ||
this._removeSelectedOptionByValue(optionFullFromValueProp); | ||
} else { | ||
keepControlOpen = keepControlOpen || false; | ||
this._selectItemByValues(optionValue, keepControlOpen); | ||
@@ -1231,8 +1307,6 @@ } | ||
if (keepControlOpen && alreadySelected) { | ||
if (alreadySelected) { | ||
this._removeSelectedOptionByValue(value); | ||
} else { | ||
if (!alreadySelected) { | ||
this._selectItemByValues(value[this.state.valueKey], keepControlOpen); | ||
} | ||
this._selectItemByValues(value[this.state.valueKey], keepControlOpen); | ||
} | ||
@@ -1239,0 +1313,0 @@ }, |
{ | ||
"name": "react-super-select", | ||
"version": "0.1.18", | ||
"version": "0.1.19", | ||
"description": "A flexible replacement for the html select control built with React", | ||
@@ -15,9 +15,2 @@ "main": "./lib/react-super-select.js", | ||
}, | ||
"dependencies": { | ||
"classnames": "^1.1.4", | ||
"lodash": "^3.7.0" | ||
}, | ||
"peerDependencies": { | ||
"react": ">=0.12.0" | ||
}, | ||
"files": [ | ||
@@ -36,39 +29,53 @@ "lib/" | ||
"devDependencies": { | ||
"babel-core": "^5.4.7", | ||
"babel-eslint": "^4.1.1", | ||
"babel-core": "^5.8.25", | ||
"babel-eslint": "^4.1.3", | ||
"babel-jest": "^5.3.0", | ||
"babelify": "^6.1.1", | ||
"browserify": "^10.2.0", | ||
"browserify-shim": "^3.8.7", | ||
"del": "^1.1.1", | ||
"eslint": "^1.3.1", | ||
"eslint-plugin-react": "^3.3.1", | ||
"gulp": "^3.8.10", | ||
"gulp-babel": "^5.1.0", | ||
"babel-plugin-object-assign": "^1.2.1", | ||
"babelify": "^6.3.0", | ||
"browserify": "^11.2.0", | ||
"browserify-shim": "^3.8.10", | ||
"classnames": "^2.1.5", | ||
"del": "^2.0.2", | ||
"docco": "^0.7.0", | ||
"eslint": "^1.6.0", | ||
"eslint-plugin-react": "^3.5.1", | ||
"gulp": "^3.9.0", | ||
"gulp-babel": "^5.2.1", | ||
"gulp-browserify": "^0.5.1", | ||
"gulp-bump": "^0.3.1", | ||
"gulp-concat": "^2.5.2", | ||
"gulp-bump": "^1.0.0", | ||
"gulp-concat": "^2.6.0", | ||
"gulp-connect": "^2.2.0", | ||
"gulp-eslint": "^1.0.0", | ||
"gulp-gh-pages": "^0.5.1", | ||
"gulp-git": "^1.2.4", | ||
"gulp-gh-pages": "^0.5.2", | ||
"gulp-git": "^1.5.0", | ||
"gulp-less": "^3.0.3", | ||
"gulp-markdown-to-json": "^0.2.1", | ||
"gulp-minify-css": "^1.1.1", | ||
"gulp-minify-css": "^1.2.1", | ||
"gulp-recess": "^1.1.2", | ||
"gulp-rename": "^1.2.2", | ||
"gulp-streamify": "0.0.5", | ||
"gulp-streamify": "^1.0.2", | ||
"gulp-task-listing": "^1.0.1", | ||
"gulp-uglify": "^1.2.0", | ||
"gulp-util": "^3.0.4", | ||
"jest-cli": ">=0.4.0", | ||
"react": "^0.13.3", | ||
"run-sequence": "^1.1.0", | ||
"gulp-uglify": "^1.4.1", | ||
"gulp-util": "^3.0.6", | ||
"jest-cli": "^0.5.10", | ||
"run-sequence": "^1.1.4", | ||
"vinyl-source-stream": "^1.1.0" | ||
}, | ||
"browserify-shim": { | ||
"classnames": "global:classNames", | ||
"lodash": "global:_", | ||
"react": "global:React" | ||
}, | ||
"scripts": { | ||
"test": "$(npm bin)/jest" | ||
"test": "$(npm bin)/jest", | ||
"build": "npm run dist:build && npm run lib:build && npm run docs:build", | ||
"dist:clean": "rm -rf ./dist", | ||
"dist:build": "npm run dist:clean && npm run dist:build-sequence", | ||
"dist:build-sequence": "$(npm bin)/gulp build:dist-gulp-sequence", | ||
"docs:build": "npm run docs:clean && npm run docs:build-sequence", | ||
"docs:build-sequence": "$(npm bin)/gulp build:docs-gulp-sequence", | ||
"docs:clean": "rm -rf ./src_docs/markdown/js/**/* docs_generated/*", | ||
"lib:clean": "rm -rf ./lib", | ||
"lib:build": "npm run lib:clean && npm run lib:build-sequence", | ||
"lib:build-sequence": "$(npm bin)/gulp build:lib-gulp-sequence" | ||
}, | ||
@@ -75,0 +82,0 @@ "readmeFilename": "README.md", |
Sorry, the diff of this file is not supported yet
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
71682
0
1556
33
4
1
0
- Removedclassnames@^1.1.4
- Removedlodash@^3.7.0
- Removedclassnames@1.2.2(transitive)
- Removedlodash@3.10.1(transitive)
- Removedreact@19.0.0(transitive)