@domql/element 0.0.1
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/package.json +6 -0
- package/src/assign.js +22 -0
- package/src/create.js +125 -0
- package/src/index.js +8 -0
- package/src/iterate.js +80 -0
- package/src/methods.js +96 -0
- package/src/set.js +46 -0
- package/src/update.js +100 -0
package/package.json
ADDED
package/src/assign.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Receives child and parent nodes as parametes
|
|
5
|
+
* and assigns them into real DOM tree
|
|
6
|
+
*/
|
|
7
|
+
export const appendNode = (node, parentNode) => {
|
|
8
|
+
parentNode.appendChild(node)
|
|
9
|
+
return node
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Receives elements and assigns the first
|
|
14
|
+
* parameter as a child of the second one
|
|
15
|
+
*/
|
|
16
|
+
export const assignNode = (element, parent, key) => {
|
|
17
|
+
parent[key || element.key] = element
|
|
18
|
+
if (element.tag !== 'shadow') {
|
|
19
|
+
appendNode(element.node, parent.node)
|
|
20
|
+
}
|
|
21
|
+
return element
|
|
22
|
+
}
|
package/src/create.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { root } from '@domql/tree'
|
|
4
|
+
import { applyPrototype } from '@domql/proto'
|
|
5
|
+
import { createNode, NODE_REGISTRY, cacheNode } from '@domql/node'
|
|
6
|
+
import { createState } from '@domql/state'
|
|
7
|
+
import { createProps } from '@domql/props'
|
|
8
|
+
import { assignClass } from '@domql/mixins'
|
|
9
|
+
import * as on from '@domql/event/src/on'
|
|
10
|
+
import { isFunction, isNumber, isString, createID, isNode } from '@domql/utils'
|
|
11
|
+
|
|
12
|
+
import { appendNode, assignNode } from './assign'
|
|
13
|
+
import set from './set'
|
|
14
|
+
import update from './update'
|
|
15
|
+
import { remove, lookup, log, keys, parse, parseDeep } from './methods'
|
|
16
|
+
|
|
17
|
+
const ENV = process.env.NODE_ENV
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Creating a domQL element using passed parameters
|
|
21
|
+
*/
|
|
22
|
+
export const create = (element, parent, key, options = {}) => {
|
|
23
|
+
// if ELEMENT is not given
|
|
24
|
+
if (element === undefined) element = {}
|
|
25
|
+
if (element === null) return
|
|
26
|
+
|
|
27
|
+
// define KEY
|
|
28
|
+
const assignedKey = element.key || key || createID.next().value
|
|
29
|
+
|
|
30
|
+
// if PARENT is not given
|
|
31
|
+
// if (parent === null) parent = root
|
|
32
|
+
// if (parent === undefined) parent = root
|
|
33
|
+
if (!parent) parent = root
|
|
34
|
+
if (isNode(parent)) parent = root[`${key}_parent`] = { node: parent }
|
|
35
|
+
|
|
36
|
+
// if element is STRING
|
|
37
|
+
if (isString(element) || isNumber(element)) {
|
|
38
|
+
element = {
|
|
39
|
+
text: element,
|
|
40
|
+
tag: (!element.proto && parent.childProto && parent.childProto.tag) ||
|
|
41
|
+
((NODE_REGISTRY.body.indexOf(key) > -1) && key) || 'string'
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// enable STATE
|
|
46
|
+
element.state = createState(element, parent)
|
|
47
|
+
|
|
48
|
+
// create PROTOtypal inheritance
|
|
49
|
+
applyPrototype(element, parent, options)
|
|
50
|
+
|
|
51
|
+
// create and assign a KEY
|
|
52
|
+
element.key = assignedKey
|
|
53
|
+
|
|
54
|
+
// set the PATH
|
|
55
|
+
if (ENV === 'test' || ENV === 'development') {
|
|
56
|
+
if (!parent.path) parent.path = []
|
|
57
|
+
element.path = parent.path.concat(assignedKey)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// if it already HAS A NODE
|
|
61
|
+
if (element.node) {
|
|
62
|
+
return assignNode(element, parent, assignedKey)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// generate a CLASS name
|
|
66
|
+
assignClass(element)
|
|
67
|
+
|
|
68
|
+
// assign METHODS
|
|
69
|
+
element.set = set
|
|
70
|
+
element.update = update
|
|
71
|
+
element.remove = remove
|
|
72
|
+
element.lookup = lookup
|
|
73
|
+
if (ENV === 'test' || ENV === 'development') {
|
|
74
|
+
element.keys = keys
|
|
75
|
+
element.parse = parse
|
|
76
|
+
element.parseDeep = parseDeep
|
|
77
|
+
element.log = log
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// run `on.init`
|
|
81
|
+
if (element.on && isFunction(element.on.init)) {
|
|
82
|
+
on.init(element.on.init, element, element.state)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// enable TRANSFORM in data
|
|
86
|
+
if (!element.transform) element.transform = {}
|
|
87
|
+
|
|
88
|
+
// enable CACHING
|
|
89
|
+
if (!element.__cached) element.__cached = {}
|
|
90
|
+
|
|
91
|
+
// enable EXEC
|
|
92
|
+
if (!element.__exec) element.__exec = {}
|
|
93
|
+
|
|
94
|
+
// enable CHANGES storing
|
|
95
|
+
if (!element.__changes) element.__changes = []
|
|
96
|
+
|
|
97
|
+
// enable CHANGES storing
|
|
98
|
+
const hasRoot = parent.parent && parent.parent.key === ':root'
|
|
99
|
+
if (!element.__root) element.__root = hasRoot ? parent : parent.__root
|
|
100
|
+
|
|
101
|
+
// apply props settings
|
|
102
|
+
createProps(element, parent)
|
|
103
|
+
|
|
104
|
+
// don't render IF in condition
|
|
105
|
+
if (isFunction(element.if) && !element.if(element, element.state)) {
|
|
106
|
+
// TODO: move as fragment
|
|
107
|
+
const ifFragment = cacheNode({ tag: 'fragment' })
|
|
108
|
+
element.__ifFragment = appendNode(ifFragment, parent.node)
|
|
109
|
+
element.__ifFalsy = true
|
|
110
|
+
return
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// CREATE a real NODE
|
|
114
|
+
createNode(element)
|
|
115
|
+
|
|
116
|
+
// assign NODE
|
|
117
|
+
assignNode(element, parent, key)
|
|
118
|
+
|
|
119
|
+
// run `on.render`
|
|
120
|
+
if (element.on && isFunction(element.on.render)) {
|
|
121
|
+
on.render(element.on.render, element, element.state)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return element
|
|
125
|
+
}
|
package/src/index.js
ADDED
package/src/iterate.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { exec, isFunction, isNumber, isString, overwrite } from '@domql/utils'
|
|
4
|
+
import { isMethod } from './methods'
|
|
5
|
+
|
|
6
|
+
export const applyEvents = element => {
|
|
7
|
+
const { node, on } = element
|
|
8
|
+
for (const param in on) {
|
|
9
|
+
if (
|
|
10
|
+
param === 'init' ||
|
|
11
|
+
param === 'render' ||
|
|
12
|
+
param === 'update'
|
|
13
|
+
) continue
|
|
14
|
+
|
|
15
|
+
const appliedFunction = element.on[param]
|
|
16
|
+
if (isFunction(appliedFunction)) {
|
|
17
|
+
node.addEventListener(param, event =>
|
|
18
|
+
appliedFunction(event, element, element.state),
|
|
19
|
+
true)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const throughInitialExec = element => {
|
|
25
|
+
for (const param in element) {
|
|
26
|
+
const prop = element[param]
|
|
27
|
+
if (isFunction(prop) && !isMethod(param)) {
|
|
28
|
+
element.__exec[param] = prop
|
|
29
|
+
element[param] = prop(element, element.state)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const throughUpdatedExec = (element, options) => {
|
|
35
|
+
const { __exec } = element
|
|
36
|
+
const changes = {}
|
|
37
|
+
|
|
38
|
+
for (const param in __exec) {
|
|
39
|
+
const prop = element[param]
|
|
40
|
+
const newExec = __exec[param](element, element.state)
|
|
41
|
+
|
|
42
|
+
// if element is string
|
|
43
|
+
if (prop && prop.node && (isString(newExec) || isNumber(newExec))) {
|
|
44
|
+
overwrite(prop, { text: newExec }, options)
|
|
45
|
+
} else if (newExec !== prop) {
|
|
46
|
+
element.__cached[param] = changes[param] = prop
|
|
47
|
+
element[param] = newExec
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return changes
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const throughInitialDefine = element => {
|
|
55
|
+
const { define } = element
|
|
56
|
+
for (const param in define) {
|
|
57
|
+
let prop = element[param]
|
|
58
|
+
|
|
59
|
+
if (isFunction(prop) && !isMethod(param)) {
|
|
60
|
+
element.__exec[param] = prop
|
|
61
|
+
element[param] = prop = exec(prop, element)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
element.__cached[param] = prop
|
|
65
|
+
element[param] = define[param](prop, element, element.state)
|
|
66
|
+
}
|
|
67
|
+
return element
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const throughUpdatedDefine = element => {
|
|
71
|
+
const { define, __exec } = element
|
|
72
|
+
const changes = {}
|
|
73
|
+
for (const param in define) {
|
|
74
|
+
const execParam = __exec[param]
|
|
75
|
+
if (execParam) element.__cached[param] = execParam(element, element.state)
|
|
76
|
+
const cached = exec(element.__cached[param], element)
|
|
77
|
+
element[param] = define[param](cached, element, element.state)
|
|
78
|
+
}
|
|
79
|
+
return changes
|
|
80
|
+
}
|
package/src/methods.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { isObject, isObjectLike } from '@domql/utils'
|
|
4
|
+
import { registry } from '@domql/mixins'
|
|
5
|
+
|
|
6
|
+
// TODO: update these files
|
|
7
|
+
export const lookup = function (key) {
|
|
8
|
+
const element = this
|
|
9
|
+
let { parent } = element
|
|
10
|
+
|
|
11
|
+
while (parent.key !== key) {
|
|
12
|
+
parent = parent.parent
|
|
13
|
+
if (!parent) return
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return parent
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const remove = function (params) {
|
|
20
|
+
const element = this
|
|
21
|
+
element.node.remove()
|
|
22
|
+
delete element.parent[element.key]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const get = function (param) {
|
|
26
|
+
const element = this
|
|
27
|
+
return element[param]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const set = function () {
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const update = function () {
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const defineSetter = (element, key, get, set) =>
|
|
37
|
+
Object.defineProperty(element, key, { get, set })
|
|
38
|
+
|
|
39
|
+
export const keys = function () {
|
|
40
|
+
const element = this
|
|
41
|
+
const keys = []
|
|
42
|
+
for (const param in element) {
|
|
43
|
+
if (!isObject(registry[param])) {
|
|
44
|
+
keys.push(param)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return keys
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const parse = function () {
|
|
51
|
+
const element = this
|
|
52
|
+
const obj = {}
|
|
53
|
+
const keys = element.keys()
|
|
54
|
+
keys.forEach(v => (obj[v] = element[v]))
|
|
55
|
+
return obj
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const parseDeep = function (param) {
|
|
59
|
+
const element = this
|
|
60
|
+
const orig = param || element
|
|
61
|
+
const obj = {}
|
|
62
|
+
const keys = orig.keys && orig.keys()
|
|
63
|
+
if (!keys) return
|
|
64
|
+
keys.forEach(v => {
|
|
65
|
+
const prop = orig[v]
|
|
66
|
+
if (isObjectLike(prop)) parseDeep(prop)
|
|
67
|
+
else obj[v] = prop
|
|
68
|
+
})
|
|
69
|
+
return obj
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const log = function (...args) {
|
|
73
|
+
const element = this
|
|
74
|
+
console.group(element.key)
|
|
75
|
+
if (args.length) {
|
|
76
|
+
args.forEach(v => console.log(`%c${v}:\n`, 'font-weight: bold', element[v]))
|
|
77
|
+
} else {
|
|
78
|
+
console.log(element.path)
|
|
79
|
+
const keys = element.keys()
|
|
80
|
+
keys.forEach(v => console.log(`%c${v}:\n`, 'font-weight: bold', element[v]))
|
|
81
|
+
}
|
|
82
|
+
console.groupEnd(element.key)
|
|
83
|
+
return element
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export const isMethod = function (param) {
|
|
87
|
+
return param === 'set' ||
|
|
88
|
+
param === 'update' ||
|
|
89
|
+
param === 'remove' ||
|
|
90
|
+
param === 'lookup' ||
|
|
91
|
+
param === 'keys' ||
|
|
92
|
+
param === 'parse' ||
|
|
93
|
+
param === 'parseDeep' ||
|
|
94
|
+
param === 'if' ||
|
|
95
|
+
param === 'log'
|
|
96
|
+
}
|
package/src/set.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import create from './create'
|
|
4
|
+
|
|
5
|
+
const removeContentElement = (params, element) => {
|
|
6
|
+
if (params && element.content) {
|
|
7
|
+
if (element.content.node) {
|
|
8
|
+
if (element.content.tag === 'fragment') element.node.innerHTML = ''
|
|
9
|
+
else element.node.removeChild(element.content.node)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (element.__cached && element.__cached.content) {
|
|
13
|
+
if (element.__cached.content.tag === 'fragment') element.__cached.content.parent.node.innerHTML = ''
|
|
14
|
+
else element.__cached.content.remove()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
delete element.content
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const set = function (params, enter, leave) {
|
|
22
|
+
const element = this
|
|
23
|
+
|
|
24
|
+
removeContentElement(params, element)
|
|
25
|
+
|
|
26
|
+
if (params) {
|
|
27
|
+
const { childProto } = params
|
|
28
|
+
if (!childProto && element.childProto) params.childProto = element.childProto
|
|
29
|
+
create(params, element, 'content', {
|
|
30
|
+
ignoreChildProto: true
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return element
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default set
|
|
38
|
+
|
|
39
|
+
// if (element.content && (isFunction(element.content) || element.content.node)) {
|
|
40
|
+
// // leave(element, () => {
|
|
41
|
+
// // console.log('remove', element.content)
|
|
42
|
+
// // element.content.remove()
|
|
43
|
+
// // element.content.update(params)
|
|
44
|
+
// // element.node.removeChild(element.content.node)
|
|
45
|
+
// // delete element.content
|
|
46
|
+
// }
|
package/src/update.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { overwrite, isFunction, isObject, isString, isNumber, merge } from '@domql/utils'
|
|
4
|
+
import { registry } from '@domql/mixins'
|
|
5
|
+
import { updateProps } from '@domql/props'
|
|
6
|
+
import { createNode } from '@domql/node'
|
|
7
|
+
import * as on from '@domql/event/src/on'
|
|
8
|
+
|
|
9
|
+
import { isMethod } from './methods'
|
|
10
|
+
import { throughUpdatedDefine, throughUpdatedExec } from './iterate'
|
|
11
|
+
import { appendNode } from './assign'
|
|
12
|
+
|
|
13
|
+
const UPDATE_DEFAULT_OPTIONS = {
|
|
14
|
+
stackChanges: false,
|
|
15
|
+
cleanExec: true,
|
|
16
|
+
preventRecursive: false
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const update = function (params = {}, options = UPDATE_DEFAULT_OPTIONS) {
|
|
20
|
+
const element = this
|
|
21
|
+
const { define, parent, node } = element
|
|
22
|
+
|
|
23
|
+
// console.groupCollapsed('Update:', element.path)
|
|
24
|
+
// console.log('params:')
|
|
25
|
+
// console.log(params)
|
|
26
|
+
// console.log('props:')
|
|
27
|
+
// console.log(element.props)
|
|
28
|
+
// console.log('element:')
|
|
29
|
+
// console.log(element)
|
|
30
|
+
// console.log('PARAMS.PROPS:')
|
|
31
|
+
// console.log(params.props)
|
|
32
|
+
// console.groupEnd('Update:')
|
|
33
|
+
// if params is string
|
|
34
|
+
if (isString(params) || isNumber(params)) {
|
|
35
|
+
params = { text: params }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (element.on && isFunction(element.on.initUpdate)) {
|
|
39
|
+
on.initUpdate(element.on.initUpdate, element, element.state)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// console.log(element, parent)
|
|
43
|
+
updateProps(params.props, element, parent)
|
|
44
|
+
// // console.log(element.path)
|
|
45
|
+
// // console.log(element)
|
|
46
|
+
|
|
47
|
+
// console.groupCollapsed('UPDATE:')
|
|
48
|
+
// console.log(element)
|
|
49
|
+
// console.groupEnd('UPDATE:')
|
|
50
|
+
|
|
51
|
+
const overwriteChanges = overwrite(element, params, UPDATE_DEFAULT_OPTIONS)
|
|
52
|
+
const execChanges = throughUpdatedExec(element, UPDATE_DEFAULT_OPTIONS)
|
|
53
|
+
const definedChanges = throughUpdatedDefine(element)
|
|
54
|
+
|
|
55
|
+
if (UPDATE_DEFAULT_OPTIONS.stackChanges && element.__stackChanges) {
|
|
56
|
+
const stackChanges = merge(definedChanges, merge(execChanges, overwriteChanges))
|
|
57
|
+
element.__stackChanges.push(stackChanges)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (isFunction(element.if)) {
|
|
61
|
+
// TODO: move as fragment
|
|
62
|
+
const ifPassed = element.if(element, element.state)
|
|
63
|
+
if (element.__ifFalsy && ifPassed) {
|
|
64
|
+
createNode(element)
|
|
65
|
+
appendNode(element.node, element.__ifFragment)
|
|
66
|
+
delete element.__ifFalsy
|
|
67
|
+
} else if (element.node && !ifPassed) {
|
|
68
|
+
element.node.remove()
|
|
69
|
+
element.__ifFalsy = true
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// console.log(node)
|
|
74
|
+
// console.groupEnd('Update:')
|
|
75
|
+
|
|
76
|
+
if (!node || options.preventRecursive) return
|
|
77
|
+
|
|
78
|
+
for (const param in element) {
|
|
79
|
+
const prop = element[param]
|
|
80
|
+
|
|
81
|
+
if (isMethod(param) || isObject(registry[param]) || prop === undefined) continue
|
|
82
|
+
|
|
83
|
+
const hasDefined = define && define[param]
|
|
84
|
+
const ourParam = registry[param]
|
|
85
|
+
|
|
86
|
+
// // console.log(prop)
|
|
87
|
+
|
|
88
|
+
if (ourParam) {
|
|
89
|
+
if (isFunction(ourParam)) ourParam(prop, element, node)
|
|
90
|
+
} else if (prop && isObject(prop) && !hasDefined) {
|
|
91
|
+
update.call(prop, params[prop], UPDATE_DEFAULT_OPTIONS)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (element.on && isFunction(element.on.update)) {
|
|
96
|
+
on.update(element.on.update, element, element.state)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export default update
|