Source RapidContext_Widget_Button.js

1/*
2 * RapidContext <https://www.rapidcontext.com/>
3 * Copyright (c) 2007-2023 Per Cederberg. All rights reserved.
4 *
5 * This program is free software: you can redistribute it and/or
6 * modify it under the terms of the BSD license.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * See the RapidContext LICENSE for more details.
13 */
14
15// Namespace initialization
16if (typeof(RapidContext) == "undefined") {
17    RapidContext = {};
18}
19RapidContext.Widget = RapidContext.Widget || { Classes: {} };
20
21/**
22 * Creates a new button widget.
23 *
24 * @constructor
25 * @param {Object} attrs the widget and node attributes
26 * @param {boolean} [attrs.disabled] the disabled widget flag, defaults to
27 *            false
28 * @param {boolean} [attrs.hidden] the hidden widget flag, defaults to false
29 * @param {boolean} [attrs.highlight] the highlight option flag,
30 *            defaults to false
31 * @param {string} [attrs.icon] the icon reference to use, defaults
32 *            to null (no icon)
33 * @param {...(string|Node|Array)} [child] the child widgets or DOM nodes
34 *
35 * @return {Widget} the widget DOM node
36 *
37 * @class The button widget class. Used to provide a simple push
38 *     button, using the `<button>` HTML element.
39 * @extends RapidContext.Widget
40 *
41 * @example <caption>JavaScript</caption>
42 * let closeBtn = RapidContext.Widget.Button({ icon: "OK", highlight: true }, "Close");
43 *
44 * @example <caption>User Interface XML</caption>
45 * <Button id="closeBtn" icon="OK" highlight="true">Close</Button>
46 */
47RapidContext.Widget.Button = function (attrs/*, ...*/) {
48    function textNode(val) {
49        let el = document.createElement("t");
50        el.innerText = String(val && val.textContent || val).trim();
51        return el;
52    }
53    let o = MochiKit.DOM.BUTTON({ type: attrs.type || "button" });
54    RapidContext.Widget._widgetMixin(o, RapidContext.Widget.Button);
55    o.addClass("widgetButton");
56    o.setAttrs(attrs);
57    let children = Array.from(arguments).slice(1).filter(Boolean);
58    children.forEach(function (item) {
59        o.addChildNode((item.nodeType === 1) ? item : textNode(item));
60    });
61    return o;
62};
63
64// Register widget class
65RapidContext.Widget.Classes.Button = RapidContext.Widget.Button;
66
67/**
68 * Updates the widget or HTML DOM node attributes.
69 *
70 * @param {Object} attrs the widget and node attributes to set
71 * @param {boolean} [attrs.disabled] the disabled widget flag
72 * @param {boolean} [attrs.hidden] the hidden widget flag
73 * @param {boolean} [attrs.highlight] the highlight option flag
74 * @param {Icon|Object|string} [attrs.icon] the icon reference to use
75 */
76RapidContext.Widget.Button.prototype.setAttrs = function (attrs) {
77    attrs = Object.assign({}, attrs);
78    if ("highlight" in attrs) {
79        this.classList.toggle("primary", RapidContext.Data.bool(attrs.highlight));
80        delete attrs.highlight;
81    }
82    if ("icon" in attrs) {
83        let child = this.querySelector("i");
84        if (!attrs.icon) {
85            child && RapidContext.Widget.destroyWidget(child);
86        } else if (!child) {
87            this.insertBefore(RapidContext.Widget.Icon(attrs.icon), this.firstChild);
88        } else if (attrs.icon.nodeType) {
89            child.replaceWith(attrs.icon);
90        } else if (child.setAttrs) {
91            child.setAttrs(attrs.icon);
92        } else if (typeof(attrs.icon) === "string") {
93            child.className = attrs.icon;
94        } else {
95            Object.keys(attrs.icon).forEach((k) => child.setAttribute(k, attrs.icon[k]));
96        }
97        delete attrs.icon;
98    }
99    this.__setAttrs(attrs);
100};
101