git @ Cat's Eye Technologies DAM / master
Merge pull request #2 from cpressey/develop-0.2 Develop 0.2 Chris Pressey authored 7 months ago GitHub committed 7 months ago
17 changed file(s) with 442 addition(s) and 258 deletion(s). Raw diff Collapse all Expand all
0 node_modules/
1 package-lock.json
1010 **DAM** is a tiny library for creating bits of an HTML5 document.
1111 (I'd say "for creating user interfaces" but that may be overstating
1212 it a tad.) It's written in ES5 Javascript, so it can be used directly
13 by most modern web browsers, or it can be transpiled to ES6 in a
14 frontend build process. It's about 1K in size (uncompressed), and it
15 comes with a "standard widget library" that bloats it to about 6K.
13 by most modern web browsers, or it can included as part of a modern
14 frontend build process. Even uncompressed it's only about 1K in size,
15 and it ships with a minified version which includes a "standard widget
16 library" that is still less than 4K.
1617
17 The current version of DAM is 0.1.
18 The current version of DAM is 0.2.
1819
1920 Basic usage
2021 -----------
2122
22 If you want to just drop DAM's basic functionality into a web page,
23 you can use it like this:
23 The simplest way to use DAM is to simply load it directly on a web page,
24 and use it like so:
2425
25 <script src="dam.js"></script>
26 <script src="dist/dam-0.2.js"></script>
2627 <script>
2728 var div=DAM.maker('div'), p=DAM.maker('p'), span=DAM.maker('span'), button=DAM.maker('button');
2829 var d = div(
3334 );
3435 document.getElementById('container').appendChild(d);
3536 </script>
36
37 (You can also import DAM as an ES6 module in a frontend build process.
38 See the [demo/es6build/](demo/es6build/) directory of this repository
39 for an example of this.)
4037
4138 `DAM.maker` is a function that takes a tag string and returns a function that
4239 creates and returns a DOM Element with that tag.
6461
6562 A simple example based on the code above:
6663
67 <script src="dam.js"></script>
64 <script src="dist/dam-0.2.js"></script>
6865 <script>
6966 var div=DAM.maker('div'), p=DAM.maker('p'), span=DAM.maker('span'), button=DAM.maker('button');
7067 function makeGreeting(config) {
115112 import { makeCheckbox, makePanel } from "./dam-widgets.js"
116113
117114 However, you're not required to do this. If you just want an ES5 file that
118 you can drop onto a web page, DAM ships with `dam-plus-widgets-web.js` for
119 this purpose. Just:
115 you can load in a web page, DAM ships with `dist/dam-plus-widgets-0.2.min.js`
116 for this purpose. Just:
120117
121 <script src="dam-plus-widgets-web.js"></script>
118 <script src="dist/dam-plus-widgets-0.2.min.js"></script>
122119
123120 and then you will have `DAM` as well as all the standard widget makers (nested
124121 under `DAM`) at your fingertips.
122
123 ### Distribution files
124
125 Note that the `package.json` supplied in this repository builds the files
126 in `dist/` from the source files in `src/` using Browserify and Babel.
127 It builds minified versions too. But this is just a convenience. The
128 file `src/dam.js` is ES5 JavaScript and can be loaded directly in a web
129 page and it will work fine in most modern browsers. Similarly,
130 `dam-plus-widgets-0.2.js` could, in a pinch, be constructed by hand from
131 the files `src/dam.js` and `src/dam-widgets.js`.
132
133 You can also import the DAM source files as ES6 modules in your own frontend
134 build process. See the [demo/es6build/](demo/es6build/) directory of this
135 repository for an example of this.
125136
126137 ### Advanced widget creation
127138
141152 * [Cyclobots](https://catseye.tc/installation/Cyclobots)
142153 * [Chzrxl](https://catseye.tc/installation/Chzrxl)
143154 * [Maze Clouds](https://catseye.tc/installation/Maze_Clouds)
155 * [Erratic Turtle Graphics](https://catseye.tc/installation/Erratic_Turtle_Graphics)
156 * [Latcarf](https://catseye.tc/installation/Latcarf)
144157
145158 Related work
146159 ------------
161174
162175 [hyperscript]: https://github.com/hyperhype/hyperscript
163176 [hyperscript-helpers]: https://github.com/ohanhi/hyperscript-helpers
164
165 TODO
166 ----
167
168 Function to set the value of a DAM range control in an orderly fashion
1111
1212 <div id="installation"></div>
1313
14 <script src="../src/dam-plus-widgets-web.js"></script>
14 <script src="../dist/dam-plus-widgets-web.js"></script>
1515 <script>
1616 var div=DAM.maker('div'), span=DAM.maker('span');
1717 var understood = false;
0 Demonstration of using DAM in an ES6 project transpiled to ES5 with Browserify and Babel.
2323
2424 <div id="installation"></div>
2525
26 <script src="../src/dam-plus-widgets-web.js"></script>
26 <script src="../dist/dam-plus-widgets-web.js"></script>
2727 <script>
2828 var div=DAM.maker("div"), p=DAM.maker("p"), span=DAM.maker("span"), button=DAM.maker("button");
2929 var statusBar = span();
1111
1212 <div id="installation"></div>
1313
14 <script src="../src/dam-plus-widgets-web.js"></script>
14 <script src="../dist/dam-plus-widgets-web.js"></script>
1515 <script>
16 var div=DAM.maker("div"), p=DAM.maker("p"), span=DAM.maker("span"), button=DAM.maker("button");
16 var div=DAM.maker("div"),button=DAM.maker("button");
17 var range = DAM.makeRange({
18 title: "Fudge factor",
19 min: 0,
20 max: 100,
21 value: 50,
22 onchange: function(v) {
23 console.log(v);
24 }
25 })
1726 document.getElementById('installation').appendChild(
1827 div(
19 DAM.makeRange({
20 title: "Fudge factor",
21 min: 0,
22 max: 100,
23 value: 50,
24 onchange: function(v) {
25 console.log(v);
26 }
27 })
28 div(range),
29 div(
30 button(
31 "Programatically set value to 33",
32 { onclick: function() { range.setValue(33); } }
33 )
34 )
2835 )
2936 );
3037 </script>
1111
1212 <div id="installation"></div>
1313
14 <script src="../src/dam-plus-widgets-web.js"></script>
14 <script src="../dist/dam-plus-widgets-web.js"></script>
1515 <script>
1616 var div=DAM.maker("div"), p=DAM.maker("p"), span=DAM.maker("span"), button=DAM.maker("button");
17 var statusBar = span();
18 function updateStatus(msg) {
19 statusBar.innerHTML += "<p>selected " + msg + "</p>";
20 }
1721 document.getElementById('installation').appendChild(
1822 div(
1923 DAM.makeSelect({
3337 }
3438 ],
3539 onchange: function(option) {
36 alert(option.value);
40 updateStatus(option.value);
3741 }
38 })
42 }),
43 statusBar
3944 )
4045 );
4146 </script>
1313
1414 <div id="installation"></div>
1515
16 <script src="../src/dam-plus-widgets-web.js"></script>
16 <script src="../dist/dam-plus-widgets-web.js"></script>
1717
1818 <script>var module = {};</script>
1919 <script src="https://unpkg.com/storeon@0.8.2/index.js"></script>
0 /* dam.js version 0.2. This file is in the public domain. */
1
2 (function() {
3 var DAM = {};
4 DAM.makeElem = function(tag, args) {
5 args = args || [];
6 var elem = document.createElement(tag);
7 for (var i = 0; i < args.length; i++) {
8 var arg = args[i];
9 if (arg instanceof Element) {
10 elem.appendChild(arg);
11 } else if (typeof arg === 'string' || arg instanceof String) {
12 elem.appendChild(document.createTextNode(arg));
13 } else if (typeof arg === 'object' && arg !== null) {
14 Object.keys(arg).forEach(function(key) {
15 if (key.substring(0, 2) === 'on') {
16 elem.addEventListener(key.substring(2), arg[key]);
17 } else if (arg[key] === null) {
18 elem.removeAttribute(key);
19 } else {
20 elem.setAttribute(key, arg[key]);
21 }
22 });
23 } else {
24 console.log(arg);
25 }
26 }
27 return elem;
28 };
29 DAM.maker = function(tag) {
30 return function() {
31 return DAM.makeElem(tag, arguments);
32 };
33 };
34 if (typeof module !== 'undefined') {
35 module.exports = DAM;
36 } else if (typeof window !== 'undefined') {
37 window.DAM = DAM;
38 }
39 })();
0 !function(){var e={makeElem:function(e,n){n=n||[];for(var t=document.createElement(e),o=0;o<n.length;o++){var r=n[o];r instanceof Element?t.appendChild(r):"string"==typeof r||r instanceof String?t.appendChild(document.createTextNode(r)):"object"==typeof r&&null!==r?Object.keys(r).forEach(function(e){"on"===e.substring(0,2)?t.addEventListener(e.substring(2),r[e]):null===r[e]?t.removeAttribute(e):t.setAttribute(e,r[e])}):console.log(r)}return t},maker:function(n){return function(){return e.makeElem(n,arguments)}}};"undefined"!=typeof module?module.exports=e:"undefined"!=typeof window&&(window.DAM=e)}();
0 (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
1 "use strict";
2
3 var _dam = _interopRequireDefault(require("./dam.js"));
4
5 var _damWidgets = require("./dam-widgets.js");
6
7 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
8
9 /* dam-plus-widgets.js version 0.2. This file is in the public domain. */
10 window.DAM = _dam["default"];
11 _dam["default"].makeCheckbox = _damWidgets.makeCheckbox;
12 _dam["default"].makePanel = _damWidgets.makePanel;
13 _dam["default"].makeSelect = _damWidgets.makeSelect;
14 _dam["default"].makeRange = _damWidgets.makeRange;
15
16 },{"./dam-widgets.js":2,"./dam.js":3}],2:[function(require,module,exports){
17 "use strict";
18
19 var _dam = _interopRequireDefault(require("./dam.js"));
20
21 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
22
23 /* dam-widgets.js version 0.2. This file is in the public domain. */
24
25 /* if you want to use this file in an ES5 context, either remove the following line
26 and ensure dam.js has already been loaded, or just use `dam-plus-widgets-web.js`
27 instead of this file, it's probably easier to do that, just do that instead. */
28
29 /*
30 * A labelled checkbox, where the checkbox appears to the left of the label.
31 * Arguments after the first (config) argument will be applied to the label element.
32 */
33 function makeCheckbox(config) {
34 if (typeof _dam["default"].makeCheckboxCounter === 'undefined') _dam["default"].makeCheckboxCounter = 0;
35 var checkboxId = 'cfzzzb_' + _dam["default"].makeCheckboxCounter++;
36
37 var _onchange = config.onchange || function (b) {}; // config label: make copy of arguments, replace first with a bespoke config
38
39
40 var args = new Array(arguments.length);
41
42 for (var i = 0; i < args.length; ++i) {
43 args[i] = arguments[i];
44 }
45
46 args[0] = {
47 'for': checkboxId,
48 'class': "dam-widget dam-checkbox"
49 };
50 return _dam["default"].makeElem('span', [_dam["default"].makeElem('input', [{
51 type: 'checkbox',
52 id: checkboxId,
53 onchange: function onchange(e) {
54 _onchange(e.target.checked);
55 }
56 }, config.checkboxAttrs || {}]), _dam["default"].makeElem('label', args)]);
57 }
58
59 ;
60 /*
61 * A collapsible panel.
62 * Arguments after the first (config) argument will be applied to the inner container div element.
63 */
64
65 function makePanel(config) {
66 var isOpen = !!config.isOpen;
67 var title = config.title || "";
68
69 function getLabel() {
70 return (isOpen ? "∇" : "⊳") + " " + title;
71 } // config inner container
72
73
74 var args = new Array(arguments.length);
75
76 for (var i = 0; i < args.length; ++i) {
77 args[i] = arguments[i];
78 }
79
80 args[0] = {};
81
82 var innerContainer = _dam["default"].makeElem('div', args);
83
84 innerContainer.style.display = isOpen ? "block" : "none";
85
86 var button = _dam["default"].makeElem('button', [getLabel(), {
87 onclick: function onclick(e) {
88 isOpen = !isOpen;
89 button.textContent = getLabel();
90 innerContainer.style.display = isOpen ? "block" : "none";
91 }
92 }]);
93
94 return _dam["default"].makeElem("div", [{
95 'class': "dam-widget dam-panel"
96 }, button, innerContainer]);
97 }
98
99 ;
100 /*
101 * A select dropdown.
102 */
103
104 function makeSelect(config) {
105 var title = config.title || "";
106 var options = config.options || [];
107
108 var onchange = config.onchange || function (v) {};
109
110 var select = _dam["default"].makeElem('select');
111
112 for (var i = 0; i < options.length; i++) {
113 var op = _dam["default"].makeElem('option');
114
115 op.value = options[i].value;
116 op.text = options[i].text;
117 op.selected = !!options[i].selected;
118 select.options.add(op);
119 }
120
121 select.addEventListener('change', function (e) {
122 onchange(options[select.selectedIndex]);
123 });
124 return _dam["default"].makeElem('label', [{
125 'class': "dam-widget dam-select"
126 }, title, select]);
127 }
128
129 ;
130 /*
131 * A range control.
132 */
133
134 function makeRange(config) {
135 var title = config.title || "";
136 var min_ = config['min'];
137 var max_ = config['max'];
138 var value = config.value || min_;
139
140 var _onchange2 = config.onchange || function (v) {};
141
142 var textInputSize = config.textInputSize || 5;
143 var textInput;
144 var slider;
145 slider = _dam["default"].makeElem('input', [{
146 type: "range",
147 min: min_,
148 max: max_,
149 value: value,
150 onchange: function onchange(e) {
151 var v = parseInt(slider.value, 10);
152
153 if (!isNaN(v) && v >= min_ && v <= max_) {
154 textInput.value = "" + v;
155
156 _onchange2(v);
157 }
158 }
159 }]);
160 textInput = _dam["default"].makeElem('input', [{
161 size: "" + textInputSize,
162 value: "" + value,
163 onchange: function onchange(e) {
164 var v = parseInt(textInput.value, 10);
165
166 if (!isNaN(v) && v >= min_ && v <= max_) {
167 slider.value = "" + v;
168
169 _onchange2(v);
170 }
171 }
172 }]);
173
174 var incButton = _dam["default"].makeElem('button', ['+', {
175 onclick: function onclick(e) {
176 var v = parseInt(textInput.value, 10);
177
178 if (!isNaN(v) && v < max_) {
179 v++;
180 textInput.value = "" + v;
181 slider.value = "" + v;
182
183 _onchange2(v);
184 }
185 }
186 }]);
187
188 var decButton = _dam["default"].makeElem('button', ['-', {
189 onclick: function onclick(e) {
190 var v = parseInt(textInput.value, 10);
191
192 if (!isNaN(v) && v > min_) {
193 v--;
194 textInput.value = "" + v;
195 slider.value = "" + v;
196
197 _onchange2(v);
198 }
199 }
200 }]);
201
202 var range = _dam["default"].makeElem('span', [{
203 'class': "dam-widget dam-range"
204 }, _dam["default"].makeElem('label', [title, slider]), textInput, decButton, incButton]);
205
206 range.setValue = function (v) {
207 if (!isNaN(v) && v >= min_ && v <= max_) {
208 textInput.value = "" + v;
209 slider.value = "" + v;
210
211 _onchange2(v);
212 }
213 };
214
215 return range;
216 }
217
218 ;
219 if (typeof module !== 'undefined') module.exports = {
220 'makeCheckbox': makeCheckbox,
221 'makePanel': makePanel,
222 'makeSelect': makeSelect,
223 'makeRange': makeRange
224 };
225
226 },{"./dam.js":3}],3:[function(require,module,exports){
227 "use strict";
228
229 function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
230
231 /* dam.js version 0.2. This file is in the public domain. */
232 (function () {
233 var DAM = {};
234
235 DAM.makeElem = function (tag, args) {
236 args = args || [];
237 var elem = document.createElement(tag);
238
239 for (var i = 0; i < args.length; i++) {
240 var arg = args[i];
241
242 if (arg instanceof Element) {
243 elem.appendChild(arg);
244 } else if (typeof arg === 'string' || arg instanceof String) {
245 elem.appendChild(document.createTextNode(arg));
246 } else if (_typeof(arg) === 'object' && arg !== null) {
247 Object.keys(arg).forEach(function (key) {
248 if (key.substring(0, 2) === 'on') {
249 elem.addEventListener(key.substring(2), arg[key]);
250 } else if (arg[key] === null) {
251 elem.removeAttribute(key);
252 } else {
253 elem.setAttribute(key, arg[key]);
254 }
255 });
256 } else {
257 console.log(arg);
258 }
259 }
260
261 return elem;
262 };
263
264 DAM.maker = function (tag) {
265 return function () {
266 return DAM.makeElem(tag, arguments);
267 };
268 };
269
270 if (typeof module !== 'undefined') {
271 module.exports = DAM;
272 } else if (typeof window !== 'undefined') {
273 window.DAM = DAM;
274 }
275 })();
276
277 },{}]},{},[1]);
0 !function e(t,n,a){function o(u,r){if(!n[u]){if(!t[u]){var i="function"==typeof require&&require;if(!r&&i)return i(u,!0);if(l)return l(u,!0);var c=new Error("Cannot find module '"+u+"'");throw c.code="MODULE_NOT_FOUND",c}var f=n[u]={exports:{}};t[u][0].call(f.exports,function(e){return o(t[u][1][e]||e)},f,f.exports,e,t,n,a)}return n[u].exports}for(var l="function"==typeof require&&require,u=0;u<a.length;u++)o(a[u]);return o}({1:[function(e,t,n){"use strict";var a,o=(a=e("./dam.js"))&&a.__esModule?a:{default:a},l=e("./dam-widgets.js");window.DAM=o.default,o.default.makeCheckbox=l.makeCheckbox,o.default.makePanel=l.makePanel,o.default.makeSelect=l.makeSelect,o.default.makeRange=l.makeRange},{"./dam-widgets.js":2,"./dam.js":3}],2:[function(e,t,n){"use strict";var a,o=(a=e("./dam.js"))&&a.__esModule?a:{default:a};void 0!==t&&(t.exports={makeCheckbox:function(e){void 0===o.default.makeCheckboxCounter&&(o.default.makeCheckboxCounter=0);for(var t="cfzzzb_"+o.default.makeCheckboxCounter++,n=e.onchange||function(e){},a=new Array(arguments.length),l=0;l<a.length;++l)a[l]=arguments[l];return a[0]={for:t,class:"dam-widget dam-checkbox"},o.default.makeElem("span",[o.default.makeElem("input",[{type:"checkbox",id:t,onchange:function(e){n(e.target.checked)}},e.checkboxAttrs||{}]),o.default.makeElem("label",a)])},makePanel:function(e){var t=!!e.isOpen,n=e.title||"";function a(){return(t?"∇":"⊳")+" "+n}for(var l=new Array(arguments.length),u=0;u<l.length;++u)l[u]=arguments[u];l[0]={};var r=o.default.makeElem("div",l);r.style.display=t?"block":"none";var i=o.default.makeElem("button",[a(),{onclick:function(e){t=!t,i.textContent=a(),r.style.display=t?"block":"none"}}]);return o.default.makeElem("div",[{class:"dam-widget dam-panel"},i,r])},makeSelect:function(e){for(var t=e.title||"",n=e.options||[],a=e.onchange||function(e){},l=o.default.makeElem("select"),u=0;u<n.length;u++){var r=o.default.makeElem("option");r.value=n[u].value,r.text=n[u].text,r.selected=!!n[u].selected,l.options.add(r)}return l.addEventListener("change",function(e){a(n[l.selectedIndex])}),o.default.makeElem("label",[{class:"dam-widget dam-select"},t,l])},makeRange:function(e){var t,n,a=e.title||"",l=e.min,u=e.max,r=e.value||l,i=e.onchange||function(e){},c=e.textInputSize||5;n=o.default.makeElem("input",[{type:"range",min:l,max:u,value:r,onchange:function(e){var a=parseInt(n.value,10);!isNaN(a)&&a>=l&&a<=u&&(t.value=""+a,i(a))}}]),t=o.default.makeElem("input",[{size:""+c,value:""+r,onchange:function(e){var a=parseInt(t.value,10);!isNaN(a)&&a>=l&&a<=u&&(n.value=""+a,i(a))}}]);var f=o.default.makeElem("button",["+",{onclick:function(e){var a=parseInt(t.value,10);!isNaN(a)&&a<u&&(a++,t.value=""+a,n.value=""+a,i(a))}}]),d=o.default.makeElem("button",["-",{onclick:function(e){var a=parseInt(t.value,10);!isNaN(a)&&a>l&&(a--,t.value=""+a,n.value=""+a,i(a))}}]),m=o.default.makeElem("span",[{class:"dam-widget dam-range"},o.default.makeElem("label",[a,n]),t,d,f]);return m.setValue=function(e){!isNaN(e)&&e>=l&&e<=u&&(t.value=""+e,n.value=""+e,i(e))},m}})},{"./dam.js":3}],3:[function(e,t,n){"use strict";function a(e){return(a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var o;o={makeElem:function(e,t){t=t||[];for(var n=document.createElement(e),o=0;o<t.length;o++){var l=t[o];l instanceof Element?n.appendChild(l):"string"==typeof l||l instanceof String?n.appendChild(document.createTextNode(l)):"object"===a(l)&&null!==l?Object.keys(l).forEach(function(e){"on"===e.substring(0,2)?n.addEventListener(e.substring(2),l[e]):null===l[e]?n.removeAttribute(e):n.setAttribute(e,l[e])}):console.log(l)}return n},maker:function(e){return function(){return o.makeElem(e,arguments)}}},void 0!==t?t.exports=o:"undefined"!=typeof window&&(window.DAM=o)},{}]},{},[1]);
0 {
1 "name": "catseye-DAM",
2 "version": "0.2.0",
3 "description": "You've tried the Document Object Model, now try the Document *Awesome* Model",
4 "repository": "https://github.com/catseye/DAM.git",
5 "license": "UNLICENSE",
6 "scripts": {
7 "build:dam": "cp src/dam.js dist/dam-0.2.js",
8 "minify:dam": "cat dist/dam-0.2.js | terser --compress --mangle | uglifyjs > dist/dam-0.2.min.js",
9 "build:dam-plus-widgets": "browserify src/dam-plus-widgets.js -t [ babelify --presets [ @babel/preset-env ] ] -g [ envify --NODE_ENV production ] > dist/dam-plus-widgets-0.2.js",
10 "minify:dam-plus-widgets": "cat dist/dam-plus-widgets-0.2.js | terser --compress --mangle | uglifyjs > dist/dam-plus-widgets-0.2.min.js",
11 "build:all": "npm run build:dam && npm run minify:dam && npm run build:dam-plus-widgets && npm run minify:dam-plus-widgets"
12 },
13 "devDependencies": {
14 "@babel/core": "^7.5.4",
15 "@babel/preset-env": "^7.5.4",
16 "babelify": "^10.0.0",
17 "browserify": "^16.3.0",
18 "envify": "^4.1.0",
19 "terser": "^4.1.2",
20 "uglify-js": "^3.6.0",
21 "uglifyify": "^5.0.1"
22 }
23 }
+0
-208
src/dam-plus-widgets-web.js less more
0 /* dam-plus-widgets-web.js version 0.1. This file is in the public domain. */
1
2 /* This file is recommended if you just want to use DAM and its standard
3 widget library on an HTML page without bothering with JS build stuff.
4 It consists of dam.js followed by dam-widgets.js, both with only small
5 hand modifications to make them load as-is in ES5. */
6
7 var DAM = (function() {
8 var DAM = {};
9 DAM.makeElem = function(tag, args) {
10 args = args || [];
11 var elem = document.createElement(tag);
12 for (var i = 0; i < args.length; i++) {
13 var arg = args[i];
14 if (arg instanceof Element) {
15 elem.appendChild(arg);
16 } else if (typeof arg === 'string' || arg instanceof String) {
17 elem.appendChild(document.createTextNode(arg));
18 } else if (typeof arg === 'object' && arg !== null) {
19 Object.keys(arg).forEach(function(key) {
20 if (key.substring(0, 2) === 'on') {
21 elem.addEventListener(key.substring(2), arg[key]);
22 } else if (arg[key] === null) {
23 elem.removeAttribute(key);
24 } else {
25 elem.setAttribute(key, arg[key]);
26 }
27 });
28 } else {
29 console.log(arg);
30 }
31 }
32 return elem;
33 };
34 DAM.maker = function(tag) {
35 return function() {
36 return DAM.makeElem(tag, arguments);
37 };
38 };
39 return DAM;
40 })();
41
42 (function(DAM) { // ENTER-SCOPE
43
44 /*
45 * A labelled checkbox, where the checkbox appears to the left of the label.
46 * Arguments after the first (config) argument will be applied to the label element.
47 */
48 DAM.makeCheckbox = function(config) {
49 if (typeof DAM.makeCheckboxCounter === 'undefined') DAM.makeCheckboxCounter = 0;
50 var checkboxId = 'cfzzzb_' + (DAM.makeCheckboxCounter++);
51
52 var onchange = config.onchange || function(b) {};
53
54 // config label: make copy of arguments, replace first with a bespoke config
55 var args = new Array(arguments.length);
56 for(var i = 0; i < args.length; ++i) {
57 args[i] = arguments[i];
58 }
59 args[0] = { 'for': checkboxId, 'class': "dam-widget dam-checkbox" }
60
61 return DAM.makeElem('span', [
62 DAM.makeElem('input', [
63 {
64 type: 'checkbox',
65 id: checkboxId,
66 onchange: function(e) {
67 onchange(e.target.checked);
68 }
69 },
70 config.checkboxAttrs || {}
71 ]),
72 DAM.makeElem('label', args)
73 ]);
74 };
75
76 /*
77 * A collapsible panel.
78 * Arguments after the first (config) argument will be applied to the inner container div element.
79 */
80 DAM.makePanel = function(config) {
81 var isOpen = !!(config.isOpen);
82 var title = config.title || "";
83
84 function getLabel() {
85 return (isOpen ? "∇" : "⊳") + " " + title;
86 }
87
88 // config inner container
89 var args = new Array(arguments.length);
90 for(var i = 0; i < args.length; ++i) {
91 args[i] = arguments[i];
92 }
93 args[0] = {}
94
95 var innerContainer = DAM.makeElem('div', args);
96 innerContainer.style.display = isOpen ? "block" : "none";
97
98 var button = DAM.makeElem('button', [
99 getLabel(),
100 {
101 onclick: function(e) {
102 isOpen = !isOpen;
103 button.textContent = getLabel();
104 innerContainer.style.display = isOpen ? "block" : "none";
105 }
106 }
107 ]);
108
109 return DAM.makeElem("div", [{ 'class': "dam-widget dam-panel" }, button, innerContainer]);
110 };
111
112 /*
113 * A select dropdown.
114 */
115 DAM.makeSelect = function(config) {
116 var title = config.title || "";
117 var options = config.options || [];
118 var onchange = config.onchange || function(v) {};
119
120 var select = DAM.makeElem('select');
121 for (var i = 0; i < options.length; i++) {
122 var op = DAM.makeElem('option');
123 op.value = options[i].value;
124 op.text = options[i].text;
125 op.selected = !!(options[i].selected);
126 select.options.add(op);
127 }
128 select.addEventListener('change', function(e) {
129 onchange(options[select.selectedIndex]);
130 });
131 return DAM.makeElem('label', [{ 'class': "dam-widget dam-select" }, title, select]);
132 };
133
134 /*
135 * A range control.
136 */
137 DAM.makeRange = function(config) {
138 var title = config.title || "";
139 var min_ = config['min'];
140 var max_ = config['max'];
141 var value = config.value || min_;
142 var onchange = config.onchange || function(v) {};
143 var textInputSize = config.textInputSize || 5;
144
145 var textInput; var slider;
146
147 slider = DAM.makeElem('input', [
148 {
149 type: "range", min: min_, max: max_, value: value,
150 onchange: function(e) {
151 var v = parseInt(slider.value, 10);
152 if (!isNaN(v)) {
153 textInput.value = "" + v;
154 onchange(v);
155 }
156 }
157 }
158 ]);
159
160 textInput = DAM.makeElem('input', [
161 {
162 size: "" + textInputSize,
163 value: "" + value,
164 onchange: function(e) {
165 var v = parseInt(textInput.value, 10);
166 if (!isNaN(v) && v >= min_ && v <= max_) {
167 slider.value = "" + v;
168 onchange(v);
169 }
170 }
171 }
172 ]);
173
174 var incButton = DAM.makeElem('button', ['+',
175 {
176 onclick: function(e) {
177 var v = parseInt(textInput.value, 10);
178 if ((!isNaN(v)) && v < max_) {
179 v++;
180 textInput.value = "" + v;
181 slider.value = "" + v;
182 onchange(v);
183 }
184 }
185 }
186 ]);
187
188 var decButton = DAM.makeElem('button', ['-',
189 {
190 onclick: function(e) {
191 var v = parseInt(textInput.value, 10);
192 if ((!isNaN(v)) && v > min_) {
193 v--;
194 textInput.value = "" + v;
195 slider.value = "" + v;
196 onchange(v);
197 }
198 }
199 }
200 ]);
201
202 return DAM.makeElem('span', [{ 'class': "dam-widget dam-range" }, DAM.makeElem('label', [title, slider]), textInput, decButton, incButton]);
203 };
204
205 })(DAM); // EXIT-SCOPE
206
207 if (typeof module !== 'undefined') module.exports = DAM;
0 /* dam-plus-widgets.js version 0.2. This file is in the public domain. */
1
2 import DAM from './dam.js'
3 import { makeCheckbox, makePanel, makeSelect, makeRange} from './dam-widgets.js'
4
5 window.DAM = DAM;
6 DAM.makeCheckbox = makeCheckbox;
7 DAM.makePanel = makePanel;
8 DAM.makeSelect = makeSelect;
9 DAM.makeRange = makeRange;
0 /* dam-widgets.js version 0.1. This file is in the public domain. */
0 /* dam-widgets.js version 0.2. This file is in the public domain. */
11
22 /* if you want to use this file in an ES5 context, either remove the following line
33 and ensure dam.js has already been loaded, or just use `dam-plus-widgets-web.js`
55
66 import DAM from './dam.js'
77
8 (function(DAM) { // ENTER-SCOPE
9
108 /*
119 * A labelled checkbox, where the checkbox appears to the left of the label.
1210 * Arguments after the first (config) argument will be applied to the label element.
1311 */
14 DAM.makeCheckbox = function(config) {
12 function makeCheckbox(config) {
1513 if (typeof DAM.makeCheckboxCounter === 'undefined') DAM.makeCheckboxCounter = 0;
1614 var checkboxId = 'cfzzzb_' + (DAM.makeCheckboxCounter++);
1715
4341 * A collapsible panel.
4442 * Arguments after the first (config) argument will be applied to the inner container div element.
4543 */
46 DAM.makePanel = function(config) {
44 function makePanel(config) {
4745 var isOpen = !!(config.isOpen);
4846 var title = config.title || "";
4947
7876 /*
7977 * A select dropdown.
8078 */
81 DAM.makeSelect = function(config) {
79 function makeSelect(config) {
8280 var title = config.title || "";
8381 var options = config.options || [];
8482 var onchange = config.onchange || function(v) {};
10098 /*
10199 * A range control.
102100 */
103 DAM.makeRange = function(config) {
101 function makeRange(config) {
104102 var title = config.title || "";
105103 var min_ = config['min'];
106104 var max_ = config['max'];
115113 type: "range", min: min_, max: max_, value: value,
116114 onchange: function(e) {
117115 var v = parseInt(slider.value, 10);
118 if (!isNaN(v)) {
116 if (!isNaN(v) && v >= min_ && v <= max_) {
119117 textInput.value = "" + v;
120118 onchange(v);
121119 }
165163 }
166164 ]);
167165
168 return DAM.makeElem('span', [{ 'class': "dam-widget dam-range" }, DAM.makeElem('label', [title, slider]), textInput, decButton, incButton]);
166 var range = DAM.makeElem('span', [
167 { 'class': "dam-widget dam-range" },
168 DAM.makeElem('label', [title, slider]),
169 textInput,
170 decButton,
171 incButton
172 ]);
173 range.setValue = function(v) {
174 if (!isNaN(v) && v >= min_ && v <= max_) {
175 textInput.value = "" + v;
176 slider.value = "" + v;
177 onchange(v);
178 }
179 };
180 return range;
169181 };
170182
171 })(DAM); // EXIT-SCOPE
172
173 if (typeof module !== 'undefined') module.exports = DAM;
183 if (typeof module !== 'undefined') module.exports = {
184 'makeCheckbox': makeCheckbox,
185 'makePanel': makePanel,
186 'makeSelect': makeSelect,
187 'makeRange': makeRange
188 };
0 /* dam.js version 0.1. This file is in the public domain. */
0 /* dam.js version 0.2. This file is in the public domain. */
11
22 (function() {
33 var DAM = {};