From 3300c861171eae95e0593ce3483954cc82f8fa3c Mon Sep 17 00:00:00 2001 From: Jake Harding Date: Thu, 21 Feb 2013 21:33:19 -0800 Subject: [PATCH 1/2] Hide hint with input's value is overflowing. Fixes #16. --- src/js/input_view.js | 27 +++++++++++++++++++++++++++ src/js/typeahead_view.js | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/js/input_view.js b/src/js/input_view.js index e36a599c..dfc55b4f 100644 --- a/src/js/input_view.js +++ b/src/js/input_view.js @@ -50,6 +50,9 @@ var InputView = (function() { setTimeout(that._compareQueryToInputValue, 0); }); } + + // helps with calculating the width of the input's value + this.$overflowHelper = buildOverflowHelper(this.$input); } utils.mixin(InputView.prototype, EventTarget, { @@ -126,6 +129,12 @@ var InputView = (function() { return (this.$input.css('direction') || 'ltr').toLowerCase(); }, + isOverflow: function() { + this.$overflowHelper.text(this.getInputValue()); + + return this.$overflowHelper.width() > this.$input.width(); + }, + isCursorAtEnd: function() { var valueLength = this.$input.val().length, selectionStart = this.$input[0].selectionStart, @@ -150,6 +159,24 @@ var InputView = (function() { return InputView; + function buildOverflowHelper($input) { + return $('') + .css({ + // position helper off-screen + position: 'absolute', + left: '-9999px', + visibility: 'hidden', + // use same font css as input to calculate accurate width + font: $input.css('font'), + wordSpacing: $input.css('word-spacing'), + letterSpacing: $input.css('letter-spacing'), + textIndent: $input.css('text-indent'), + textRendering: $input.css('text-rendering'), + textTransform: $input.css('text-transform') + }) + .insertAfter($input); + } + function compareQueries(a, b) { // strips leading whitespace and condenses all whitespace a = (a || '').replace(/^\s*/g, '').replace(/\s{2,}/g, ' ').toLowerCase(); diff --git a/src/js/typeahead_view.js b/src/js/typeahead_view.js index b80d1a77..bf086db2 100644 --- a/src/js/typeahead_view.js +++ b/src/js/typeahead_view.js @@ -122,7 +122,7 @@ var TypeaheadView = (function() { beginsWithQuery, match; - if (hint && this.dropdownView.isOpen()) { + if (hint && this.dropdownView.isOpen() && !this.inputView.isOverflow()) { inputValue = this.inputView.getInputValue(); query = inputValue .replace(/\s{2,}/g, ' ') // condense whitespace From 1ce87812eda60bbf0f424beba02963cfc05bc79d Mon Sep 17 00:00:00 2001 From: Jake Harding Date: Thu, 21 Feb 2013 21:34:06 -0800 Subject: [PATCH 2/2] Add tests. --- test/input_view_spec.js | 16 ++++++++++++++++ test/typeahead_view_spec.js | 12 ++++++++++++ 2 files changed, 28 insertions(+) diff --git a/test/input_view_spec.js b/test/input_view_spec.js index 27233070..c3c095b5 100644 --- a/test/input_view_spec.js +++ b/test/input_view_spec.js @@ -208,6 +208,22 @@ describe('InputView', function() { }); }); + describe('#isOverflow', function() { + describe('when input\'s value is overflowing', function() { + it('should return false', function() { + this.$input.val(new Array(1000).join('a')); + expect(this.inputView.isOverflow()).toBe(true); + }); + }); + + describe('when input\'s value is not overflowing', function() { + it('should return false', function() { + this.$input.val('t'); + expect(this.inputView.isOverflow()).toBe(false); + }); + }); + }); + describe('#isCursorAtEnd', function() { beforeEach(function() { this.$input.val('text cursor goes here'); diff --git a/test/typeahead_view_spec.js b/test/typeahead_view_spec.js index 2ca3500e..84d3da6c 100644 --- a/test/typeahead_view_spec.js +++ b/test/typeahead_view_spec.js @@ -453,6 +453,18 @@ describe('TypeaheadView', function() { // ------------ function _updateHintSpecHelper(view, eventType) { + describe('if input\'s value is overflowing', function() { + it('should clear hint', function() { + this.inputView.isOverflow.andReturn(true); + this.inputView.getInputValue.andReturn('bl'); + this.dropdownView.getFirstSuggestion.andReturn({ value: 'blah' }); + + this[view].trigger(eventType); + + expect(this.inputView.setHintValue).not.toHaveBeenCalled(); + }); + }); + describe('if dropdown menu is closed', function() { it('should not show hint', function() { this.dropdownView.isOpen.andReturn(false);