Skip to content

Commit

Permalink
Merge f55900d into f3d2c44
Browse files Browse the repository at this point in the history
  • Loading branch information
Haprog committed Mar 20, 2019
2 parents f3d2c44 + f55900d commit 010b767
Show file tree
Hide file tree
Showing 19 changed files with 180 additions and 32 deletions.
2 changes: 1 addition & 1 deletion bower.json
Expand Up @@ -38,7 +38,7 @@
"polymer": "^2.0.0",
"vaadin-control-state-mixin": "vaadin/vaadin-control-state-mixin#^2.1.1",
"vaadin-overlay": "vaadin/vaadin-overlay#^3.2.0",
"vaadin-text-field": "vaadin/vaadin-text-field#^2.1.1",
"vaadin-text-field": "vaadin/vaadin-text-field#^2.3.0",
"vaadin-themable-mixin": "vaadin/vaadin-themable-mixin#^1.3.2",
"vaadin-lumo-styles": "vaadin/vaadin-lumo-styles#^1.1.1",
"vaadin-material-styles": "vaadin/vaadin-material-styles#^1.1.2",
Expand Down
15 changes: 15 additions & 0 deletions demo/combo-box-basic-demos.html
Expand Up @@ -40,6 +40,21 @@ <h3>Configuring the Combo Box</h3>
</template>
</vaadin-demo-snippet>

<h3>Clear Button</h3>

<p>Use the clear-button-visible attribute to display the clear button of an individual combobox.</p>

<vaadin-demo-snippet id="combo-box-basic-demos-clear-button" when-defined="vaadin-combo-box">
<template preserve-content>
<vaadin-combo-box label="Element" clear-button-visible></vaadin-combo-box>
<script>
window.addDemoReadyListener('#combo-box-basic-demos-clear-button', function(document) {
document.querySelector('vaadin-combo-box').items = ['Hydrogen', 'Helium', 'Lithium'];
});
</script>
</template>
</vaadin-demo-snippet>


<h3>Allow Custom Values</h3>
<p>Allow the user to set any value for the field in addition to selecting a value from the dropdown menu.</p>
Expand Down
13 changes: 8 additions & 5 deletions src/vaadin-combo-box-mixin.html
Expand Up @@ -352,8 +352,9 @@
_onClick(e) {
this._closeOnBlurIsPrevented = true;

const clearButton = this.$.input ? this.$.input.$.clearButton : this._clearElement;
const path = e.composedPath();
if (path.indexOf(this._clearElement) !== -1) {
if (path.indexOf(clearButton) !== -1) {
this._clear();
this.focus();
} else if (path.indexOf(this.inputElement) !== -1) {
Expand Down Expand Up @@ -933,17 +934,19 @@
if (this._toggleElement) {
this._toggleElement.addEventListener('click', this._preventDefault);
}
if (this._clearElement) {
this._clearElement.addEventListener('click', this._preventDefault);
const clearButton = this.$.input ? this.$.input.$.clearButton : this._clearElement;
if (clearButton) {
clearButton.addEventListener('click', this._preventDefault);
}
}

_restoreInputBlur() {
if (this._toggleElement) {
this._toggleElement.removeEventListener('click', this._preventDefault);
}
if (this._clearElement) {
this._clearElement.removeEventListener('click', this._preventDefault);
const clearButton = this.$.input ? this.$.input.$.clearButton : this._clearElement;
if (clearButton) {
clearButton.removeEventListener('click', this._preventDefault);
}
}

Expand Down
31 changes: 22 additions & 9 deletions src/vaadin-combo-box.html
Expand Up @@ -33,12 +33,6 @@
width: 100%;
min-width: 0;
}

:host([disabled]) [part="clear-button"],
:host([readonly]) [part="clear-button"],
:host(:not([has-value])) [part="clear-button"] {
display: none;
}
</style>

<vaadin-text-field part="text-field" id="input"
Expand All @@ -63,12 +57,12 @@

on-change="_stopPropagation"
on-input="_inputValueChanged"
clear-button-visible="[[clearButtonVisible]]"

theme$="[[theme]]"
>
<slot name="prefix" slot="prefix"></slot>

<div part="clear-button" id="clearButton" slot="suffix" role="button" aria-label="Clear"></div>
<div part="toggle-button" id="toggleButton" slot="suffix" role="button" aria-label="Toggle"></div>

</vaadin-text-field>
Expand Down Expand Up @@ -338,6 +332,14 @@
readonly: {
type: Boolean,
value: false
},

/**
* Set to true to display the clear icon which clears the input.
*/
clearButtonVisible: {
type: Boolean,
value: false
}
};
}
Expand All @@ -361,9 +363,20 @@
ready() {
super.ready();

this._nativeInput = this.$.input.focusElement;
this._nativeInput = this.inputElement.focusElement;
this._toggleElement = this.$.toggleButton;
this._clearElement = this.$.clearButton;

// Stop propagation of Esc in capturing phase so that
// vaadin-text-field will not handle Esc as a shortcut
// to clear the value
this.addEventListener('keydown', e => {
if (this._isEventKey(e, 'esc')) {
this._stopPropagation(e);
// Trigger _onEscape method of vaadin-combo-box-mixin because
// bubbling phase is not reached.
this._onEscape(e);
}
}, true);

this._nativeInput.setAttribute('role', 'combobox');
this._nativeInput.setAttribute('aria-autocomplete', 'list');
Expand Down
5 changes: 0 additions & 5 deletions test/aria.html
Expand Up @@ -35,9 +35,6 @@
function getToggleIcon() {
return comboBox._toggleElement;
}
function getClearIcon() {
return comboBox._clearElement;
}
function getItemElement(i) {
return comboBox.$.overlay._selector.querySelectorAll('vaadin-combo-box-item')[i];
}
Expand All @@ -63,8 +60,6 @@
expect(getNativeInput().hasAttribute('aria-labelledby')).to.be.true;
expect(getToggleIcon().getAttribute('role')).to.equal('button');
expect(getToggleIcon().getAttribute('aria-label')).to.equal('Toggle');
expect(getClearIcon().getAttribute('role')).to.equal('button');
expect(getClearIcon().getAttribute('aria-label')).to.equal('Clear');
});
});

Expand Down
14 changes: 10 additions & 4 deletions test/selecting-items.html
Expand Up @@ -20,6 +20,12 @@
</template>
</test-fixture>

<test-fixture id="combobox-clear">
<template>
<vaadin-combo-box clear-button-visible style="width: 320px;"></vaadin-combo-box>
</template>
</test-fixture>

<script>
describe('selecting a value', () => {
let combobox;
Expand Down Expand Up @@ -197,7 +203,7 @@

it('should fire on clear', () => {
combobox.value = 'foo';
fire('click', combobox._clearElement);
fire('click', combobox.$.input.$.clearButton);

expect(changeSpy.callCount).to.equal(1);
});
Expand Down Expand Up @@ -254,12 +260,12 @@
let combobox;
let clearIcon;
beforeEach(() => {
combobox = fixture('combobox');
combobox = fixture('combobox-clear');
combobox.items = ['foo', 'bar'];

combobox.value = 'foo';

clearIcon = combobox._clearElement;
clearIcon = combobox.inputElement.$.clearButton;

// needed for Edge <= 14 in Polymer 2
combobox.updateStyles();
Expand Down Expand Up @@ -299,7 +305,7 @@
expect(combobox.opened).to.eql(true);
});

it('should cancel down event to avoid input blur', () => {
it('should cancel click event to avoid input blur', () => {
combobox.open();

const event = fire('click', clearIcon);
Expand Down
8 changes: 0 additions & 8 deletions test/toggling-dropdown.html
Expand Up @@ -306,10 +306,6 @@
expect(getComputedStyle(combobox._toggleElement).display).not.to.equal('none');
});

it('clearIcon should be hidden when disabled', () => {
expect(getComputedStyle(combobox._clearElement).display).to.equal('none');
});

it('dropdown should not be shown when disabled', () => {
combobox.inputElement.dispatchEvent(new CustomEvent('click', {bubbles: true, composed: true}));
expect(combobox.opened).to.be.false;
Expand All @@ -326,10 +322,6 @@
expect(getComputedStyle(combobox._toggleElement).display).not.to.equal('none');
});

it('clearIcon should be hidden when read-only', () => {
expect(getComputedStyle(combobox._clearElement).display).to.equal('none');
});

it('dropdown should not be shown when read-only', () => {
combobox.inputElement.dispatchEvent(new CustomEvent('click', {bubbles: true, composed: true}));
expect(combobox.opened).to.be.false;
Expand Down
44 changes: 44 additions & 0 deletions test/vaadin-combo-box-light.html
Expand Up @@ -174,6 +174,50 @@

expect(spy.called).to.be.true;
});

describe('custom clear-button', () => {
let clearButton;

beforeEach(() => {
clearButton = comboBox.querySelector('.clear-button');
comboBox.value = 'foo';
});

it('should fire `change` event on clear', () => {
const changeSpy = sinon.spy();
comboBox.addEventListener('change', changeSpy);

fire('click', clearButton);
expect(changeSpy.callCount).to.equal(1);
});

it('should clear the selection when clicking on the clear button', () => {
comboBox.open();

fire('click', clearButton);

expect(comboBox.value).to.eql('');
expect(comboBox.$.overlay._selectedItem).to.be.null;
expect(comboBox.selectedItem).to.be.null;
});

it('should not close the dropdown after clearing a selection', () => {
comboBox.open();

fire('click', clearButton);

expect(comboBox.opened).to.eql(true);
});

it('should cancel click event to avoid input blur', () => {
comboBox.open();

const event = fire('click', clearButton);

expect(event.defaultPrevented).to.eql(true);
});

});
});

describe('theme attribute', () => {
Expand Down
44 changes: 44 additions & 0 deletions test/vaadin-combo-box.html
Expand Up @@ -42,6 +42,12 @@
</template>
</test-fixture>

<test-fixture id="combobox-clear">
<template>
<vaadin-combo-box clear-button-visible></vaadin-combo-box>
</template>
</test-fixture>

<script>
describe('Properties', () => {
let comboBox;
Expand Down Expand Up @@ -370,6 +376,44 @@
).to.equal('foo');
});
});

describe('no clear-button-visible attribute', () => {
let textfield;

beforeEach(() => {
textfield = comboBox.inputElement;
});

it('should not have clear-button-visible by default', () => {
expect(comboBox).to.have.property('clearButtonVisible', false);
expect(textfield).to.have.property('clearButtonVisible', false);
});
});

describe('clear-button-visible attribute', () => {
let comboBox, textfield, clearButton;

beforeEach(() => {
comboBox = fixture('combobox-clear');
textfield = comboBox.inputElement;
clearButton = textfield.$.clearButton;
});

it('should propagate clear-button-visible attribute to textfield', () => {
expect(comboBox).to.have.property('clearButtonVisible', true);
expect(textfield).to.have.property('clearButtonVisible', true);
});

it('clear button should be hidden when disabled', () => {
comboBox.disabled = true;
expect(getComputedStyle(clearButton).display).to.equal('none');
});

it('clear button should be hidden when read-only', () => {
comboBox.readonly = true;
expect(getComputedStyle(clearButton).display).to.equal('none');
});
});
});
</script>

Expand Down
29 changes: 29 additions & 0 deletions test/visual/clear-button.html
@@ -0,0 +1,29 @@
<!DOCTYPE html>

<head lang="en">
<meta charset="UTF-8">

<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
<script>
const theme = window.location.search.replace(/.*theme=(\w+).*/, '$1') || 'lumo';
document.write(`<link rel="import" href="../../theme/${theme}/vaadin-combo-box.html">`);
</script>
</head>

<body>

<div id="clear-button-tests" style="padding: 10px;">
No value
<vaadin-combo-box clear-button-visible></vaadin-combo-box>

<br>Basic value
<vaadin-combo-box clear-button-visible value="Carbon" items='["Carbon"]'></vaadin-combo-box>

<br>Disabled
<vaadin-combo-box clear-button-visible value="Carbon" items='["Carbon"]' disabled></vaadin-combo-box>

<br>Read-only
<vaadin-combo-box clear-button-visible value="Carbon" items='["Carbon"]' readonly></vaadin-combo-box>
</div>

</body>
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions test/visual/test.js
Expand Up @@ -22,6 +22,13 @@ gemini.suite('vaadin-combo-box', function(rootSuite) {
.capture('default');
});

gemini.suite(`clear-button-tests-${theme}`, function(suite) {
suite
.setUrl(`clear-button.html?theme=${theme}`)
.setCaptureElements('#clear-button-tests')
.capture('default');
});

gemini.suite(`icons-${theme}`, function(suite) {
suite
.setUrl(`icons.html?theme=${theme}`)
Expand Down

0 comments on commit 010b767

Please sign in to comment.