UNPKG

8.97 kBJavaScriptView Raw
1
2export default {
3
4 PIPE: /\s?\|\s?/,
5 PIPES: /\s?,\s?|\s+/,
6
7 value (element, model) {
8
9 if (!model) throw new Error('Utility.value - requires model argument');
10 if (!element) throw new Error('Utility.value - requires element argument');
11
12 const type = this.type(element);
13
14 if (type === 'radio' || type === 'checkbox') {
15 const name = this.name(element);
16 const query = 'input[type="' + type + '"][name="' + name + '"]';
17 const form = this.form(element);
18 const elements = form ? this.form(element).querySelectorAll(query) : [ element ];
19 const multiple = elements.length > 1;
20
21 let result = multiple ? [] : undefined;
22
23 for (let i = 0, l = elements.length; i < l; i++) {
24 const child = elements[i];
25 const checked = this.checked(child);
26
27 if (!checked) continue;
28 const value = this.value(child, model);
29
30 if (multiple) {
31 result.push(value);
32 } else {
33 result = value;
34 break;
35 }
36
37 }
38
39 return result;
40 } else if (type === 'select-one' || type === 'select-multiple') {
41 const multiple = this.multiple(element);
42 const options = element.options;
43 let result = multiple ? [] : undefined;
44
45 for (let i = 0, l = options.length; i < l; i++) {
46 const option = options[i];
47 const selected = option.selected;
48 const value = this.value(option, model);
49 const match = this[multiple ? 'includes' : 'compare'](this.data, value);
50
51 // !disabled &&
52 // this.data !== undefined &&
53
54 if (selected && !match) {
55 if (this.multiple) {
56 result.push(value);
57 } else {
58 result = value;
59 }
60 } else if (!selected && match) {
61 option.selected = true;
62 }
63
64 }
65
66 return result;
67 // } else if (
68 // element.nodeName === 'INPUT' || element.nodeName.indexOf('-INPUT') !== -1 ||
69 // element.nodeName === 'OPTION' || element.nodeName.indexOf('-OPTION') !== -1 ||
70 // element.nodeName === 'TEXTAREA' || element.nodeName.indexOf('-TEXTAREA') !== -1
71 // ) {
72 } else {
73 const attribute = element.attributes['o-value'];
74 if (attribute) {
75 const values = this.binderValues(attribute.value);
76 const value = this.getByPath(model, values);
77 return value || element.value;
78 } else {
79 return element.value;
80 }
81 }
82 },
83
84 form (element) {
85 if (element.form) {
86 return element.form;
87 } else {
88 while (element = element.parentElement) {
89 if (element.nodeName === 'FORM' || element.nodeName.indexOf('-FORM') !== -1) {
90 return element;
91 }
92 }
93 }
94 },
95
96 type (element) {
97 if (typeof element.type === 'string') {
98 return element.type;
99 } else {
100 return element.getAttribute('type');
101 }
102 },
103
104 name (element) {
105 if (typeof element.name === 'string') {
106 return element.name;
107 } else {
108 return element.getAttribute('name');
109 }
110 },
111
112 checked (element) {
113 if (typeof element.checked === 'boolean') {
114 return element.checked;
115 } else {
116 switch (element.getAttribute('checked')) {
117 case undefined: return false;
118 case 'true': return true;
119 case null: return false;
120 case '': return true;
121 default: return false;
122 }
123 }
124 },
125
126 multiple (element) {
127 if (typeof element.multiple === 'boolean') {
128 return element.multiple;
129 } else {
130 switch (element.getAttribute('multiple')) {
131 case undefined: return false;
132 case 'true': return true;
133 case null: return false;
134 case '': return true;
135 default: return false;
136 }
137 }
138 },
139
140 disabled (element) {
141 if (typeof element.disabled === 'boolean') {
142 return element.disabled;
143 } else {
144 switch (element.getAttribute('disabled')) {
145 case undefined: return false;
146 case 'true': return true;
147 case null: return false;
148 case '': return true;
149 default: return false;
150 }
151 }
152 },
153
154 index (items, item) {
155
156 for (let i = 0, l = items.length; i < l; i++) {
157 if (this.match(items[i], item)) {
158 return i;
159 }
160 }
161
162 return -1;
163 },
164
165 includes (items, item) {
166
167 for (let i = 0, l = items.length; i < l; i++) {
168 if (this.match(items[i], item)) {
169 return true;
170 }
171 }
172
173 return false;
174 },
175
176 match (source, target) {
177
178 if (source === target) {
179 return true;
180 }
181
182 if (typeof source !== typeof target) {
183 return false;
184 }
185
186 if (source.constructor !== target.constructor) {
187 return false;
188 }
189
190 if (typeof source !== 'object' || typeof target !== 'object') {
191 return source === target;
192 }
193
194 const sourceKeys = Object.keys(source);
195 const targetKeys = Object.keys(target);
196
197 if (sourceKeys.length !== targetKeys.length) {
198 return false;
199 }
200
201 for (let i = 0, l = sourceKeys.length; i < l; i++) {
202 const name = sourceKeys[i];
203
204 if (!this.match(source[name], target[name])) {
205 return false;
206 }
207
208 }
209
210 return true;
211 },
212
213 binderNames (data) {
214 data = data.split('o-')[1];
215 return data ? data.split('-') : [];
216 },
217
218 binderValues (data) {
219 data = data.split(this.PIPE)[0];
220 return data ? data.split('.') : [];
221 },
222
223 binderPipes (data) {
224 data = data.split(this.PIPE)[1];
225 return data ? data.split(this.PIPES) : [];
226 },
227
228 ensureElement (data) {
229 data.query = data.query || '';
230 data.scope = data.scope || document.body;
231 data.position = data.position || 'beforeend';
232
233 let element = data.scope.querySelector(`${data.name}${data.query}`);
234
235 if (!element) {
236 element = document.createElement(data.name);
237 data.scope.insertAdjacentElement(data.position, element);
238 }
239
240 for (let i = 0, l = data.attributes.length; i < l; i++) {
241 const { name, value } = data.attributes[i];
242 element.setAttribute(name, value);
243 }
244
245 return element;
246 },
247
248 setByPath (data, path, value) {
249 const keys = typeof path === 'string' ? path.split('.') : path;
250 const last = keys.length - 1;
251
252 for (let i = 0; i < last; i++) {
253 const key = keys[i];
254
255 if (!(key in data)) {
256
257 if (isNaN(keys[i + 1])) {
258 data[key] = {};
259 } else {
260 data[key] = [];
261 }
262
263 }
264
265 data = data[key];
266 }
267
268 return data[keys[last]] = value;
269 },
270
271 getByPath (data, path) {
272 const keys = typeof path === 'string' ? path.split('.') : path;
273 const last = keys.length - 1;
274
275 if (keys[last] === '$key' || keys[last] === '$index') {
276 return keys[last - 1];
277 }
278
279 for (let i = 0; i < last; i++) {
280 const key = keys[i];
281
282 if (key in data === false) {
283 return undefined;
284 } else {
285 data = data[key];
286 }
287
288 }
289
290 return data[keys[last]];
291 },
292
293 clone (source) {
294
295 if (
296 source === null ||
297 source === undefined ||
298 source.constructor !== Array &&
299 source.constructor !== Object
300 ) {
301 return source;
302 }
303
304 var target = source.constructor();
305
306 for (const name in source) {
307 const descriptor = Object.getOwnPropertyDescriptor(source, name);
308
309 if (descriptor) {
310
311 if ('value' in descriptor) {
312 descriptor.value = this.clone(descriptor.value);
313 }
314
315 Object.defineProperty(target, name, descriptor);
316 }
317
318 }
319
320 return target;
321 }
322
323 // walker (node, callback) {
324 // callback(node);
325 // node = node.firstChild;
326 // while (node) {
327 // this.walker(node, callback);
328 // node = node.nextSibling;
329 // }
330 // },
331
332};