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); |
+ } |
+} |