webr 0.0.5
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.
- data/README.md +4 -0
- data/Rakefile +19 -0
- data/app/webr.rb +57 -0
- data/bin/webr +6 -0
- data/ext/jasmine/lib/jasmine.js +2423 -0
- data/ext/jsdom/lib/jsdom.js +70 -0
- data/ext/jsdom/lib/jsdom/browser/domtohtml.js +198 -0
- data/ext/jsdom/lib/jsdom/browser/htmlencoding.js +381 -0
- data/ext/jsdom/lib/jsdom/browser/htmltodom.js +151 -0
- data/ext/jsdom/lib/jsdom/browser/index.js +484 -0
- data/ext/jsdom/lib/jsdom/level1/core.js +1610 -0
- data/ext/jsdom/lib/jsdom/level2/core.js +406 -0
- data/ext/jsdom/lib/jsdom/level2/events.js +358 -0
- data/ext/jsdom/lib/jsdom/level2/html.js +1424 -0
- data/ext/jsdom/lib/jsdom/level2/index.js +7 -0
- data/ext/jsdom/lib/jsdom/level2/languages/javascript.js +17 -0
- data/ext/jsdom/lib/jsdom/level3/core.js +514 -0
- data/ext/jsdom/lib/jsdom/level3/events.js +296 -0
- data/ext/jsdom/lib/jsdom/level3/html.js +5 -0
- data/ext/jsdom/lib/jsdom/level3/index.js +7 -0
- data/ext/node-htmlparser/lib/node-htmlparser.js +769 -0
- data/ext/node-htmlparser/lib/node-htmlparser.min.js +22 -0
- data/ext/request/request.js +116 -0
- data/js/jasmine-start.js +10 -0
- data/js/webr.js +97 -0
- data/jspec/jasmine_spec.js +23 -0
- data/lib/webr.rb +17 -0
- data/lib/webr/browser.rb +44 -0
- data/lib/webr/jasmine.rb +6 -0
- data/lib/webr/jasmine/browser.rb +15 -0
- data/lib/webr/jasmine/reporter.rb +16 -0
- data/lib/webr/jasmine/reporter/base.rb +40 -0
- data/lib/webr/jasmine/reporter/console.rb +79 -0
- data/lib/webr/jasmine/reporter/html.rb +179 -0
- data/lib/webr/portal.rb +19 -0
- data/lib/webr/runtime.rb +23 -0
- data/lib/webr/version.rb +3 -0
- data/spec/data/plain.html +13 -0
- data/spec/data/script-embedded.html +17 -0
- data/spec/data/script-external-onload.html +11 -0
- data/spec/data/script-external-onload.js +11 -0
- data/spec/data/script-external.html +11 -0
- data/spec/data/script-external.js +1 -0
- data/spec/data/script-jquery-1.4.2.html +12 -0
- data/spec/data/script-jquery-1.4.3.html +12 -0
- data/spec/data/script-jquery.js +3 -0
- data/spec/lib/webr/browser_spec.rb +133 -0
- data/spec/lib/webr/jasmine/browser_spec.rb +22 -0
- data/spec/lib/webr/jasmine/reporter/html_spec.rb +15 -0
- data/spec/spec_helper.rb +4 -0
- data/tasks/spec.rake +16 -0
- data/webr.gemspec +30 -0
- metadata +207 -0
@@ -0,0 +1,151 @@
|
|
1
|
+
var HTMLDecode = require('./htmlencoding').HTMLDecode;
|
2
|
+
|
3
|
+
var HtmlToDom = function(parser){
|
4
|
+
|
5
|
+
if(parser && parser.write) {
|
6
|
+
// sax parser
|
7
|
+
this.appendHtmlToElement = function(html, element){
|
8
|
+
|
9
|
+
var currentElement = element, currentLevel = 0;
|
10
|
+
|
11
|
+
parser.onerror = function (e) {};
|
12
|
+
|
13
|
+
parser.ontext = function (t) {
|
14
|
+
var ownerDocument = currentElement.ownerDocument || currentElement;
|
15
|
+
var newText = ownerDocument.createTextNode(t);
|
16
|
+
currentElement.appendChild(newText);
|
17
|
+
};
|
18
|
+
|
19
|
+
parser.onopentag = function (node) {
|
20
|
+
var nodeName = node.name.toLowerCase(),
|
21
|
+
document = currentElement.ownerDocument || currentElement,
|
22
|
+
newElement = document.createElement(nodeName),
|
23
|
+
i = 0,
|
24
|
+
length = (node.attributes && node.attributes.length) ?
|
25
|
+
node.attributes.length :
|
26
|
+
0;
|
27
|
+
|
28
|
+
for (i in node.attributes)
|
29
|
+
{
|
30
|
+
if (node.attributes.hasOwnProperty(i)) {
|
31
|
+
newElement.setAttribute(i, node.attributes[i]);
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
for (var i=0; i<node.attributes.length; i++) {
|
36
|
+
newElement.setAttribute(i, node.attributes.item(i));
|
37
|
+
}
|
38
|
+
currentElement.appendChild(newElement);
|
39
|
+
currentElement = newElement;
|
40
|
+
};
|
41
|
+
|
42
|
+
parser.onclosetag = function(node) {
|
43
|
+
currentElement = currentElement.parentNode;
|
44
|
+
}
|
45
|
+
|
46
|
+
parser.write(html).close();
|
47
|
+
|
48
|
+
return element;
|
49
|
+
}
|
50
|
+
|
51
|
+
} else if(parser && (parser.ParseHtml || parser.DefaultHandler)) {
|
52
|
+
|
53
|
+
// Forgiving HTML parser
|
54
|
+
|
55
|
+
if(parser.ParseHtml){
|
56
|
+
// davglass/node-htmlparser
|
57
|
+
} else if(parser.DefaultHandler){
|
58
|
+
// tautologistics/node-htmlparser
|
59
|
+
parser.ParseHtml = function(rawHtml){
|
60
|
+
var handler = new this.DefaultHandler();
|
61
|
+
var parser = new this.Parser(handler);
|
62
|
+
parser.parseComplete(rawHtml);
|
63
|
+
return handler.dom;
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
this.appendHtmlToElement = function(html, element){
|
68
|
+
|
69
|
+
if (typeof html !== 'string') {
|
70
|
+
html +='';
|
71
|
+
}
|
72
|
+
|
73
|
+
var parsed = parser.ParseHtml(html);
|
74
|
+
|
75
|
+
for (var i = 0; i < parsed.length; i++) {
|
76
|
+
setChild.call(element, parsed[i]);
|
77
|
+
}
|
78
|
+
|
79
|
+
return element;
|
80
|
+
|
81
|
+
}
|
82
|
+
|
83
|
+
} else if(parser && parser.moduleName == 'HTML5') { /* HTML5 parser */
|
84
|
+
this.appendHtmlToElement = function(html, element) {
|
85
|
+
if(typeof html !== 'string') html += '';
|
86
|
+
var p = new parser.Parser({document: element.ownerDocument});
|
87
|
+
p.parse_fragment(html, element);
|
88
|
+
element.appendChild(p.fragment);
|
89
|
+
}
|
90
|
+
} else {
|
91
|
+
|
92
|
+
this.appendHtmlToElement = function(){
|
93
|
+
var sys = require('sys');
|
94
|
+
sys.puts('');
|
95
|
+
sys.puts('###########################################################');
|
96
|
+
sys.puts('# WARNING: No HTML parser could be found.');
|
97
|
+
sys.puts('# Element.innerHTML setter support has been disabled');
|
98
|
+
sys.puts('# Element.innerHTML getter support will still function');
|
99
|
+
sys.puts('# Download: http://github.com/tautologistics/node-htmlparser');
|
100
|
+
sys.puts('###########################################################');
|
101
|
+
sys.puts('');
|
102
|
+
|
103
|
+
}
|
104
|
+
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
// utility function for forgiving parser
|
109
|
+
var setChild = function(node) {
|
110
|
+
|
111
|
+
var newNode, currentDocument = this._ownerDocument || this;
|
112
|
+
|
113
|
+
if (node.type == 'tag' || node.type == 'script' || node.type == 'style') {
|
114
|
+
try{
|
115
|
+
newNode = currentDocument.createElement(node.name);
|
116
|
+
}catch (err) {
|
117
|
+
//console.log("raw: "+node.raw);
|
118
|
+
}
|
119
|
+
}
|
120
|
+
if (node.type == 'text') {
|
121
|
+
newNode = currentDocument.createTextNode(HTMLDecode(node.data));
|
122
|
+
}
|
123
|
+
if (node.type == 'comment') {
|
124
|
+
newNode = currentDocument.createComment(node.data);
|
125
|
+
}
|
126
|
+
if (node.attribs && newNode) {
|
127
|
+
for (var c in node.attribs) {
|
128
|
+
// catchin errors here helps with improperly escaped attributes
|
129
|
+
// but properly fixing this should (can only?) be done in the htmlparser itself
|
130
|
+
try{
|
131
|
+
newNode.setAttribute(c.toLowerCase(), HTMLDecode(node.attribs[c]));
|
132
|
+
}catch(err) {
|
133
|
+
//console.log("raw: "+node.raw);
|
134
|
+
//console.log(node.attribs);
|
135
|
+
//console.log("offender: "+node.attribs[c]);
|
136
|
+
}
|
137
|
+
}
|
138
|
+
}
|
139
|
+
if (node.children && newNode) {
|
140
|
+
for (var c = 0; c < node.children.length; c++) {
|
141
|
+
setChild.call(newNode, node.children[c]);
|
142
|
+
}
|
143
|
+
}
|
144
|
+
if (newNode) {
|
145
|
+
return this.appendChild(newNode);
|
146
|
+
} else {
|
147
|
+
return null;
|
148
|
+
}
|
149
|
+
};
|
150
|
+
|
151
|
+
exports.HtmlToDom = HtmlToDom;
|
@@ -0,0 +1,484 @@
|
|
1
|
+
var sys = require('sys'),
|
2
|
+
http = require('http'),
|
3
|
+
url = require('url'),
|
4
|
+
HtmlToDom = require('./htmltodom').HtmlToDom,
|
5
|
+
domToHtml = require('./domtohtml').domToHtml,
|
6
|
+
htmlencoding = require('./htmlencoding'),
|
7
|
+
HTMLEncode = htmlencoding.HTMLEncode,
|
8
|
+
HTMLDecode = htmlencoding.HTMLDecode,
|
9
|
+
_console = {
|
10
|
+
log: console.log,
|
11
|
+
info: console.info,
|
12
|
+
warn: console.warn,
|
13
|
+
error: console.error
|
14
|
+
};
|
15
|
+
|
16
|
+
exports.windowAugmentation = function(dom, options) {
|
17
|
+
options = options || {};
|
18
|
+
var window = exports.createWindow(dom, options),
|
19
|
+
setupDoc = (typeof options.document === 'undefined');
|
20
|
+
|
21
|
+
if (setupDoc) {
|
22
|
+
browser = browserAugmentation(dom, options),
|
23
|
+
options.document = new (browser.Document)();
|
24
|
+
}
|
25
|
+
|
26
|
+
window.document = options.document;
|
27
|
+
|
28
|
+
if (options.document.childNodes.length === 0) {
|
29
|
+
window.document.appendChild(
|
30
|
+
window.document.createElement("html")
|
31
|
+
);
|
32
|
+
var head = window.document.createElement('head');
|
33
|
+
window.document.documentElement.appendChild(head);
|
34
|
+
head.appendChild(
|
35
|
+
window.document.createElement('title')
|
36
|
+
);
|
37
|
+
window.document.documentElement.appendChild(
|
38
|
+
window.document.createElement('body')
|
39
|
+
);
|
40
|
+
}
|
41
|
+
|
42
|
+
if (!window.document.addEventListener) {
|
43
|
+
window.document.addEventListener = function() {};
|
44
|
+
}
|
45
|
+
|
46
|
+
window.console = _console;
|
47
|
+
window.document.compareDocumentPosition = function() {};
|
48
|
+
window.document.documentElement.style = {};
|
49
|
+
window.document.documentElement.hasAttribute = true;
|
50
|
+
return window;
|
51
|
+
}
|
52
|
+
|
53
|
+
exports.createWindow = function(dom, options) {
|
54
|
+
options = options || {};
|
55
|
+
var document,
|
56
|
+
window = {
|
57
|
+
get document() { return document },
|
58
|
+
set document(doc) {
|
59
|
+
document = doc;
|
60
|
+
if (document) {
|
61
|
+
document.defaultView = window;
|
62
|
+
document.parentWindow = window;
|
63
|
+
}
|
64
|
+
},
|
65
|
+
setTimeout: setTimeout,
|
66
|
+
setInterval: setInterval,
|
67
|
+
clearInterval: clearInterval,
|
68
|
+
clearTimeout: clearTimeout,
|
69
|
+
name: 'nodejs',
|
70
|
+
innerWidth: 1024,
|
71
|
+
innerHeight: 768,
|
72
|
+
length: 1,
|
73
|
+
outerWidth: 1024,
|
74
|
+
outerHeight: 768,
|
75
|
+
pageXOffset: 0,
|
76
|
+
pageYOffset: 0,
|
77
|
+
screenX: 0,
|
78
|
+
screenY: 0,
|
79
|
+
screenLeft: 0,
|
80
|
+
screenTop: 0,
|
81
|
+
scrollX: 0,
|
82
|
+
scrollY: 0,
|
83
|
+
scrollTop: 0,
|
84
|
+
scrollLeft: 0
|
85
|
+
};
|
86
|
+
|
87
|
+
window.frames = [window];
|
88
|
+
window.contentWindow = window;
|
89
|
+
window.addEventListener2 = function(type, fn, capture) {
|
90
|
+
fn.apply(window);
|
91
|
+
};
|
92
|
+
|
93
|
+
window.getComputedStyle = function(node) {
|
94
|
+
var s = node.style,
|
95
|
+
cs = {};
|
96
|
+
|
97
|
+
for (var n in s) {
|
98
|
+
cs[n] = s[n];
|
99
|
+
}
|
100
|
+
cs.__proto__ = {
|
101
|
+
getPropertyValue: function(name) {
|
102
|
+
return node.style[name];
|
103
|
+
}
|
104
|
+
};
|
105
|
+
return cs;
|
106
|
+
};
|
107
|
+
window.addEventListener = function() {};
|
108
|
+
|
109
|
+
window.alert = function () {};
|
110
|
+
window.blur = function () {};
|
111
|
+
window.close = function () {};
|
112
|
+
window.confirm = function () {};
|
113
|
+
window.createPopup = function () {};
|
114
|
+
window.focus = function () {};
|
115
|
+
window.moveBy = function () {};
|
116
|
+
window.moveTo = function () {};
|
117
|
+
window.open = function () {};
|
118
|
+
window.print = function () {};
|
119
|
+
window.prompt = function () {};
|
120
|
+
window.resizeBy = function () {};
|
121
|
+
window.resizeTo = function () {};
|
122
|
+
window.scroll = function () {};
|
123
|
+
window.scrollBy = function () {};
|
124
|
+
window.scrollTo = function () {};
|
125
|
+
|
126
|
+
// Author: Swizec
|
127
|
+
// some scripts expect a proper window.location; try parsing it from options.url
|
128
|
+
if (options.url) {
|
129
|
+
var host = options.url.split("://", 2)[1].split("/", 1)[0];
|
130
|
+
window.location = { href: options.url,
|
131
|
+
hash: (options.url.indexOf('#') > -1) ? "#"+options.url.split("#", 2)[1] : '',
|
132
|
+
host: host,
|
133
|
+
hostname: host.split(":", 2)[0],
|
134
|
+
pathname: (function () {
|
135
|
+
var path = options.url.split("://", 2)[1].split("/", 2)[1];
|
136
|
+
return (path) ? path.split('#', 2)[0] : '';
|
137
|
+
})(),
|
138
|
+
port: (host.split(":", 2)[1]) ? host.split(":", 2)[1] : 80,
|
139
|
+
protocol: options.url.split("://", 2)[0]+":",
|
140
|
+
search: (options.url.indexOf('?') > -1) ? "?"+options.url.split("?", 2)[1] : '',
|
141
|
+
// TODO: find a way to actually implement these
|
142
|
+
reload: function () {},
|
143
|
+
replace: function () {}
|
144
|
+
}
|
145
|
+
}else {
|
146
|
+
window.location = { href: __filename };
|
147
|
+
}
|
148
|
+
|
149
|
+
window.navigator = {
|
150
|
+
userAgent: 'Node.js (' + process.platform + '; U; rv:' + process.version + ')',
|
151
|
+
appName: 'Node.js jsDom',
|
152
|
+
platform: process.platform,
|
153
|
+
appVersion: process.version
|
154
|
+
};
|
155
|
+
|
156
|
+
window.window = window;
|
157
|
+
window.self = window;
|
158
|
+
|
159
|
+
window.close = function() {
|
160
|
+
var len = document._nodes.length, i, el;
|
161
|
+
for (i = 0; i < len; i++) {
|
162
|
+
el = document._nodes[i];
|
163
|
+
document._nodes[i] = null;
|
164
|
+
if (el.parentNode) {
|
165
|
+
el.parentNode.removeChild(el);
|
166
|
+
}
|
167
|
+
}
|
168
|
+
delete document._attributes._parentNode;
|
169
|
+
delete document._ownerDocument;
|
170
|
+
delete document._children[0]._parentNode;
|
171
|
+
delete document._children[0]._ownerDocument;
|
172
|
+
delete document.defaultView;
|
173
|
+
delete document.contentWindow;
|
174
|
+
delete document.contentDocument;
|
175
|
+
delete document.parentWindow;
|
176
|
+
delete document._documentElement;
|
177
|
+
|
178
|
+
delete window.self;
|
179
|
+
delete window.window;
|
180
|
+
delete window.contentWindow;
|
181
|
+
delete window.document;
|
182
|
+
len = window.frames.length;
|
183
|
+
for (i = 0; i < len; i++) {
|
184
|
+
if (window !== window.frames[i]) {
|
185
|
+
window.frames[i].close();
|
186
|
+
}
|
187
|
+
delete window.frames[i];
|
188
|
+
}
|
189
|
+
};
|
190
|
+
|
191
|
+
return window;
|
192
|
+
};
|
193
|
+
|
194
|
+
var htmlparser = null; //Caching for HTMLParser require. HUGE performace boost.
|
195
|
+
/**
|
196
|
+
* 5000 iterations
|
197
|
+
* Without cache: ~1800+ms
|
198
|
+
* With cache: ~80ms
|
199
|
+
*/
|
200
|
+
|
201
|
+
var browserAugmentation = exports.browserAugmentation = function(dom, options) {
|
202
|
+
|
203
|
+
if(!options) options = {};
|
204
|
+
|
205
|
+
// set up html parser - use a provided one or try and load from library
|
206
|
+
|
207
|
+
var htmltodom;
|
208
|
+
|
209
|
+
if(options.parser) {
|
210
|
+
htmltodom = new HtmlToDom(options.parser);
|
211
|
+
} else {
|
212
|
+
try {
|
213
|
+
if (!htmlparser) {//Only require once
|
214
|
+
htmlparser = require('htmlparser');
|
215
|
+
}
|
216
|
+
htmltodom = new HtmlToDom(htmlparser);
|
217
|
+
} catch(e) {
|
218
|
+
try {
|
219
|
+
htmlparser = require('node-htmlparser/lib/node-htmlparser');
|
220
|
+
htmltodom = new HtmlToDom(htmlparser);
|
221
|
+
} catch(e) {
|
222
|
+
htmltodom = new HtmlToDom();
|
223
|
+
}
|
224
|
+
}
|
225
|
+
}
|
226
|
+
|
227
|
+
/***************************************
|
228
|
+
* Browser Augmentation *
|
229
|
+
***************************************/
|
230
|
+
|
231
|
+
|
232
|
+
if (!dom.Node.prototype.__proto__.addEventListener) {
|
233
|
+
dom.Node.prototype.addEventListener = function(){};
|
234
|
+
}
|
235
|
+
|
236
|
+
|
237
|
+
dom.Element.prototype.getElementsByClassName = function(className) {
|
238
|
+
|
239
|
+
function filterByClassName(child) {
|
240
|
+
if (!child) {
|
241
|
+
return false;
|
242
|
+
}
|
243
|
+
|
244
|
+
if (child.nodeType &&
|
245
|
+
child.nodeType === dom.Node.prototype.ENTITY_REFERENCE_NODE)
|
246
|
+
{
|
247
|
+
child = child._entity;
|
248
|
+
}
|
249
|
+
|
250
|
+
var classString = child.className;
|
251
|
+
if (classString) {
|
252
|
+
var s = classString.split(" ");
|
253
|
+
for (var i=0; i<s.length; i++) {
|
254
|
+
if (s[i] === className) {
|
255
|
+
return true;
|
256
|
+
}
|
257
|
+
}
|
258
|
+
}
|
259
|
+
return false;
|
260
|
+
}
|
261
|
+
|
262
|
+
var disableLiveLists = this.ownerDocument &&
|
263
|
+
this.ownerDocument.implementation &&
|
264
|
+
this.ownerDocument.implementation.hasFeature("DisableLiveLists");
|
265
|
+
|
266
|
+
return new dom.NodeList(dom.mapper(this, filterByClassName), !disableLiveLists);
|
267
|
+
};
|
268
|
+
|
269
|
+
dom.Document.prototype.__defineSetter__("title",function(value) {
|
270
|
+
this.getElementsByTagName('title')[0].innerHTML = value;
|
271
|
+
return value;
|
272
|
+
});
|
273
|
+
|
274
|
+
dom.Document.prototype.__defineGetter__("title",function() {
|
275
|
+
// Swizec - sometimes there is no title
|
276
|
+
var elements = this.getElementsByTagName('title');
|
277
|
+
return (elements.length > 0) ? elements[0].innerHTML : '';
|
278
|
+
});
|
279
|
+
|
280
|
+
dom.Element.prototype.__defineGetter__('sourceIndex', function() {
|
281
|
+
/*
|
282
|
+
* According to QuirksMode:
|
283
|
+
* Get the sourceIndex of element x. This is also the index number for
|
284
|
+
* the element in the document.getElementsByTagName('*') array.
|
285
|
+
* http://www.quirksmode.org/dom/w3c_core.html#t77
|
286
|
+
*/
|
287
|
+
var items = this.ownerDocument.getElementsByTagName('*'),
|
288
|
+
len = items.length;
|
289
|
+
|
290
|
+
for (var i = 0; i < len; i++) {
|
291
|
+
if (items[i] === this) {
|
292
|
+
return i;
|
293
|
+
}
|
294
|
+
}
|
295
|
+
});
|
296
|
+
|
297
|
+
dom.Document.prototype.__defineGetter__('outerHTML', function() {
|
298
|
+
var html = domToHtml(this.documentElement);
|
299
|
+
if (this.doctype) {
|
300
|
+
html = this.doctype.toString() + '\n' + html;
|
301
|
+
}
|
302
|
+
return html;
|
303
|
+
});
|
304
|
+
|
305
|
+
dom.Element.prototype.__defineGetter__('outerHTML', function() {
|
306
|
+
return domToHtml(this);
|
307
|
+
});
|
308
|
+
|
309
|
+
dom.Element.prototype.__defineGetter__('innerHTML', function() {
|
310
|
+
return domToHtml(this.childNodes, true);
|
311
|
+
});
|
312
|
+
dom.Element.prototype.__defineSetter__('doctype', function() {
|
313
|
+
throw new core.DOMException(NO_MODIFICATION_ALLOWED_ERR);
|
314
|
+
});
|
315
|
+
dom.Element.prototype.__defineGetter__('doctype', function() {
|
316
|
+
var r = null;
|
317
|
+
if (this.nodeName == '#document') {
|
318
|
+
if (this._doctype) {
|
319
|
+
r = this._doctype;
|
320
|
+
}
|
321
|
+
}
|
322
|
+
return r;
|
323
|
+
});
|
324
|
+
|
325
|
+
dom.Element.prototype.__defineSetter__('innerHTML', function(html) {
|
326
|
+
//Check for lib first
|
327
|
+
|
328
|
+
if (html === null) {
|
329
|
+
return null;
|
330
|
+
}
|
331
|
+
|
332
|
+
//Clear the children first:
|
333
|
+
for (var i = this.childNodes.length-1; i >= 0; i--) {
|
334
|
+
if (this.childNodes[i].parentNode) {
|
335
|
+
this.childNodes[i].parentNode.removeChild(this.childNodes[i]);
|
336
|
+
}
|
337
|
+
}
|
338
|
+
if (this.nodeName === '#document') {
|
339
|
+
parseDocType(this, html);
|
340
|
+
}
|
341
|
+
var nodes = htmltodom.appendHtmlToElement(html, this);
|
342
|
+
return html;
|
343
|
+
});
|
344
|
+
|
345
|
+
var DOC_HTML5 = /<!doctype html>/is,
|
346
|
+
DOC_TYPE = /<!DOCTYPE (\w.*)">/is;
|
347
|
+
|
348
|
+
var parseDocType = function(doc, html) {
|
349
|
+
var publicID = '',
|
350
|
+
systemID = '',
|
351
|
+
fullDT = '',
|
352
|
+
name = 'HTML',
|
353
|
+
set = true,
|
354
|
+
html5DT = html.match(DOC_HTML5),
|
355
|
+
dt = html.match(DOC_TYPE);
|
356
|
+
|
357
|
+
//Default, No doctype === null
|
358
|
+
doc._doctype = null;
|
359
|
+
|
360
|
+
if (html5DT && html5DT[0]) { //Handle the HTML shorty doctype
|
361
|
+
fullDT = html5DT[0];
|
362
|
+
|
363
|
+
} else if (dt && dt[1]) { //Parse the doctype
|
364
|
+
fullDT = dt[0];
|
365
|
+
dt = dt[1].split(' "');
|
366
|
+
var _id1 = dt.pop().replace(/"/g, ''),
|
367
|
+
_id2 = dt.pop().replace(/"/g, '');
|
368
|
+
|
369
|
+
if (_id1.indexOf('-//') !== -1) {
|
370
|
+
publicID = _id1;
|
371
|
+
}
|
372
|
+
if (_id2.indexOf('-//') !== -1) {
|
373
|
+
publicID = _id2;
|
374
|
+
}
|
375
|
+
if (_id1.indexOf('://') !== -1) {
|
376
|
+
systemID = _id1;
|
377
|
+
}
|
378
|
+
if (_id2.indexOf('://') !== -1) {
|
379
|
+
systemID = _id2;
|
380
|
+
}
|
381
|
+
if (dt.length) {
|
382
|
+
dt = dt[0].split(' ');
|
383
|
+
name = dt[0].toUpperCase();
|
384
|
+
}
|
385
|
+
} else {
|
386
|
+
//No DocType found
|
387
|
+
return;
|
388
|
+
}
|
389
|
+
doc._doctype = new dom.DOMImplementation().createDocumentType(name, publicID, systemID);
|
390
|
+
doc._doctype._ownerDocument = doc;
|
391
|
+
doc._doctype._fullDT = fullDT;
|
392
|
+
doc._doctype.toString = function() {
|
393
|
+
return this._fullDT;
|
394
|
+
};
|
395
|
+
}
|
396
|
+
|
397
|
+
dom.Document.prototype.__defineGetter__("body", function() {
|
398
|
+
return this.getElementsByTagName("body").item(0);
|
399
|
+
});
|
400
|
+
|
401
|
+
dom.Document.prototype.__defineGetter__("head", function() {
|
402
|
+
return this.getElementsByTagName("head").item(0);
|
403
|
+
});
|
404
|
+
|
405
|
+
// Author: Swizec
|
406
|
+
// styleSheets is an interface to all of the css on a page
|
407
|
+
// some scripts like readability.js expect this to exist
|
408
|
+
dom.Document.prototype.__defineGetter__("styleSheets", function () {
|
409
|
+
var styles = new Array(),
|
410
|
+
nodes1 = this.getElementsByTagName("style"),
|
411
|
+
nodes2 = (this.head) ? this.head.getElementsByTagName("link") : [],
|
412
|
+
node;
|
413
|
+
|
414
|
+
function StyleSheet(node) {
|
415
|
+
this.cssText = node.textContent;
|
416
|
+
this.disabled = false;
|
417
|
+
this.href = (node.attributes['href']) ? node.attributes['href'] : '';
|
418
|
+
this.media = (node.attributes['media']) ? node.attributes['media'] : 'screen';
|
419
|
+
this.title = node.attributes['title'];
|
420
|
+
this.type = node.attributes['type'];
|
421
|
+
}
|
422
|
+
|
423
|
+
for (var i=0; i < nodes1.length; i++ ) {
|
424
|
+
node = nodes1.item(i);
|
425
|
+
styles.push(new StyleSheet(node));
|
426
|
+
}
|
427
|
+
|
428
|
+
for (var i=0; i< nodes2.length; i++ ) {
|
429
|
+
node = nodes2.item(i);
|
430
|
+
if (node.attributes['rel'] == 'stylesheet') {
|
431
|
+
styles.push(new StyleSheet(node));
|
432
|
+
}
|
433
|
+
}
|
434
|
+
|
435
|
+
return styles;
|
436
|
+
});
|
437
|
+
|
438
|
+
dom.Document.prototype.console = _console;
|
439
|
+
|
440
|
+
dom.Element.prototype.__defineGetter__('nodeName', function(val) {
|
441
|
+
return this._nodeName.toUpperCase();
|
442
|
+
});
|
443
|
+
|
444
|
+
dom.Element.prototype.__defineGetter__('tagName', function(val) {
|
445
|
+
var t = this._tagName.toUpperCase();
|
446
|
+
//Document should not return a tagName
|
447
|
+
if (this.nodeName === '#document') {
|
448
|
+
t = null;
|
449
|
+
}
|
450
|
+
return t;
|
451
|
+
});
|
452
|
+
|
453
|
+
dom.Element.prototype.scrollTop = 0;
|
454
|
+
dom.Element.prototype.scrollLeft = 0;
|
455
|
+
|
456
|
+
|
457
|
+
dom.Element.prototype.__defineGetter__('text', function() {
|
458
|
+
if (this.attributes.getNamedItem('value')) {
|
459
|
+
return this.value;
|
460
|
+
} else {
|
461
|
+
return this.innerHTML;
|
462
|
+
}
|
463
|
+
});
|
464
|
+
|
465
|
+
dom.Element.prototype.__defineGetter__('textContent', function() {
|
466
|
+
var stripHTML = /<\S[^><]*>/g;
|
467
|
+
var out = this.innerHTML;
|
468
|
+
//Remove all the HTML
|
469
|
+
out = out.replace(stripHTML, '');
|
470
|
+
//Now decode the encoded text content
|
471
|
+
out = HTMLDecode(out);
|
472
|
+
return out;
|
473
|
+
});
|
474
|
+
dom.Element.prototype.__defineSetter__('textContent', function(txt) {
|
475
|
+
//Un encode all the entities
|
476
|
+
txt = HTMLEncode(txt);
|
477
|
+
//Set the content
|
478
|
+
this.innerHTML = txt;
|
479
|
+
return txt;
|
480
|
+
});
|
481
|
+
|
482
|
+
|
483
|
+
return dom;
|
484
|
+
}
|