@cocreate/elements 1.48.0 → 2.0.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/.github/FUNDING.yml +1 -1
- package/.github/workflows/automated.yml +18 -7
- package/CHANGELOG.md +753 -700
- package/CONTRIBUTING.md +6 -6
- package/README.md +9 -9
- package/demo/index.html +1 -1
- package/docs/index.html +7 -7
- package/package.json +5 -5
- package/src/crudHandler.js +3 -1
- package/src/dataHandler.js +7 -0
- package/src/dataObject.js +54 -0
- package/src/formHandler.js +4 -3
- package/src/formSelectors.js +1 -0
- package/src/getDataHandler.js +2 -57
- package/src/hrefHandler.js +104 -0
- package/src/iframeHandler.js +90 -0
- package/src/index.js +446 -13
- package/src/setDataHandler.js +8 -3
- package/src/socketHandler.js +2 -2
- package/src/socketSelectors.js +3 -0
- package/src/srcHandler.js +1 -0
- package/src/valueQuery.js +3 -4
- package/src/valueQuerySelector.js +1 -0
- package/test/href-handler.test.cjs +132 -0
- package/test/lazy-loading.test.cjs +168 -0
- package/src/dndHandler.js +0 -158
package/CONTRIBUTING.md
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
# Contributing to CoCreate-elements
|
|
2
2
|
|
|
3
|
-
This project is work of [many contributors](https://github.com/
|
|
4
|
-
You're encouraged to submit [pull requests](https://github.com/
|
|
5
|
-
[propose features and discuss issues](https://github.com/
|
|
3
|
+
This project is work of [many contributors](https://github.com/CoCreateJS/elements/graphs/contributors).
|
|
4
|
+
You're encouraged to submit [pull requests](https://github.com/CoCreateJS/elements/pulls),
|
|
5
|
+
[propose features and discuss issues](https://github.com/CoCreateJS/elements/issues).
|
|
6
6
|
|
|
7
7
|
In the examples below, substitute your Github username for `contributor` in URLs.
|
|
8
8
|
|
|
9
9
|
## Fork the Project
|
|
10
10
|
|
|
11
|
-
Fork the [project on Github](https://github.com/
|
|
11
|
+
Fork the [project on Github](https://github.com/CoCreateJS/elements) and check out your copy.
|
|
12
12
|
|
|
13
13
|
```
|
|
14
14
|
git elements https://github.com/contributor/CoCreate-elements.git
|
|
15
15
|
cd CoCreate-elements
|
|
16
|
-
git remote add upstream https://
|
|
16
|
+
git remote add upstream https://github.com/CoCreateJS/elements.git
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
## Create a Topic Branch
|
|
@@ -75,7 +75,7 @@ git push origin my-feature-branch
|
|
|
75
75
|
|
|
76
76
|
## Make a Pull Request
|
|
77
77
|
|
|
78
|
-
Go to [https://github.com/
|
|
78
|
+
Go to [https://github.com/CoCreateJS/elements](https://github.com/CoCreateJS/elements) and select your feature branch.
|
|
79
79
|
Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days.
|
|
80
80
|
|
|
81
81
|
## Rebase
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Bind any HTML element directly to your data using HTML5 attributes. An element d
|
|
|
6
6
|
|
|
7
7
|
## Documentation
|
|
8
8
|
|
|
9
|
-
For a complete guide and working demo refer to the [documentation](https://
|
|
9
|
+
For a complete guide and working demo refer to the [documentation](https://CoCreateJS.com/docs/elements).
|
|
10
10
|
|
|
11
11
|
## Table of Contents
|
|
12
12
|
|
|
@@ -61,7 +61,7 @@ yarn add @cocreate/elements
|
|
|
61
61
|
### CDN
|
|
62
62
|
|
|
63
63
|
```html
|
|
64
|
-
<script src="https://cdn.
|
|
64
|
+
<script src="https://cdn.CoCreateJS.com/elements/latest/CoCreate-elements.min.js"></script>
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
---
|
|
@@ -437,7 +437,7 @@ elements.init(document.querySelector("#profile"));
|
|
|
437
437
|
|
|
438
438
|
## Announcements
|
|
439
439
|
|
|
440
|
-
All updates to this library are documented in our [CHANGELOG](https://github.com/
|
|
440
|
+
All updates to this library are documented in our [CHANGELOG](https://github.com/CoCreateJS/elements/blob/master/CHANGELOG.md) and [releases](https://github.com/CoCreateJS/elements/releases). You may also subscribe to email for releases and breaking changes.
|
|
441
441
|
|
|
442
442
|
---
|
|
443
443
|
|
|
@@ -451,15 +451,15 @@ Upcoming enhancements include:
|
|
|
451
451
|
* Development mode diagnostics for unbound and misconfigured scopes
|
|
452
452
|
* Devtools inspection of an element's scope and subscriptions
|
|
453
453
|
|
|
454
|
-
If you are interested in the future direction of this project, please take a look at our open [issues](https://github.com/
|
|
454
|
+
If you are interested in the future direction of this project, please take a look at our open [issues](https://github.com/CoCreateJS/elements/issues) and [pull requests](https://github.com/CoCreateJS/elements/pulls). We would love to hear your feedback.
|
|
455
455
|
|
|
456
456
|
---
|
|
457
457
|
|
|
458
458
|
## How to Contribute
|
|
459
459
|
|
|
460
|
-
We encourage contribution to our libraries (you might even score some nifty swag), please see our [CONTRIBUTING](https://github.com/
|
|
460
|
+
We encourage contribution to our libraries (you might even score some nifty swag), please see our [CONTRIBUTING](https://github.com/CoCreateJS/elements/blob/master/CONTRIBUTING.md) guide for details.
|
|
461
461
|
|
|
462
|
-
We want this library to be community-driven, and CoCreate led. We need your help to realize this goal. To help make sure we are building the right things in the right order, we ask that you create [issues](https://github.com/
|
|
462
|
+
We want this library to be community-driven, and CoCreate led. We need your help to realize this goal. To help make sure we are building the right things in the right order, we ask that you create [issues](https://github.com/CoCreateJS/elements/issues) and [pull requests](https://github.com/CoCreateJS/elements/pulls) or merely upvote or comment on existing issues or pull requests.
|
|
463
463
|
|
|
464
464
|
We appreciate your continued support, thank you!
|
|
465
465
|
|
|
@@ -469,7 +469,7 @@ We appreciate your continued support, thank you!
|
|
|
469
469
|
|
|
470
470
|
CoCreate-elements is guided and supported by the CoCreate Developer Experience Team.
|
|
471
471
|
|
|
472
|
-
Please Email the Developer Experience Team [here](mailto:develop@
|
|
472
|
+
Please Email the Developer Experience Team [here](mailto:develop@CoCreateJS.com) in case of any queries.
|
|
473
473
|
|
|
474
474
|
CoCreate-elements is maintained and funded by CoCreate. The names and logos for CoCreate are trademarks of CoCreate, LLC.
|
|
475
475
|
|
|
@@ -479,9 +479,9 @@ CoCreate-elements is maintained and funded by CoCreate. The names and logos for
|
|
|
479
479
|
|
|
480
480
|
This software is dual-licensed under the GNU Affero General Public License version 3 (AGPLv3) and a commercial license.
|
|
481
481
|
|
|
482
|
-
* **Open Source Use**: For open-source projects and non-commercial use, this software is available under the AGPLv3. The AGPLv3 allows you to freely use, modify, and distribute this software, provided that all modifications and derivative works are also licensed under the AGPLv3. For the full license text, see the [LICENSE file](https://github.com/
|
|
482
|
+
* **Open Source Use**: For open-source projects and non-commercial use, this software is available under the AGPLv3. The AGPLv3 allows you to freely use, modify, and distribute this software, provided that all modifications and derivative works are also licensed under the AGPLv3. For the full license text, see the [LICENSE file](https://github.com/CoCreateJS/elements/blob/master/LICENSE).
|
|
483
483
|
|
|
484
|
-
* **Commercial Use**: For-profit companies and individuals intending to use this software for commercial purposes must obtain a commercial license. The commercial license is available when you sign up for an API key on our [website](https://
|
|
484
|
+
* **Commercial Use**: For-profit companies and individuals intending to use this software for commercial purposes must obtain a commercial license. The commercial license is available when you sign up for an API key on our [website](https://CoCreateJS.com). This license permits proprietary use and modification of the software without the copyleft requirements of the AGPLv3. It is ideal for integrating this software into proprietary commercial products and applications.
|
|
485
485
|
|
|
486
486
|
If you have not purchased a commercial license and intend to use this software for commercial purposes, you are required to sign up for an API key on our website.
|
|
487
487
|
|
package/demo/index.html
CHANGED
|
@@ -195,6 +195,6 @@
|
|
|
195
195
|
|
|
196
196
|
<!-- <script src="../dist/CoCreate-elements.js"></script> -->
|
|
197
197
|
<!-- <script src="../../../CoCreateJS/dist/CoCreate.js"></script> -->
|
|
198
|
-
<script src="https://
|
|
198
|
+
<script src="https://CoCreateJS.com/dist/CoCreate.js"></script>
|
|
199
199
|
</body>
|
|
200
200
|
</html>
|
package/docs/index.html
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<meta name="robots" content="index,follow" />
|
|
14
14
|
<meta
|
|
15
15
|
property="og:image"
|
|
16
|
-
content="https://cdn.
|
|
16
|
+
content="https://cdn.CoCreateJS.com/docs/elements.png" />
|
|
17
17
|
|
|
18
18
|
<title>CoCreate-elements Documentation | CoCreateJS</title>
|
|
19
19
|
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
rel="icon"
|
|
23
23
|
type="image/png"
|
|
24
24
|
sizes="32x32"
|
|
25
|
-
href="https://
|
|
25
|
+
href="https://CoCreateJS.com/images/favicon.ico" />
|
|
26
26
|
<link
|
|
27
27
|
rel="stylesheet"
|
|
28
28
|
href="../index.css"
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
share-title="CoCreate elements"
|
|
76
76
|
share-height="600"
|
|
77
77
|
share-width="700"
|
|
78
|
-
share-media="https://cdn.
|
|
78
|
+
share-media="https://cdn.CoCreateJS.com/docs/elements.png"
|
|
79
79
|
hover="display:block!important"
|
|
80
80
|
hover-query=".social-networks">
|
|
81
81
|
<div class="display:none social-networks">
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
></a>
|
|
107
107
|
</div>
|
|
108
108
|
<a
|
|
109
|
-
href="https://github.com/
|
|
109
|
+
href="https://github.com/CoCreateJS/CoCreate-elements"
|
|
110
110
|
target="_blank"
|
|
111
111
|
class="margin-right:15px"
|
|
112
112
|
><i src="/assets/svg/github.svg"></i
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
<p class="padding:10px_0px line-height:1.5">
|
|
146
146
|
Or you can use cdn link:
|
|
147
147
|
</p>
|
|
148
|
-
<pre><code class="language-html"><script>https://cdn.
|
|
148
|
+
<pre><code class="language-html"><script>https://cdn.CoCreateJS.com/elements/latest/CoCreate-elements.min.js</script></code></pre>
|
|
149
149
|
|
|
150
150
|
<div
|
|
151
151
|
id="elements-usage"
|
|
@@ -330,13 +330,13 @@
|
|
|
330
330
|
</div>
|
|
331
331
|
</div>
|
|
332
332
|
<button
|
|
333
|
-
href="https://github.com/
|
|
333
|
+
href="https://github.com/CoCreateJS/CoCreate-elements/tree/master/docs/index.html?message=docs%3A%20describe%20your%20change..."
|
|
334
334
|
target="_blank"
|
|
335
335
|
class="display:flex justify-content:center align-items:center position:fixed bottom:15px right:15px height:50px width:50px border-radius:50% box-shadow:0px_2px_10px_0px_rgba(0,_0,_0,_0.4)">
|
|
336
336
|
<i src="../assets/svg/pencil-alt.svg"></i>
|
|
337
337
|
</button>
|
|
338
338
|
</main>
|
|
339
339
|
|
|
340
|
-
<script src="https://
|
|
340
|
+
<script src="https://CoCreateJS.com/dist/CoCreate.js"></script>
|
|
341
341
|
</body>
|
|
342
342
|
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cocreate/elements",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Fetch content into any html element by using html5 attributes to query data stored in CoCreate headless CMS. If data is changed it will instantly reflect in html tags as changes are broadcasted in realtime",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"elements",
|
|
@@ -22,17 +22,17 @@
|
|
|
22
22
|
},
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
25
|
-
"url": "git+https://
|
|
25
|
+
"url": "git+https://github.com/CoCreateJS/elements.git"
|
|
26
26
|
},
|
|
27
27
|
"author": "CoCreate LLC",
|
|
28
28
|
"license": "AGPL-3.0",
|
|
29
29
|
"bugs": {
|
|
30
|
-
"url": "https://github.com/
|
|
30
|
+
"url": "https://github.com/CoCreateJS/elements/issues"
|
|
31
31
|
},
|
|
32
|
-
"homepage": "https://
|
|
32
|
+
"homepage": "https://CoCreateJS.com/docs/elements",
|
|
33
33
|
"funding": {
|
|
34
34
|
"type": "GitHub Sponsors ❤",
|
|
35
|
-
"url": "https://github.com/sponsors/
|
|
35
|
+
"url": "https://github.com/sponsors/CoCreateJS"
|
|
36
36
|
},
|
|
37
37
|
"main": "./src/index.js",
|
|
38
38
|
"dependencies": {
|
package/src/crudHandler.js
CHANGED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// CRUD runtime. Loaded by data selectors, CRUD actions, or an Elements API call.
|
|
2
|
+
import "@cocreate/element-prototype";
|
|
3
|
+
|
|
4
|
+
export { init } from "./initHandler.js";
|
|
5
|
+
export { read, save } from "./crudHandler.js";
|
|
6
|
+
export { getData } from "./getDataHandler.js";
|
|
7
|
+
export { setDataType } from "./setDataHandler.js";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { getAttributes, checkValue } from "@cocreate/utils";
|
|
2
|
+
|
|
3
|
+
export const environment = localStorage.getItem("environment");
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Parses and normalizes HTML attributes from an element into a canonical CRUD data object.
|
|
7
|
+
* Infers execution type (object, index, array, database, storage, data) dynamically.
|
|
8
|
+
*
|
|
9
|
+
* @param {Element} element
|
|
10
|
+
* @returns {Object|undefined} Normalized data payload object
|
|
11
|
+
*/
|
|
12
|
+
export function getDataObject(element) {
|
|
13
|
+
const data = getAttributes(element);
|
|
14
|
+
const crudType = ["storage", "database", "array", "index", "object"];
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < crudType.length; i++) {
|
|
17
|
+
if (!checkValue(data[crudType[i]])) return;
|
|
18
|
+
|
|
19
|
+
if (data[crudType[i]] && data[crudType[i]].includes(",")) {
|
|
20
|
+
const array = data[crudType[i]].split(",");
|
|
21
|
+
data[crudType[i]] = [];
|
|
22
|
+
|
|
23
|
+
for (let j = 0; j < array.length; j++) {
|
|
24
|
+
const item = array[j].trim();
|
|
25
|
+
if (crudType[i] === "object") {
|
|
26
|
+
data[crudType[i]].push({ _id: item });
|
|
27
|
+
} else {
|
|
28
|
+
data[crudType[i]].push(item);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (data.object || data.object === "" || data.key || data.key === "") {
|
|
35
|
+
if (!data.array || (data.array && !data.array.length)) return;
|
|
36
|
+
data.type = "object";
|
|
37
|
+
} else if (data.index || data.index === "") {
|
|
38
|
+
if (!data.array || (data.array && !data.array.length)) return;
|
|
39
|
+
data.type = "index";
|
|
40
|
+
} else if (data.array || data.array === "") data.type = "array";
|
|
41
|
+
else if (data.database || data.database === "") data.type = "database";
|
|
42
|
+
else if (data.storage || data.storage === "") data.type = "storage";
|
|
43
|
+
else if (data.data) data.type = "data";
|
|
44
|
+
|
|
45
|
+
if (
|
|
46
|
+
environment &&
|
|
47
|
+
!data.database &&
|
|
48
|
+
["array", "index", "object"].includes(data.type)
|
|
49
|
+
)
|
|
50
|
+
data.database = environment;
|
|
51
|
+
|
|
52
|
+
delete data.isRealtime;
|
|
53
|
+
return data;
|
|
54
|
+
}
|
package/src/formHandler.js
CHANGED
|
@@ -2,6 +2,7 @@ import Observer from "@cocreate/observer";
|
|
|
2
2
|
import { getAttributeNames, ObjectId, queryElements } from "@cocreate/utils";
|
|
3
3
|
import Action from "@cocreate/actions";
|
|
4
4
|
import elementPrototype from "@cocreate/element-prototype";
|
|
5
|
+
import { formSelector } from "./formSelectors.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Initializes form elements. If no parameter is provided, or null is passed, it queries and initializes all form elements.
|
|
@@ -13,7 +14,7 @@ import elementPrototype from "@cocreate/element-prototype";
|
|
|
13
14
|
* - If an array of form elements is provided, each element in the array is initialized.
|
|
14
15
|
*/
|
|
15
16
|
function init(elements) {
|
|
16
|
-
if (!elements) elements = document.querySelectorAll(
|
|
17
|
+
if (!elements) elements = document.querySelectorAll(formSelector);
|
|
17
18
|
else if (!Array.isArray(elements)) elements = [elements];
|
|
18
19
|
|
|
19
20
|
for (let element of elements) {
|
|
@@ -242,7 +243,7 @@ function setValue(form) {
|
|
|
242
243
|
Observer.init({
|
|
243
244
|
name: "CoCreateForm",
|
|
244
245
|
types: ["addedNodes"],
|
|
245
|
-
selector:
|
|
246
|
+
selector: formSelector,
|
|
246
247
|
callback: (mutation) => init(mutation.target)
|
|
247
248
|
});
|
|
248
249
|
|
|
@@ -258,7 +259,7 @@ Observer.init({
|
|
|
258
259
|
"object",
|
|
259
260
|
"index"
|
|
260
261
|
]),
|
|
261
|
-
selector:
|
|
262
|
+
selector: formSelector,
|
|
262
263
|
callback: (mutation) => setAttribute(mutation.target, null, [mutation.attributeName])
|
|
263
264
|
});
|
|
264
265
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const formSelector = "form, fieldset";
|
package/src/getDataHandler.js
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getAttributes,
|
|
3
|
-
checkValue
|
|
4
|
-
} from "@cocreate/utils";
|
|
5
|
-
|
|
6
1
|
import {
|
|
7
2
|
elements,
|
|
8
3
|
forms,
|
|
@@ -13,7 +8,8 @@ import {
|
|
|
13
8
|
import { getSubscription } from "./subscribeHandler.js";
|
|
14
9
|
import { read, save } from "./crudHandler.js";
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
import { environment, getDataObject } from "./dataObject.js";
|
|
12
|
+
export { getDataObject } from "./dataObject.js";
|
|
17
13
|
|
|
18
14
|
function registerFormElement(form, element, data) {
|
|
19
15
|
if (!form || !data?.type) return;
|
|
@@ -37,57 +33,6 @@ function registerFormElement(form, element, data) {
|
|
|
37
33
|
formObject.types.get(data.type).set(element, data);
|
|
38
34
|
}
|
|
39
35
|
|
|
40
|
-
/**
|
|
41
|
-
* Parses and normalizes HTML attributes from an element into a canonical CRUD data object.
|
|
42
|
-
* Infers execution type (object, index, array, database, storage, data) dynamically.
|
|
43
|
-
*
|
|
44
|
-
* @param {Element} element
|
|
45
|
-
* @returns {Object|undefined} Normalized data payload object
|
|
46
|
-
*/
|
|
47
|
-
export function getDataObject(element) {
|
|
48
|
-
const data = getAttributes(element);
|
|
49
|
-
const crudType = ["storage", "database", "array", "index", "object"];
|
|
50
|
-
|
|
51
|
-
for (let i = 0; i < crudType.length; i++) {
|
|
52
|
-
if (!checkValue(data[crudType[i]])) return;
|
|
53
|
-
|
|
54
|
-
if (data[crudType[i]] && data[crudType[i]].includes(",")) {
|
|
55
|
-
const array = data[crudType[i]].split(",");
|
|
56
|
-
data[crudType[i]] = [];
|
|
57
|
-
|
|
58
|
-
for (let j = 0; j < array.length; j++) {
|
|
59
|
-
const item = array[j].trim();
|
|
60
|
-
if (crudType[i] === "object") {
|
|
61
|
-
data[crudType[i]].push({ _id: item });
|
|
62
|
-
} else {
|
|
63
|
-
data[crudType[i]].push(item);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (data.object || data.object === "" || data.key || data.key === "") {
|
|
70
|
-
if (!data.array || (data.array && !data.array.length)) return;
|
|
71
|
-
data.type = "object";
|
|
72
|
-
} else if (data.index || data.index === "") {
|
|
73
|
-
if (!data.array || (data.array && !data.array.length)) return;
|
|
74
|
-
data.type = "index";
|
|
75
|
-
} else if (data.array || data.array === "") data.type = "array";
|
|
76
|
-
else if (data.database || data.database === "") data.type = "database";
|
|
77
|
-
else if (data.storage || data.storage === "") data.type = "storage";
|
|
78
|
-
else if (data.data) data.type = "data";
|
|
79
|
-
|
|
80
|
-
if (
|
|
81
|
-
environment &&
|
|
82
|
-
!data.database &&
|
|
83
|
-
["array", "index", "object"].includes(data.type)
|
|
84
|
-
)
|
|
85
|
-
data.database = environment;
|
|
86
|
-
|
|
87
|
-
delete data.isRealtime;
|
|
88
|
-
return data;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
36
|
/**
|
|
92
37
|
* Registers an element and its generated dataKey into local client maps.
|
|
93
38
|
* Binds element save/read helper methods and associates form context.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import Actions from "@cocreate/actions";
|
|
2
|
+
import { queryElements } from "@cocreate/utils";
|
|
3
|
+
|
|
4
|
+
const selector = "[href], [target]";
|
|
5
|
+
|
|
6
|
+
function init() {
|
|
7
|
+
document.link ||= { islink: "true" };
|
|
8
|
+
document.addEventListener("click", linkEvent, true);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Delegation also handles links inserted after this feature loads.
|
|
12
|
+
function linkEvent(event) {
|
|
13
|
+
const target = event.target.closest?.(selector);
|
|
14
|
+
if (!target || target.hasAttribute("download") || target.closest("[actions]")) return;
|
|
15
|
+
open(target, event);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function open(target, event) {
|
|
19
|
+
if (!target) return;
|
|
20
|
+
const doc = target.ownerDocument || document;
|
|
21
|
+
if (doc.link?.islink === "false" || doc.link?.islink === false) return;
|
|
22
|
+
if (!target.getAttribute("href")) return;
|
|
23
|
+
event?.preventDefault();
|
|
24
|
+
openLink(target);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function openLink(link) {
|
|
28
|
+
const href = link.getAttribute("href");
|
|
29
|
+
const target = link.getAttribute("target");
|
|
30
|
+
|
|
31
|
+
if (!target || target === "_self") {
|
|
32
|
+
const currentUrl = new URL(location.href);
|
|
33
|
+
const targetUrl = new URL(href, location.href);
|
|
34
|
+
const currentPath = currentUrl.pathname.replace("/index.html", "/");
|
|
35
|
+
const targetPath = targetUrl.pathname.replace("/index.html", "/");
|
|
36
|
+
if (currentPath !== targetPath || currentUrl.hash !== targetUrl.hash) {
|
|
37
|
+
location.href = href;
|
|
38
|
+
}
|
|
39
|
+
} else if (target === "_window") {
|
|
40
|
+
window.open(href, "_blank", "location=yes,height=570,width=520,scrollbars=yes,status=yes");
|
|
41
|
+
} else {
|
|
42
|
+
window.open(href, target);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Actions passes its chain element; resolve its associated link before opening it.
|
|
47
|
+
function href(element, context) {
|
|
48
|
+
const link = element.closest("[href], [target], [state_to]") ||
|
|
49
|
+
element.querySelector("[href], [target], [state_to]");
|
|
50
|
+
if (!link || link.hasAttribute("download")) return;
|
|
51
|
+
return open(link, context?.event);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function linkDocuments(element) {
|
|
55
|
+
const targets = element.hasAttribute("link-query")
|
|
56
|
+
? queryElements({ element, prefix: "link" }) : [document];
|
|
57
|
+
return new Set(targets.map(target => target.nodeType === 9 ? target :
|
|
58
|
+
target.contentDocument || target.document || target.ownerDocument).filter(Boolean));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function disableHref(element) {
|
|
62
|
+
for (const doc of linkDocuments(element)) {
|
|
63
|
+
doc.link = { islink: "false" };
|
|
64
|
+
doc.removeEventListener("click", linkEvent, true);
|
|
65
|
+
doc.addEventListener("click", preventDefault, true);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function enableHref(element) {
|
|
70
|
+
for (const doc of linkDocuments(element)) {
|
|
71
|
+
doc.link = { islink: "true" };
|
|
72
|
+
doc.removeEventListener("click", preventDefault, true);
|
|
73
|
+
doc.addEventListener("click", linkEvent, true);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function preventDefault(event) {
|
|
78
|
+
event.preventDefault();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
Actions.init([
|
|
82
|
+
{
|
|
83
|
+
name: "disableHref",
|
|
84
|
+
endEvent: "disableHref",
|
|
85
|
+
callback: action => {
|
|
86
|
+
disableHref(action.element);
|
|
87
|
+
action.end();
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: "enableHref",
|
|
92
|
+
endEvent: "enableHref",
|
|
93
|
+
callback: action => {
|
|
94
|
+
enableHref(action.element);
|
|
95
|
+
action.end();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
]);
|
|
99
|
+
|
|
100
|
+
Actions.href = href;
|
|
101
|
+
init();
|
|
102
|
+
|
|
103
|
+
export { open, disableHref, enableHref };
|
|
104
|
+
export default { open, disableHref, enableHref };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import observer from "@cocreate/observer";
|
|
2
|
+
import { relayEvents } from "@cocreate/utils/iframe";
|
|
3
|
+
|
|
4
|
+
export function clickedElement(frames) {
|
|
5
|
+
for (const frame of frames) {
|
|
6
|
+
try {
|
|
7
|
+
const frameDocument = frame.contentDocument;
|
|
8
|
+
if (frameDocument.clickedElement === undefined) {
|
|
9
|
+
frameDocument.addEventListener("click", (e) => {
|
|
10
|
+
frame.clickedElement = e.target;
|
|
11
|
+
frameDocument.clickedElement = e.target;
|
|
12
|
+
const ClickedElementEvent = frame.ownerDocument.defaultView.CustomEvent;
|
|
13
|
+
frame.dispatchEvent(new ClickedElementEvent("clickedElement", {
|
|
14
|
+
bubbles: true,
|
|
15
|
+
detail: {
|
|
16
|
+
cursor: { x: e.clientX, y: e.clientY },
|
|
17
|
+
document: frameDocument
|
|
18
|
+
}
|
|
19
|
+
}));
|
|
20
|
+
});
|
|
21
|
+
frameDocument.clickedElement = null;
|
|
22
|
+
}
|
|
23
|
+
} catch (iframeError) {
|
|
24
|
+
console.log(
|
|
25
|
+
`Cross-origin frame handling failed for: ${frame}`,
|
|
26
|
+
iframeError
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function hoveredElement(frames) {
|
|
33
|
+
for (const frame of frames) {
|
|
34
|
+
try {
|
|
35
|
+
const frameDocument = frame.contentDocument;
|
|
36
|
+
if (frameDocument.hoveredElement === undefined) {
|
|
37
|
+
frameDocument.hoveredElement = null;
|
|
38
|
+
frame.hoveredElement = null;
|
|
39
|
+
|
|
40
|
+
const emitHoveredElement = (event) => {
|
|
41
|
+
const HoveredElementEvent = frame.ownerDocument.defaultView.CustomEvent;
|
|
42
|
+
frame.dispatchEvent(new HoveredElementEvent("hoveredElement", {
|
|
43
|
+
bubbles: true,
|
|
44
|
+
detail: {
|
|
45
|
+
cursor: { x: event.clientX, y: event.clientY },
|
|
46
|
+
document: frameDocument
|
|
47
|
+
}
|
|
48
|
+
}));
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
frameDocument.addEventListener("mouseover", (event) => {
|
|
52
|
+
frame.hoveredElement = event.target;
|
|
53
|
+
frameDocument.hoveredElement = event.target;
|
|
54
|
+
emitHoveredElement(event);
|
|
55
|
+
});
|
|
56
|
+
frameDocument.addEventListener("mouseout", (event) => {
|
|
57
|
+
const nextElement = event.relatedTarget;
|
|
58
|
+
frame.hoveredElement = nextElement;
|
|
59
|
+
frameDocument.hoveredElement = nextElement;
|
|
60
|
+
emitHoveredElement(event);
|
|
61
|
+
});
|
|
62
|
+
frameDocument.addEventListener("mousemove", (event) => {
|
|
63
|
+
frame.hoveredElement = event.target;
|
|
64
|
+
frameDocument.hoveredElement = event.target;
|
|
65
|
+
emitHoveredElement(event);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
} catch (iframeError) {
|
|
69
|
+
console.log(
|
|
70
|
+
`Cross-origin frame handling failed for: ${frame}`,
|
|
71
|
+
iframeError
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
clickedElement(document.querySelectorAll("iframe"));
|
|
78
|
+
hoveredElement(document.querySelectorAll("iframe"));
|
|
79
|
+
relayEvents(document.querySelectorAll("iframe"));
|
|
80
|
+
|
|
81
|
+
observer.init({
|
|
82
|
+
name: "CoCreateIframes",
|
|
83
|
+
types: ["addedNodes"],
|
|
84
|
+
selector: "iframe",
|
|
85
|
+
callback: (mutation) => {
|
|
86
|
+
clickedElement([mutation.target]);
|
|
87
|
+
hoveredElement([mutation.target]);
|
|
88
|
+
relayEvents([mutation.target]);
|
|
89
|
+
}
|
|
90
|
+
});
|