|
7 | 7 | exportModule('data-context-binding', ['data-context'], function factory(DC) { |
8 | 8 |
|
9 | 9 | 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 || ''; |
12 | 14 |
|
13 | 15 |
|
14 | 16 | //TODO [ x ] default bind ... |
|
24 | 26 | bindAllElements: { value: bindAllElements, writable: false, configurable: false, enumerable: false }, |
25 | 27 | bindElement: { value: bindElement, writable: false, configurable: false, enumerable: false }, |
26 | 28 | bindingContext: { value: bindingContext, writable: false, configurable: false, enumerable: false }, |
| 29 | + loadDataUrl: { value: loadDataUrl, writable: false, configurable: false, enumerable: false }, |
27 | 30 |
|
28 | 31 | progess: { value: progessBind, writable: false, configurable: false, enumerable: false }, |
29 | 32 | context: { value: contextBind, writable: false, configurable: false, enumerable: false }, |
|
39 | 42 | disabled: { value: disabledBind, writable: true, configurable: false, enumerable: false }, |
40 | 43 | class: { value: classToggleBind, writable: true, configurable: false, enumerable: false }, |
41 | 44 | attribute: { value: attributeBind, writable: true, configurable: false, enumerable: false }, |
| 45 | + property: { value: propertyBind, writable: true, configurable: false, enumerable: false }, |
42 | 46 |
|
43 | 47 | input: { value: valueBind, writable: true, configurable: false, enumerable: false }, |
44 | 48 | input_checkbox: { value: checkBind, writable: true, configurable: false, enumerable: false }, |
|
76 | 80 |
|
77 | 81 | var htmlElement = document.documentElement; |
78 | 82 |
|
79 | | - if (htmlElement) { |
| 83 | + if (value !== undefined) { |
80 | 84 |
|
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 | + } |
86 | 88 |
|
87 | | - if (!htmlElement.datacontext) { |
| 89 | + if (!htmlElement.datacontext) { |
88 | 90 |
|
89 | | - value = document.querySelector("script#data")?.innerText; |
| 91 | + value = document.querySelector("script#data")?.innerText; |
90 | 92 |
|
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)); |
94 | 95 | } |
95 | 96 |
|
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 => { |
97 | 134 |
|
98 | | - return htmlElement?.datacontext; |
| 135 | + pDebug('Error fetching data:', error); |
| 136 | + }); |
| 137 | + } |
99 | 138 | } |
100 | 139 |
|
101 | 140 | function waitForReadyState(state, cb) { |
|
172 | 211 |
|
173 | 212 | if (element.contextValue && !rebinding) { return; } |
174 | 213 |
|
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 |
176 | 215 |
|
177 | 216 | if (element.attributes.link) { |
178 | 217 |
|
|
222 | 261 |
|
223 | 262 | function _template(selectors, isMultiple = false) { |
224 | 263 |
|
| 264 | + if (selectors[0] === ':') { |
| 265 | + |
| 266 | + element.innerOriginalHTML = element.innerHTML; |
| 267 | + element.innerHTML = ''; |
| 268 | + selectors = selectors.substring(1); |
| 269 | + } |
| 270 | + |
225 | 271 | if (!selectors) { _tryBind(); return; } |
226 | 272 |
|
227 | 273 | var templateElement = null; |
|
583 | 629 | function _findPathAndSource() { |
584 | 630 |
|
585 | 631 | 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)) { |
587 | 634 |
|
588 | 635 | d.arrPath = d.arrPath.concat( |
589 | 636 | d.rootElement.attributes.path.value |
|
1000 | 1047 | this.value = this.contextValue(); |
1001 | 1048 |
|
1002 | 1049 | // I am alive! |
1003 | | - return true; |
| 1050 | + //return true; |
| 1051 | + return this.contextValue() === undefined ? false : true; |
1004 | 1052 | } |
1005 | 1053 | function setValueBind(event) { |
1006 | 1054 |
|
|
1023 | 1071 | } |
1024 | 1072 |
|
1025 | 1073 | // I am alive! |
1026 | | - return true; |
| 1074 | + //return true; |
| 1075 | + return this.contextValue() === undefined ? false : true; |
1027 | 1076 |
|
1028 | 1077 | function change(ev) { if (this.contextValue !== undefined) { this.contextValue(this.value); } } |
1029 | 1078 | function keydown(ev) { if (ev.keyCode === 27) { this.value = this.contextValue(); } } |
|
1249 | 1298 | if (event.eventName === "unbind") { |
1250 | 1299 |
|
1251 | 1300 | updateAttributeBinding.call(this, false, this.attributeBindingName, this.attributeBindingValue); |
| 1301 | + delete this.isValueInverted; |
| 1302 | + delete this.attributeBindingName; |
| 1303 | + delete this.attributeBindingValue; |
1252 | 1304 |
|
1253 | 1305 | // I am dead! |
1254 | 1306 | return false; |
|
1258 | 1310 |
|
1259 | 1311 | this.isValueInverted = event.isValueInverted; |
1260 | 1312 | this.attributeBindingName = event.bindArgs[0] || ''; |
1261 | | - this.attributeBindingValue = event.bindArgs[1] || ''; |
| 1313 | + this.attributeBindingValue = event.bindArgs[1] || this.contextValue() || ''; |
1262 | 1314 | } |
1263 | 1315 |
|
1264 | 1316 | updateAttributeBinding.call(this, |
|
1270 | 1322 | // I am alive! |
1271 | 1323 | return this.contextValue() === undefined ? false : true; |
1272 | 1324 | } |
| 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 | + } |
1273 | 1356 |
|
1274 | 1357 |
|
1275 | 1358 | function updateAttributeBinding(isEnabled, attributeName, attributeValue = '') { |
1276 | 1359 |
|
1277 | 1360 | if (attributeName) { |
1278 | 1361 |
|
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') { |
1280 | 1379 |
|
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)); |
1282 | 1413 | } |
| 1414 | + |
| 1415 | + return templateValue; |
1283 | 1416 | } |
1284 | 1417 |
|
1285 | 1418 | //#endregion |
|
0 commit comments