Skip to content

Commit

Permalink
This PR is implementing the another "result" function for the $ (`s…
Browse files Browse the repository at this point in the history
…elector`) function .

The new "result" function `toArray()` returns an `array of strings` which is an usual array with has all selected `id's` and you can apply all appropriate arrays methods to it.
The reason of this PR - in some cases, you need to get the array of strings from the `selector`, instead of use the current `each` iterator. Moreover, the source data already presented as an array of strings, so you don't need to iterate it once more time.
Changed files:
- `lib/javascript.d.ts`: updated declaration of `$` - the `toArray() is added;
- `lib/sandbox.js`: implementation of the `toArray()` function;
- `test/testFunctions.js`: test added for the `toArray()` function;
- `docs/en/javascript.md`: documentation updates of the `$` function description.
  • Loading branch information
PeterVoronov committed Apr 11, 2024
1 parent af09773 commit 973646e
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 1 deletion.
8 changes: 7 additions & 1 deletion docs/en/javascript.md
Expand Up @@ -1352,6 +1352,7 @@ Sends to an adapter the message `unsubscribe` to inform adapter to not poll the
### $ - Selector
```js
$(selector).on(function(obj) {});
$(selector).toArray();
$(selector).each(function(id, i) {});
$(selector).setState(value, ack);
$(selector).getState();
Expand Down Expand Up @@ -1396,7 +1397,7 @@ Find all channels with `common.role="switch"` and belongs to `enum.rooms.Wohnzim
Take all their states, where id ends with `".STATE"` and make subscription on all these states.
If some of these states change, the callback will be called like for "on" function.

Following functions are possible, setState, getState (only from first), on, each
Following functions are possible, setState, getState (only from first), on, each, toArray

```js
// Switch on all switches in "Wohnzimmer"
Expand All @@ -1413,6 +1414,11 @@ $('channel[role=switch][state.id=*.STATE](rooms=Wohnzimmer)').each((id, i) => {
}
});
```
Or you can get a an usual array of ids and process it your own way:
```js
// get some state and filter only which has an `true` value
const enabled = $('channel[role=switch][state.id=*.STATE](rooms=Wohnzimmer)').toArray().filter((id) => getState(id)?.val === true);
```
### readFile
```js
Expand Down
5 changes: 5 additions & 0 deletions lib/javascript.d.ts
Expand Up @@ -1043,6 +1043,11 @@ declare global {
/** Contains the error if one happened */
error?: string;

/**
* Return the result as an array of state ids
*/
toArray(): Array<string>;

/**
* Executes a function for each state id in the result array
* The execution is canceled if a callback returns false
Expand Down
6 changes: 6 additions & 0 deletions lib/sandbox.js
Expand Up @@ -643,6 +643,9 @@ function sandBox(script, name, verbose, debug, context) {
// If some error in the selector
if (selectorHasInvalidType || isInsideEnumString || isInsideCommonString || isInsideNativeString) {
result.length = 0;
result.toArray = function () {
return [];
};
result.each = function () {
return this;
};
Expand Down Expand Up @@ -932,6 +935,9 @@ function sandBox(script, name, verbose, debug, context) {
yield result[i];
}
};
result.toArray = function () {
return [...resUnique];
};
result.each = function (callback) {
if (typeof callback === 'function') {
let r;
Expand Down
41 changes: 41 additions & 0 deletions test/testFunctions.js
@@ -1,4 +1,5 @@
const expect = require('chai').expect;
const { log } = require('node:console');
const setup = require('./lib/setup');

let objects = null;
Expand Down Expand Up @@ -927,6 +928,46 @@ describe.only('Test JS', function () {
objects.setObject(script._id, script);
});

it('Test JS: test $().toArray()', function (done) {
this.timeout(1000);
// add script
const script = {
_id: 'script.js.selectorToArray',
type: 'script',
common: {
name: 'selectorToArray',
enabled: true,
verbose: true,
engine: 'system.adapter.javascript.0',
engineType: 'Javascript/js',
source: `createState('selector.test_1.state', true, () => {\n` +
` createState('selector.test_2.state', false, () => {\n` +
` createState('selector.test_3.state', true, () => {\n` +
` $(createState('selector.test_4.id', true, () => {\n` +
` const states = $('state[id=javascript.0.selector.test_*.state]')` +
` .toArray().filter((id) => getState(id)?.val === true);\n` +
` if (Array.isArray(states)) {\n` +
` createState('selector.result', states.length, true);\n` +
` }\n` +
` }));\n` +
` });\n` +
` });\n` +
`});`,
},
native: {}
};

const onStateChanged = function (id, state){
if (id !== 'javascript.0.selector.result') return;
removeStateChangedHandler(onStateChanged);
expect(state.val).to.be.equal(2);
done();
};
addStateChangedHandler(onStateChanged);
objects.setObject(script._id, script);
});


it('Test JS: test stopScript', function (done) {
this.timeout(5000);
// add script
Expand Down

0 comments on commit 973646e

Please sign in to comment.