Skip to content

Commit 05c9d8e

Browse files
committed
v2.0
1 parent 884d888 commit 05c9d8e

4 files changed

Lines changed: 114 additions & 27 deletions

File tree

browser.js

Lines changed: 107 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//TODO [ x ] template binding
1616
//TODO [ x ] Event > : 'new', 'set', 'reposition', 'delete', '-change', 'bind', 'unbind'
1717
//TODO [ x ] DOM Attribute: 'path', 'bind', 'unbinded', 'template', 'templates', 'rebinding', 'onbind', 'link'
18+
//TODO [ x ] rootDataContext: '#' > document.documentElement.datacontext // bind to root data context
1819

1920
var DataContextBinding = Object.defineProperties(bindDataContext, {
2021

@@ -24,6 +25,7 @@
2425
bindElement: { value: bindElement, writable: false, configurable: false, enumerable: false },
2526
bindingContext: { value: bindingContext, writable: false, configurable: false, enumerable: false },
2627

28+
progess: { value: progessBind, writable: false, configurable: false, enumerable: false },
2729
context: { value: contextBind, writable: false, configurable: false, enumerable: false },
2830
change: { value: changeBind, writable: false, configurable: false, enumerable: false },
2931
innerHTML: { value: innerHTMLBind, writable: true, configurable: false, enumerable: false },
@@ -104,11 +106,11 @@
104106
setTimeout(waitForReadyState, 0, state, cb);
105107
}
106108

107-
function bindAllElements(rootElement, rebinding = false) {
109+
function bindAllElements(rootElement, rebinding = false, isChildrenOnly = false) {
108110

109111
if (!rootElement) { rootElement = document.documentElement; }
110112

111-
bindElement(rootElement, rebinding);
113+
if (!isChildrenOnly) { bindElement(rootElement, rebinding); }
112114

113115
rootElement
114116
.querySelectorAll(`[bind],[onbind],[template],[templates],[rebinding],[link],[unbinded]`)
@@ -202,22 +204,35 @@
202204

203205
function _link(path) {
204206

205-
if (element.linked) { return; }
207+
if (element.linked) {
208+
209+
if (rebinding) { bindAllElements(element, true, true); }
210+
211+
return;
212+
}
206213

207214
var { CreateLink } = globalScope?.modules?.['ws-user'];
208215

209216
if (CreateLink) {
210217

211218
element.linked = true;
212219
element.wsLink = CreateLink(path, element);
213-
element.wsLink.bindAllElements = function (elem, rebind = false) { bindAllElements(elem, rebind); };
214220
}
215221
}
216222

217223
function _template(selectors, isMultiple = false) {
218224

219225
if (!selectors) { _tryBind(); return; }
220226

227+
var templateElement = null;
228+
229+
try { templateElement = element.querySelector(selectors) || document.querySelector(selectors); }
230+
catch { templateElement = null; }
231+
232+
if (!templateElement && element.attributes.template_fetching) { return; }
233+
234+
element.removeAttribute('template_fetching');
235+
221236
//remove element children
222237
var i = 0;
223238
while (i < element.childElementCount) {
@@ -232,11 +247,6 @@
232247
else { i++; }
233248
}
234249

235-
var templateElement = null;
236-
237-
try { templateElement = element.querySelector(selectors) || document.querySelector(selectors); }
238-
catch { templateElement = null; }
239-
240250

241251
if (!templateElement) { return fetchContent(); }
242252

@@ -246,6 +256,8 @@
246256

247257
function fetchContent() {
248258

259+
element.setAttribute('template_fetching', '');
260+
249261
fetch(selectors).then(function (res) {
250262

251263
res.text().then(function (textContent) {
@@ -255,6 +267,8 @@
255267
? templateElement.innerHTML = textContent
256268
: templateElement.innerHTML = '<div>' + encodeHTML(textContent) + '</div>';
257269
bindTemplate();
270+
271+
element.removeAttribute('template_fetching');
258272
});
259273
});
260274

@@ -289,7 +303,7 @@
289303

290304
if (_bindingContext?.value?._isDataContext) {
291305

292-
if (isFunctionNotAdded('addTemplate')) {
306+
if (isFunctionNotAdded('addTemplate', element)) {
293307

294308
_bindingContext.value.on(
295309
"-",
@@ -306,7 +320,7 @@
306320
);
307321
}
308322

309-
if (isFunctionNotAdded('removeTemplate')) {
323+
if (isFunctionNotAdded('removeTemplate', element)) {
310324

311325
_bindingContext.value.on(
312326
"-",
@@ -334,10 +348,15 @@
334348
return appendTemplate();
335349

336350

337-
function isFunctionNotAdded(fnName) {
351+
function isFunctionNotAdded(fnName, element) {
338352

339353
return _bindingContext?.value?._events?.["-"]
340-
?.find(function (fn) { return fn.name.includes(fnName); }) === undefined;
354+
?.find(function (fn) {
355+
356+
return fn.name.includes(fnName)
357+
&& fn.isActive === element;
358+
359+
}) === undefined;
341360
}
342361
function appendTemplate(key, target) {
343362

@@ -503,7 +522,8 @@
503522
source: null,
504523
property: null,
505524
arrPath: []
506-
};
525+
},
526+
isMultiple = Boolean(elem.attributes.templates);
507527

508528
_findPathAndSource();
509529
_selectSource();
@@ -573,6 +593,12 @@
573593
);
574594
}
575595

596+
if (d.arrPath.at(-1) === '#') {
597+
598+
d.source = document.documentElement.datacontext;
599+
d.arrPath.pop();
600+
}
601+
576602
if (d.rootElement.datacontext !== undefined) {
577603

578604
d.source = d.rootElement.datacontext;
@@ -606,7 +632,7 @@
606632
d.source = _nextSource(d, arrPath.pop(), {});
607633
}
608634

609-
_nextSource(d, d.property, "");
635+
_nextSource(d, d.property, isMultiple ? [] : "");
610636
}
611637

612638
function _nextSource(d, property, defValue) {
@@ -648,6 +674,15 @@
648674

649675
if (d.source[property]?._isDataContext) { return d.source[property]; }
650676

677+
if (isMultiple) {
678+
679+
d.source[property] = createDataContext(Array.isArray(d.source[property]) ? d.source[property] : []);
680+
681+
setTimeout(function () { bindElement(d.rootElement, true); });
682+
683+
return d.source[property];
684+
}
685+
651686
if (d.source[property] !== undefined) {
652687

653688
d.source[property] = createDataContext(d.source[property]);
@@ -804,7 +839,10 @@
804839

805840
if (event.eventName === "set") {
806841

807-
event.newValue._events = event.oldValue._events;
842+
if (event.oldValue?._isDataContext) {
843+
844+
event.newValue._events = event.oldValue._events;
845+
}
808846

809847
emitProperties(event.newValue, event.oldValue, event.eventName);
810848
}
@@ -853,6 +891,55 @@
853891

854892
//#region *** Default bind ***
855893

894+
function progessBind(event) {
895+
896+
if (event.eventName === "unbind") {
897+
898+
if (this.wsLink) {
899+
900+
this.wsLink.onreadystate = null;
901+
}
902+
}
903+
904+
if (event.eventName === "bind") {
905+
906+
this.isValueInverted = event.isValueInverted;
907+
this.attributeBindingName = event.bindArgs[0] || '';
908+
this.attributeBindingValue = event.bindArgs[1] || '';
909+
910+
var parent = this.parentElement;
911+
912+
while (!this.wsLink && parent) {
913+
914+
this.wsLink = parent.wsLink;
915+
parent = parent.parentElement;
916+
}
917+
918+
if (this.wsLink) {
919+
920+
this.wsLink.onreadystate = handleReadyState.bind(this);
921+
}
922+
923+
handleReadyState.call(this, this.wsLink?.readyState);
924+
}
925+
926+
// I am alive!
927+
return this.isConnected;
928+
929+
function handleReadyState(wsState) {
930+
931+
if (!this.isConnected) {
932+
933+
this.wsLink.onreadystate = null;
934+
return;
935+
}
936+
937+
wsState = wsState === 1;
938+
wsState = this.isValueInverted ? !wsState : wsState;
939+
940+
updateAttributeBinding.call(this, wsState, this.attributeBindingName, this.attributeBindingValue);
941+
}
942+
}
856943
function contextBind(event) {
857944

858945
return false;
@@ -1148,12 +1235,12 @@
11481235
function toggle(element, isPrimary) {
11491236

11501237
if (isPrimary) {
1151-
element.primaryClasses.forEach(function (c) { element.classList.add(c); });
1152-
element.secondaryClasses.forEach(function (c) { element.classList.remove(c); });
1238+
element.primaryClasses?.forEach(function (c) { element.classList.add(c); });
1239+
element.secondaryClasses?.forEach(function (c) { element.classList.remove(c); });
11531240
}
11541241
else {
1155-
element.primaryClasses.forEach(function (c) { element.classList.remove(c); });
1156-
element.secondaryClasses.forEach(function (c) { element.classList.add(c); });
1242+
element.primaryClasses?.forEach(function (c) { element.classList.remove(c); });
1243+
element.secondaryClasses?.forEach(function (c) { element.classList.add(c); });
11571244
}
11581245
}
11591246
}

demo.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
<head>
55
<meta charset="utf-8" />
66
<title path="arr[0].str" bind>DEMO 'data-context-binding'</title>
7-
<!--<script async src="https://cdn.jsdelivr.net/npm/data-context"></script>-->
8-
<!--<script async src="https://cdn.jsdelivr.net/npm/data-context-binding"></script>-->
9-
<script async src="./datacontext.js"></script>
10-
<script async type="text/javascript" src="./browser.js"></script>
7+
<script async src="https://cdn.jsdelivr.net/npm/data-context"></script>
8+
<script async src="https://cdn.jsdelivr.net/npm/data-context-binding"></script>
9+
<!--<script async src="./datacontext.js"></script>-->
10+
<!--<script async type="text/javascript" src="./browser.js"></script>-->
1111
<script id="data" type="application/json">
1212
{"arr":[{"str":"DB - DEMO"},{"str":"111"},{"str":"222"},{"str":"333"},{"str":"444"},{"str":"555"}]}
1313
</script>

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "data-context-binding",
33
"description": "Simple and lightweight solution for binding data to DOM elements.",
4-
"version": "2.0.0-beta.9",
4+
"version": "2.0.0-beta.10",
55
"license": "MIT",
66
"keywords": [
77
"data",

0 commit comments

Comments
 (0)