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:

committed by
Paladox none

parent
41461ae327
commit
7953a9a194
@@ -197,7 +197,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
_handleInputKeydown(e) {
|
_handleInputKeydown(e) {
|
||||||
const input = e.detail.input;
|
const input = e.detail.input.inputElement;
|
||||||
if (input.selectionStart !== input.selectionEnd ||
|
if (input.selectionStart !== input.selectionEnd ||
|
||||||
input.selectionStart !== 0) {
|
input.selectionStart !== 0) {
|
||||||
return;
|
return;
|
||||||
|
@@ -336,15 +336,17 @@ limitations under the License.
|
|||||||
sandbox.stub(element, '_computeRemovable').returns(true);
|
sandbox.stub(element, '_computeRemovable').returns(true);
|
||||||
// Next line is a workaround for Firefix not moving cursor
|
// Next line is a workaround for Firefix not moving cursor
|
||||||
// on input field update
|
// on input field update
|
||||||
assert.equal(input.$.input.selectionStart, 0);
|
assert.equal(input.$.input.inputElement.selectionStart, 0);
|
||||||
input.text = 'test';
|
input.text = 'test';
|
||||||
MockInteractions.focus(input.$.input);
|
MockInteractions.focus(input.$.input);
|
||||||
flushAsynchronousOperations();
|
flushAsynchronousOperations();
|
||||||
assert.equal(element.accounts.length, 2);
|
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);
|
assert.equal(element.accounts.length, 2);
|
||||||
input.text = '';
|
input.text = '';
|
||||||
MockInteractions.pressAndReleaseKeyOn(input.$.input, 8); // Backspace
|
MockInteractions.pressAndReleaseKeyOn(
|
||||||
|
input.$.input.inputElement, 8); // Backspace
|
||||||
assert.equal(element.accounts.length, 1);
|
assert.equal(element.accounts.length, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -127,7 +127,7 @@ limitations under the License.
|
|||||||
.title,
|
.title,
|
||||||
.value {
|
.value {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: top;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
.title {
|
.title {
|
||||||
padding-right: .5em;
|
padding-right: .5em;
|
||||||
|
@@ -19,7 +19,6 @@ limitations under the License.
|
|||||||
<link rel="import" href="../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html">
|
<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="../../../bower_components/polymer/polymer.html">
|
||||||
<link rel="import" href="../../shared/gr-autocomplete/gr-autocomplete.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="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
|
||||||
<link rel="import" href="../../../styles/shared-styles.html">
|
<link rel="import" href="../../../styles/shared-styles.html">
|
||||||
|
|
||||||
@@ -39,16 +38,12 @@ limitations under the License.
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
font: inherit;
|
font: inherit;
|
||||||
outline: none;
|
outline: none;
|
||||||
padding: 0 .25em 0 .25em;
|
padding: .25em;
|
||||||
}
|
|
||||||
gr-button {
|
|
||||||
background-color: #f1f2f3;
|
|
||||||
border-radius: 0 2px 2px 0;
|
|
||||||
border-left-width: 0;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<form>
|
<form>
|
||||||
<gr-autocomplete
|
<gr-autocomplete
|
||||||
|
show-search-icon
|
||||||
id="searchInput"
|
id="searchInput"
|
||||||
text="{{_inputVal}}"
|
text="{{_inputVal}}"
|
||||||
query="[[query]]"
|
query="[[query]]"
|
||||||
@@ -57,8 +52,8 @@ limitations under the License.
|
|||||||
multi
|
multi
|
||||||
borderless
|
borderless
|
||||||
threshold="[[_threshold]]"
|
threshold="[[_threshold]]"
|
||||||
tab-complete></gr-autocomplete>
|
tab-complete
|
||||||
<gr-button id="searchButton">Search</gr-button>
|
vertical-offset="30"></gr-autocomplete>
|
||||||
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
|
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
@@ -103,10 +103,6 @@
|
|||||||
Gerrit.URLEncodingBehavior,
|
Gerrit.URLEncodingBehavior,
|
||||||
],
|
],
|
||||||
|
|
||||||
listeners: {
|
|
||||||
'searchButton.tap': '_preventDefaultAndNavigateToInputVal',
|
|
||||||
},
|
|
||||||
|
|
||||||
keyBindings: {
|
keyBindings: {
|
||||||
'/': '_handleForwardSlashKey',
|
'/': '_handleForwardSlashKey',
|
||||||
},
|
},
|
||||||
|
@@ -59,17 +59,6 @@ limitations under the License.
|
|||||||
document.activeElement;
|
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 => {
|
test('enter in search input triggers nav', done => {
|
||||||
sandbox.stub(page, 'show', () => {
|
sandbox.stub(page, 'show', () => {
|
||||||
page.show.restore();
|
page.show.restore();
|
||||||
|
@@ -15,44 +15,79 @@ limitations under the License.
|
|||||||
-->
|
-->
|
||||||
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
<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-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-autocomplete-dropdown/gr-autocomplete-dropdown.html">
|
||||||
<link rel="import" href="../../shared/gr-cursor-manager/gr-cursor-manager.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">
|
<link rel="import" href="../../../styles/shared-styles.html">
|
||||||
|
|
||||||
<dom-module id="gr-autocomplete">
|
<dom-module id="gr-autocomplete">
|
||||||
<template>
|
<template>
|
||||||
<style include="shared-styles">
|
<style include="shared-styles">
|
||||||
input {
|
.searchIcon {
|
||||||
font-size: 1em;
|
display: none;
|
||||||
|
}
|
||||||
|
.searchIcon.showSearchIcon {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
iron-icon {
|
||||||
|
margin-right: .5em;
|
||||||
|
}
|
||||||
|
paper-input:not(.borderless) {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
paper-input {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@apply --gr-autocomplete;
|
@apply --gr-autocomplete;
|
||||||
|
--paper-input-container: {
|
||||||
|
padding: 0;
|
||||||
|
min-width: 15em;
|
||||||
}
|
}
|
||||||
input.borderless,
|
--paper-input-container-input: {
|
||||||
input.borderless:focus {
|
font-size: 1em;
|
||||||
border: none;
|
}
|
||||||
outline: none;
|
--paper-input-container-underline: {
|
||||||
|
display: none;
|
||||||
|
};
|
||||||
|
--paper-input-container-underline-focus: {
|
||||||
|
display: none;
|
||||||
|
};
|
||||||
|
--paper-input-container-underline-disabled: {
|
||||||
|
display: none;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
paper-input.warnUncommitted {
|
||||||
|
--paper-input-container-input: {
|
||||||
|
color: #ff0000;
|
||||||
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
input.warnUncommitted {
|
|
||||||
color: red;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div>
|
<paper-input
|
||||||
<input
|
no-label-float
|
||||||
id="input"
|
id="input"
|
||||||
class$="[[_computeClass(borderless)]]"
|
class$="[[_computeClass(borderless)]]"
|
||||||
is="iron-input"
|
is="iron-input"
|
||||||
disabled$="[[disabled]]"
|
disabled$="[[disabled]]"
|
||||||
bind-value="{{text}}"
|
value="{{text}}"
|
||||||
placeholder="[[placeholder]]"
|
placeholder="[[placeholder]]"
|
||||||
on-keydown="_handleKeydown"
|
on-keydown="_handleKeydown"
|
||||||
on-focus="_onInputFocus"
|
on-focus="_onInputFocus"
|
||||||
on-blur="_onInputBlur"
|
on-blur="_onInputBlur"
|
||||||
autocomplete="off"/>
|
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
|
<gr-autocomplete-dropdown
|
||||||
vertical-align="top"
|
vertical-align="top"
|
||||||
vertical-offset="20"
|
vertical-offset="[[verticalOffset]]"
|
||||||
horizontal-align="auto"
|
horizontal-align="auto"
|
||||||
id="suggestions"
|
id="suggestions"
|
||||||
on-item-selected="_handleItemSelect"
|
on-item-selected="_handleItemSelect"
|
||||||
@@ -62,7 +97,6 @@ limitations under the License.
|
|||||||
index="[[_index]]"
|
index="[[_index]]"
|
||||||
position-target="[[_inputElement]]">
|
position-target="[[_inputElement]]">
|
||||||
</gr-autocomplete-dropdown>
|
</gr-autocomplete-dropdown>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<script src="gr-autocomplete.js"></script>
|
<script src="gr-autocomplete.js"></script>
|
||||||
</dom-module>
|
</dom-module>
|
||||||
|
@@ -71,6 +71,16 @@
|
|||||||
allowNonSuggestedValues: Boolean,
|
allowNonSuggestedValues: Boolean,
|
||||||
borderless: Boolean,
|
borderless: Boolean,
|
||||||
disabled: 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: {
|
text: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -162,7 +172,8 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
selectAll() {
|
selectAll() {
|
||||||
this.$.input.setSelectionRange(0, this.$.input.value.length);
|
const nativeInputElement = this.$.input.inputElement;
|
||||||
|
nativeInputElement.setSelectionRange(0, this.$.input.value.length);
|
||||||
},
|
},
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
@@ -194,11 +205,15 @@
|
|||||||
this._focused = true;
|
this._focused = true;
|
||||||
this._updateSuggestions();
|
this._updateSuggestions();
|
||||||
this.$.input.classList.remove('warnUncommitted');
|
this.$.input.classList.remove('warnUncommitted');
|
||||||
|
// Needed so that --paper-input-container-input updated style is applied.
|
||||||
|
this.updateStyles();
|
||||||
},
|
},
|
||||||
|
|
||||||
_onInputBlur() {
|
_onInputBlur() {
|
||||||
this.$.input.classList.toggle('warnUncommitted',
|
this.$.input.classList.toggle('warnUncommitted',
|
||||||
this.warnUncommitted && this.text.length && !this._focused);
|
this.warnUncommitted && this.text.length && !this._focused);
|
||||||
|
// Needed so that --paper-input-container-input updated style is applied.
|
||||||
|
this.updateStyles();
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateSuggestions() {
|
_updateSuggestions() {
|
||||||
@@ -362,5 +377,9 @@
|
|||||||
|
|
||||||
this._textChangedSinceCommit = false;
|
this._textChangedSinceCommit = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_computeShowSearchIconClass(showSearchIcon) {
|
||||||
|
return showSearchIcon ? 'showSearchIcon' : '';
|
||||||
|
},
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
@@ -283,13 +283,27 @@ limitations under the License.
|
|||||||
test('_focused flag properly triggered', done => {
|
test('_focused flag properly triggered', done => {
|
||||||
flush(() => {
|
flush(() => {
|
||||||
assert.isFalse(element._focused);
|
assert.isFalse(element._focused);
|
||||||
const input = element.$$('input');
|
const input = element.$$('paper-input').inputElement;
|
||||||
MockInteractions.focus(input);
|
MockInteractions.focus(input);
|
||||||
assert.isTrue(element._focused);
|
assert.isTrue(element._focused);
|
||||||
done();
|
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', () => {
|
test('_focused flag shows/hides the suggestions', () => {
|
||||||
const openStub = sandbox.stub(element.$.suggestions, 'open');
|
const openStub = sandbox.stub(element.$.suggestions, 'open');
|
||||||
const closedStub = sandbox.stub(element.$.suggestions, 'close');
|
const closedStub = sandbox.stub(element.$.suggestions, 'close');
|
||||||
@@ -449,8 +463,12 @@ limitations under the License.
|
|||||||
element.text = 'blah blah blah';
|
element.text = 'blah blah blah';
|
||||||
MockInteractions.blur(element.$.input);
|
MockInteractions.blur(element.$.input);
|
||||||
assert.isTrue(inputClassList.contains('warnUncommitted'));
|
assert.isTrue(inputClassList.contains('warnUncommitted'));
|
||||||
|
assert.equal(getComputedStyle(element.$.input.inputElement).color,
|
||||||
|
'rgb(255, 0, 0)');
|
||||||
MockInteractions.focus(element.$.input);
|
MockInteractions.focus(element.$.input);
|
||||||
assert.isFalse(inputClassList.contains('warnUncommitted'));
|
assert.isFalse(inputClassList.contains('warnUncommitted'));
|
||||||
|
assert.notEqual(getComputedStyle(element.$.input.inputElement).color,
|
||||||
|
'rgb(255, 0, 0)ed');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('disabled', () => {
|
test('disabled', () => {
|
||||||
|
@@ -19,6 +19,8 @@ limitations under the License.
|
|||||||
<iron-iconset-svg name="gr-icons" size="24">
|
<iron-iconset-svg name="gr-icons" size="24">
|
||||||
<svg>
|
<svg>
|
||||||
<defs>
|
<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 -->
|
<!-- 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>
|
<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 -->
|
<!-- This is a custom PolyGerrit SVG -->
|
||||||
|
Reference in New Issue
Block a user