@gogocat/data-bind 1.12.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/.editorconfig +14 -14
- package/.vscode/launch.json +12 -12
- package/CONFIGURATION.md +294 -0
- package/REACTIVE_MODE.md +553 -0
- package/README.md +266 -829
- package/babel.config.json +30 -0
- package/dist/js/_escape.d.ts +14 -0
- package/dist/js/_escape.d.ts.map +1 -0
- package/dist/js/applyBinding.d.ts +11 -0
- package/dist/js/applyBinding.d.ts.map +1 -0
- package/dist/js/attrBinding.d.ts +12 -0
- package/dist/js/attrBinding.d.ts.map +1 -0
- package/dist/js/binder.d.ts +67 -0
- package/dist/js/binder.d.ts.map +1 -0
- package/dist/js/changeBinding.d.ts +19 -0
- package/dist/js/changeBinding.d.ts.map +1 -0
- package/dist/js/commentWrapper.d.ts +39 -0
- package/dist/js/commentWrapper.d.ts.map +1 -0
- package/dist/js/config.d.ts +55 -0
- package/dist/js/config.d.ts.map +1 -0
- package/dist/js/createBindingOption.d.ts +32 -0
- package/dist/js/createBindingOption.d.ts.map +1 -0
- package/dist/js/createEventBinding.d.ts +10 -0
- package/dist/js/createEventBinding.d.ts.map +1 -0
- package/dist/js/cssBinding.d.ts +15 -0
- package/dist/js/cssBinding.d.ts.map +1 -0
- package/dist/js/dataBind.js +2756 -2530
- package/dist/js/dataBind.min.js +8 -1
- package/dist/js/dataBind.min.js.map +1 -1
- package/dist/js/domWalker.d.ts +9 -0
- package/dist/js/domWalker.d.ts.map +1 -0
- package/dist/js/forOfBinding.d.ts +12 -0
- package/dist/js/forOfBinding.d.ts.map +1 -0
- package/dist/js/hoverBinding.d.ts +13 -0
- package/dist/js/hoverBinding.d.ts.map +1 -0
- package/dist/js/ifBinding.d.ts +12 -0
- package/dist/js/ifBinding.d.ts.map +1 -0
- package/dist/js/index.d.ts +10 -0
- package/dist/js/index.d.ts.map +1 -0
- package/dist/js/modelBinding.d.ts +12 -0
- package/dist/js/modelBinding.d.ts.map +1 -0
- package/dist/js/postProcess.d.ts +3 -0
- package/dist/js/postProcess.d.ts.map +1 -0
- package/dist/js/pubSub.d.ts +11 -0
- package/dist/js/pubSub.d.ts.map +1 -0
- package/dist/js/reactiveProxy.d.ts +28 -0
- package/dist/js/reactiveProxy.d.ts.map +1 -0
- package/dist/js/renderForOfBinding.d.ts +8 -0
- package/dist/js/renderForOfBinding.d.ts.map +1 -0
- package/dist/js/renderIfBinding.d.ts +22 -0
- package/dist/js/renderIfBinding.d.ts.map +1 -0
- package/dist/js/renderIteration.d.ts +16 -0
- package/dist/js/renderIteration.d.ts.map +1 -0
- package/dist/js/renderTemplate.d.ts +14 -0
- package/dist/js/renderTemplate.d.ts.map +1 -0
- package/dist/js/renderTemplatesBinding.d.ts +19 -0
- package/dist/js/renderTemplatesBinding.d.ts.map +1 -0
- package/dist/js/showBinding.d.ts +13 -0
- package/dist/js/showBinding.d.ts.map +1 -0
- package/dist/js/switchBinding.d.ts +13 -0
- package/dist/js/switchBinding.d.ts.map +1 -0
- package/dist/js/textBinding.d.ts +13 -0
- package/dist/js/textBinding.d.ts.map +1 -0
- package/dist/js/types/_escape.d.ts +14 -0
- package/dist/js/types/_escape.d.ts.map +1 -0
- package/dist/js/types/applyBinding.d.ts +11 -0
- package/dist/js/types/applyBinding.d.ts.map +1 -0
- package/dist/js/types/attrBinding.d.ts +12 -0
- package/dist/js/types/attrBinding.d.ts.map +1 -0
- package/dist/js/types/binder.d.ts +67 -0
- package/dist/js/types/binder.d.ts.map +1 -0
- package/dist/js/types/changeBinding.d.ts +19 -0
- package/dist/js/types/changeBinding.d.ts.map +1 -0
- package/dist/js/types/commentWrapper.d.ts +39 -0
- package/dist/js/types/commentWrapper.d.ts.map +1 -0
- package/dist/js/types/config.d.ts +55 -0
- package/dist/js/types/config.d.ts.map +1 -0
- package/dist/js/types/createBindingOption.d.ts +32 -0
- package/dist/js/types/createBindingOption.d.ts.map +1 -0
- package/dist/js/types/createEventBinding.d.ts +10 -0
- package/dist/js/types/createEventBinding.d.ts.map +1 -0
- package/dist/js/types/cssBinding.d.ts +15 -0
- package/dist/js/types/cssBinding.d.ts.map +1 -0
- package/dist/js/types/domWalker.d.ts +9 -0
- package/dist/js/types/domWalker.d.ts.map +1 -0
- package/dist/js/types/forOfBinding.d.ts +12 -0
- package/dist/js/types/forOfBinding.d.ts.map +1 -0
- package/dist/js/types/hoverBinding.d.ts +13 -0
- package/dist/js/types/hoverBinding.d.ts.map +1 -0
- package/dist/js/types/ifBinding.d.ts +12 -0
- package/dist/js/types/ifBinding.d.ts.map +1 -0
- package/dist/js/types/index.d.ts +10 -0
- package/dist/js/types/index.d.ts.map +1 -0
- package/dist/js/types/modelBinding.d.ts +12 -0
- package/dist/js/types/modelBinding.d.ts.map +1 -0
- package/dist/js/types/postProcess.d.ts +3 -0
- package/dist/js/types/postProcess.d.ts.map +1 -0
- package/dist/js/types/pubSub.d.ts +11 -0
- package/dist/js/types/pubSub.d.ts.map +1 -0
- package/dist/js/types/reactiveProxy.d.ts +28 -0
- package/dist/js/types/reactiveProxy.d.ts.map +1 -0
- package/dist/js/types/renderForOfBinding.d.ts +8 -0
- package/dist/js/types/renderForOfBinding.d.ts.map +1 -0
- package/dist/js/types/renderIfBinding.d.ts +22 -0
- package/dist/js/types/renderIfBinding.d.ts.map +1 -0
- package/dist/js/types/renderIteration.d.ts +16 -0
- package/dist/js/types/renderIteration.d.ts.map +1 -0
- package/dist/js/types/renderTemplate.d.ts +14 -0
- package/dist/js/types/renderTemplate.d.ts.map +1 -0
- package/dist/js/types/renderTemplatesBinding.d.ts +19 -0
- package/dist/js/types/renderTemplatesBinding.d.ts.map +1 -0
- package/dist/js/types/showBinding.d.ts +13 -0
- package/dist/js/types/showBinding.d.ts.map +1 -0
- package/dist/js/types/switchBinding.d.ts +13 -0
- package/dist/js/types/switchBinding.d.ts.map +1 -0
- package/dist/js/types/textBinding.d.ts +13 -0
- package/dist/js/types/textBinding.d.ts.map +1 -0
- package/dist/js/types/types.d.ts +111 -0
- package/dist/js/types/types.d.ts.map +1 -0
- package/dist/js/types/util.d.ts +119 -0
- package/dist/js/types/util.d.ts.map +1 -0
- package/dist/js/types.d.ts +111 -0
- package/dist/js/types.d.ts.map +1 -0
- package/dist/js/util.d.ts +119 -0
- package/dist/js/util.d.ts.map +1 -0
- package/eslint.config.js +124 -0
- package/examples/DBMONSTER_COMPARISON.md +123 -0
- package/examples/afterRenderDemo.html +119 -0
- package/examples/bootstrap/css/animate.css +1579 -1579
- package/examples/bootstrap/css/bootstrap.min.css +6 -6
- package/examples/bootstrap/css/homeservices.css +378 -390
- package/examples/bootstrap/css/open-iconic.css +511 -511
- package/examples/bootstrap/fonts/open-iconic.svg +543 -543
- package/examples/bootstrap/js/compMessageDialog.js +20 -19
- package/examples/bootstrap/js/compSearchBar.js +12 -19
- package/examples/bootstrap/js/compSearchResults.js +50 -46
- package/examples/bootstrap/js/featureAdsResult.json +65 -65
- package/examples/bootstrap/js/searchResult.json +57 -57
- package/examples/bootstrap.html +343 -332
- package/examples/css/baseTodo.css +141 -141
- package/examples/css/dbMonsterStyles.css +27 -27
- package/examples/css/indexTodo.css +374 -374
- package/examples/dbmonsterForOfReactive.html +40 -0
- package/examples/dbmonsterReact.html +19 -0
- package/examples/forOfBindingSimpleDebug.html +45 -0
- package/examples/globalConfig.html +131 -0
- package/examples/js/afterRenderDemo.js +190 -0
- package/examples/js/appTodo.js +46 -46
- package/examples/js/attrBindingDemo.js +2 -2
- package/examples/js/dbMonApp.js +24 -26
- package/examples/js/dbMonAppReact.jsx +79 -0
- package/examples/js/dbMonAppReactive.js +28 -0
- package/examples/js/fiberDemo.js +4 -4
- package/examples/js/filtersDemo.js +8 -8
- package/examples/js/forOfDemo.js +7 -9
- package/examples/js/forOfDemoComplex.js +44 -17
- package/examples/js/form.js +14 -14
- package/examples/js/globalConfig.js +117 -0
- package/examples/js/ifBindingDemo.js +16 -16
- package/examples/js/reactiveDemo.js +119 -0
- package/examples/js/switchBindingDemo.js +8 -8
- package/examples/react-dbmonster/dist/bundle.js +43 -0
- package/examples/react-dbmonster/package-lock.json +537 -0
- package/examples/react-dbmonster/package.json +16 -0
- package/examples/react-dbmonster/src/index.jsx +80 -0
- package/examples/reactiveDemo.html +127 -0
- package/examples/refreshRateTest.html +75 -75
- package/index.html +841 -0
- package/package.json +31 -34
- package/rollup.config.js +79 -36
- package/src/{_escape.js → _escape.ts} +19 -17
- package/src/{applyBinding.js → applyBinding.ts} +27 -18
- package/src/{attrBinding.js → attrBinding.ts} +14 -13
- package/src/{binder.js → binder.ts} +289 -181
- package/src/changeBinding.ts +93 -0
- package/src/{commentWrapper.js → commentWrapper.ts} +33 -30
- package/src/config.ts +107 -0
- package/src/{createBindingOption.js → createBindingOption.ts} +39 -15
- package/src/createEventBinding.ts +88 -0
- package/src/{cssBinding.js → cssBinding.ts} +13 -11
- package/src/{domWalker.js → domWalker.ts} +44 -30
- package/src/{forOfBinding.js → forOfBinding.ts} +4 -3
- package/src/hoverBinding.ts +84 -0
- package/src/{ifBinding.js → ifBinding.ts} +14 -12
- package/src/index.ts +53 -0
- package/src/{modelBinding.js → modelBinding.ts} +11 -9
- package/src/{postProcess.js → postProcess.ts} +6 -4
- package/src/{pubSub.js → pubSub.ts} +24 -21
- package/src/reactiveProxy.ts +285 -0
- package/src/{renderForOfBinding.js → renderForOfBinding.ts} +54 -32
- package/src/{renderIfBinding.js → renderIfBinding.ts} +41 -19
- package/src/{renderIteration.js → renderIteration.ts} +24 -8
- package/src/renderTemplate.ts +165 -0
- package/src/renderTemplatesBinding.ts +73 -0
- package/src/{showBinding.js → showBinding.ts} +4 -3
- package/src/{switchBinding.js → switchBinding.ts} +18 -15
- package/src/{textBinding.js → textBinding.ts} +5 -4
- package/src/types.ts +124 -0
- package/src/util.ts +810 -0
- package/test/css/reporter.css +9 -9
- package/test/globals.d.ts +19 -0
- package/test/helpers/testHelper.js +46 -11
- package/test/mocks/featureAdsResult.json +65 -65
- package/test/mocks/searchResult.json +57 -57
- package/test/specs/{attrBinding.spec.js → attrBinding.spec.ts} +103 -106
- package/test/specs/{binder.spec.js → binder.spec.ts} +29 -27
- package/test/specs/blurBinding.spec.ts +60 -0
- package/test/specs/chainableUse.spec.ts +125 -0
- package/test/specs/clickBinding.spec.ts +194 -0
- package/test/specs/{cssBinding.spec.js → cssBinding.spec.ts} +72 -79
- package/test/specs/{dataBindBootstrap.spec.js → dataBindBootstrap.spec.ts} +332 -313
- package/test/specs/{filter.spec.js → filter.spec.ts} +75 -76
- package/test/specs/{forOfBinding.spec.js → forOfBinding.spec.ts} +208 -219
- package/test/specs/formBinding.spec.ts +272 -0
- package/test/specs/ifBinding.spec.ts +165 -0
- package/test/specs/{nestedComponent.spec.js → nestedComponent.spec.ts} +88 -88
- package/test/specs/reactiveProxy.spec.ts +465 -0
- package/test/specs/{showBinding.spec.js → showBinding.spec.ts} +148 -149
- package/test/specs/{switchBinding.spec.js → switchBinding.spec.ts} +172 -173
- package/test/specs/templateBinding.spec.ts +273 -0
- package/test/specs/{textBinding.spec.js → textBinding.spec.ts} +47 -48
- package/test/tsconfig.json +31 -0
- package/test-output.txt +200 -0
- package/test-reactive.html +224 -0
- package/tsconfig.json +28 -0
- package/vendors/lodash.custom.js +4577 -4577
- package/vendors/lodash.custom.min.js +45 -45
- package/vitest.config.js +27 -0
- package/.eslintrc.js +0 -1
- package/.grunt/grunt-contrib-jasmine/boot.js +0 -161
- package/.grunt/grunt-contrib-jasmine/dist/js/dataBind.js +0 -9
- package/.grunt/grunt-contrib-jasmine/grunt-template-jasmine-istanbul/reporter.js +0 -23
- package/.grunt/grunt-contrib-jasmine/jasmine-html.js +0 -853
- package/.grunt/grunt-contrib-jasmine/jasmine.css +0 -271
- package/.grunt/grunt-contrib-jasmine/jasmine.js +0 -9761
- package/.grunt/grunt-contrib-jasmine/jasmine_favicon.png +0 -0
- package/.grunt/grunt-contrib-jasmine/json2.js +0 -489
- package/.grunt/grunt-contrib-jasmine/reporter.js +0 -107
- package/coverage/coverage.json +0 -1
- package/coverage/lcov/lcov-report/base.css +0 -213
- package/coverage/lcov/lcov-report/index.html +0 -93
- package/coverage/lcov/lcov-report/js/dataBind.js.html +0 -6596
- package/coverage/lcov/lcov-report/js/index.html +0 -93
- package/coverage/lcov/lcov-report/prettify.css +0 -1
- package/coverage/lcov/lcov-report/prettify.js +0 -1
- package/coverage/lcov/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov/lcov-report/sorter.js +0 -158
- package/coverage/lcov/lcov.info +0 -1991
- package/eslintrc.json +0 -40
- package/examples/bootstrap/js/bootstrap.min.js +0 -6
- package/examples/bootstrap/js/popper.min.js +0 -5
- package/examples/bootstrap/js/searchSuggestion.js +0 -58
- package/examples/bootstrap/js/typeahead.jquery.js +0 -1538
- package/gruntfile.js +0 -92
- package/gulpfile.js +0 -32
- package/src/applyBindingExport.js +0 -5
- package/src/changeBinding.js +0 -63
- package/src/config.js +0 -66
- package/src/createEventBinding.js +0 -46
- package/src/eventSystem.js +0 -46
- package/src/hoverBinding.js +0 -57
- package/src/index.js +0 -26
- package/src/renderTemplate.js +0 -128
- package/src/renderTemplatesBinding.js +0 -44
- package/src/util.js +0 -648
- package/test/specs/blurBinding.spec.js +0 -57
- package/test/specs/formBinding.spec.js +0 -316
- package/test/specs/ifBinding.spec.js +0 -169
- package/test/specs/templateBinding.spec.js +0 -117
- package/vendors/jasmine-jquery.js +0 -841
- package/vendors/jquery-3.2.1.min.js +0 -4
package/src/util.js
DELETED
|
@@ -1,648 +0,0 @@
|
|
|
1
|
-
import * as config from './config';
|
|
2
|
-
|
|
3
|
-
const hasIsArray = Array.isArray;
|
|
4
|
-
|
|
5
|
-
const REGEX = {
|
|
6
|
-
BAD_TAGS: /<(script|del)(?=[\s>])[\w\W]*?<\/\1\s*>/ig,
|
|
7
|
-
FOR_OF: /(.*?)\s+(?:in|of)\s+(.*)/,
|
|
8
|
-
FUNCTION_PARAM: /\((.*?)\)/,
|
|
9
|
-
HTML_TAG: /^[\s]*<([a-z][^\/\s>]+)/i,
|
|
10
|
-
OBJECT_LITERAL: /^\{.+\}$/,
|
|
11
|
-
PIPE: /\|/,
|
|
12
|
-
WHITE_SPACES: /\s+/g,
|
|
13
|
-
LINE_BREAKS_TABS: /(\r\n|\n|\r|\t)/gm,
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const IS_SUPPORT_TEMPLATE = 'content' in document.createElement('template');
|
|
17
|
-
|
|
18
|
-
const WRAP_MAP = {
|
|
19
|
-
div: ['div', '<div>', '</div>'],
|
|
20
|
-
thead: ['table', '<table>', '</table>'],
|
|
21
|
-
col: ['colgroup', '<table><colgroup>', '</colgroup></table>'],
|
|
22
|
-
tr: ['tbody', '<table><tbody>', '</tbody></table>'],
|
|
23
|
-
td: ['tr', '<table><tr>', '</tr></table>'],
|
|
24
|
-
};
|
|
25
|
-
WRAP_MAP.caption = WRAP_MAP.colgroup = WRAP_MAP.tbody = WRAP_MAP.tfoot = WRAP_MAP.thead;
|
|
26
|
-
WRAP_MAP.th = WRAP_MAP.td;
|
|
27
|
-
|
|
28
|
-
const isArray = (obj) => {
|
|
29
|
-
return hasIsArray ? Array.isArray(obj) : Object.prototype.toString.call(obj) === '[object Array]';
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const isJsObject = (obj) => {
|
|
33
|
-
return obj !== null && typeof obj === 'object' && Object.prototype.toString.call(obj) === '[object Object]';
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const isPlainObject = (obj) => {
|
|
37
|
-
if (!isJsObject(obj)) {
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// If has modified constructor
|
|
42
|
-
const ctor = obj.constructor;
|
|
43
|
-
if (typeof ctor !== 'function') return false;
|
|
44
|
-
|
|
45
|
-
// If has modified prototype
|
|
46
|
-
const prot = ctor.prototype;
|
|
47
|
-
if (isJsObject(prot) === false) return false;
|
|
48
|
-
|
|
49
|
-
// If constructor does not have an Object-specific method
|
|
50
|
-
if (prot.hasOwnProperty('isPrototypeOf') === false) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Most likely a plain Object
|
|
55
|
-
return true;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// test if string contains '{...}'. string must not contains tab, line breaks
|
|
59
|
-
const isObjectLiteralString = (str = '') => {
|
|
60
|
-
return REGEX.OBJECT_LITERAL.test(str);
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const isEmptyObject = (obj) => {
|
|
64
|
-
if (isJsObject(obj)) {
|
|
65
|
-
return Object.getOwnPropertyNames(obj).length === 0;
|
|
66
|
-
}
|
|
67
|
-
return false;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
function getFirstHtmlStringTag(htmlString) {
|
|
71
|
-
const match = htmlString.match(REGEX.HTML_TAG);
|
|
72
|
-
if (match) {
|
|
73
|
-
return match[1];
|
|
74
|
-
}
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function removeBadTags(htmlString = '') {
|
|
79
|
-
return htmlString.replace(REGEX.BAD_TAGS, '');
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function createHtmlFragment(htmlString) {
|
|
83
|
-
if (typeof htmlString !== 'string') {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
// use template element
|
|
87
|
-
if (IS_SUPPORT_TEMPLATE) {
|
|
88
|
-
const template = document.createElement('template');
|
|
89
|
-
template.innerHTML = removeBadTags(htmlString);
|
|
90
|
-
return template.content;
|
|
91
|
-
}
|
|
92
|
-
// use document fragment with wrap html tag for tr, td etc.
|
|
93
|
-
const fragment = document.createDocumentFragment();
|
|
94
|
-
const queryContainer = document.createElement('div');
|
|
95
|
-
const firstTag = getFirstHtmlStringTag(htmlString);
|
|
96
|
-
const wrap = WRAP_MAP[firstTag || 'div'];
|
|
97
|
-
|
|
98
|
-
if (wrap[0] === 'div') {
|
|
99
|
-
return document.createRange().createContextualFragment(htmlString);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
queryContainer.insertAdjacentHTML('beforeend', `${wrap[1]}${htmlString}${wrap[2]}`);
|
|
103
|
-
|
|
104
|
-
const query = queryContainer.querySelector(wrap[0]);
|
|
105
|
-
|
|
106
|
-
while (query.firstChild) {
|
|
107
|
-
fragment.appendChild(query.firstChild);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return fragment;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const generateElementCache = (bindingAttrs) => {
|
|
114
|
-
const elementCache = {};
|
|
115
|
-
|
|
116
|
-
for (const i in bindingAttrs) {
|
|
117
|
-
if (bindingAttrs.hasOwnProperty(i)) {
|
|
118
|
-
if (isArray(bindingAttrs)) {
|
|
119
|
-
elementCache[bindingAttrs[i]] = [];
|
|
120
|
-
} else {
|
|
121
|
-
elementCache[i] = [];
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return elementCache;
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
// simplified version of Lodash _.get
|
|
131
|
-
const _get = function get(obj, path, def) {
|
|
132
|
-
function everyFunc(step) {
|
|
133
|
-
return !(step && (obj = obj[step]) === undefined);
|
|
134
|
-
}
|
|
135
|
-
const fullPath = path
|
|
136
|
-
.replace(/\[/g, '.')
|
|
137
|
-
.replace(/]/g, '')
|
|
138
|
-
.split('.')
|
|
139
|
-
.filter(Boolean);
|
|
140
|
-
|
|
141
|
-
return fullPath.every(everyFunc) ? obj : def;
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* getViewModelValue
|
|
146
|
-
* @description walk a object by provided string path. eg 'a.b.c'
|
|
147
|
-
* @param {object} viewModel
|
|
148
|
-
* @param {string} prop
|
|
149
|
-
* @return {object}
|
|
150
|
-
*/
|
|
151
|
-
const getViewModelValue = (viewModel, prop) => {
|
|
152
|
-
return _get(viewModel, prop);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
// simplified version of Lodash _.set
|
|
156
|
-
// https://stackoverflow.com/questions/54733539/javascript-implementation-of-lodash-set-method
|
|
157
|
-
const _set = (obj, path, value) => {
|
|
158
|
-
if (Object(obj) !== obj) return obj; // When obj is not an object
|
|
159
|
-
// If not yet an array, get the keys from the string-path
|
|
160
|
-
if (!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || [];
|
|
161
|
-
|
|
162
|
-
// Iterate all of them except the last one
|
|
163
|
-
path.slice(0, -1).reduce((a, c, i) =>
|
|
164
|
-
Object(a[c]) === a[c] ? // Does the key exist and is its value an object?
|
|
165
|
-
// Yes: then follow that path
|
|
166
|
-
a[c] :
|
|
167
|
-
// No: create the key. Is the next key a potential array-index?
|
|
168
|
-
a[c] = Math.abs(path[i+1])>>0 === +path[i+1] ?
|
|
169
|
-
[] : // Yes: assign a new array object
|
|
170
|
-
{}, // No: assign a new plain object
|
|
171
|
-
obj)[path[path.length-1]] = value; // Finally assign the value to the last key
|
|
172
|
-
|
|
173
|
-
// Return the top-level object to allow chaining
|
|
174
|
-
return obj;
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* setViewModelValue
|
|
179
|
-
* @description populate viewModel object by path string
|
|
180
|
-
* @param {object} obj
|
|
181
|
-
* @param {string} prop
|
|
182
|
-
* @param {string} value
|
|
183
|
-
* @return {call} underscore set
|
|
184
|
-
*/
|
|
185
|
-
const setViewModelValue = (obj, prop, value) => {
|
|
186
|
-
return _set(obj, prop, value);
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
const getViewModelPropValue = (viewModel, bindingCache) => {
|
|
190
|
-
let dataKey = bindingCache.dataKey;
|
|
191
|
-
let paramList = bindingCache.parameters;
|
|
192
|
-
const isInvertBoolean = dataKey.charAt(0) === '!';
|
|
193
|
-
|
|
194
|
-
if (isInvertBoolean) {
|
|
195
|
-
dataKey = isInvertBoolean ? dataKey.substring(1) : dataKey;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
let ret = getViewModelValue(viewModel, dataKey);
|
|
199
|
-
|
|
200
|
-
if (typeof ret === 'function') {
|
|
201
|
-
const viewModelContext = resolveViewModelContext(viewModel, dataKey);
|
|
202
|
-
const oldViewModelProValue = bindingCache.elementData ? bindingCache.elementData.viewModelPropValue : null;
|
|
203
|
-
paramList = paramList ? resolveParamList(viewModel, paramList) : [];
|
|
204
|
-
// let args = [oldViewModelProValue, bindingCache.el].concat(paramList);
|
|
205
|
-
const args = paramList.concat([oldViewModelProValue, bindingCache.el]);
|
|
206
|
-
ret = ret.apply(viewModelContext, args);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
ret = isInvertBoolean ? !Boolean(ret) : ret;
|
|
210
|
-
|
|
211
|
-
// call through fitlers to get final value
|
|
212
|
-
ret = filtersViewModelPropValue({
|
|
213
|
-
value: ret,
|
|
214
|
-
viewModel: viewModel,
|
|
215
|
-
bindingCache: bindingCache,
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
return ret;
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
const filtersViewModelPropValue = ({value, viewModel, bindingCache}) => {
|
|
222
|
-
let ret = value;
|
|
223
|
-
if (bindingCache.filters) {
|
|
224
|
-
each(bindingCache.filters, (index, filter) => {
|
|
225
|
-
const viewModelContext = resolveViewModelContext(viewModel, filter);
|
|
226
|
-
const filterFn = getViewModelValue.call(viewModelContext, viewModelContext, filter);
|
|
227
|
-
try {
|
|
228
|
-
ret = filterFn.call(viewModelContext, ret);
|
|
229
|
-
} catch (err) {
|
|
230
|
-
throwErrorMessage(err, `Invalid filter: ${filter}`);
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
return ret;
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
const parseStringToJson = (str) => {
|
|
238
|
-
// fix unquote or single quote keys and replace single quote to double quote
|
|
239
|
-
const ret = str.replace(/(\s*?{\s*?|\s*?,\s*?)(['"])?([a-zA-Z0-9]+)(['"])?:/g, '$1"$3":').replace(/'/g, '"');
|
|
240
|
-
return JSON.parse(ret);
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* arrayRemoveMatch
|
|
245
|
-
* @description remove match items in fromArray out of toArray
|
|
246
|
-
* @param {array} toArray
|
|
247
|
-
* @param {array} frommArray
|
|
248
|
-
* @return {boolean}
|
|
249
|
-
*/
|
|
250
|
-
const arrayRemoveMatch = (toArray, frommArray) => {
|
|
251
|
-
return toArray.filter((value, index) => {
|
|
252
|
-
return frommArray.indexOf(value) < 0;
|
|
253
|
-
});
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
const getFormData = ($form) => {
|
|
257
|
-
const data = {};
|
|
258
|
-
|
|
259
|
-
if (!$form instanceof HTMLFormElement) {
|
|
260
|
-
return data;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const formData = new FormData($form);
|
|
264
|
-
|
|
265
|
-
formData.forEach((value, key) => {
|
|
266
|
-
if (!Object.prototype.hasOwnProperty.call( Object, key ) ) {
|
|
267
|
-
data[key] = value;
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
if (!Array.isArray(data[key])) {
|
|
271
|
-
data[key] = [data[key]];
|
|
272
|
-
}
|
|
273
|
-
data[key].push(value);
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
return data;
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* getFunctionParameterList
|
|
281
|
-
* @description convert parameter string to arrary
|
|
282
|
-
* eg. '("a","b","c")' > ["a","b","c"]
|
|
283
|
-
* @param {string} str
|
|
284
|
-
* @return {array} paramlist
|
|
285
|
-
*/
|
|
286
|
-
const getFunctionParameterList = (str) => {
|
|
287
|
-
if (!str || str.length > config.maxDatakeyLength) {
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
let paramlist = str.match(REGEX.FUNCTION_PARAM);
|
|
291
|
-
|
|
292
|
-
if (paramlist && paramlist[1]) {
|
|
293
|
-
paramlist = paramlist[1].split(',');
|
|
294
|
-
paramlist.forEach(function(v, i) {
|
|
295
|
-
paramlist[i] = v.trim();
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
return paramlist;
|
|
299
|
-
};
|
|
300
|
-
|
|
301
|
-
const extractFilterList = (cacheData) => {
|
|
302
|
-
if (!cacheData || !cacheData.dataKey || cacheData.dataKey.length > config.maxDatakeyLength) {
|
|
303
|
-
return cacheData;
|
|
304
|
-
}
|
|
305
|
-
const filterList = cacheData.dataKey.split(REGEX.PIPE);
|
|
306
|
-
let isOnceIndex;
|
|
307
|
-
cacheData.dataKey = filterList[0].trim();
|
|
308
|
-
if (filterList.length > 1) {
|
|
309
|
-
filterList.shift(0);
|
|
310
|
-
filterList.forEach(function(v, i) {
|
|
311
|
-
filterList[i] = v.trim();
|
|
312
|
-
if (filterList[i] === config.constants.filters.ONCE) {
|
|
313
|
-
cacheData.isOnce = true;
|
|
314
|
-
isOnceIndex = i;
|
|
315
|
-
}
|
|
316
|
-
});
|
|
317
|
-
// don't store filter 'once' - because it is internal logic not a property from viewModel
|
|
318
|
-
if (isOnceIndex >= 0) {
|
|
319
|
-
filterList.splice(isOnceIndex, 1);
|
|
320
|
-
}
|
|
321
|
-
cacheData.filters = filterList;
|
|
322
|
-
}
|
|
323
|
-
return cacheData;
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
const invertObj = (sourceObj) => {
|
|
327
|
-
return Object.keys(sourceObj).reduce(function(obj, key) {
|
|
328
|
-
obj[sourceObj[key]] = key;
|
|
329
|
-
return obj;
|
|
330
|
-
}, {});
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
const createDeferredObj = () => {
|
|
334
|
-
const dfObj = {};
|
|
335
|
-
|
|
336
|
-
dfObj.promise = new Promise((resolve, reject) => {
|
|
337
|
-
dfObj.resolve = resolve;
|
|
338
|
-
dfObj.reject = reject;
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
return dfObj;
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* debounce
|
|
346
|
-
* @description decorate a function to be debounce using requestAnimationFrame
|
|
347
|
-
* @param {function} fn
|
|
348
|
-
* @param {context} ctx
|
|
349
|
-
* @return {function}
|
|
350
|
-
*/
|
|
351
|
-
const debounceRaf = (fn, ctx = null) => {
|
|
352
|
-
return (function(fn, ctx) {
|
|
353
|
-
let dfObj = createDeferredObj();
|
|
354
|
-
let rafId = 0;
|
|
355
|
-
|
|
356
|
-
// return decorated fn
|
|
357
|
-
return function() {
|
|
358
|
-
/* eslint-disable prefer-rest-params */
|
|
359
|
-
const args = Array.from ? Array.from(arguments) : Array.prototype.slice.call(arguments);
|
|
360
|
-
|
|
361
|
-
window.cancelAnimationFrame(rafId);
|
|
362
|
-
rafId = window.requestAnimationFrame(() => {
|
|
363
|
-
try {
|
|
364
|
-
// fn is Binder.render function
|
|
365
|
-
fn.apply(ctx, args);
|
|
366
|
-
// dfObj.resolve is function provided in .then promise chain
|
|
367
|
-
// ctx is the current component
|
|
368
|
-
dfObj.resolve(ctx);
|
|
369
|
-
} catch (err) {
|
|
370
|
-
console.error('error in rendering: ', err);
|
|
371
|
-
dfObj.reject(err);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// reset dfObj - otherwise then callbacks will not be in execution order
|
|
375
|
-
// example:
|
|
376
|
-
// myApp.render().then(function(){console.log('ok1')});
|
|
377
|
-
// myApp.render().then(function(){console.log('ok2')});
|
|
378
|
-
// myApp.render().then(function(){console.log('ok3')});
|
|
379
|
-
// >> ok1, ok2, ok3
|
|
380
|
-
dfObj = createDeferredObj();
|
|
381
|
-
|
|
382
|
-
window.cancelAnimationFrame(rafId);
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
return dfObj.promise;
|
|
386
|
-
};
|
|
387
|
-
})(fn, ctx);
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* getNodeAttrObj
|
|
392
|
-
* @description convert Node attributes object to a json object
|
|
393
|
-
* @param {object} node
|
|
394
|
-
* @param {array} skipList
|
|
395
|
-
* @return {object}
|
|
396
|
-
*/
|
|
397
|
-
const getNodeAttrObj = (node, skipList) => {
|
|
398
|
-
let attributesLength = 0;
|
|
399
|
-
let skipArray;
|
|
400
|
-
|
|
401
|
-
if (!node || node.nodeType !== 1 || !node.hasAttributes()) {
|
|
402
|
-
return;
|
|
403
|
-
}
|
|
404
|
-
if (skipList) {
|
|
405
|
-
skipArray = [];
|
|
406
|
-
skipArray = typeof skipList === 'string' ? skipArray.push(skipList) : skipList;
|
|
407
|
-
}
|
|
408
|
-
const attrObj = {};
|
|
409
|
-
attributesLength = node.attributes.length;
|
|
410
|
-
|
|
411
|
-
if (attributesLength) {
|
|
412
|
-
for (let i = 0; i < attributesLength; i += 1) {
|
|
413
|
-
const attribute = node.attributes.item(i);
|
|
414
|
-
attrObj[attribute.nodeName] = attribute.nodeValue;
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
if (isArray(skipArray)) {
|
|
419
|
-
skipArray.forEach((item) => {
|
|
420
|
-
if (attrObj[item]) {
|
|
421
|
-
delete attrObj[item];
|
|
422
|
-
}
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
return attrObj;
|
|
426
|
-
};
|
|
427
|
-
|
|
428
|
-
/**
|
|
429
|
-
* extend
|
|
430
|
-
* @param {boolean} isDeepMerge
|
|
431
|
-
* @param {object} target
|
|
432
|
-
* @param {object} sources
|
|
433
|
-
* @return {object} merged object
|
|
434
|
-
*/
|
|
435
|
-
const extend = (isDeepMerge = false, target, ...sources) => {
|
|
436
|
-
if (!sources.length) {
|
|
437
|
-
return target;
|
|
438
|
-
}
|
|
439
|
-
const source = sources.shift();
|
|
440
|
-
if (source === undefined) {
|
|
441
|
-
return target;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
if (!isDeepMerge) {
|
|
445
|
-
return Object.assign(target, ...sources);
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
if (isMergebleObject(target) && isMergebleObject(source)) {
|
|
449
|
-
Object.keys(source).forEach((key) => {
|
|
450
|
-
if (isMergebleObject(source[key])) {
|
|
451
|
-
if (!target[key]) {
|
|
452
|
-
target[key] = {};
|
|
453
|
-
}
|
|
454
|
-
extend(target[key], source[key]);
|
|
455
|
-
} else {
|
|
456
|
-
target[key] = source[key];
|
|
457
|
-
}
|
|
458
|
-
});
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
return extend(true, target, ...sources);
|
|
462
|
-
};
|
|
463
|
-
|
|
464
|
-
const each = (obj, fn) => {
|
|
465
|
-
if (typeof obj !== 'object' || typeof fn !== 'function') {
|
|
466
|
-
return;
|
|
467
|
-
}
|
|
468
|
-
let keys = [];
|
|
469
|
-
let keysLength = 0;
|
|
470
|
-
const isArrayObj = isArray(obj);
|
|
471
|
-
let key;
|
|
472
|
-
let value;
|
|
473
|
-
let i = 0;
|
|
474
|
-
|
|
475
|
-
if (isArrayObj) {
|
|
476
|
-
keysLength = obj.length;
|
|
477
|
-
} else if (isJsObject(obj)) {
|
|
478
|
-
keys = Object.keys(obj);
|
|
479
|
-
keysLength = keys.length;
|
|
480
|
-
} else {
|
|
481
|
-
throw new TypeError('Object is not an array or object');
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
for (i = 0; i < keysLength; i += 1) {
|
|
485
|
-
if (isArrayObj) {
|
|
486
|
-
key = i;
|
|
487
|
-
value = obj[i];
|
|
488
|
-
} else {
|
|
489
|
-
key = keys[i];
|
|
490
|
-
value = obj[key];
|
|
491
|
-
}
|
|
492
|
-
fn(key, value);
|
|
493
|
-
}
|
|
494
|
-
};
|
|
495
|
-
|
|
496
|
-
const isMergebleObject = (item) => {
|
|
497
|
-
return isJsObject(item) && !isArray(item);
|
|
498
|
-
};
|
|
499
|
-
|
|
500
|
-
/**
|
|
501
|
-
* cloneDomNode
|
|
502
|
-
* @param {object} element
|
|
503
|
-
* @return {object} cloned element
|
|
504
|
-
* @description helper function to clone node
|
|
505
|
-
*/
|
|
506
|
-
const cloneDomNode = (element) => {
|
|
507
|
-
return element.cloneNode(true);
|
|
508
|
-
};
|
|
509
|
-
|
|
510
|
-
/**
|
|
511
|
-
* insertAfter
|
|
512
|
-
* @param {object} parentNode
|
|
513
|
-
* @param {object} newNode
|
|
514
|
-
* @param {object} referenceNode
|
|
515
|
-
* @return {object} node
|
|
516
|
-
* @description helper function to insert new node before the reference node
|
|
517
|
-
*/
|
|
518
|
-
const insertAfter = (parentNode, newNode, referenceNode) => {
|
|
519
|
-
const refNextElement = referenceNode && referenceNode.nextSibling ? referenceNode.nextSibling : null;
|
|
520
|
-
return parentNode.insertBefore(newNode, refNextElement);
|
|
521
|
-
};
|
|
522
|
-
|
|
523
|
-
const resolveViewModelContext = (viewModel, datakey) => {
|
|
524
|
-
let ret = viewModel;
|
|
525
|
-
if (typeof datakey !== 'string') {
|
|
526
|
-
return ret;
|
|
527
|
-
}
|
|
528
|
-
const bindingDataContext = datakey.split('.');
|
|
529
|
-
if (bindingDataContext.length > 1) {
|
|
530
|
-
if (bindingDataContext[0] === config.bindingDataReference.rootDataKey) {
|
|
531
|
-
ret = viewModel[config.bindingDataReference.rootDataKey] || viewModel;
|
|
532
|
-
} else if (bindingDataContext[0] === config.bindingDataReference.currentData) {
|
|
533
|
-
ret = viewModel[config.bindingDataReference.currentData] || viewModel;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
return ret;
|
|
537
|
-
};
|
|
538
|
-
|
|
539
|
-
const resolveParamList = (viewModel, paramList) => {
|
|
540
|
-
if (!viewModel || !isArray(paramList)) {
|
|
541
|
-
return;
|
|
542
|
-
}
|
|
543
|
-
return paramList.map((param) => {
|
|
544
|
-
param = param.trim();
|
|
545
|
-
|
|
546
|
-
if (param === config.bindingDataReference.currentIndex) {
|
|
547
|
-
// convert '$index' to value
|
|
548
|
-
param = viewModel[config.bindingDataReference.currentIndex];
|
|
549
|
-
} else if (param === config.bindingDataReference.currentData) {
|
|
550
|
-
// convert '$data' to value or current viewModel
|
|
551
|
-
param = viewModel[config.bindingDataReference.currentData] || viewModel;
|
|
552
|
-
} else if (param === config.bindingDataReference.rootDataKey) {
|
|
553
|
-
// convert '$root' to root viewModel
|
|
554
|
-
param = viewModel[config.bindingDataReference.rootDataKey] || viewModel;
|
|
555
|
-
}
|
|
556
|
-
return param;
|
|
557
|
-
});
|
|
558
|
-
};
|
|
559
|
-
|
|
560
|
-
const removeElement = (el) => {
|
|
561
|
-
if (el && el.parentNode) {
|
|
562
|
-
el.parentNode.removeChild(el);
|
|
563
|
-
}
|
|
564
|
-
};
|
|
565
|
-
|
|
566
|
-
const emptyElement = (node) => {
|
|
567
|
-
if (node && node.firstChild) {
|
|
568
|
-
while (node.firstChild) {
|
|
569
|
-
node.removeChild(node.firstChild);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
return node;
|
|
573
|
-
};
|
|
574
|
-
|
|
575
|
-
const throwErrorMessage = (err = null, errorMessage = '') => {
|
|
576
|
-
const message = err && err.message ? err.message : errorMessage;
|
|
577
|
-
if (typeof console.error === 'function') {
|
|
578
|
-
return console.error(message);
|
|
579
|
-
}
|
|
580
|
-
return console.log(message);
|
|
581
|
-
};
|
|
582
|
-
|
|
583
|
-
/**
|
|
584
|
-
* parseBindingObjectString
|
|
585
|
-
* @description parse bining object string to object with value always stringify
|
|
586
|
-
* @param {string} str - eg '{ id: $data.id, name: $data.name }'
|
|
587
|
-
* @return {object} - eg { id: '$data.id', name: '$data.name'}
|
|
588
|
-
*/
|
|
589
|
-
const parseBindingObjectString = (str = '') => {
|
|
590
|
-
let objectLiteralString = str.trim();
|
|
591
|
-
const ret = {};
|
|
592
|
-
|
|
593
|
-
if (!REGEX.OBJECT_LITERAL.test(str)) {
|
|
594
|
-
return null;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
// clearn up line breaks and remove first { character
|
|
598
|
-
objectLiteralString = objectLiteralString
|
|
599
|
-
.replace(REGEX.LINE_BREAKS_TABS, '')
|
|
600
|
-
.substring(1);
|
|
601
|
-
|
|
602
|
-
// remove last } character
|
|
603
|
-
objectLiteralString = objectLiteralString.substring(0, objectLiteralString.length - 1);
|
|
604
|
-
|
|
605
|
-
objectLiteralString.split(',').forEach((item) => {
|
|
606
|
-
const keyVal = item.trim();
|
|
607
|
-
// ignore if last empty item - eg split last comma in object literal
|
|
608
|
-
if (keyVal) {
|
|
609
|
-
const prop = keyVal.split(':');
|
|
610
|
-
const key = prop[0].trim();
|
|
611
|
-
ret[key] = `${prop[1]}`.trim();
|
|
612
|
-
}
|
|
613
|
-
});
|
|
614
|
-
|
|
615
|
-
return ret;
|
|
616
|
-
};
|
|
617
|
-
|
|
618
|
-
export {
|
|
619
|
-
REGEX,
|
|
620
|
-
arrayRemoveMatch,
|
|
621
|
-
cloneDomNode,
|
|
622
|
-
createHtmlFragment,
|
|
623
|
-
debounceRaf,
|
|
624
|
-
each,
|
|
625
|
-
emptyElement,
|
|
626
|
-
extend,
|
|
627
|
-
extractFilterList,
|
|
628
|
-
generateElementCache,
|
|
629
|
-
getFormData,
|
|
630
|
-
getFunctionParameterList,
|
|
631
|
-
getNodeAttrObj,
|
|
632
|
-
getViewModelPropValue,
|
|
633
|
-
getViewModelValue,
|
|
634
|
-
insertAfter,
|
|
635
|
-
invertObj,
|
|
636
|
-
isArray,
|
|
637
|
-
isEmptyObject,
|
|
638
|
-
isJsObject,
|
|
639
|
-
isPlainObject,
|
|
640
|
-
isObjectLiteralString,
|
|
641
|
-
parseStringToJson,
|
|
642
|
-
parseBindingObjectString,
|
|
643
|
-
removeElement,
|
|
644
|
-
resolveParamList,
|
|
645
|
-
resolveViewModelContext,
|
|
646
|
-
setViewModelValue,
|
|
647
|
-
throwErrorMessage,
|
|
648
|
-
};
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
describe('Given [data-bind-comp="blur-component"] initised', () => {
|
|
2
|
-
const namespace = {};
|
|
3
|
-
const testBlurValue = 'onBlur called';
|
|
4
|
-
|
|
5
|
-
jasmine.getFixtures().fixturesPath = 'test';
|
|
6
|
-
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
loadFixtures('./fixtures/blurBinding.html');
|
|
9
|
-
|
|
10
|
-
namespace.viewModel = {
|
|
11
|
-
heading: 'blur component test',
|
|
12
|
-
myData: 'blur component',
|
|
13
|
-
onFocusFn: function(e, $element) {},
|
|
14
|
-
onBlurFn: function(e, $element) {
|
|
15
|
-
this.myData = testBlurValue;
|
|
16
|
-
this.updateView();
|
|
17
|
-
},
|
|
18
|
-
updateView: function(opt) {
|
|
19
|
-
this.APP.render(opt);
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
namespace.blurComponent = dataBind.init(document.querySelector('[data-bind-comp="blur-component"]'), namespace.viewModel);
|
|
24
|
-
namespace.blurComponent.render();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
afterEach(() => {
|
|
28
|
-
// clean up app
|
|
29
|
-
// clean up all app/components
|
|
30
|
-
for (const prop in namespace) {
|
|
31
|
-
if (namespace.hasOwnProperty(prop)) {
|
|
32
|
-
delete namespace[prop];
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('should render heading defined in viewModel', (done) => {
|
|
38
|
-
setTimeout(() => {
|
|
39
|
-
expect(document.getElementById('heading').textContent).toBe(namespace.viewModel.heading);
|
|
40
|
-
expect(document.getElementById('blurInput').value).toBe(namespace.viewModel.myData);
|
|
41
|
-
done();
|
|
42
|
-
}, 200);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should update "blurInput" value after onBlur', (done) => {
|
|
46
|
-
const $blurInput = document.getElementById('blurInput');
|
|
47
|
-
setTimeout(() => {
|
|
48
|
-
$blurInput.focus();
|
|
49
|
-
$blurInput.blur();
|
|
50
|
-
|
|
51
|
-
setTimeout(() => {
|
|
52
|
-
expect($blurInput.value).toBe(testBlurValue);
|
|
53
|
-
done();
|
|
54
|
-
}, 200);
|
|
55
|
-
}, 200);
|
|
56
|
-
});
|
|
57
|
-
});
|