Comparing version 0.8.17 to 0.8.18
/** | ||
* ctrling.js (c) 2022/23 Stefan Goessner | ||
* ver. 0.8.17 | ||
* ver. 0.8.18 | ||
* @license MIT License | ||
@@ -30,3 +30,2 @@ */ | ||
this.#main = this.shadowRoot.querySelector('main'); | ||
console.log(this.#main) | ||
} | ||
@@ -52,3 +51,6 @@ | ||
// see https://stackoverflow.com/questions/28776079/do-let-statements-create-properties-on-the-global-object | ||
this.#refObj = ref && (globalThis[ref] || eval(ref)); | ||
try { | ||
this.#refObj = ref && (globalThis[ref] || eval(ref)); | ||
} | ||
catch (e) { this.addSection({sec:'hdr',text:"Ctrling: 'ref' object " + e.message}); } | ||
} | ||
@@ -65,3 +67,3 @@ else if (name === 'width') { | ||
else if (name === 'darkmode') { | ||
if (this.getAttribute('darkmode') === '') { | ||
if (this.hasAttribute('darkmode')) { | ||
this.style.setProperty("--bkg-1", "var(--dark-bkg-1)"); | ||
@@ -74,3 +76,3 @@ this.style.setProperty("--bkg-2", "var(--dark-bkg-2)"); | ||
} | ||
else { | ||
else { // removed via API ... | ||
this.style.setProperty("--bkg-1", "var(--lite-bkg-1)"); | ||
@@ -104,3 +106,3 @@ this.style.setProperty("--bkg-2", "var(--lite-bkg-2)"); | ||
window.clearInterval(this.timer); | ||
this.#timer = window.setInterval(() => this.updateControls(), 1000/this.#ticksPerSecond) | ||
this.#timer = window.setInterval(() => this.updateControlValues(), 1000/this.#ticksPerSecond) | ||
} | ||
@@ -139,3 +141,3 @@ } | ||
this.#oninit(this); | ||
if (this.#usrValueCallback) | ||
@@ -158,3 +160,3 @@ this.#usrValueCallback({ctrl:this}); // call initially once with empty arguments object ... | ||
const obj = this.#refObj; | ||
const members = Object.getOwnPropertyNames(obj); | ||
const members = Object.keys(obj); //Object.getOwnPropertyNames(obj); | ||
const sectype = {"boolean":"chk","number":"num","string":"txt"}; | ||
@@ -164,4 +166,8 @@ | ||
for (const m of members) { | ||
if (!m.startsWith('_') && ['boolean','number','string'].includes(typeof obj[m])) | ||
this.addSection({"sec":`${sectype[typeof obj[m]]}`,"label":m,"path":`$['${m}']`}); | ||
if (!m.startsWith('_')) { | ||
if (typeof obj[m] === 'string' && obj[m].startsWith('#')) // rgb color ... | ||
this.addSection({"sec":`col`,"label":m,"path":`$['${m}']`}); | ||
else if (['boolean','number','string'].includes(typeof obj[m])) | ||
this.addSection({"sec":`${sectype[typeof obj[m]]}`,"label":m,"path":`$['${m}']`}); | ||
} | ||
} | ||
@@ -202,3 +208,3 @@ if (src) { | ||
} | ||
#setRefValue(obj, member, value, section, elem) { | ||
#setRefValue(ctrl, obj, member, value, section, elem) { | ||
value = (value === true || | ||
@@ -211,3 +217,3 @@ value === false || | ||
if (this.#usrValueCallback !== undefined) { | ||
this.#usrValueCallback({ctrl:this, obj, member, value, section, elem}); | ||
this.#usrValueCallback({ctrl, obj, member, value, section, elem}); | ||
} | ||
@@ -284,3 +290,3 @@ return value; | ||
} | ||
replaceSection(idx, sec) { | ||
updateSection(idx, sec) { | ||
if (idx >= 0) { | ||
@@ -317,3 +323,3 @@ if (sec !== undefined) { | ||
const input = elem.querySelector('input'); | ||
this.#addListeners(args, [{type:"input", elem:elem.querySelector('input'), hdl:(e) => this.#setRefValue(obj, member, !!e.target.checked, args, elem)}]); | ||
this.#addListeners(args, [{type:"input", elem:elem.querySelector('input'), hdl:(e) => this.#setRefValue(this, obj, member, !!e.target.checked, args, elem)}]); | ||
args._upd = () => { input.checked = obj[member] ? 'checked' : '' }; | ||
@@ -327,3 +333,3 @@ return elem; | ||
const input = elem.querySelector('input'); | ||
this.#addListeners(args, [{type:"input", elem:input, hdl:(e) => { input.nextSibling.innerHTML = this.#setRefValue(obj, member, e.target.value, args, elem) }}]); | ||
this.#addListeners(args, [{type:"input", elem:input, hdl:(e) => { input.nextSibling.innerHTML = this.#setRefValue(this, obj, member, e.target.value, args, elem) }}]); | ||
args._upd = () => { input.nextSibling.innerHTML = input.value = this.#getRefValue(obj, member, "#000000"); }; | ||
@@ -338,4 +344,4 @@ return elem; | ||
const input = elem.querySelector('input'); | ||
this.#addListeners(args, [{type:"input", elem:input, hdl:(e) => this.#setRefValue(obj, member, round(+e.target.value, args.fractions), args, elem)}, | ||
{type:"change",elem:input, hdl:(e) => this.#setRefValue(obj, member, e.target.value=round(+e.target.value, args.fractions), args, elem)} ]); | ||
this.#addListeners(args, [{type:"input", elem:input, hdl:(e) => this.#setRefValue(this, obj, member, round(+e.target.value, args.fractions), args, elem)}, | ||
{type:"change",elem:input, hdl:(e) => this.#setRefValue(this, obj, member, e.target.value=round(+e.target.value, args.fractions), args, elem)} ]); | ||
args._upd = () => { input.value = this.#getRefValue(obj, member, 0); }; | ||
@@ -357,3 +363,3 @@ return elem; | ||
const input = elem.querySelector('input'); | ||
this.#addListeners(args, [{type:"input", elem:input, hdl:(e) => { input.nextSibling.innerHTML = this.#setRefValue(obj, member, +e.target.value, args, elem) }}]); | ||
this.#addListeners(args, [{type:"input", elem:input, hdl:(e) => { input.nextSibling.innerHTML = this.#setRefValue(this, obj, member, +e.target.value, args, elem) }}]); | ||
args._upd = () => { input.nextSibling.innerHTML = input.value = this.#getRefValue(obj, member, 0); }; | ||
@@ -368,3 +374,3 @@ return elem; | ||
const select = elem.querySelector('select'); | ||
this.#addListeners(args, [{type:"input", elem:select, hdl:(e) => this.#setRefValue(obj, member, isNaN(e.target.value) ? e.target.value : +e.target.value, args, elem)}]); | ||
this.#addListeners(args, [{type:"input", elem:select, hdl:(e) => this.#setRefValue(this, obj, member, isNaN(e.target.value) ? e.target.value : +e.target.value, args, elem)}]); | ||
args._upd = () => { select.value = this.#getRefValue(obj, member, options[0][1]); }; | ||
@@ -430,3 +436,3 @@ return elem; | ||
const [obj, member] = this.#getRef(e.target._ctrlpath); | ||
this.#setRefValue(obj, member, isNaN(e.target.value) ? e.target.value : +e.target.value, args, elem)}}); | ||
this.#setRefValue(this, obj, member, isNaN(e.target.value) ? e.target.value : +e.target.value, args, elem)}}); | ||
} | ||
@@ -443,3 +449,3 @@ this.#addListeners(args, listeners); | ||
} | ||
// static methods ... | ||
static stringify(value) { | ||
@@ -446,0 +452,0 @@ return Array.isArray(value) ? JSON.stringify(value) |
@@ -39,3 +39,3 @@ --- | ||
`ctrl-ing` is a tiny HTML custom element used to interactively control your Web-App parameters or JavaScript/JSON object values in a comfortable way with the following characteristics: | ||
`ctrl-ing` is a tiny HTML custom element used to interactively control your Web-App parameters or JavaScript/JSON/DOM object values in a comfortable way with the following characteristics: | ||
@@ -45,2 +45,3 @@ * tiny footprint `18.7/11.3 kB` un/compressed. | ||
* easy prototypical generation with low effort. | ||
* given an object, a menu template can even be created automatically. | ||
* no programming required. | ||
@@ -174,2 +175,4 @@ * getting a pleasing GUI. | ||
### 3.1 `<ctrl-ing>` Attributes | ||
For an `<ctrl-ing>` element following optional attributes are supported: | ||
@@ -186,11 +189,12 @@ | ||
|`autogenerate` | - | Automatically generate a prototype menu from the object given by `ref` attribute. | | ||
|`tickspersecond` | `4` | How often to update sections per second. | | ||
|`callback` | - | If present, will be called with each user value change by input sections. The attribute value must obey the [JSONPath](https://ietf-wg-jsonpath.github.io/draft-ietf-jsonpath-base/draft-ietf-jsonpath-base.html#name-normalized-paths) syntax rules and might be a global function or a static object method. | | ||
|`tickspersecond` | `4` | How often to update sections per second (on external value change). | | ||
|`callback` | - | If present, will be called with each user value change by input sections. The attribute value must obey the [JSONPath](https://ietf-wg-jsonpath.github.io/draft-ietf-jsonpath-base/draft-ietf-jsonpath-base.html#name-normalized-paths) syntax rules and might be a global function or an object method. | | ||
<figcaption>Table 1: Supported <code>ctrl-ing</code> attributes.</figcaption><br> | ||
The `callback` function or method will be handed over an argument object with the structure | ||
The `callback` function or method will be handed over an argument object with the structure: | ||
```js | ||
args = { | ||
ctrl, // current `<ctrl-ing>` element object. | ||
obj, // parent object holding the member, whose value is to be set. | ||
@@ -203,4 +207,14 @@ member, // the member name, whose value is to be set. | ||
``` | ||
Please note, that during a single initial call of the `callback` function an empty `args` object will be passed as an argument. | ||
Please note, that a first initial call of the `callback` function – when exists – is automatically done during initialization time. A reduced object `args = {ctrl}` will be passed as an argument then. | ||
### 3.2 Automatical Menu Generation | ||
It is possible to let a `<ctrl-ing>` element automatically generate a GUI menu from a given JavaScript object. | ||
```html | ||
<ctrl-ing ref="obj" autogenerate></ctrl-ing> | ||
``` | ||
## 4. Sections Reference | ||
@@ -833,3 +847,3 @@ | ||
The `<ctrl-ing>` menu's internals are hidden behind the shadow DOM. For offering programmatical access to these internals, an API is provided. Here is an example. | ||
The `<ctrl-ing>` menu internals are hidden behind the shadow DOM. For offering programmatical access to these internals, an API is provided. Here is an example how to use it. | ||
@@ -863,4 +877,4 @@ ```html | ||
1. The API works properly at the earliest, after the `<ctrl-ing>` element is completely initialized. In order to ensure this, we need to encapsulate the API method calls in a callback function `oninit((ctrl) => { ... })`. The callback function recieves the `<ctrl-ing>` element object as a single argument. | ||
2. The `setAttr` method is merely syntactic sugar for native `setAttribute` method. It additionally supports chaining of method calls only. | ||
1. Ensure to start with API calls when the `<ctrl-ing>` element is completely initialized. | ||
2. The `setAttr` method is merely syntactic sugar for the native `setAttribute` method. It additionally supports chaining of method calls only. | ||
3. `addSection` methods are used to sequentially build the control menu. They get a single object literal argument representing a section. | ||
@@ -872,3 +886,4 @@ 4. Note the intentional typo with the `path` value. That will be corrected in (6). | ||
**Properties** | ||
The API works properly at the earliest after the <ctrl-ing> element is completely initialized. In order to ensure this, we want to encapsulate the API method calls in a callback function oninit((ctrl) => { ... }). The callback function receives the <ctrl-ing> element object as a single argument. | ||
| Method | Returns | Comment | | ||
@@ -879,3 +894,3 @@ |:--|:--|:--| | ||
|`insertSection(idx,sec)` | `this` | Insert a new section object `sec` to the sections array after the section at index `idx`. | | ||
|`oninit(fn)` | - | Invoking a callback function `fn`, while ensuring that the control menu object is completely initialized. | | ||
|`oninit(fn)` | - | Invoking a callback function `fn`, while ensuring that the control menu object is completely initialized. The callback function receives the `<ctrl-ing>` element object as a single argument. | | ||
|`removeAttr(attr)` | `this` | Remove `<ctrl-ing>`'s attribute `attr`. | | ||
@@ -892,3 +907,3 @@ |`removeSection(idx)` | `this` | Remove the section at index `idx`. | | ||
API methods may be used to modify the `<ctrl-ing>` menu itself. This is shown by a tiny example. | ||
API methods may be used to modify the `<ctrl-ing>` menu itself. Here is an example, how to disable a section. | ||
@@ -920,3 +935,2 @@ | ||
``` | ||
<ctrl-ing id="ctrlslf" ref="objslf" callback="$['callbk']"> | ||
@@ -930,3 +944,3 @@ [ {"sec":"hdr","text":"Self-Control"}, | ||
<script> | ||
const ctrl = document.getElementById('ctrl'); | ||
const ctrl = document.getElementById('ctrlslf'); | ||
const obj = { | ||
@@ -933,0 +947,0 @@ disable: false, |
{ | ||
"name": "ctrling", | ||
"version": "0.8.17", | ||
"version": "0.8.18", | ||
"description": "An appealing prototypical GUI for controlling your Web-App, JSON or JavaScript Object Values", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
4328634
32
756