Skip to content

Commit ba4dfd6

Browse files
committed
[ Refactor ] valueOf() utility
[ Migrate ] likeArray() from WebCell
1 parent 4797b2e commit ba4dfd6

File tree

10 files changed

+177
-103
lines changed

10 files changed

+177
-103
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "dom-renderer",
3-
"version": "1.0.0-alpha",
3+
"version": "1.0.0-beta",
44
"description": "Template engine based on HTML 5, ECMAScript 6 & MVVM",
55
"keywords": [
66
"template",
Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { insertableIndexOf, likeArray } from '../object/array';
2+
13
import { parseDOM } from './parser';
24

35
/**
@@ -15,20 +17,6 @@ export function indexOf(node, inNodes) {
1517
return index;
1618
}
1719

18-
/**
19-
* @param {Node[]} list
20-
* @param {Number} [index]
21-
*
22-
* @return {Number}
23-
*/
24-
export function insertableIndexOf(list, index) {
25-
return !(index != null) || index > list.length
26-
? list.length
27-
: index < 0
28-
? list.length + index
29-
: index;
30-
}
31-
3220
/**
3321
* @param {ParentNode} parent
3422
* @param {Node|String} child - https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/append#Parameters
@@ -57,7 +45,7 @@ export function insertTo(parent, child, position, inNodes) {
5745
export function makeNode(fragment) {
5846
if (fragment instanceof Node) return fragment;
5947

60-
if (Object(fragment) instanceof String) return parseDOM(fragment);
48+
if (!likeArray(fragment)) return parseDOM(fragment + '');
6149

6250
let node = document.createDocumentFragment();
6351

@@ -70,3 +58,35 @@ export function makeNode(fragment) {
7058

7159
return node;
7260
}
61+
62+
/**
63+
* @param {HTMLElement} input
64+
*
65+
* @return {String|String[]}
66+
*/
67+
export function valueOf(input) {
68+
const { type, value } = input;
69+
70+
switch (type) {
71+
case 'radio':
72+
case 'checkbox': {
73+
const root = input.form || input.getRootNode();
74+
75+
const data = Array.from(
76+
root.querySelectorAll(
77+
`input[type="${type}"][name="${input.name}"]`
78+
),
79+
item => item.checked && item.value
80+
).filter(Boolean);
81+
82+
return type === 'radio' ? data[0] : data;
83+
}
84+
case 'select-multiple':
85+
return Array.from(
86+
input.options,
87+
node => node.selected && node.value
88+
).filter(Boolean);
89+
}
90+
91+
return value;
92+
}

source/DOM/parser.js

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -128,34 +128,3 @@ export function scanDOM(root, expression, { attribute, text, ...element }) {
128128
}
129129
});
130130
}
131-
132-
/**
133-
* @param {HTMLElement} input
134-
*
135-
* @return {String|String[]}
136-
*/
137-
export function valueOf(input) {
138-
switch (input.type || input.tagName.toLowerCase()) {
139-
case 'radio':
140-
return input.checked ? input.value : null;
141-
case 'checkbox':
142-
return Array.from(
143-
input.form
144-
? input.form.elements[input.name]
145-
: input
146-
.getRootNode()
147-
.querySelectorAll(
148-
`input[type="checkbox"][name="${input.name}"]`
149-
),
150-
node => (node.checked ? node.value : null)
151-
);
152-
case 'select':
153-
return input.multiple
154-
? Array.from(input.options, node =>
155-
node.selected ? node.value : null
156-
)
157-
: input.value;
158-
}
159-
160-
return input.value;
161-
}

source/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
export * from './DOM/parser';
1+
export * from './object/array';
22

3+
export * from './DOM/parser';
4+
export * from './DOM/manipulate';
35
export * from './DOM/CustomInputEvent';
4-
56
export * from './DOM/timer';
67

78
export { default as Template } from './view/Template';
8-
99
export { default as Model } from './view/Model';
10-
1110
export { default } from './view/View';
11+
export { default as ViewList } from './view/ViewList';

source/object/array.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* @param {*} object
3+
*
4+
* @return {Boolean}
5+
*/
6+
export function likeArray(object) {
7+
object = Object(object);
8+
9+
return (
10+
!(object instanceof String) &&
11+
!(object instanceof Function) &&
12+
!(object instanceof Node) &&
13+
(object[Symbol.iterator] instanceof Function ||
14+
typeof object.length === 'number')
15+
);
16+
}
17+
18+
/**
19+
* @param {Node[]} list
20+
* @param {Number} [index]
21+
*
22+
* @return {Number}
23+
*/
24+
export function insertableIndexOf(list, index) {
25+
return !(index != null) || index > list.length
26+
? list.length
27+
: index < 0
28+
? list.length + index
29+
: index;
30+
}

source/view/View.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
import Model from './Model';
22

3-
import {
4-
parseDOM,
5-
scanDOM,
6-
stringifyDOM,
7-
attributeMap,
8-
valueOf
9-
} from '../DOM/parser';
3+
import { parseDOM, scanDOM, stringifyDOM, attributeMap } from '../DOM/parser';
104

115
import Template from './Template';
12-
136
import ViewList from './ViewList';
147

158
import { debounce, nextTick } from '../DOM/timer';
16-
9+
import { valueOf } from '../DOM/manipulate';
1710
import CustomInputEvent, { watchInput } from '../DOM/CustomInputEvent';
1811

1912
const { forEach, push, concat } = Array.prototype;

source/view/ViewList.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import View from './View';
22

3-
import { insertableIndexOf, insertTo, makeNode } from '../DOM/insert';
3+
import { insertableIndexOf } from '../object/array';
4+
5+
import { insertTo, makeNode } from '../DOM/manipulate';
46

57
const root_list = new WeakMap(),
68
list_root = new WeakMap(),

test/array.spec.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { likeArray, insertableIndexOf } from '../source/object/array';
2+
3+
describe('Array utility methods', () => {
4+
/**
5+
* @test {likeArray}
6+
*/
7+
it('detects Array-like object', () => {
8+
likeArray(false).should.be.false();
9+
likeArray(null).should.be.false();
10+
likeArray(undefined).should.be.false();
11+
likeArray(NaN).should.be.false();
12+
likeArray('').should.be.false();
13+
14+
likeArray([]).should.be.true();
15+
likeArray({ length: 0 }).should.be.true();
16+
17+
likeArray(() => {}).should.be.false();
18+
likeArray(document.createElement('form')).should.be.false();
19+
});
20+
21+
/**
22+
* @test {insertableIndexOf}
23+
*/
24+
it('gets insertable index of an Array', () => {
25+
const list = [1, 2, 3];
26+
27+
insertableIndexOf(list, 1).should.be.equal(1);
28+
29+
insertableIndexOf(list, 4).should.be.equal(3);
30+
31+
insertableIndexOf(list, -1).should.be.equal(2);
32+
});
33+
});

test/insert.spec.js

Lines changed: 0 additions & 42 deletions
This file was deleted.

test/manipulate.spec.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { parseDOM } from '../source/DOM/parser';
2+
3+
import { indexOf, insertTo, valueOf } from '../source/DOM/manipulate';
4+
5+
const form = parseDOM(`<form>
6+
<input type="radio" name="radio" value="r1" checked>
7+
<input type="radio" name="radio" value="r2">
8+
9+
<input type="checkbox" name="check" value="c1" checked>
10+
<input type="checkbox" name="check" value="c2">
11+
<input type="checkbox" name="check" value="c3" checked>
12+
13+
<select name="select" multiple>
14+
<option>s1</option>
15+
<option selected>s2</option>
16+
<option selected>s3</option>
17+
</select>
18+
19+
<textarea name="text">example</textarea>
20+
</form>`).firstChild;
21+
22+
describe('DOM inserting', () => {
23+
/**
24+
* @test {indexOf}
25+
*/
26+
it('gets the index of DOM nodes', () => {
27+
indexOf(form.firstElementChild).should.be.equal(0);
28+
29+
indexOf(form.firstElementChild, true).should.be.equal(1);
30+
});
31+
32+
/**
33+
* @test {insertTo}
34+
*/
35+
it('inserts Nodes to an Element by index', () => {
36+
insertTo(form, 'test', -2, true);
37+
38+
insertTo(form, 'test', Infinity, true);
39+
40+
form.outerHTML.should.be.equal(`<form>
41+
<input type="radio" name="radio" value="r1" checked="">
42+
<input type="radio" name="radio" value="r2">
43+
44+
<input type="checkbox" name="check" value="c1" checked="">
45+
<input type="checkbox" name="check" value="c2">
46+
<input type="checkbox" name="check" value="c3" checked="">
47+
48+
<select name="select" multiple="">
49+
<option>s1</option>
50+
<option selected="">s2</option>
51+
<option selected="">s3</option>
52+
</select>
53+
54+
test<textarea name="text">example</textarea>
55+
test</form>`);
56+
});
57+
58+
/**
59+
* @test {valueOf}
60+
*/
61+
it('gets values of Form fields', () => {
62+
const { radio, check, select, text } = form.elements;
63+
64+
valueOf(radio).should.be.equal('r1');
65+
valueOf(check).should.be.eql(['c1', 'c3']);
66+
valueOf(select).should.be.eql(['s2', 's3']);
67+
valueOf(text).should.be.equal('example');
68+
});
69+
});

0 commit comments

Comments
 (0)