diff --git a/src/Select.js b/src/Select.js index 4d874a5cb3..2e185467e0 100644 --- a/src/Select.js +++ b/src/Select.js @@ -237,12 +237,7 @@ var Select = React.createClass({ focusedOption = values[0]; valueForState = values[0].value; } else { - for (var optionIndex = 0; optionIndex < filteredOptions.length; ++optionIndex) { - if (!filteredOptions[optionIndex].disabled) { - focusedOption = filteredOptions[optionIndex]; - break; - } - } + focusedOption = this.getFirstFocusableOption(filteredOptions); valueForState = values.map(function(v) { return v.value; }).join(this.props.delimiter); } @@ -256,6 +251,15 @@ var Select = React.createClass({ }; }, + getFirstFocusableOption: function (options) { + + for (var optionIndex = 0; optionIndex < options.length; ++optionIndex) { + if (!options[optionIndex].disabled) { + return options[optionIndex]; + } + } + }, + initValuesArray: function(values, options) { if (!Array.isArray(values)) { if (typeof values === 'string') { @@ -472,7 +476,7 @@ var Select = React.createClass({ return filteredOptions[key]; } } - return filteredOptions[0]; + return this.getFirstFocusableOption(filteredOptions); }, handleInputChange: function(event) { @@ -589,7 +593,10 @@ var Select = React.createClass({ if (this.props.allowCreate && !this.state.focusedOption) { return this.selectValue(this.state.inputValue); } - return this.selectValue(this.state.focusedOption); + + if (this.state.focusedOption) { + return this.selectValue(this.state.focusedOption); + } }, focusOption: function(op) { diff --git a/test/Select-test.js b/test/Select-test.js index 83a89c5685..862beb50cb 100644 --- a/test/Select-test.js +++ b/test/Select-test.js @@ -1,8 +1,7 @@ 'use strict'; /* global describe, it, beforeEach */ -var helper = require('../testHelpers/jsdomHelper'); -helper(); +var jsdomHelper = require('../testHelpers/jsdomHelper'); var sinon = require('sinon'); var unexpected = require('unexpected'); @@ -13,6 +12,8 @@ var expect = unexpected .installPlugin(unexpectedDom) .installPlugin(unexpectedSinon); +jsdomHelper(); + var React = require('react/addons'); var TestUtils = React.addons.TestUtils; @@ -895,6 +896,45 @@ describe('Select', function() { 'to have text', 'Select...'); }); + it("doesn't select anything when a disabled option is the only item in the list after a search", function () { + + typeSearchText('tw'); // Only 'two' in the list + pressEnterToAccept(); + expect(onChange, 'was not called'); + // And the menu is still open + expect(React.findDOMNode(instance), 'to contain no elements matching', DISPLAYED_SELECTION_SELECTOR) + expect(React.findDOMNode(instance), 'queried for' , '.Select-option', + 'to satisfy', [ + expect.it('to have text', 'Two') + ]); + }); + + it("doesn't select anything when a disabled option value matches the entered text", function () { + + typeSearchText('two'); // Matches value + pressEnterToAccept(); + expect(onChange, 'was not called'); + // And the menu is still open + expect(React.findDOMNode(instance), 'to contain no elements matching', DISPLAYED_SELECTION_SELECTOR) + expect(React.findDOMNode(instance), 'queried for' , '.Select-option', + 'to satisfy', [ + expect.it('to have text', 'Two') + ]); + }); + + it("doesn't select anything when a disabled option label matches the entered text", function () { + + typeSearchText('Two'); // Matches label + pressEnterToAccept(); + expect(onChange, 'was not called'); + // And the menu is still open + expect(React.findDOMNode(instance), 'to contain no elements matching', DISPLAYED_SELECTION_SELECTOR) + expect(React.findDOMNode(instance), 'queried for' , '.Select-option', + 'to satisfy', [ + expect.it('to have text', 'Two') + ]); + }); + it('shows disabled results in a search', function () { typeSearchText('t');