UNPKG

4.91 kBJavaScriptView Raw
1var ElementType = require("./ElementType.js"),
2 arrayPush = Array.prototype.push,
3 DomUtils = module.exports;
4
5function filterArray(test, arr, recurse, limit){
6 var result = [], childs;
7
8 for(var i = 0, j = arr.length; i < j; i++){
9 if(test(arr[i])){
10 result.push(arr[i]);
11 if(--limit <= 0) break;
12 }
13
14 childs = arr[i].children;
15 if(recurse && childs){
16 childs = filterArray(test, childs, recurse, limit);
17 arrayPush.apply(result, childs);
18 limit -= childs.length;
19 if(limit <= 0) break;
20 }
21 }
22
23 return result;
24}
25
26function filter(test, element, recurse, limit){
27 if(recurse !== false) recurse = true;
28 if(isNaN(limit)) limit = Infinity;
29 if(!Array.isArray(element)) element = [element];
30
31 return filterArray(test, element, recurse, limit);
32}
33
34DomUtils.testElement = function(options, element){
35 var type = element.type,
36 keys = Object.keys(options),
37 len = keys.length;
38
39 for(var i = 0; i < len; i++){
40 var key = keys[i];
41
42 switch(key){
43 case "tag_name":
44 if(type !== ElementType.Tag && type !== ElementType.Script && type !== ElementType.Style) return false;
45 if(!options.tag_name(element.name)) return false;
46 break;
47 case "tag_type":
48 if(!options.tag_type(type)) return false;
49 break;
50 case "tag_contains":
51 if(type !== ElementType.Text && type !== ElementType.Comment && type !== ElementType.Directive) return false;
52 if(!options.tag_contains(element.data)) return false;
53 break;
54 default:
55 if(!element.attribs || !options[key](element.attribs[key])) return false;
56 break;
57 }
58 }
59
60 return true;
61}
62
63DomUtils.getElements = function(options, element, recurse, limit){
64 var keys = Object.keys(options),
65 len = keys.length;
66
67 for(var i = 0; i < len; i++){
68 var key = keys[i];
69
70 if(typeof options[key] !== "function"){
71 var checker = options[key];
72 options[key] = function(val){ return val === checker };
73 }
74 }
75
76 return filter(this.testElement.bind(null, options), element, recurse, limit);
77}
78
79DomUtils.getElementById = function(id, element, recurse){
80 var result;
81
82 if(typeof id === "function"){
83 result = filter(function(elem){ return elem.attribs && id(elem.attribs) }, element, recurse, 1);
84 }else{
85 result = filter(function(elem){ return elem.attribs && elem.attribs.id === id }, element, recurse, 1);
86 }
87
88 return result.length ? result[0] : null;
89}
90
91DomUtils.getElementsByTagName = function(name, element, recurse, limit){
92 if(typeof name === "function") return filter(function(elem){
93 var type = elem.type;
94 if(type !== ElementType.Tag && type !== ElementType.Script && type !== ElementType.Style)
95 return false;
96 return name(elem.name);
97 }, element, recurse, limit);
98
99 return filter(function(elem){
100 var type = elem.type;
101 if(type !== ElementType.Tag && type !== ElementType.Script && type !== ElementType.Style)
102 return false;
103 return elem.name === name;
104 }, element, recurse, limit);
105}
106
107DomUtils.getElementsByTagType = function(type, element, recurse, limit){
108 if(typeof type === "function")
109 return filter(function(elem){ return type(elem.type) }, element, recurse, limit);
110 else
111 return filter(function(elem){ return elem.type === type }, element, recurse, limit);
112}
113
114DomUtils.getInnerHTML = function(elem){
115 if(!elem.children) return "";
116
117 var childs = elem.children,
118 childNum = childs.length,
119 ret = "";
120
121 for(var i = 0; i < childNum; i++){
122 ret += this.getOuterHTML(childs[i]);
123 }
124
125 return ret;
126}
127
128DomUtils.getOuterHTML = function(elem){
129 var type = elem.type,
130 name = elem.name;
131
132 if(type === ElementType.Text) return elem.data;
133 if(type === ElementType.Comment) return "<!--" + elem.data + "-->";
134
135 var attrStr = "";
136 if(elem.attribs){
137 var attrs = Object.keys(elem.attribs),
138 len = attrs.length;
139
140 for(var i = 0; i < len; i++){
141 var attr = attrs[i],
142 val = elem.attribs[attr];
143
144 attrStr += " " + attr + "=\"" + val + "\"";
145
146 /* Is this required? Method forgets quotes
147 if(/^[^\s"\'\`\=\<\>]+$/.test(val))
148 attrStr += val;
149 else if(val.indeOf("\"") !== -1)
150 attrStr += "'" + val + "'";
151 else
152 attrStr += "\"" + val + "\"";
153 */
154 }
155 }
156
157 var ret = "<" + name + attrStr + ">";
158
159 if(type === ElementType.Directive) return ret;
160
161 ret += this.getInnerHTML(elem) + "</" + name + ">"
162 return ret;
163}