als-document 0.5.0 → 0.6.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/document/document.js +192 -0
- package/document/test.js +678 -0
- package/document.js +372 -142
- package/document.min.js +1 -0
- package/index.js +6 -0
- package/package.json +3 -3
- package/parser/parser.js +89 -40
- package/parser/test.js +7 -7
- package/query/query.js +1 -1
- package/query/readme.md +5 -2
- package/readme.md +242 -68
- package/selector/selector.js +14 -13
- package/selector/test.js +1 -1
- package/test/test.js +3 -1
- package/parser/readme.md +0 -121
- package/selector/readme.md +0 -74
package/document.js
CHANGED
|
@@ -1,3 +1,124 @@
|
|
|
1
|
+
class HtmlSelector {
|
|
2
|
+
constructor(html) {
|
|
3
|
+
if(typeof html == 'string') {
|
|
4
|
+
this.html = new HtmlParser(html)
|
|
5
|
+
this.elements.forEach((element,i) => {this.makeSelectable(element)});
|
|
6
|
+
} else console.log('Parameter is not string')
|
|
7
|
+
}
|
|
8
|
+
get elements() {return this.html.elements}
|
|
9
|
+
|
|
10
|
+
makeSelectable(element) {
|
|
11
|
+
if(element.type == 'tag' && element.status !== 'close') {
|
|
12
|
+
element.$$ = (query) => this.$$(query,element.index,element.endIndex)
|
|
13
|
+
element.$ = (query) => this.$(query,element.index,element.endIndex)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
$(query,start=0,end=this.elements.length) {
|
|
18
|
+
return this.$$(query,start,end,true)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
$$(query,start=0,end=this.elements.length,single=false) {
|
|
22
|
+
let result = []
|
|
23
|
+
this.selectors = new Query(query).selectors
|
|
24
|
+
this.query = query
|
|
25
|
+
this.selectors.forEach(selector => {
|
|
26
|
+
for(let i=start; i<end; i++) {
|
|
27
|
+
let el = this.elements[i]
|
|
28
|
+
if(this.checkElement(el,selector) && !result.includes(el)) result.push(el)
|
|
29
|
+
if(single && result.length == 1) break
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
if(single && result.length == 1) return result[0]
|
|
33
|
+
else if(single && result.length == 0) return null
|
|
34
|
+
else return result
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
checkElement(el,selector) {
|
|
38
|
+
if(selector == undefined) return true
|
|
39
|
+
if(el == null) return false
|
|
40
|
+
let {tag,classList,attribs,id,prev,ancestors,parents,prevAny} = selector
|
|
41
|
+
|
|
42
|
+
if(el.status == 'close' || el.type == 'text') return false
|
|
43
|
+
if(id !== undefined && el.id == undefined) return false
|
|
44
|
+
if(id && id !== el.id) return false
|
|
45
|
+
if(tag && el.tag == undefined) return false
|
|
46
|
+
else if(tag && tag !== el.tag) return false
|
|
47
|
+
if(classList !== undefined && el.classList == undefined) return false
|
|
48
|
+
else if(classList !== undefined && Array.isArray(el.classList)) {
|
|
49
|
+
if(classList.every(e => el.classList.includes(e)) == false) return false
|
|
50
|
+
}
|
|
51
|
+
if(this.checkAttribs(attribs,el) == false) return false
|
|
52
|
+
if(this.checkElement(el.prev,prev) == false) return false
|
|
53
|
+
if(this.checkAncestors(el.ancestors,ancestors) == false) return false
|
|
54
|
+
if(this.checkParents(el.ancestors,parents) == false) return false
|
|
55
|
+
if(el.parent) {
|
|
56
|
+
if(this.prevAny(el.parent.children,el.childIndex,prevAny) == false) return false
|
|
57
|
+
}
|
|
58
|
+
return true
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
prevAny(children=[],index,prevAny) {
|
|
62
|
+
let size = children.length
|
|
63
|
+
if((size == 0 || index == 0) && prevAny) return false
|
|
64
|
+
for(let i=index; i>=0; i--) {
|
|
65
|
+
if(this.checkElement(children[i],prevAny)) return true
|
|
66
|
+
}
|
|
67
|
+
return false
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
checkAncestors(ancestors=[],selectorAncestors=[]) {
|
|
71
|
+
let count = 0
|
|
72
|
+
if(selectorAncestors.length == 0) return true
|
|
73
|
+
let endIndex = ancestors.length-1
|
|
74
|
+
let selectorIndex = selectorAncestors.length-1
|
|
75
|
+
while(selectorIndex>=0) {
|
|
76
|
+
for(let i=endIndex; i>=0; i--) {
|
|
77
|
+
endIndex=i-1
|
|
78
|
+
if(this.checkElement(ancestors[i],selectorAncestors[selectorIndex]) == true) {
|
|
79
|
+
count++
|
|
80
|
+
break
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
selectorIndex--
|
|
84
|
+
}
|
|
85
|
+
if(count == selectorAncestors.length) return true
|
|
86
|
+
else return false
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
checkParents(ancestors=[],selectorParents=[]) {
|
|
90
|
+
if(selectorParents.length == 0) return true
|
|
91
|
+
if(ancestors.length < selectorParents.length) return false
|
|
92
|
+
let index = ancestors.length-1
|
|
93
|
+
for(let i=selectorParents.length-1; i>=0; i--) {
|
|
94
|
+
if(this.checkElement(ancestors[index],selectorParents[i]) == false) return false
|
|
95
|
+
index--
|
|
96
|
+
}
|
|
97
|
+
return true
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
checkAttribs(attribs=[],el) {
|
|
101
|
+
let elAttribs = el.attribs
|
|
102
|
+
let names = Object.keys(elAttribs)
|
|
103
|
+
let passedTests = 0
|
|
104
|
+
if(attribs) for(let i=0; i<attribs.length; i++) {
|
|
105
|
+
let {name,value,check} = attribs[i]
|
|
106
|
+
if(name == 'inner' && value !== undefined && check && el.innerText) {
|
|
107
|
+
if(check(el.innerText)) passedTests++
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if(!names.includes(name)) continue
|
|
111
|
+
else if(value == undefined) passedTests++
|
|
112
|
+
else if(value && elAttribs[name]) {
|
|
113
|
+
if(check(elAttribs[name]) == false) continue
|
|
114
|
+
else passedTests++
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if(passedTests == attribs.length) return true
|
|
118
|
+
else return false
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
1
122
|
class Query {
|
|
2
123
|
static get(query) {
|
|
3
124
|
let q = new Query(query)
|
|
@@ -144,7 +265,7 @@ class Query {
|
|
|
144
265
|
return selector
|
|
145
266
|
}
|
|
146
267
|
}
|
|
147
|
-
|
|
268
|
+
|
|
148
269
|
class HtmlParser {
|
|
149
270
|
static parse(html) {
|
|
150
271
|
let result = new HtmlParser(html)
|
|
@@ -155,14 +276,22 @@ class HtmlParser {
|
|
|
155
276
|
this.indexes = []
|
|
156
277
|
this.events = []
|
|
157
278
|
this.html = this.htmlString = html
|
|
279
|
+
this.htmlString = this.htmlString.replace(/\<\!\-\-([\S\s]*?)\-\-\>/gm,'') // remove all comments
|
|
158
280
|
this.removeScripts()
|
|
159
281
|
this.removeStyles()
|
|
160
282
|
this.removeEventStrings()
|
|
161
|
-
this.htmlString = this.htmlString.replace(/\<\!\-\-([\S\s]*?)\-\-\>/gm,'') // remove all comments
|
|
162
283
|
this.root = this.parse()
|
|
284
|
+
this.clean()
|
|
163
285
|
}
|
|
164
286
|
}
|
|
165
287
|
|
|
288
|
+
clean() {
|
|
289
|
+
let toDelete = ['events','indexes','scripts','styles','htmlString','html']
|
|
290
|
+
toDelete.forEach(name => {
|
|
291
|
+
delete this[name]
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
166
295
|
checkHtml(html,isGood=false) {
|
|
167
296
|
if(html == '') console.log('html parameter is empty')
|
|
168
297
|
else if(typeof html !== 'string') console.log(`html parameter has to be string. Recieved ${typeof html}`)
|
|
@@ -222,6 +351,9 @@ class HtmlParser {
|
|
|
222
351
|
}
|
|
223
352
|
this.elements = elements
|
|
224
353
|
let root = this.getPairs()
|
|
354
|
+
root.level = 0
|
|
355
|
+
root.elements = this.elements
|
|
356
|
+
this.innerHTML(root)
|
|
225
357
|
return root
|
|
226
358
|
}
|
|
227
359
|
|
|
@@ -252,19 +384,18 @@ class HtmlParser {
|
|
|
252
384
|
getPairs(parent={type:'root',children:[]},startIndex = 0,endIndex=this.elements.length,level=0,childIndex=0) {
|
|
253
385
|
for(let index = startIndex; index < endIndex; index++) {
|
|
254
386
|
if(this.indexes.includes(index)) continue
|
|
255
|
-
|
|
387
|
+
let element = this.elements[index];
|
|
256
388
|
let child
|
|
257
389
|
if(typeof element == 'string') child = element
|
|
258
390
|
else if(element.type == 'tag') {
|
|
259
391
|
if(element.status == 'single') {
|
|
260
392
|
child = element
|
|
261
393
|
child.parent = parent
|
|
262
|
-
}
|
|
263
|
-
else if(element.status == 'open') {
|
|
394
|
+
} else if(element.status == 'open') {
|
|
264
395
|
child = this.lookForPair(element,index,parent,level)
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
this.addChild(parent,child,index,level
|
|
396
|
+
} else element.index = index
|
|
397
|
+
}
|
|
398
|
+
this.addChild(parent,child,index,level)
|
|
268
399
|
childIndex++
|
|
269
400
|
}
|
|
270
401
|
return parent
|
|
@@ -289,30 +420,25 @@ class HtmlParser {
|
|
|
289
420
|
return child
|
|
290
421
|
}
|
|
291
422
|
|
|
292
|
-
addChild(parent,child,index,level
|
|
423
|
+
addChild(parent,child,index,level) {
|
|
293
424
|
if(typeof child == 'string') {
|
|
294
425
|
child = this.addScriptsAndStyles(parent,child,index)
|
|
295
|
-
child = {type:'text',text:child}
|
|
426
|
+
child = {type:'text',text:child,parent}
|
|
296
427
|
this.elements[index] = child
|
|
297
428
|
}
|
|
298
429
|
if(child) {
|
|
299
430
|
delete child.status
|
|
431
|
+
if(child.type !== 'text') {
|
|
432
|
+
this.innerHTML(child)
|
|
433
|
+
this.outerHTML(child)
|
|
434
|
+
this.innerText(child)
|
|
435
|
+
}
|
|
300
436
|
this.getElements(child)
|
|
301
|
-
this.innerHTML(child)
|
|
302
|
-
this.outerHTML(child)
|
|
303
|
-
this.innerText(child)
|
|
304
437
|
this.getAncestors(child)
|
|
305
438
|
this.getAttribute(child)
|
|
306
|
-
child
|
|
439
|
+
this.nextAndPrev(child)
|
|
307
440
|
child.index = index
|
|
308
441
|
child.level = level
|
|
309
|
-
child.prev = null
|
|
310
|
-
child.next = null
|
|
311
|
-
if(parent.children.length > 0) {
|
|
312
|
-
let prevI = parent.children.length-1
|
|
313
|
-
parent.children[prevI].next = child
|
|
314
|
-
child.prev = parent.children[prevI]
|
|
315
|
-
}
|
|
316
442
|
parent.children.push(child)
|
|
317
443
|
}
|
|
318
444
|
this.indexes.push(index)
|
|
@@ -337,10 +463,45 @@ class HtmlParser {
|
|
|
337
463
|
}});
|
|
338
464
|
}
|
|
339
465
|
|
|
340
|
-
|
|
341
|
-
Object.defineProperty(element, '
|
|
342
|
-
return
|
|
343
|
-
}
|
|
466
|
+
nextAndPrev(element) {
|
|
467
|
+
Object.defineProperty(element, 'childIndex', {
|
|
468
|
+
get() {return this.parent.children.map(o => o.index).indexOf(this.index)}
|
|
469
|
+
});
|
|
470
|
+
Object.defineProperty(element, 'prev', {
|
|
471
|
+
get() {
|
|
472
|
+
let i = this.childIndex, brothers = this.parent.children
|
|
473
|
+
return i == 0 ? null : brothers[i-1]
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
Object.defineProperty(element, 'next', {
|
|
477
|
+
get() {
|
|
478
|
+
let i = this.childIndex, brothers = this.parent.children
|
|
479
|
+
return i == brothers.length-1 ? null : brothers[i+1]
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
getElements(element,self=this) {
|
|
485
|
+
if(element.type !== 'text')
|
|
486
|
+
Object.defineProperty(element, 'elements', {
|
|
487
|
+
configurable:true,
|
|
488
|
+
get() {
|
|
489
|
+
let endIndex = isNaN(this.endIndex) ? this.index + 1 : this.endIndex+1
|
|
490
|
+
return self.elements.slice(this.index,endIndex)
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
Object.defineProperty(element, '$elements', {
|
|
494
|
+
configurable:true,
|
|
495
|
+
get() {return self.elements}
|
|
496
|
+
});
|
|
497
|
+
Object.defineProperty(element, 'root', {
|
|
498
|
+
configurable:true,
|
|
499
|
+
get() {return self.root}
|
|
500
|
+
});
|
|
501
|
+
Object.defineProperty(element, 'html', {
|
|
502
|
+
configurable:true,
|
|
503
|
+
get() {return self}
|
|
504
|
+
});
|
|
344
505
|
}
|
|
345
506
|
|
|
346
507
|
outerHTML(element) {
|
|
@@ -357,62 +518,71 @@ class HtmlParser {
|
|
|
357
518
|
else return ''
|
|
358
519
|
}})
|
|
359
520
|
}
|
|
360
|
-
|
|
361
521
|
innerHTML(element) {
|
|
522
|
+
element.tab = ' '
|
|
523
|
+
element.n = '\n'
|
|
362
524
|
Object.defineProperty(element, 'innerHTML', { get() {
|
|
363
|
-
let tab = ' ',result = '',firstLevel,space=''
|
|
525
|
+
// let tab = ' ',result = '',firstLevel,space=''
|
|
526
|
+
let {tab,n} = this
|
|
527
|
+
let result = '',firstLevel,space=''
|
|
364
528
|
let {elements} = this
|
|
365
529
|
let endIndex = elements.length
|
|
366
|
-
|
|
530
|
+
let end = endIndex-1,start=1
|
|
531
|
+
if(this.type == 'root') {
|
|
532
|
+
end = endIndex
|
|
533
|
+
start = 0
|
|
534
|
+
}
|
|
535
|
+
for(let i = start; i < end; i++) {
|
|
367
536
|
let element = elements[i]
|
|
368
|
-
let {level,
|
|
537
|
+
let {level,text} = element
|
|
369
538
|
if(firstLevel == undefined) firstLevel = level
|
|
370
|
-
if(i ==
|
|
539
|
+
if(i == end) space = ''
|
|
371
540
|
else if(level) space = Array.from(Array(level-firstLevel).keys()).map(n => tab).join('')
|
|
372
541
|
result += space + text
|
|
373
|
-
if(endIndex > 3) result +=
|
|
542
|
+
if(endIndex > 3) result += n
|
|
374
543
|
}
|
|
375
544
|
return result
|
|
376
545
|
}});
|
|
377
546
|
}
|
|
378
547
|
|
|
379
548
|
parseElement(tagString) {
|
|
380
|
-
let text = tagString
|
|
381
549
|
let type = 'tag'
|
|
382
|
-
if(tagString == '<!DOCTYPE html>') return {tag:'!DOCTYPE html',status:'single',attribs:{},type}
|
|
550
|
+
if(tagString == '<!DOCTYPE html>') return {tag:'!DOCTYPE html',status:'single',attribs:{},type,text:tagString}
|
|
383
551
|
let status = 'close'
|
|
384
552
|
let tag = tagString.match(/(?<=\<\/)(\w*\-?)*/)
|
|
385
553
|
if(tag == null) {
|
|
386
554
|
tag = tagString.match(/(?<=\<)(\w*\-?)*/)
|
|
387
555
|
if(tag) {
|
|
388
556
|
tag = tag[0]
|
|
389
|
-
if(
|
|
557
|
+
if(HtmlParser.singleTags.includes(tag)) status='single'
|
|
390
558
|
else status = 'open'
|
|
391
559
|
}
|
|
392
560
|
} else tag = tag[0]
|
|
393
|
-
let {classList,attribs,style,id} = this.parseAttributes(tagString)
|
|
561
|
+
let {classList,attribs,style,id,text} = this.parseAttributes(tagString)
|
|
394
562
|
let obj = {tag,status,attribs,type,classList,text,style,id}
|
|
395
563
|
return obj
|
|
396
564
|
}
|
|
397
|
-
singleTags = ['comment','area','base','br','col','command','embed','hr','img','input','keygen','link','meta','param','source','track','wbr']
|
|
565
|
+
static singleTags = ['comment','area','base','br','col','command','embed','hr','img','input','keygen','link','meta','param','source','track','wbr']
|
|
398
566
|
|
|
399
567
|
parseAttributes(tagString,classList=[],attribs={},style={},id=null) {
|
|
568
|
+
let text = tagString
|
|
400
569
|
let attributes = tagString.match(/(?<=\s)(\w*\-?)*(\s*?\=\s*?\"[\s\S]*?\")?/g)
|
|
401
570
|
if(attributes) attributes.forEach(attribString => {
|
|
402
571
|
let [name,value] = attribString.split('=')
|
|
403
572
|
if(value !== undefined && name !== '') {
|
|
404
573
|
value = value.trim().replace(/^\"/,'').replace(/\"$/m,'')
|
|
405
|
-
|
|
406
574
|
let eventIndex = value.match(/(?<=\{\{\{\{event\s)(\d*)?/)
|
|
407
|
-
if(eventIndex !== null)
|
|
408
|
-
|
|
575
|
+
if(eventIndex !== null) {
|
|
576
|
+
value = this.events[eventIndex[0]]
|
|
577
|
+
text = tagString.replace(`{{{{event ${eventIndex[0]}`,value)
|
|
578
|
+
}
|
|
409
579
|
if(name == 'class') classList = value.split(/\s\s?\s?/)
|
|
410
580
|
else if(name == 'style') style = this.parseInlineCss(value)
|
|
411
581
|
else if(name == 'id') id = value
|
|
412
582
|
attribs[name] = value
|
|
413
583
|
} else if(name !== '') attribs[name] = undefined
|
|
414
584
|
});
|
|
415
|
-
return {classList,attribs,style,id}
|
|
585
|
+
return {classList,attribs,style,id,text}
|
|
416
586
|
}
|
|
417
587
|
|
|
418
588
|
parseInlineCss(textCss) {
|
|
@@ -432,131 +602,191 @@ class HtmlParser {
|
|
|
432
602
|
}
|
|
433
603
|
}
|
|
434
604
|
|
|
435
|
-
|
|
436
|
-
class HtmlSelector {
|
|
605
|
+
class Document extends HtmlSelector {
|
|
437
606
|
constructor(html) {
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
this.html = html
|
|
441
|
-
this.elements = html.elements
|
|
442
|
-
this.makeSelectable()
|
|
443
|
-
} else console.log('Parameter is not string')
|
|
607
|
+
super(html)
|
|
608
|
+
this.elements.forEach((element) => {this.addMethods(element)});
|
|
444
609
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
610
|
+
|
|
611
|
+
addMethods(element) {
|
|
612
|
+
if(element.type == 'tag' && element.status !== 'close') {
|
|
613
|
+
this.insert(element)
|
|
614
|
+
this.buildAttribs(element)
|
|
615
|
+
this.classlistMethods(element)
|
|
616
|
+
this.style(element)
|
|
617
|
+
this.id(element)
|
|
618
|
+
}
|
|
453
619
|
}
|
|
454
620
|
|
|
455
|
-
|
|
456
|
-
|
|
621
|
+
id(element,self=this) {
|
|
622
|
+
if(element.id !== undefined)
|
|
623
|
+
if(!!Object.getOwnPropertyDescriptor(element, 'id')['get']) return
|
|
624
|
+
if(element.id == null || element.id !== undefined) {
|
|
625
|
+
if(typeof element.id == 'string') delete element.id
|
|
626
|
+
Object.defineProperty(element, 'id', {
|
|
627
|
+
get() {return this.attribs.id ? this.attribs.id : null},
|
|
628
|
+
set(value) {
|
|
629
|
+
this.attribs.id = value
|
|
630
|
+
self.changeElementText(this)
|
|
631
|
+
}
|
|
632
|
+
})
|
|
633
|
+
}
|
|
457
634
|
}
|
|
458
635
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
636
|
+
style(element,obj={},self=this) {
|
|
637
|
+
if(element.style !== undefined) obj = {...element.style}
|
|
638
|
+
const convertProp = str => str.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`);
|
|
639
|
+
const handler = {
|
|
640
|
+
get(target,prop,receiver) {
|
|
641
|
+
if(prop === 'target') return target
|
|
642
|
+
return Reflect.get(...arguments);
|
|
643
|
+
},
|
|
644
|
+
set(obj, prop, value) {
|
|
645
|
+
obj[prop] = value
|
|
646
|
+
element.attribs.style = Object.keys(obj).map(key => `${convertProp(key)}:${obj[key]};`).join('')
|
|
647
|
+
self.changeElementText(this)
|
|
648
|
+
},
|
|
649
|
+
deleteProperty(obj, prop) {
|
|
650
|
+
if (prop in obj) {
|
|
651
|
+
delete obj[prop];
|
|
652
|
+
element.attribs.style = Object.keys(obj).map(key => `${convertProp(key)}:${obj[key]};`).join('')
|
|
653
|
+
}
|
|
654
|
+
self.changeElementText(this)
|
|
468
655
|
}
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
else if(single && result.length == 0) return null
|
|
472
|
-
else return result
|
|
656
|
+
};
|
|
657
|
+
element.style = new Proxy(obj, handler);
|
|
473
658
|
}
|
|
474
659
|
|
|
475
|
-
|
|
476
|
-
if(
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
if(id && id !== el.id) return false
|
|
483
|
-
if(tag && el.tag == undefined) return false
|
|
484
|
-
else if(tag && tag !== el.tag) return false
|
|
485
|
-
if(classList !== undefined && el.classList == undefined) return false
|
|
486
|
-
else if(classList !== undefined && Array.isArray(el.classList)) {
|
|
487
|
-
if(classList.every(e => el.classList.includes(e)) == false) return false
|
|
660
|
+
classlistMethods(element,self=this) {
|
|
661
|
+
if(element.classList == undefined) element.classList = []
|
|
662
|
+
element.classList.add = function(newClass) {
|
|
663
|
+
if(element.attribs.class == undefined) element.attribs.class = ''
|
|
664
|
+
this.push(newClass)
|
|
665
|
+
element.attribs.class += ' '+newClass
|
|
666
|
+
self.changeElementText(this)
|
|
488
667
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
if(el.parent) {
|
|
494
|
-
if(this.prevAny(el.parent.children,el.childIndex,prevAny) == false) return false
|
|
668
|
+
element.classList.remove = function(clsToRemove) {
|
|
669
|
+
this.splice(this.indexOf(clsToRemove),1)
|
|
670
|
+
element.attribs.class = this.filter(c => c !== undefined).join(' ')
|
|
671
|
+
self.changeElementText(this)
|
|
495
672
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
let size = children.length
|
|
501
|
-
if((size == 0 || index == 0) && prevAny) return false
|
|
502
|
-
for(let i=index; i>=0; i--) {
|
|
503
|
-
if(this.checkElement(children[i],prevAny)) return true
|
|
673
|
+
element.classList.toggle = function(clsToToggle) {
|
|
674
|
+
if(this.includes(clsToToggle)) this.remove(clsToToggle)
|
|
675
|
+
else this.add(clsToToggle)
|
|
676
|
+
self.changeElementText(this)
|
|
504
677
|
}
|
|
505
|
-
return false
|
|
506
678
|
}
|
|
507
679
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
680
|
+
buildAttribs(element,self=this) {
|
|
681
|
+
if(!element.attr) element.attr = function(name,value) {
|
|
682
|
+
let notForRemove = ['class','style','id']
|
|
683
|
+
let notForChange = ['style','id']
|
|
684
|
+
if(name && value === undefined) return this.attribs[name]
|
|
685
|
+
else if(name && value === null && !notForRemove.includes(name)) {
|
|
686
|
+
delete this.attribs[name]
|
|
687
|
+
} else if(name && value !== undefined && value !== null && !notForChange.includes(name)) {
|
|
688
|
+
this.attribs[name] = value
|
|
689
|
+
if(name == 'class') {
|
|
690
|
+
this.classList = value.split(' ').filter(c => c !== ' ')
|
|
691
|
+
self.classlistMethods(this)
|
|
519
692
|
}
|
|
520
693
|
}
|
|
521
|
-
|
|
694
|
+
self.changeElementText(this)
|
|
522
695
|
}
|
|
523
|
-
if(count == selectorAncestors.length) return true
|
|
524
|
-
else return false
|
|
525
696
|
}
|
|
526
697
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
if(
|
|
533
|
-
|
|
698
|
+
insert(element) {
|
|
699
|
+
let self = this
|
|
700
|
+
element.insert = function(newElement,pos=0) {
|
|
701
|
+
let elements
|
|
702
|
+
let $elements = this.$elements
|
|
703
|
+
if(typeof newElement == 'string') {
|
|
704
|
+
newElement = new HtmlParser(newElement)
|
|
705
|
+
newElement.elements.forEach(el => {
|
|
706
|
+
self.html.getElements(el)
|
|
707
|
+
self.makeSelectable(el);
|
|
708
|
+
self.addMethods(el);
|
|
709
|
+
});
|
|
710
|
+
elements = newElement.elements
|
|
711
|
+
newElement = newElement.root.children[0]
|
|
712
|
+
} else {
|
|
713
|
+
let {index,endIndex} = newElement
|
|
714
|
+
let count = isNaN(endIndex - index) ? 1 : endIndex - index+1
|
|
715
|
+
elements = $elements.splice(index,count)
|
|
716
|
+
let {parent,childIndex} = newElement
|
|
717
|
+
parent.children.splice(childIndex,1)
|
|
718
|
+
}
|
|
719
|
+
self.rebildElements($elements)
|
|
720
|
+
self.addElement(this,$elements,newElement,elements,pos)
|
|
534
721
|
}
|
|
535
|
-
|
|
722
|
+
element.remove = function() {
|
|
723
|
+
let {$elements,elements,parent,childIndex,index} = this
|
|
724
|
+
$elements.splice(index,elements.length)
|
|
725
|
+
parent.children.splice(childIndex,1)
|
|
726
|
+
parent.endIndex = parent.endIndex-elements.length
|
|
727
|
+
self.rebildElements($elements)
|
|
728
|
+
}
|
|
729
|
+
Object.defineProperty(element, 'before', { set(newEl) {this.insert(newEl,0)}})
|
|
730
|
+
Object.defineProperty(element, 'after', { set(newEl) {this.insert(newEl,3)}})
|
|
731
|
+
Object.defineProperty(element, 'last', { set(newEl) {this.insert(newEl,2)}})
|
|
732
|
+
Object.defineProperty(element, 'first', { set(newEl) {this.insert(newEl,1)}})
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
addElement(element,$elements,newElement,elements,pos) {
|
|
736
|
+
let {parent,level,index,endIndex} = element
|
|
737
|
+
if(pos == 0) { // beforebegin
|
|
738
|
+
$elements.splice(index,0,...elements) // add elements to $elements
|
|
739
|
+
parent.children.splice(element.childIndex,0,newElement) // add as child before
|
|
740
|
+
} else if(pos == 3) { // afterend
|
|
741
|
+
$elements.splice(endIndex+1,0,...elements) // add elements to $elements
|
|
742
|
+
parent.children.splice(element.childIndex+1,0,newElement) // add element as child after
|
|
743
|
+
} else if(pos == 1 || pos == 2) {
|
|
744
|
+
level = level+1
|
|
745
|
+
parent = element
|
|
746
|
+
if(pos == 1) { // afterbegin
|
|
747
|
+
$elements.splice(index+1,0,...elements) // add elements to $elements
|
|
748
|
+
element.children.unshift(newElement) // add element as first child
|
|
749
|
+
} else if(pos == 2) { // beforeend
|
|
750
|
+
$elements.splice(endIndex-1,0,...elements) // add elements to $elements
|
|
751
|
+
element.children.push(newElement) // add element as last child
|
|
752
|
+
}
|
|
753
|
+
element.endIndex = element.endIndex + elements.length
|
|
754
|
+
}
|
|
755
|
+
this.rebildElements($elements)
|
|
756
|
+
this.rebuildChild(elements[0],parent,element.html,level)
|
|
536
757
|
}
|
|
537
758
|
|
|
538
|
-
|
|
539
|
-
let
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
if(name == 'inner' && value !== undefined && check && el.innerText) {
|
|
545
|
-
if(check(el.innerText)) passedTests++
|
|
759
|
+
rebildElements($elements) {
|
|
760
|
+
for(let i=0; i<$elements.length; i++) {
|
|
761
|
+
let {endIndex,index} = $elements[i]
|
|
762
|
+
if(endIndex) {
|
|
763
|
+
let gap = endIndex - index
|
|
764
|
+
$elements[i].endIndex = i + gap
|
|
546
765
|
}
|
|
547
|
-
|
|
548
|
-
if(!names.includes(name)) continue
|
|
549
|
-
else if(value == undefined) passedTests++
|
|
550
|
-
else if(value && elAttribs[name]) {
|
|
551
|
-
if(check(elAttribs[name]) == false) continue
|
|
552
|
-
else passedTests++
|
|
553
|
-
}
|
|
766
|
+
$elements[i].index = i
|
|
554
767
|
}
|
|
555
|
-
if(passedTests == attribs.length) return true
|
|
556
|
-
else return false
|
|
557
768
|
}
|
|
558
|
-
}
|
|
559
769
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
770
|
+
rebuildChild(child,parent,html,level) {
|
|
771
|
+
if(child.endIndex !== undefined) { // add level to close tag
|
|
772
|
+
child.elements[child.elements.length-1].level = level
|
|
773
|
+
}
|
|
774
|
+
html.getElements(child,html) // bind element to this.$elements
|
|
775
|
+
child.parent = parent
|
|
776
|
+
child.level = level
|
|
777
|
+
if(child.children)
|
|
778
|
+
if(child.children.length > 0)
|
|
779
|
+
child.children.forEach(grandChild => {
|
|
780
|
+
this.rebuildChild(grandChild,child,html,level+1)
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
changeElementText(element) {
|
|
785
|
+
let {type,status,attribs,tag} = element
|
|
786
|
+
if(type == 'tag' && status !== 'close') {
|
|
787
|
+
let atts = Object.keys(attribs)
|
|
788
|
+
atts = atts.length>0 ? ' '+atts.map(name => `${name}${attribs[name] ? `="${attribs[name]}"`: ''}`).join(' ') : ''
|
|
789
|
+
element.text = `<${tag}${atts}>`
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
}
|