Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
Workaround IE11 not having `element.labels` and Safari not populating
`element.labels` in shadowroots
  • Loading branch information
dfreedm committed Feb 22, 2018
1 parent a77d64e commit 70edf1f
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 3 deletions.
55 changes: 52 additions & 3 deletions lib/utils/gestures.html
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,59 @@
/** @type {(function(MouseEvent): void | undefined)} */
GestureRecognizer.prototype.click;

// keep track of any labels hit by tghe mouseCanceller
// keep track of any labels hit by the mouseCanceller
/** @type {!Array<!HTMLLabelElement>} */
const clickedLabels = [];

/** @type {!Map<string, boolean>} */
const labellable = {
'button': true,
'input': true,
'keygen': true,
'meter': true,
'output': true,
'textarea': true,
'progress': true,
'select': true
};

/**
* @param {HTMLElement} el Element to check labelling status
* @return {boolean} element can have labels
*/
function canBeLabelled(el) {
return labellable[el.localName] || false;
}

/**
* @param {HTMLElement} el Element that may be labelled.
* @return {!Array<!HTMLLabelElement>} Relevant label for `el`
*/
function matchingLabels(el) {
/** @type {!Array<!HTMLLabelElement>} */
let labels = el.labels;
// IE doesn't have `labels` and Safari doesn't populate `labels` if element is in a shadowroot.
if (!labels || !labels.length) {
labels = [];
let root = el.getRootNode();
// find all labels that are ancestors
let cur = el.parentNode;
while (cur !== root) {
if (cur.localName === 'label') {
labels.push(/** @type {!HTMLLabelElement} */(cur));
}
}
// if there is an id on `el`, check for all labels with a matching `for` attribute
if (el.id) {
let matching = root.querySelectorAll(`label[for = ${el.id}]`);
for (let i = 0; i < matching.length; i++) {
labels.push(/** @type {!HTMLLabelElement} */(matching[i]));
}
}
}
return labels;
}

// touch will make synthetic mouse events
// `preventDefault` on touchend will cancel them,
// but this breaks `<input>` focus and link clicks
Expand All @@ -127,8 +176,8 @@
if (path[i].nodeType === Node.ELEMENT_NODE) {
if (path[i].localName === 'label') {
labels.push(path[i]);
} else if (path[i].labels) {
let ownerLabels = path[i].labels;
} else if (canBeLabelled(path[i])) {
let ownerLabels = matchingLabels(path[i]);
for (let j = 0; j < ownerLabels.length; j++) {
clickFromLabel = clickFromLabel || clickedLabels.indexOf(ownerLabels[j]) > -1;
}
Expand Down
15 changes: 15 additions & 0 deletions test/unit/gestures-elements.html
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,18 @@
});
</script>
</dom-module>

<dom-module id="x-native-label">
<template>
<label id="label" for="check"></label>
<input id="check" type="checkbox">
</template>
<script>
class XNativeLabel extends Polymer.Element {
static get is() {
return 'x-native-label';
}
}
customElements.define(XNativeLabel.is, XNativeLabel);
</script>
</dom-module>
23 changes: 23 additions & 0 deletions test/unit/gestures.html
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,29 @@
assert.equal(count, 1);
Polymer.Gestures.remove(window, 'tap', increment);
});

test('native label click', function() {
let el = document.createElement('x-native-label');
document.body.appendChild(el);
let target = el.$.label;
let touches = [{
clientX: 0,
clientY: 0,
identifier: 1,
// target is set to the element with `addEventListener`, which is app
target
}];
let touchstart = new CustomEvent('touchstart', {bubbles: true, composed: true});
touchstart.changedTouches = touchstart.touches = touches;
target.dispatchEvent(touchstart);
let touchend = new CustomEvent('touchend', {bubbles: true, composed: true});
touchend.touches = touchend.changedTouches = touches;
target.dispatchEvent(touchend);
let click = new MouseEvent('click', {bubbles: true, composed: true});
target.dispatchEvent(click);
assert.equal(el.$.check.checked, true);
document.body.removeChild(el);
});
});
</script>

Expand Down

0 comments on commit 70edf1f

Please sign in to comment.