@schukai/monster 3.46.0 → 3.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/source/dom/constants.mjs
CHANGED
|
@@ -59,6 +59,9 @@ export {
|
|
|
59
59
|
ATTRIBUTE_HIDDEN,
|
|
60
60
|
objectUpdaterLinkSymbol,
|
|
61
61
|
customElementUpdaterLinkSymbol,
|
|
62
|
+
optionCallbackName,
|
|
63
|
+
ATTRIBUTE_SCRIPT_HOST,
|
|
64
|
+
ATTRIBUTE_OPTION_CALLBACK
|
|
62
65
|
};
|
|
63
66
|
|
|
64
67
|
/**
|
|
@@ -86,6 +89,16 @@ const ATTRIBUTE_PREFIX = "data-monster-";
|
|
|
86
89
|
*/
|
|
87
90
|
const ATTRIBUTE_OPTIONS = `${ATTRIBUTE_PREFIX}options`;
|
|
88
91
|
|
|
92
|
+
/**
|
|
93
|
+
* This is name of the attribute to pass the script host to a control
|
|
94
|
+
*
|
|
95
|
+
* @memberOf Monster.DOM
|
|
96
|
+
* @license AGPLv3
|
|
97
|
+
* @since 3.48.0
|
|
98
|
+
* @type {string}
|
|
99
|
+
*/
|
|
100
|
+
const ATTRIBUTE_SCRIPT_HOST = `${ATTRIBUTE_PREFIX}script-host`;
|
|
101
|
+
|
|
89
102
|
/**
|
|
90
103
|
* This is the name of the attribute to pass options to a control
|
|
91
104
|
*
|
|
@@ -96,6 +109,26 @@ const ATTRIBUTE_OPTIONS = `${ATTRIBUTE_PREFIX}options`;
|
|
|
96
109
|
*/
|
|
97
110
|
const ATTRIBUTE_OPTIONS_SELECTOR = `${ATTRIBUTE_PREFIX}options-selector`;
|
|
98
111
|
|
|
112
|
+
/**
|
|
113
|
+
* This is the name of the attribute to pass the callback to a control
|
|
114
|
+
*
|
|
115
|
+
* @memberOf Monster.DOM
|
|
116
|
+
* @license AGPLv3
|
|
117
|
+
* @since 3.48.0
|
|
118
|
+
* @type {string}
|
|
119
|
+
*/
|
|
120
|
+
const ATTRIBUTE_OPTION_CALLBACK = `${ATTRIBUTE_PREFIX}option-callback`;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* This is the name of the callback to pass the callback to a control
|
|
124
|
+
*
|
|
125
|
+
* @memberOf Monster.DOM
|
|
126
|
+
* @license AGPLv3
|
|
127
|
+
* @since 3.48.0
|
|
128
|
+
* @type {string}
|
|
129
|
+
*/
|
|
130
|
+
const optionCallbackName = `initCustomControlOptionsCallback`;
|
|
131
|
+
|
|
99
132
|
/**
|
|
100
133
|
* @memberOf Monster.DOM
|
|
101
134
|
* @type {string}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import {findElementWithIdUpwards} from "./util.mjs";
|
|
8
9
|
import {internalSymbol} from "../constants.mjs";
|
|
9
10
|
import {extend} from "../data/extend.mjs";
|
|
10
11
|
import {Pathfinder} from "../data/pathfinder.mjs";
|
|
@@ -22,8 +23,11 @@ import {
|
|
|
22
23
|
ATTRIBUTE_DISABLED,
|
|
23
24
|
ATTRIBUTE_ERRORMESSAGE,
|
|
24
25
|
ATTRIBUTE_OPTIONS,
|
|
26
|
+
ATTRIBUTE_OPTION_CALLBACK,
|
|
25
27
|
ATTRIBUTE_OPTIONS_SELECTOR,
|
|
28
|
+
ATTRIBUTE_SCRIPT_HOST,
|
|
26
29
|
customElementUpdaterLinkSymbol,
|
|
30
|
+
optionCallbackName
|
|
27
31
|
} from "./constants.mjs";
|
|
28
32
|
import {findDocumentTemplate, Template} from "./template.mjs";
|
|
29
33
|
import {addObjectWithUpdaterToElement} from "./updater.mjs";
|
|
@@ -67,6 +71,12 @@ const attributeObserverSymbol = Symbol.for("@schukai/monster/dom/@@attributeObse
|
|
|
67
71
|
*/
|
|
68
72
|
const attributeMutationObserverSymbol = Symbol("@schukai/monster/dom/@@mutationObserver");
|
|
69
73
|
|
|
74
|
+
/**
|
|
75
|
+
* @private
|
|
76
|
+
* @type {symbol}
|
|
77
|
+
*/
|
|
78
|
+
const scriptHostElementSymbol = Symbol("scriptHostElement");
|
|
79
|
+
|
|
70
80
|
/**
|
|
71
81
|
* HTMLElement
|
|
72
82
|
* @external HTMLElement
|
|
@@ -212,6 +222,7 @@ class CustomElement extends HTMLElement {
|
|
|
212
222
|
});
|
|
213
223
|
this[initMethodSymbol]();
|
|
214
224
|
initOptionObserver.call(this);
|
|
225
|
+
this[scriptHostElementSymbol] = [];
|
|
215
226
|
|
|
216
227
|
}
|
|
217
228
|
|
|
@@ -520,6 +531,7 @@ class CustomElement extends HTMLElement {
|
|
|
520
531
|
self.setOptions(ScriptOptions);
|
|
521
532
|
}
|
|
522
533
|
|
|
534
|
+
|
|
523
535
|
if (self.getOption("shadowMode", false) !== false) {
|
|
524
536
|
try {
|
|
525
537
|
initShadowRoot.call(self);
|
|
@@ -541,6 +553,8 @@ class CustomElement extends HTMLElement {
|
|
|
541
553
|
}
|
|
542
554
|
}
|
|
543
555
|
|
|
556
|
+
initFromCallbackHost.call(this);
|
|
557
|
+
|
|
544
558
|
try {
|
|
545
559
|
nodeList = new Set([...elements, ...getSlottedElements.call(self)]);
|
|
546
560
|
} catch (e) {
|
|
@@ -607,7 +621,7 @@ class CustomElement extends HTMLElement {
|
|
|
607
621
|
const self = this;
|
|
608
622
|
|
|
609
623
|
if (attrName.startsWith("data-monster-option-")) {
|
|
610
|
-
setOptionFromAttribute(self, attrName, this[internalSymbol].getSubject()["options"])
|
|
624
|
+
setOptionFromAttribute(self, attrName, this[internalSymbol].getSubject()["options"])
|
|
611
625
|
}
|
|
612
626
|
|
|
613
627
|
const callback = self[attributeObserverSymbol]?.[attrName];
|
|
@@ -641,6 +655,99 @@ class CustomElement extends HTMLElement {
|
|
|
641
655
|
|
|
642
656
|
return containChildNode.call(self.shadowRoot, node);
|
|
643
657
|
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Calls a callback function if it exists.
|
|
661
|
+
*
|
|
662
|
+
* @param {string} name
|
|
663
|
+
* @param {*} args
|
|
664
|
+
* @returns {*}
|
|
665
|
+
*/
|
|
666
|
+
callCallback(name, args) {
|
|
667
|
+
const self = this;
|
|
668
|
+
return callControlCallback.call(self, name, ...args);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* @param {string} callBackFunctionName
|
|
676
|
+
* @param {*} args
|
|
677
|
+
* @return {any}
|
|
678
|
+
*/
|
|
679
|
+
function callControlCallback(callBackFunctionName, ...args) {
|
|
680
|
+
const self = this;
|
|
681
|
+
|
|
682
|
+
if (!isString(callBackFunctionName) || callBackFunctionName === "") {
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
if (callBackFunctionName in self) {
|
|
687
|
+
return self[callBackFunctionName](self, ...args);
|
|
688
|
+
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
if (!self.hasAttribute(ATTRIBUTE_SCRIPT_HOST)) {
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
if (self[scriptHostElementSymbol].length === 0) {
|
|
696
|
+
|
|
697
|
+
const targetId = self.getAttribute(ATTRIBUTE_SCRIPT_HOST);
|
|
698
|
+
if (!targetId) {
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
const list = targetId.split(",")
|
|
703
|
+
for (const id of list) {
|
|
704
|
+
const host = findElementWithIdUpwards(self, targetId);
|
|
705
|
+
if (!(host instanceof HTMLElement)) {
|
|
706
|
+
continue;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
self[scriptHostElementSymbol].push(host);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
for (const host of self[scriptHostElementSymbol]) {
|
|
714
|
+
if (callBackFunctionName in host) {
|
|
715
|
+
try {
|
|
716
|
+
return host[callBackFunctionName](self, ...args);
|
|
717
|
+
} catch (e) {
|
|
718
|
+
addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.toString());
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `callback ${callBackFunctionName} not found`);
|
|
724
|
+
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* This Function is called when the element is attached to the DOM.
|
|
729
|
+
*
|
|
730
|
+
* It looks for the attribute `data-monster-option-callback`. Is this attribute is not set, the default callback
|
|
731
|
+
* `initCustomControlOptionsCallback` is called.
|
|
732
|
+
*
|
|
733
|
+
* The callback is searched in this element and in the host element. If the callback is found, it is called with the
|
|
734
|
+
* element as parameter.
|
|
735
|
+
*
|
|
736
|
+
* The `monster
|
|
737
|
+
*
|
|
738
|
+
* @this CustomElement
|
|
739
|
+
*/
|
|
740
|
+
function initFromCallbackHost() {
|
|
741
|
+
const self = this;
|
|
742
|
+
|
|
743
|
+
let callBackFunctionName = optionCallbackName // default callback
|
|
744
|
+
if (self.hasAttribute(ATTRIBUTE_OPTION_CALLBACK)) {
|
|
745
|
+
callBackFunctionName = self.getAttribute(ATTRIBUTE_OPTION_CALLBACK);
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
callControlCallback.call(self, callBackFunctionName);
|
|
749
|
+
|
|
750
|
+
|
|
644
751
|
}
|
|
645
752
|
|
|
646
753
|
/**
|
package/source/types/version.mjs
CHANGED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import chai from "chai"
|
|
4
|
+
// import {internalSymbol} from "../../../../application/source/constants.mjs";
|
|
5
|
+
// import {ATTRIBUTE_OPTIONS} from "../../../../application/source/dom/constants.mjs";
|
|
6
|
+
import {getDocument} from "../../../../application/source/dom/util.mjs";
|
|
7
|
+
// import {ProxyObserver} from "../../../../application/source/types/proxyobserver.mjs";
|
|
8
|
+
// import {addObjectWithUpdaterToElement} from "../../../../application/source/dom/updater.mjs";
|
|
9
|
+
import {chaiDom} from "../../util/chai-dom.mjs";
|
|
10
|
+
import {initJSDOM} from "../../util/jsdom.mjs";
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
let expect = chai.expect;
|
|
14
|
+
chai.use(chaiDom);
|
|
15
|
+
|
|
16
|
+
// let html1 = `
|
|
17
|
+
// <div id="scripthost">
|
|
18
|
+
// </div>
|
|
19
|
+
//
|
|
20
|
+
// <div>
|
|
21
|
+
// <
|
|
22
|
+
// </div>
|
|
23
|
+
// `;
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
// defined in constants.mjs
|
|
27
|
+
// const updaterSymbolKey = "@schukai/monster/dom/custom-element@@options-updater-link"
|
|
28
|
+
// const updaterSymbolSymbol = Symbol.for(updaterSymbolKey);
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
describe('DOM', function () {
|
|
33
|
+
|
|
34
|
+
let CustomElement, registerCustomElement, TestComponent, document, TestComponent2,assignUpdaterToElement;
|
|
35
|
+
|
|
36
|
+
describe('initFromScriptHost()', function () {
|
|
37
|
+
|
|
38
|
+
const randomTagNumber = "monster-test"+Math.floor(Math.random() * 1000000);
|
|
39
|
+
|
|
40
|
+
before(function (done) {
|
|
41
|
+
initJSDOM().then(() => {
|
|
42
|
+
|
|
43
|
+
import("../../../../application/source/dom/customelement.mjs").then((m) => {
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
CustomElement = m['CustomElement'];
|
|
47
|
+
registerCustomElement = m['registerCustomElement'];
|
|
48
|
+
|
|
49
|
+
TestComponent2 = class extends CustomElement {
|
|
50
|
+
static getTag() {
|
|
51
|
+
return randomTagNumber;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
*
|
|
56
|
+
* @return {Object}
|
|
57
|
+
*/
|
|
58
|
+
get defaults() {
|
|
59
|
+
|
|
60
|
+
return Object.assign({}, super.defaults, {
|
|
61
|
+
test: 0,
|
|
62
|
+
templates: {
|
|
63
|
+
main: '<h1></h1><article><p>test</p><div id="container"></div></article>'
|
|
64
|
+
},
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
registerCustomElement(TestComponent2)
|
|
71
|
+
|
|
72
|
+
document = getDocument();
|
|
73
|
+
done()
|
|
74
|
+
} catch (e) {
|
|
75
|
+
done(e);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
}).catch((e) => {
|
|
80
|
+
done(e);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
});
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
afterEach(() => {
|
|
87
|
+
let mocks = document.getElementById('mocks');
|
|
88
|
+
mocks.innerHTML = "";
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
describe('call callback', function () {
|
|
92
|
+
it('should not found callback and add error attribute', function () {
|
|
93
|
+
|
|
94
|
+
let mocks = document.getElementById('mocks');
|
|
95
|
+
mocks.innerHTML = `<div id="call-back-host"></div><div id="container"></div>`;
|
|
96
|
+
|
|
97
|
+
let control = document.createElement(randomTagNumber);
|
|
98
|
+
control.setAttribute('data-monster-script-host', "call-back-host");
|
|
99
|
+
document.getElementById('container').appendChild(control);
|
|
100
|
+
expect(control.getOption('test')).is.eql(0);
|
|
101
|
+
expect(control.hasAttribute('data-monster-error')).is.true;
|
|
102
|
+
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should found callback initCustomControlOptionsCallback', function () {
|
|
106
|
+
|
|
107
|
+
let mocks = document.getElementById('mocks');
|
|
108
|
+
mocks.innerHTML = `<div id="call-back-host"></div><div id="container"></div>`;
|
|
109
|
+
|
|
110
|
+
const container = document.getElementById('call-back-host');
|
|
111
|
+
container.initCustomControlOptionsCallback = function (control) {
|
|
112
|
+
control.setOption('test', 1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
let control = document.createElement(randomTagNumber);
|
|
116
|
+
control.setAttribute('data-monster-script-host', "call-back-host");
|
|
117
|
+
document.getElementById('container').appendChild(control);
|
|
118
|
+
expect(control.getOption('test')).is.eql(1);
|
|
119
|
+
expect(control.hasAttribute('data-monster-error')).is.false;
|
|
120
|
+
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should found callback initCustomControlOptionsCallback from self', function () {
|
|
124
|
+
|
|
125
|
+
let mocks = document.getElementById('mocks');
|
|
126
|
+
mocks.innerHTML = `<div id="call-back-host"></div><div id="container"></div>`;
|
|
127
|
+
|
|
128
|
+
let control = document.createElement(randomTagNumber);
|
|
129
|
+
expect(control.getOption('test')).is.eql(0);
|
|
130
|
+
control.initCustomControlOptionsCallback = function (control) {
|
|
131
|
+
control.setOption('test', 2);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
control.setAttribute('data-monster-script-host', "call-back-host");
|
|
135
|
+
document.getElementById('container').appendChild(control);
|
|
136
|
+
expect(control.getOption('test')).is.eql(2);
|
|
137
|
+
expect(control.hasAttribute('data-monster-error')).is.false;
|
|
138
|
+
|
|
139
|
+
});
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
});
|
|
143
|
+
})
|
package/test/cases/monster.mjs
CHANGED