Skip to content

Commit fbf28b0

Browse files
committed
v2.0
1 parent 242468e commit fbf28b0

3 files changed

Lines changed: 158 additions & 25 deletions

File tree

browser.js

Lines changed: 155 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
exportModule('data-context-binding', ['data-context'], function factory(DC) {
88

99
var globalScope = this,
10-
{ createDataContext, parse, stringify } = DC,
11-
isDebug = document && Array.from(document.scripts).find(function (s) { return s.src.includes('data-context-binding'); })?.attributes.debug || false;
10+
{ createDataContext, parse, stringify, syncData } = DC,
11+
script = this.document && Array.from(document.scripts).find(function (s) { return s.src.includes('data-context-binding'); }),
12+
isDebug = script?.attributes.debug || false,
13+
dataUrl = script?.attributes?.dataUrl?.value || '';
1214

1315

1416
//TODO [ x ] default bind ...
@@ -24,6 +26,7 @@
2426
bindAllElements: { value: bindAllElements, writable: false, configurable: false, enumerable: false },
2527
bindElement: { value: bindElement, writable: false, configurable: false, enumerable: false },
2628
bindingContext: { value: bindingContext, writable: false, configurable: false, enumerable: false },
29+
loadDataUrl: { value: loadDataUrl, writable: false, configurable: false, enumerable: false },
2730

2831
progess: { value: progessBind, writable: false, configurable: false, enumerable: false },
2932
context: { value: contextBind, writable: false, configurable: false, enumerable: false },
@@ -39,6 +42,7 @@
3942
disabled: { value: disabledBind, writable: true, configurable: false, enumerable: false },
4043
class: { value: classToggleBind, writable: true, configurable: false, enumerable: false },
4144
attribute: { value: attributeBind, writable: true, configurable: false, enumerable: false },
45+
property: { value: propertyBind, writable: true, configurable: false, enumerable: false },
4246

4347
input: { value: valueBind, writable: true, configurable: false, enumerable: false },
4448
input_checkbox: { value: checkBind, writable: true, configurable: false, enumerable: false },
@@ -76,26 +80,61 @@
7680

7781
var htmlElement = document.documentElement;
7882

79-
if (htmlElement) {
83+
if (value !== undefined) {
8084

81-
if (value !== undefined) {
82-
83-
htmlElement.datacontext = value._isDataContext ? value : createDataContext(value);
84-
waitForReadyState("complete", bindAllElements.bind(this, htmlElement, true));
85-
}
85+
htmlElement.datacontext = value._isDataContext ? value : createDataContext(value);
86+
waitForReadyState("complete", bindAllElements.bind(this, htmlElement, true));
87+
}
8688

87-
if (!htmlElement.datacontext) {
89+
if (!htmlElement.datacontext) {
8890

89-
value = document.querySelector("script#data")?.innerText;
91+
value = document.querySelector("script#data")?.innerText;
9092

91-
htmlElement.datacontext = createDataContext(value && parse(value) || {});
92-
waitForReadyState("complete", bindAllElements.bind(this, htmlElement));
93-
}
93+
htmlElement.datacontext = createDataContext(value && parse(value) || {});
94+
waitForReadyState("complete", bindAllElements.bind(this, htmlElement));
9495
}
9596

96-
globalScope.datacontext = htmlElement?.datacontext;
97+
loadDataUrl();
98+
99+
globalScope.datacontext = htmlElement.datacontext;
100+
101+
return htmlElement.datacontext;
102+
}
103+
104+
function loadDataUrl(url = dataUrl) {
105+
106+
if (url) {
107+
108+
fetch(url)
109+
.then(response => {
110+
111+
if (!response.ok) { pError(`HTTP error! Status: ${response.status}`); }
112+
113+
return response.text();
114+
})
115+
.then(str => {
116+
117+
var data = parse(str);
118+
119+
Object.keys(data).forEach(function (k) {
120+
121+
if (!globalScope.datacontext[k]) {
122+
123+
globalScope.datacontext[k] = createDataContext(data[k]);
124+
}
125+
else {
126+
127+
syncData(globalScope.datacontext[k], data[k], true);
128+
}
129+
130+
globalScope.datacontext[k].resetChanges();
131+
});
132+
})
133+
.catch(error => {
97134

98-
return htmlElement?.datacontext;
135+
pDebug('Error fetching data:', error);
136+
});
137+
}
99138
}
100139

101140
function waitForReadyState(state, cb) {
@@ -172,7 +211,7 @@
172211

173212
if (element.contextValue && !rebinding) { return; }
174213

175-
if (element.bindingContext?.isActive) { element.bindingContext.isActive(false); } // for rebinding
214+
if (!element?.attributes?.template && element.bindingContext?.isActive) { element.bindingContext.isActive(false); } // for rebinding
176215

177216
if (element.attributes.link) {
178217

@@ -222,6 +261,13 @@
222261

223262
function _template(selectors, isMultiple = false) {
224263

264+
if (selectors[0] === ':') {
265+
266+
element.innerOriginalHTML = element.innerHTML;
267+
element.innerHTML = '';
268+
selectors = selectors.substring(1);
269+
}
270+
225271
if (!selectors) { _tryBind(); return; }
226272

227273
var templateElement = null;
@@ -583,7 +629,8 @@
583629
function _findPathAndSource() {
584630

585631
do {
586-
if (d.rootElement?.attributes?.path?.value) {
632+
if (d.rootElement?.attributes?.path?.value
633+
&& (d.rootElement.attributes.path.value[0] !== '.' || d.rootElement === elem)) {
587634

588635
d.arrPath = d.arrPath.concat(
589636
d.rootElement.attributes.path.value
@@ -1000,7 +1047,8 @@
10001047
this.value = this.contextValue();
10011048

10021049
// I am alive!
1003-
return true;
1050+
//return true;
1051+
return this.contextValue() === undefined ? false : true;
10041052
}
10051053
function setValueBind(event) {
10061054

@@ -1023,7 +1071,8 @@
10231071
}
10241072

10251073
// I am alive!
1026-
return true;
1074+
//return true;
1075+
return this.contextValue() === undefined ? false : true;
10271076

10281077
function change(ev) { if (this.contextValue !== undefined) { this.contextValue(this.value); } }
10291078
function keydown(ev) { if (ev.keyCode === 27) { this.value = this.contextValue(); } }
@@ -1249,6 +1298,9 @@
12491298
if (event.eventName === "unbind") {
12501299

12511300
updateAttributeBinding.call(this, false, this.attributeBindingName, this.attributeBindingValue);
1301+
delete this.isValueInverted;
1302+
delete this.attributeBindingName;
1303+
delete this.attributeBindingValue;
12521304

12531305
// I am dead!
12541306
return false;
@@ -1258,7 +1310,7 @@
12581310

12591311
this.isValueInverted = event.isValueInverted;
12601312
this.attributeBindingName = event.bindArgs[0] || '';
1261-
this.attributeBindingValue = event.bindArgs[1] || '';
1313+
this.attributeBindingValue = event.bindArgs[1] || this.contextValue() || '';
12621314
}
12631315

12641316
updateAttributeBinding.call(this,
@@ -1270,16 +1322,97 @@
12701322
// I am alive!
12711323
return this.contextValue() === undefined ? false : true;
12721324
}
1325+
function propertyBind(event) {
1326+
1327+
if (event.eventName === "unbind") {
1328+
1329+
delete this.isValueInverted;
1330+
delete this.propertyBindingName;
1331+
delete this.propertyBindingValue;
1332+
// I am dead!
1333+
return false;
1334+
}
1335+
1336+
if (event.eventName === "bind") {
1337+
this.isValueInverted = event.isValueInverted;
1338+
this.propertyBindingName = event.bindArgs[0] || '';
1339+
this.propertyBindingValue = event.bindArgs[1] || '';
1340+
}
1341+
1342+
var templateValue = this.propertyBindingValue || this.contextValue();
1343+
1344+
if (typeof templateValue === 'string') {
1345+
1346+
this[this.propertyBindingName] = resolveTemplateLiterals.call(this, templateValue, this.isValueInverted);
1347+
}
1348+
else {
1349+
1350+
this[this.propertyBindingName] = templateValue;
1351+
}
1352+
1353+
// I am alive!
1354+
return this.contextValue() === undefined ? false : true;
1355+
}
12731356

12741357

12751358
function updateAttributeBinding(isEnabled, attributeName, attributeValue = '') {
12761359

12771360
if (attributeName) {
12781361

1279-
if (isEnabled) { this.setAttribute(attributeName, attributeValue); }
1362+
attributeValue = resolveTemplateLiterals.call(this, attributeValue);
1363+
1364+
if (isEnabled) {
1365+
1366+
this.setAttribute(attributeName, attributeValue);
1367+
1368+
if (attributeName === 'template') {
1369+
1370+
bindAllElements(this, true);
1371+
}
1372+
}
1373+
1374+
else {
1375+
1376+
this.removeAttribute(attributeName);
1377+
1378+
if (attributeName === 'template') {
12801379

1281-
else { this.removeAttribute(attributeName); }
1380+
if (this.innerOriginalHTML) {
1381+
1382+
this.innerHTML = this.innerOriginalHTML;
1383+
bindAllElements(this, false, true);
1384+
}
1385+
1386+
}
1387+
}
1388+
}
1389+
}
1390+
function resolveTemplateLiterals(templateValue, isValueInverted) {
1391+
1392+
if (templateValue.indexOf('${')) {
1393+
1394+
templateValue = templateValue.replace(/\$\{([^\}]+)\}/g, function (match, propertyPath) {
1395+
1396+
var value = this.contextValue(),
1397+
propertyParts = propertyPath.split('.');
1398+
1399+
if (value === undefined) { return ''; }
1400+
1401+
while (propertyParts.length) {
1402+
1403+
value = value[propertyParts.shift()];
1404+
1405+
if (value === undefined) { return ''; }
1406+
}
1407+
1408+
if (isValueInverted) { value = !value; }
1409+
1410+
return value;
1411+
1412+
}.bind(this));
12821413
}
1414+
1415+
return templateValue;
12831416
}
12841417

12851418
//#endregion

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-rc.1",
4+
"version": "2.0.0-rc.2",
55
"license": "MIT",
66
"keywords": [
77
"conextra",

0 commit comments

Comments
 (0)