| Index: js/io-toggle.js |
| =================================================================== |
| new file mode 100644 |
| --- /dev/null |
| +++ b/js/io-toggle.js |
| @@ -0,0 +1,89 @@ |
| +/* globals module, require */ |
|
Thomas Greiner
2018/04/25 17:29:14
I noticed that none of the new files in this revie
Thomas Greiner
2018/04/25 17:29:14
Detail: You don't use `module` in this module.
a.giammarchi
2018/04/26 10:44:52
To be honest, I feel like we should have module an
a.giammarchi
2018/04/26 10:44:52
Will do.
Thomas Greiner
2018/04/26 17:00:52
Wouldn't .eslintrc.json be a more suitable place t
a.giammarchi
2018/04/27 10:59:04
absolutely!
|
| + |
| +"use strict"; |
| + |
| +const IOElement = require("./io-element"); |
| + |
| +class IOToggle extends IOElement |
| +{ |
| + // action, checked, and disabled should be reflected down the button |
| + static get observedAttributes() |
| + { |
| + return ["action", "checked", "disabled"]; |
| + } |
| + |
| + created() |
| + { |
| + this.addEventListener("click", this); |
| + this.render(); |
| + } |
| + |
| + get checked() |
| + { |
| + return this.hasAttribute("checked"); |
| + } |
| + |
| + set checked(value) |
| + { |
| + booleanAttribute.call(this, "checked", value); |
| + this.render(); |
| + } |
| + |
| + get disabled() |
| + { |
| + return this.hasAttribute("disabled"); |
| + } |
| + |
| + set disabled(value) |
| + { |
| + booleanAttribute.call(this, "disabled", value); |
| + this.firstElementChild.disabled = this._disabled; |
|
Thomas Greiner
2018/04/25 17:29:14
Why don't you call `this.render()` here?
a.giammarchi
2018/04/26 10:44:52
it's not needed, the disabled is the native DOM ac
Thomas Greiner
2018/04/26 17:00:52
I mean instead of setting `this.firstElementChild.
a.giammarchi
2018/04/27 10:59:04
I'll try that. The issue here is that disabled is
Thomas Greiner
2018/05/02 11:53:28
Thanks, looking good!
|
| + } |
| + |
| + onclick(event) |
| + { |
| + if (!this.disabled) |
| + { |
| + this.checked = !this.checked; |
| + if (this.ownerDocument.activeElement !== this.firstElementChild) |
| + { |
| + this.firstElementChild.focus(); |
| + } |
| + this.dispatchEvent(new CustomEvent("change", { |
| + bubbles: true, |
| + cancelable: true, |
| + detail: this.checked |
| + })); |
| + } |
| + } |
| + |
| + render() |
| + { |
| + this.html` |
| + <button |
| + role="checkbox" |
| + data-action="${this.action}" |
| + aria-checked="${this.checked}" |
| + aria-disabled="${this.disabled}" |
| + />`; |
| + } |
| +} |
| + |
| +IOToggle.define("io-toggle"); |
| + |
| +function asBoolean(value) |
|
Thomas Greiner
2018/04/25 17:29:14
Suggestion: "asBoolean" is quite close to "isBoole
a.giammarchi
2018/04/26 10:44:51
will do
|
| +{ |
| + return typeof value === "string" ? JSON.parse(value) : !!value; |
|
Thomas Greiner
2018/04/25 17:29:14
It's a bit unexpected that this function accepts e
a.giammarchi
2018/04/26 10:44:52
only strings can be JSON, and in this case we are
Thomas Greiner
2018/04/26 17:00:52
I can follow your line or argument right until the
a.giammarchi
2018/04/27 10:59:04
will do.
|
| +} |
| + |
| +function booleanAttribute(name, value) |
|
Thomas Greiner
2018/04/25 17:29:14
Detail: This function looks useful also for other
a.giammarchi
2018/04/26 10:44:51
Usually the way I go is: as soon as more than a co
Thomas Greiner
2018/04/26 17:00:52
That's a fair point. And it should be fine as long
a.giammarchi
2018/04/27 10:59:05
makes sense.
|
| +{ |
| + if (asBoolean(value)) |
| + { |
| + this.setAttribute(name, "true"); |
| + } |
| + else |
| + { |
| + this.removeAttribute(name); |
| + } |
| +} |