Update gr-autocomplete to paper-input

- Use the prefix slot to show an optional search icon (used by search
  bar's gr-autocomplete)
- Increase padding on search bar based on designs
  - In order for autocomplete dropdown to position correctly, allow a
    custom vertical offset parameter (that defaults to previous value)
- Remove the 'Search' button itself, as material design searches do not
  include a button.

Change-Id: Ia7405cb12b6d89d386397fa5a17ac4ca36948a33
(cherry picked from commit Ia7405cb12b6d89d386397fa5a17ac4ca36948a33)
This commit is contained in:
Becky Siegel
2017-10-16 13:55:18 -07:00
committed by Paladox none
parent 41461ae327
commit 7953a9a194
10 changed files with 121 additions and 66 deletions

View File

@@ -197,7 +197,7 @@
},
_handleInputKeydown(e) {
const input = e.detail.input;
const input = e.detail.input.inputElement;
if (input.selectionStart !== input.selectionEnd ||
input.selectionStart !== 0) {
return;

View File

@@ -336,15 +336,17 @@ limitations under the License.
sandbox.stub(element, '_computeRemovable').returns(true);
// Next line is a workaround for Firefix not moving cursor
// on input field update
assert.equal(input.$.input.selectionStart, 0);
assert.equal(input.$.input.inputElement.selectionStart, 0);
input.text = 'test';
MockInteractions.focus(input.$.input);
flushAsynchronousOperations();
assert.equal(element.accounts.length, 2);
MockInteractions.pressAndReleaseKeyOn(input.$.input, 8); // Backspace
MockInteractions.pressAndReleaseKeyOn(
input.$.input.inputElement, 8); // Backspace
assert.equal(element.accounts.length, 2);
input.text = '';
MockInteractions.pressAndReleaseKeyOn(input.$.input, 8); // Backspace
MockInteractions.pressAndReleaseKeyOn(
input.$.input.inputElement, 8); // Backspace
assert.equal(element.accounts.length, 1);
});

View File

@@ -127,7 +127,7 @@ limitations under the License.
.title,
.value {
display: table-cell;
vertical-align: top;
vertical-align: middle;
}
.title {
padding-right: .5em;

View File

@@ -19,7 +19,6 @@ limitations under the License.
<link rel="import" href="../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html">
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../shared/gr-autocomplete/gr-autocomplete.html">
<link rel="import" href="../../shared/gr-button/gr-button.html">
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
<link rel="import" href="../../../styles/shared-styles.html">
@@ -39,16 +38,12 @@ limitations under the License.
flex: 1;
font: inherit;
outline: none;
padding: 0 .25em 0 .25em;
}
gr-button {
background-color: #f1f2f3;
border-radius: 0 2px 2px 0;
border-left-width: 0;
padding: .25em;
}
</style>
<form>
<gr-autocomplete
show-search-icon
id="searchInput"
text="{{_inputVal}}"
query="[[query]]"
@@ -57,8 +52,8 @@ limitations under the License.
multi
borderless
threshold="[[_threshold]]"
tab-complete></gr-autocomplete>
<gr-button id="searchButton">Search</gr-button>
tab-complete
vertical-offset="30"></gr-autocomplete>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
</form>
</template>

View File

@@ -103,10 +103,6 @@
Gerrit.URLEncodingBehavior,
],
listeners: {
'searchButton.tap': '_preventDefaultAndNavigateToInputVal',
},
keyBindings: {
'/': '_handleForwardSlashKey',
},

View File

@@ -59,17 +59,6 @@ limitations under the License.
document.activeElement;
};
test('tap on search button triggers nav', done => {
sandbox.stub(page, 'show', () => {
page.show.restore();
assert.notEqual(getActiveElement(), element.$.searchInput);
assert.notEqual(getActiveElement(), element.$.searchButton);
done();
});
element.value = 'test';
MockInteractions.tap(element.$.searchButton);
});
test('enter in search input triggers nav', done => {
sandbox.stub(page, 'show', () => {
page.show.restore();

View File

@@ -15,54 +15,88 @@ limitations under the License.
-->
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../bower_components/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
<link rel="import" href="../../../bower_components/iron-input/iron-input.html">
<link rel="import" href="../../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.html">
<link rel="import" href="../../shared/gr-cursor-manager/gr-cursor-manager.html">
<link rel="import" href="../../shared/gr-icons/gr-icons.html">
<link rel="import" href="../../../styles/shared-styles.html">
<dom-module id="gr-autocomplete">
<template>
<style include="shared-styles">
input {
font-size: 1em;
.searchIcon {
display: none;
}
.searchIcon.showSearchIcon {
display: initial;
}
iron-icon {
margin-right: .5em;
}
paper-input:not(.borderless) {
border: 1px solid #ddd;
}
paper-input {
height: 100%;
width: 100%;
@apply --gr-autocomplete;
--paper-input-container: {
padding: 0;
min-width: 15em;
}
--paper-input-container-input: {
font-size: 1em;
}
--paper-input-container-underline: {
display: none;
};
--paper-input-container-underline-focus: {
display: none;
};
--paper-input-container-underline-disabled: {
display: none;
};
}
input.borderless,
input.borderless:focus {
border: none;
outline: none;
}
input.warnUncommitted {
color: red;
paper-input.warnUncommitted {
--paper-input-container-input: {
color: #ff0000;
font-size: 1em;
}
}
</style>
<div>
<input
id="input"
class$="[[_computeClass(borderless)]]"
is="iron-input"
disabled$="[[disabled]]"
bind-value="{{text}}"
placeholder="[[placeholder]]"
on-keydown="_handleKeydown"
on-focus="_onInputFocus"
on-blur="_onInputBlur"
autocomplete="off"/>
<gr-autocomplete-dropdown
vertical-align="top"
vertical-offset="20"
horizontal-align="auto"
id="suggestions"
on-item-selected="_handleItemSelect"
on-keydown="_handleKeydown"
suggestions="[[_suggestions]]"
role="listbox"
index="[[_index]]"
position-target="[[_inputElement]]">
</gr-autocomplete-dropdown>
</div>
<paper-input
no-label-float
id="input"
class$="[[_computeClass(borderless)]]"
is="iron-input"
disabled$="[[disabled]]"
value="{{text}}"
placeholder="[[placeholder]]"
on-keydown="_handleKeydown"
on-focus="_onInputFocus"
on-blur="_onInputBlur"
autocomplete="off">
<!-- slot is for future use (2.x) while prefix attribute is for 1.x
(current) -->
<iron-icon
icon="gr-icons:search"
slot="prefix"
prefix
class$="searchIcon [[_computeShowSearchIconClass(showSearchIcon)]]">
</iron-icon>
</paper-input>
<gr-autocomplete-dropdown
vertical-align="top"
vertical-offset="[[verticalOffset]]"
horizontal-align="auto"
id="suggestions"
on-item-selected="_handleItemSelect"
on-keydown="_handleKeydown"
suggestions="[[_suggestions]]"
role="listbox"
index="[[_index]]"
position-target="[[_inputElement]]">
</gr-autocomplete-dropdown>
</template>
<script src="gr-autocomplete.js"></script>
</dom-module>

View File

@@ -71,6 +71,16 @@
allowNonSuggestedValues: Boolean,
borderless: Boolean,
disabled: Boolean,
showSearchIcon: {
type: Boolean,
value: false,
},
// Vertical offset needed for a 1em font-size with no vertical padding.
// Inputs with additional padding will need to increase vertical offset.
verticalOffset: {
type: Number,
value: 20,
},
text: {
type: String,
@@ -162,7 +172,8 @@
},
selectAll() {
this.$.input.setSelectionRange(0, this.$.input.value.length);
const nativeInputElement = this.$.input.inputElement;
nativeInputElement.setSelectionRange(0, this.$.input.value.length);
},
clear() {
@@ -194,11 +205,15 @@
this._focused = true;
this._updateSuggestions();
this.$.input.classList.remove('warnUncommitted');
// Needed so that --paper-input-container-input updated style is applied.
this.updateStyles();
},
_onInputBlur() {
this.$.input.classList.toggle('warnUncommitted',
this.warnUncommitted && this.text.length && !this._focused);
// Needed so that --paper-input-container-input updated style is applied.
this.updateStyles();
},
_updateSuggestions() {
@@ -362,5 +377,9 @@
this._textChangedSinceCommit = false;
},
_computeShowSearchIconClass(showSearchIcon) {
return showSearchIcon ? 'showSearchIcon' : '';
},
});
})();

View File

@@ -283,13 +283,27 @@ limitations under the License.
test('_focused flag properly triggered', done => {
flush(() => {
assert.isFalse(element._focused);
const input = element.$$('input');
const input = element.$$('paper-input').inputElement;
MockInteractions.focus(input);
assert.isTrue(element._focused);
done();
});
});
test('search icon shows with showSearchIcon property', () => {
assert.equal(getComputedStyle(element.$$('iron-icon')).display,
'none');
element.showSearchIcon = true;
assert.notEqual(getComputedStyle(element.$$('iron-icon')).display,
'none');
});
test('vertical offset overridden by param if it exists', () => {
assert.equal(element.$.suggestions.verticalOffset, 20);
element.verticalOffset = 30;
assert.equal(element.$.suggestions.verticalOffset, 30);
});
test('_focused flag shows/hides the suggestions', () => {
const openStub = sandbox.stub(element.$.suggestions, 'open');
const closedStub = sandbox.stub(element.$.suggestions, 'close');
@@ -449,8 +463,12 @@ limitations under the License.
element.text = 'blah blah blah';
MockInteractions.blur(element.$.input);
assert.isTrue(inputClassList.contains('warnUncommitted'));
assert.equal(getComputedStyle(element.$.input.inputElement).color,
'rgb(255, 0, 0)');
MockInteractions.focus(element.$.input);
assert.isFalse(inputClassList.contains('warnUncommitted'));
assert.notEqual(getComputedStyle(element.$.input.inputElement).color,
'rgb(255, 0, 0)ed');
});
test('disabled', () => {

View File

@@ -19,6 +19,8 @@ limitations under the License.
<iron-iconset-svg name="gr-icons" size="24">
<svg>
<defs>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.html -->
<g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></g>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.html -->
<g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></g>
<!-- This is a custom PolyGerrit SVG -->