UNPKG

2.73 kBJavaScriptView Raw
1var ElementType = require("./ElementType.js");
2
3function DomHandler(callback, options){
4 this.dom = [];
5 this._done = false;
6 this._tagStack = [];
7 if(typeof callback === "object") this._options = callback;
8 else {
9 if(options) this._options = options; //otherwise, the prototype is used
10 if(callback) this._callback = callback;
11 }
12}
13
14//default options
15DomHandler.prototype._options = {
16 ignoreWhitespace: false //Keep whitespace-only text nodes
17};
18
19//Resets the handler back to starting state
20DomHandler.prototype.onreset = DomHandler;
21
22//Signals the handler that parsing is done
23DomHandler.prototype.onend = function(){
24 if(this._done) return;
25 this._done = true;
26 this._handleCallback(null);
27};
28
29DomHandler.prototype._handleCallback =
30DomHandler.prototype.onerror = function(error){
31 if(typeof this._callback === "function"){
32 this._callback(error, this.dom);
33 } else {
34 if(error) throw error;
35 }
36};
37
38DomHandler.prototype.onclosetag = function(name){
39 if(this._tagStack.pop().name !== name) this._handleCallback(Error("tagname didn't match!"));
40};
41
42DomHandler.prototype._addDomElement = function(element){
43 var lastChild,
44 lastTag = this._tagStack[this._tagStack.length - 1];
45
46 if(lastTag){ //There are parent elements
47 if(!lastTag.children){
48 lastTag.children = [element];
49 return;
50 }
51 lastChild = lastTag.children[lastTag.children.length - 1];
52 if(element.type === ElementType.Text && lastChild.type === ElementType.Text){
53 lastChild.data += element.data;
54 } else {
55 lastTag.children.push(element);
56 }
57 }
58 else {
59 this.dom.push(element);
60 }
61};
62
63DomHandler.prototype.onopentag = function(name, attribs, type){
64 var element = {
65 type: type,
66 name: name
67 };
68 //for some reason, an if doesn't work
69 for(var i in attribs){
70 element.attribs = attribs;
71 break;
72 }
73 this._addDomElement(element);
74 this._tagStack.push(element);
75};
76
77DomHandler.prototype.ontext = function(data){
78 if(this._options.ignoreWhitespace && data.trim() === "") return;
79 this._addDomElement({
80 data: data,
81 type: ElementType.Text
82 });
83};
84
85DomHandler.prototype.oncomment = function(data){
86 var lastTag = this._tagStack[this._tagStack.length - 1];
87
88 if(lastTag && lastTag.type === ElementType.Comment){
89 lastTag.data += data;
90 return;
91 }
92
93 var element = {
94 data: data,
95 type: ElementType.Comment
96 };
97
98 if(!lastTag) this.dom.push(element);
99 else if(!lastTag.children) lastTag.children = [element];
100 else lastTag.children.push(element);
101
102 this._tagStack.push(element);
103};
104
105DomHandler.prototype.oncommentend = function(){
106 this._tagStack.pop();
107};
108
109DomHandler.prototype.onprocessinginstruction = function(name, data){
110 this._addDomElement({
111 name: name,
112 data: data,
113 type: ElementType.Directive
114 });
115};
116
117module.exports = DomHandler;
\No newline at end of file