mattpuchlerz-jspec 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/History.rdoc +513 -0
  2. data/Manifest +57 -0
  3. data/README.rdoc +825 -0
  4. data/Rakefile +75 -0
  5. data/bin/jspec +305 -0
  6. data/jspec.gemspec +44 -0
  7. data/lib/images/bg.png +0 -0
  8. data/lib/images/hr.png +0 -0
  9. data/lib/images/loading.gif +0 -0
  10. data/lib/images/sprites.bg.png +0 -0
  11. data/lib/images/sprites.png +0 -0
  12. data/lib/images/vr.png +0 -0
  13. data/lib/jspec.css +145 -0
  14. data/lib/jspec.jquery.js +71 -0
  15. data/lib/jspec.js +1771 -0
  16. data/lib/jspec.shell.js +36 -0
  17. data/lib/jspec.timers.js +84 -0
  18. data/lib/jspec.xhr.js +183 -0
  19. data/server/browsers.rb +228 -0
  20. data/server/helpers.rb +82 -0
  21. data/server/routes.rb +57 -0
  22. data/server/server.rb +88 -0
  23. data/spec/async +1 -0
  24. data/spec/env.js +695 -0
  25. data/spec/fixtures/test.html +1 -0
  26. data/spec/fixtures/test.json +1 -0
  27. data/spec/fixtures/test.xml +5 -0
  28. data/spec/helpers.js +66 -0
  29. data/spec/server.rb +2 -0
  30. data/spec/spec.dom.html +34 -0
  31. data/spec/spec.fixtures.js +18 -0
  32. data/spec/spec.grammar-less.js +34 -0
  33. data/spec/spec.grammar.js +226 -0
  34. data/spec/spec.jquery.js +176 -0
  35. data/spec/spec.jquery.xhr.js +35 -0
  36. data/spec/spec.js +166 -0
  37. data/spec/spec.matchers.js +493 -0
  38. data/spec/spec.modules.js +67 -0
  39. data/spec/spec.node.js +46 -0
  40. data/spec/spec.rhino.js +17 -0
  41. data/spec/spec.server.html +29 -0
  42. data/spec/spec.shared-behaviors.js +80 -0
  43. data/spec/spec.utils.js +279 -0
  44. data/spec/spec.xhr.js +156 -0
  45. data/templates/default/History.md +4 -0
  46. data/templates/default/README.md +30 -0
  47. data/templates/default/lib/yourlib.js +2 -0
  48. data/templates/default/spec/server.rb +4 -0
  49. data/templates/default/spec/spec.dom.html +20 -0
  50. data/templates/default/spec/spec.rhino.js +9 -0
  51. data/templates/default/spec/spec.server.html +16 -0
  52. data/templates/default/spec/yourlib_spec.js +11 -0
  53. data/templates/rails/server.rb +4 -0
  54. data/templates/rails/spec.application.js +8 -0
  55. data/templates/rails/spec.dom.html +20 -0
  56. data/templates/rails/spec.rhino.js +8 -0
  57. data/templates/rails/spec.server.html +16 -0
  58. metadata +166 -0
@@ -0,0 +1,82 @@
1
+
2
+ helpers do
3
+
4
+ ##
5
+ # Return dotted assertion graph for _assertions_.
6
+
7
+ def assertion_graph_for assertions
8
+ return if assertions.empty?
9
+ assertions.map do |assertion|
10
+ assertion['passed'] ? green('.') : red('.')
11
+ end.join
12
+ end
13
+
14
+ ##
15
+ # Override Sinatra's #send_file to prevent caching.
16
+
17
+ def send_file path, opts = {}
18
+ stat = File.stat(path)
19
+ response['Cache-Control'] = 'no-cache'
20
+ content_type media_type(opts[:type]) ||
21
+ media_type(File.extname(path)) ||
22
+ response['Content-Type'] ||
23
+ 'application/octet-stream'
24
+ response['Content-Length'] ||= (opts[:length] || stat.size).to_s
25
+
26
+ if opts[:disposition] == 'attachment' || opts[:filename]
27
+ attachment opts[:filename] || path
28
+ elsif opts[:disposition] == 'inline'
29
+ response['Content-Disposition'] = 'inline'
30
+ end
31
+
32
+ halt ::Sinatra::Application::StaticFile.open(path, 'rb')
33
+ rescue Errno::ENOENT
34
+ not_found
35
+ end
36
+
37
+ ##
38
+ # Find the browser name for the current user agent.
39
+
40
+ def browser_name
41
+ Browser.subclasses.find do |browser|
42
+ browser.matches_agent? env['HTTP_USER_AGENT']
43
+ end.new
44
+ rescue
45
+ 'Unknown'
46
+ end
47
+
48
+ ##
49
+ # Wrap _string_ with ansi escape sequence using _code_.
50
+
51
+ def color string, code
52
+ "\e[#{code}m#{string}\e[0m"
53
+ end
54
+
55
+ ##
56
+ # Bold _string_.
57
+
58
+ def bold string
59
+ color string, 1
60
+ end
61
+
62
+ ##
63
+ # Color _string_ red.
64
+
65
+ def red string
66
+ color string, 31
67
+ end
68
+
69
+ ##
70
+ # Color _string_ green.
71
+
72
+ def green string
73
+ color string, 32
74
+ end
75
+
76
+ ##
77
+ # Color _string_ blue.
78
+
79
+ def blue string
80
+ color string, 34
81
+ end
82
+ end
@@ -0,0 +1,57 @@
1
+
2
+ get '/jspec/*' do |path|
3
+ send_file JSPEC_ROOT + '/lib/' + path
4
+ end
5
+
6
+ post '/results' do
7
+ require 'json'
8
+ data = JSON.parse request.body.read
9
+ if data['options'].include?('verbose') && data['options']['verbose'] ||
10
+ data['options'].include?('failuresOnly') && data['options']['failuresOnly']
11
+ puts "\n\n %s Passes: %s Failures: %s\n\n" % [
12
+ bold(browser_name),
13
+ green(data['stats']['passes']),
14
+ red(data['stats']['failures'])]
15
+ data['results'].compact.each do |suite|
16
+ specs = suite['specs'].compact.map do |spec|
17
+ case spec['status'].to_sym
18
+ when :pass
19
+ next if data['options'].include?('failuresOnly') && data['options']['failuresOnly']
20
+ ' ' + green(spec['description']) + assertion_graph_for(spec['assertions']).to_s + "\n"
21
+ when :fail
22
+ " #{red(spec['description'])}\n #{spec['message']}\n\n"
23
+ else
24
+ " #{blue(spec['description'])}\n"
25
+ end
26
+ end.join
27
+ unless specs.strip.empty?
28
+ puts "\n " + bold(suite['description'])
29
+ puts specs
30
+ end
31
+ end
32
+ else
33
+ puts "%20s Passes: %s Failures: %s" % [
34
+ bold(browser_name),
35
+ green(data['stats']['passes']),
36
+ red(data['stats']['failures'])]
37
+ end
38
+ halt 200
39
+ end
40
+
41
+ get '/*' do |path|
42
+ pass unless File.exists?(path)
43
+ send_file path
44
+ end
45
+
46
+ #--
47
+ # Simulation Routes
48
+ #++
49
+
50
+ get '/slow/*' do |seconds|
51
+ sleep seconds.to_i
52
+ halt 200
53
+ end
54
+
55
+ get '/status/*' do |code|
56
+ halt code.to_i
57
+ end
@@ -0,0 +1,88 @@
1
+
2
+ $:.unshift File.dirname(__FILE__)
3
+
4
+ require 'sinatra'
5
+ require 'thread'
6
+ require 'browsers'
7
+ require 'helpers'
8
+ require 'routes'
9
+
10
+ module JSpec
11
+ class Server
12
+
13
+ ##
14
+ # Suite HTML.
15
+
16
+ attr_accessor :suite
17
+
18
+ ##
19
+ # Host string.
20
+
21
+ attr_reader :host
22
+
23
+ ##
24
+ # Port number.
25
+
26
+ attr_reader :port
27
+
28
+ ##
29
+ # Server instance.
30
+
31
+ attr_reader :server
32
+
33
+ ##
34
+ # Initialize.
35
+
36
+ def initialize suite, port
37
+ @suite, @port, @host = suite, port, :localhost
38
+ end
39
+
40
+ ##
41
+ # URI formed by the given host and port.
42
+
43
+ def uri
44
+ 'http://%s:%d' % [host, port]
45
+ end
46
+
47
+ ##
48
+ # Start the server with _browsers_ which defaults to all supported browsers.
49
+
50
+ def start browsers = nil
51
+ browsers ||= Browser.subclasses.map { |browser| browser.new }
52
+ browsers.map do |browser|
53
+ Thread.new {
54
+ sleep 1
55
+ if browser.supported?
56
+ browser.setup
57
+ browser.visit uri + '/' + suite
58
+ browser.teardown
59
+ end
60
+ }
61
+ end.push(Thread.new {
62
+ start!
63
+ }).reverse.each { |thread| thread.join }
64
+ end
65
+
66
+ private
67
+
68
+ #:nodoc:
69
+
70
+ def start!
71
+ Sinatra::Application.class_eval do
72
+ begin
73
+ $stderr.puts 'Started JSpec server at http://%s:%d' % [host, port.to_i]
74
+ detect_rack_handler.run self, :Host => host, :Port => port do |server|
75
+ trap 'INT' do
76
+ server.respond_to?(:stop!) ? server.stop! : server.stop
77
+ end
78
+ end
79
+ rescue Errno::EADDRINUSE
80
+ raise "Port #{port} already in use"
81
+ rescue Errno::EACCES
82
+ raise "Permission Denied on port #{port}"
83
+ end
84
+ end
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1 @@
1
+ cookies!
@@ -0,0 +1,695 @@
1
+ /*
2
+ * Simulated browser environment for Rhino
3
+ * By John Resig <http://ejohn.org/>
4
+ * Copyright 2007 John Resig, under the MIT License
5
+ */
6
+
7
+ // The window Object
8
+ var window = this;
9
+
10
+ (function(){
11
+
12
+ // Browser Navigator
13
+
14
+ window.navigator = {
15
+ get userAgent(){
16
+ return "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3";
17
+ }
18
+ };
19
+
20
+ var curLocation = (new java.io.File("./")).toURL();
21
+
22
+ window.__defineSetter__("location", function(url){
23
+ var xhr = new XMLHttpRequest();
24
+ xhr.open("GET", url);
25
+ xhr.onreadystatechange = function(){
26
+ curLocation = new java.net.URL( curLocation, url );
27
+ window.document = xhr.responseXML;
28
+
29
+ var event = document.createEvent();
30
+ event.initEvent("load");
31
+ window.dispatchEvent( event );
32
+ };
33
+ xhr.send();
34
+ });
35
+
36
+ window.__defineGetter__("location", function(url){
37
+ return {
38
+ get protocol(){
39
+ return curLocation.getProtocol() + ":";
40
+ },
41
+ get href(){
42
+ return curLocation.toString();
43
+ },
44
+ toString: function(){
45
+ return this.href;
46
+ }
47
+ };
48
+ });
49
+
50
+ // Timers
51
+
52
+ var timers = [];
53
+
54
+ window.setTimeout = function(fn, time){
55
+ var num;
56
+ return num = setInterval(function(){
57
+ fn();
58
+ clearInterval(num);
59
+ }, time);
60
+ };
61
+
62
+ window.setInterval = function(fn, time){
63
+ var num = timers.length;
64
+
65
+ timers[num] = new java.lang.Thread(new java.lang.Runnable({
66
+ run: function(){
67
+ while (true){
68
+ java.lang.Thread.currentThread().sleep(time);
69
+ fn();
70
+ }
71
+ }
72
+ }));
73
+
74
+ timers[num].start();
75
+
76
+ return num;
77
+ };
78
+
79
+ window.clearInterval = function(num){
80
+ if ( timers[num] ) {
81
+ timers[num].stop();
82
+ delete timers[num];
83
+ }
84
+ };
85
+
86
+ // Window Events
87
+
88
+ var events = [{}];
89
+
90
+ window.addEventListener = function(type, fn){
91
+ if ( !this.uuid || this == window ) {
92
+ this.uuid = events.length;
93
+ events[this.uuid] = {};
94
+ }
95
+
96
+ if ( !events[this.uuid][type] )
97
+ events[this.uuid][type] = [];
98
+
99
+ if ( events[this.uuid][type].indexOf( fn ) < 0 )
100
+ events[this.uuid][type].push( fn );
101
+ };
102
+
103
+ window.removeEventListener = function(type, fn){
104
+ if ( !this.uuid || this == window ) {
105
+ this.uuid = events.length;
106
+ events[this.uuid] = {};
107
+ }
108
+
109
+ if ( !events[this.uuid][type] )
110
+ events[this.uuid][type] = [];
111
+
112
+ events[this.uuid][type] =
113
+ events[this.uuid][type].filter(function(f){
114
+ return f != fn;
115
+ });
116
+ };
117
+
118
+ window.dispatchEvent = function(event){
119
+ if ( event.type ) {
120
+ if ( this.uuid && events[this.uuid][event.type] ) {
121
+ var self = this;
122
+
123
+ events[this.uuid][event.type].forEach(function(fn){
124
+ fn.call( self, event );
125
+ });
126
+ }
127
+
128
+ if ( this["on" + event.type] )
129
+ this["on" + event.type].call( self, event );
130
+ }
131
+ };
132
+
133
+ // DOM Document
134
+
135
+ window.DOMDocument = function(file){
136
+ this._file = file;
137
+ this._dom = Packages.javax.xml.parsers.
138
+ DocumentBuilderFactory.newInstance()
139
+ .newDocumentBuilder().parse(file);
140
+
141
+ if ( !obj_nodes.containsKey( this._dom ) )
142
+ obj_nodes.put( this._dom, this );
143
+ };
144
+
145
+ DOMDocument.prototype = {
146
+ createTextNode: function(text){
147
+ return makeNode( this._dom.createTextNode(
148
+ text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")) );
149
+ },
150
+ createElement: function(name){
151
+ return makeNode( this._dom.createElement(name.toLowerCase()) );
152
+ },
153
+ getElementsByTagName: function(name){
154
+ return new DOMNodeList( this._dom.getElementsByTagName(
155
+ name.toLowerCase()) );
156
+ },
157
+ getElementById: function(id){
158
+ var elems = this._dom.getElementsByTagName("*");
159
+
160
+ for ( var i = 0; i < elems.length; i++ ) {
161
+ var elem = elems.item(i);
162
+ if ( elem.getAttribute("id") == id )
163
+ return makeNode(elem);
164
+ }
165
+
166
+ return null;
167
+ },
168
+ get body(){
169
+ return this.getElementsByTagName("body")[0];
170
+ },
171
+ get documentElement(){
172
+ return makeNode( this._dom.getDocumentElement() );
173
+ },
174
+ get ownerDocument(){
175
+ return null;
176
+ },
177
+ addEventListener: window.addEventListener,
178
+ removeEventListener: window.removeEventListener,
179
+ dispatchEvent: window.dispatchEvent,
180
+ get nodeName() {
181
+ return "#document";
182
+ },
183
+ importNode: function(node, deep){
184
+ return makeNode( this._dom.importNode(node._dom, deep) );
185
+ },
186
+ toString: function(){
187
+ return "Document" + (typeof this._file == "string" ?
188
+ ": " + this._file : "");
189
+ },
190
+ get innerHTML(){
191
+ return this.documentElement.outerHTML;
192
+ },
193
+
194
+ get defaultView(){
195
+ return {
196
+ getComputedStyle: function(elem){
197
+ return {
198
+ getPropertyValue: function(prop){
199
+ prop = prop.replace(/\-(\w)/g,function(m,c){
200
+ return c.toUpperCase();
201
+ });
202
+ var val = elem.style[prop];
203
+
204
+ if ( prop == "opacity" && val == "" )
205
+ val = "1";
206
+
207
+ return val;
208
+ }
209
+ };
210
+ }
211
+ };
212
+ },
213
+
214
+ createEvent: function(){
215
+ return {
216
+ type: "",
217
+ initEvent: function(type){
218
+ this.type = type;
219
+ }
220
+ };
221
+ }
222
+ };
223
+
224
+ function getDocument(node){
225
+ return obj_nodes.get(node);
226
+ }
227
+
228
+ // DOM NodeList
229
+
230
+ window.DOMNodeList = function(list){
231
+ this._dom = list;
232
+ this.length = list.getLength();
233
+
234
+ for ( var i = 0; i < this.length; i++ ) {
235
+ var node = list.item(i);
236
+ this[i] = makeNode( node );
237
+ }
238
+ };
239
+
240
+ DOMNodeList.prototype = {
241
+ toString: function(){
242
+ return "[ " +
243
+ Array.prototype.join.call( this, ", " ) + " ]";
244
+ },
245
+ get outerHTML(){
246
+ return Array.prototype.map.call(
247
+ this, function(node){return node.outerHTML;}).join('');
248
+ }
249
+ };
250
+
251
+ // DOM Node
252
+
253
+ window.DOMNode = function(node){
254
+ this._dom = node;
255
+ };
256
+
257
+ DOMNode.prototype = {
258
+ get nodeType(){
259
+ return this._dom.getNodeType();
260
+ },
261
+ get nodeValue(){
262
+ return this._dom.getNodeValue();
263
+ },
264
+ get nodeName() {
265
+ return this._dom.getNodeName();
266
+ },
267
+ cloneNode: function(deep){
268
+ return makeNode( this._dom.cloneNode(deep) );
269
+ },
270
+ get ownerDocument(){
271
+ return getDocument( this._dom.ownerDocument );
272
+ },
273
+ get documentElement(){
274
+ return makeNode( this._dom.documentElement );
275
+ },
276
+ get parentNode() {
277
+ return makeNode( this._dom.getParentNode() );
278
+ },
279
+ get nextSibling() {
280
+ return makeNode( this._dom.getNextSibling() );
281
+ },
282
+ get previousSibling() {
283
+ return makeNode( this._dom.getPreviousSibling() );
284
+ },
285
+ toString: function(){
286
+ return '"' + this.nodeValue + '"';
287
+ },
288
+ get outerHTML(){
289
+ return this.nodeValue;
290
+ }
291
+ };
292
+
293
+ // DOM Element
294
+
295
+ window.DOMElement = function(elem){
296
+ this._dom = elem;
297
+ this.style = {
298
+ get opacity(){ return this._opacity; },
299
+ set opacity(val){ this._opacity = val + ""; }
300
+ };
301
+
302
+ // Load CSS info
303
+ var styles = (this.getAttribute("style") || "").split(/\s*;\s*/);
304
+
305
+ for ( var i = 0; i < styles.length; i++ ) {
306
+ var style = styles[i].split(/\s*:\s*/);
307
+ if ( style.length == 2 )
308
+ this.style[ style[0] ] = style[1];
309
+ }
310
+ };
311
+
312
+ DOMElement.prototype = extend( new DOMNode(), {
313
+ get nodeName(){
314
+ return this.tagName.toUpperCase();
315
+ },
316
+ get tagName(){
317
+ return this._dom.getTagName();
318
+ },
319
+ toString: function(){
320
+ return "<" + this.tagName + (this.id ? "#" + this.id : "" ) + ">";
321
+ },
322
+ get outerHTML(){
323
+ var ret = "<" + this.tagName, attr = this.attributes;
324
+
325
+ for ( var i in attr )
326
+ ret += " " + i + "='" + attr[i] + "'";
327
+
328
+ if ( this.childNodes.length || this.nodeName == "SCRIPT" )
329
+ ret += ">" + this.childNodes.outerHTML +
330
+ "</" + this.tagName + ">";
331
+ else
332
+ ret += "/>";
333
+
334
+ return ret;
335
+ },
336
+
337
+ get attributes(){
338
+ var attr = {}, attrs = this._dom.getAttributes();
339
+
340
+ for ( var i = 0; i < attrs.getLength(); i++ )
341
+ attr[ attrs.item(i).nodeName ] = attrs.item(i).nodeValue;
342
+
343
+ return attr;
344
+ },
345
+
346
+ get innerHTML(){
347
+ return this.childNodes.outerHTML;
348
+ },
349
+ set innerHTML(html){
350
+ html = html.replace(/<\/?([A-Z]+)/g, function(m){
351
+ return m.toLowerCase();
352
+ });
353
+
354
+ var nodes = this.ownerDocument.importNode(
355
+ new DOMDocument( new java.io.ByteArrayInputStream(
356
+ (new java.lang.String("<wrap>" + html + "</wrap>"))
357
+ .getBytes("UTF8"))).documentElement, true).childNodes;
358
+
359
+ while (this.firstChild)
360
+ this.removeChild( this.firstChild );
361
+
362
+ for ( var i = 0; i < nodes.length; i++ )
363
+ this.appendChild( nodes[i] );
364
+ },
365
+
366
+ get textContent(){
367
+ return nav(this.childNodes);
368
+
369
+ function nav(nodes){
370
+ var str = "";
371
+ for ( var i = 0; i < nodes.length; i++ )
372
+ if ( nodes[i].nodeType == 3 )
373
+ str += nodes[i].nodeValue;
374
+ else if ( nodes[i].nodeType == 1 )
375
+ str += nav(nodes[i].childNodes);
376
+ return str;
377
+ }
378
+ },
379
+ set textContent(text){
380
+ while (this.firstChild)
381
+ this.removeChild( this.firstChild );
382
+ this.appendChild( this.ownerDocument.createTextNode(text));
383
+ },
384
+
385
+ style: {},
386
+ clientHeight: 0,
387
+ clientWidth: 0,
388
+ offsetHeight: 0,
389
+ offsetWidth: 0,
390
+
391
+ get disabled() {
392
+ var val = this.getAttribute("disabled");
393
+ return val != "false" && !!val;
394
+ },
395
+ set disabled(val) { return this.setAttribute("disabled",val); },
396
+
397
+ get checked() {
398
+ var val = this.getAttribute("checked");
399
+ return val != "false" && !!val;
400
+ },
401
+ set checked(val) { return this.setAttribute("checked",val); },
402
+
403
+ get selected() {
404
+ if ( !this._selectDone ) {
405
+ this._selectDone = true;
406
+
407
+ if ( this.nodeName == "OPTION" && !this.parentNode.getAttribute("multiple") ) {
408
+ var opt = this.parentNode.getElementsByTagName("option");
409
+
410
+ if ( this == opt[0] ) {
411
+ var select = true;
412
+
413
+ for ( var i = 1; i < opt.length; i++ )
414
+ if ( opt[i].selected ) {
415
+ select = false;
416
+ break;
417
+ }
418
+
419
+ if ( select )
420
+ this.selected = true;
421
+ }
422
+ }
423
+ }
424
+
425
+ var val = this.getAttribute("selected");
426
+ return val != "false" && !!val;
427
+ },
428
+ set selected(val) { return this.setAttribute("selected",val); },
429
+
430
+ get className() { return this.getAttribute("class") || ""; },
431
+ set className(val) {
432
+ return this.setAttribute("class",
433
+ val.replace(/(^\s*|\s*$)/g,""));
434
+ },
435
+
436
+ get type() { return this.getAttribute("type") || ""; },
437
+ set type(val) { return this.setAttribute("type",val); },
438
+
439
+ get value() { return this.getAttribute("value") || ""; },
440
+ set value(val) { return this.setAttribute("value",val); },
441
+
442
+ get src() { return this.getAttribute("src") || ""; },
443
+ set src(val) { return this.setAttribute("src",val); },
444
+
445
+ get id() { return this.getAttribute("id") || ""; },
446
+ set id(val) { return this.setAttribute("id",val); },
447
+
448
+ getAttribute: function(name){
449
+ return this._dom.hasAttribute(name) ?
450
+ new String( this._dom.getAttribute(name) ) :
451
+ null;
452
+ },
453
+ setAttribute: function(name,value){
454
+ this._dom.setAttribute(name,value);
455
+ },
456
+ removeAttribute: function(name){
457
+ this._dom.removeAttribute(name);
458
+ },
459
+
460
+ get childNodes(){
461
+ return new DOMNodeList( this._dom.getChildNodes() );
462
+ },
463
+ get firstChild(){
464
+ return makeNode( this._dom.getFirstChild() );
465
+ },
466
+ get lastChild(){
467
+ return makeNode( this._dom.getLastChild() );
468
+ },
469
+ appendChild: function(node){
470
+ this._dom.appendChild( node._dom );
471
+ },
472
+ insertBefore: function(node,before){
473
+ this._dom.insertBefore( node._dom, before ? before._dom : before );
474
+ },
475
+ removeChild: function(node){
476
+ this._dom.removeChild( node._dom );
477
+ },
478
+
479
+ getElementsByTagName: DOMDocument.prototype.getElementsByTagName,
480
+
481
+ addEventListener: window.addEventListener,
482
+ removeEventListener: window.removeEventListener,
483
+ dispatchEvent: window.dispatchEvent,
484
+
485
+ click: function(){
486
+ var event = document.createEvent();
487
+ event.initEvent("click");
488
+ this.dispatchEvent(event);
489
+ },
490
+ submit: function(){
491
+ var event = document.createEvent();
492
+ event.initEvent("submit");
493
+ this.dispatchEvent(event);
494
+ },
495
+ focus: function(){
496
+ var event = document.createEvent();
497
+ event.initEvent("focus");
498
+ this.dispatchEvent(event);
499
+ },
500
+ blur: function(){
501
+ var event = document.createEvent();
502
+ event.initEvent("blur");
503
+ this.dispatchEvent(event);
504
+ },
505
+ get elements(){
506
+ return this.getElementsByTagName("*");
507
+ },
508
+ get contentWindow(){
509
+ return this.nodeName == "IFRAME" ? {
510
+ document: this.contentDocument
511
+ } : null;
512
+ },
513
+ get contentDocument(){
514
+ if ( this.nodeName == "IFRAME" ) {
515
+ if ( !this._doc )
516
+ this._doc = new DOMDocument(
517
+ new java.io.ByteArrayInputStream((new java.lang.String(
518
+ "<html><head><title></title></head><body></body></html>"))
519
+ .getBytes("UTF8")));
520
+ return this._doc;
521
+ } else
522
+ return null;
523
+ }
524
+ });
525
+
526
+ // Helper method for extending one object with another
527
+
528
+ function extend(a,b) {
529
+ for ( var i in b ) {
530
+ var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i);
531
+
532
+ if ( g || s ) {
533
+ if ( g )
534
+ a.__defineGetter__(i, g);
535
+ if ( s )
536
+ a.__defineSetter__(i, s);
537
+ } else
538
+ a[i] = b[i];
539
+ }
540
+ return a;
541
+ }
542
+
543
+ // Helper method for generating the right
544
+ // DOM objects based upon the type
545
+
546
+ var obj_nodes = new java.util.HashMap();
547
+
548
+ function makeNode(node){
549
+ if ( node ) {
550
+ if ( !obj_nodes.containsKey( node ) )
551
+ obj_nodes.put( node, node.getNodeType() ==
552
+ Packages.org.w3c.dom.Node.ELEMENT_NODE ?
553
+ new DOMElement( node ) : new DOMNode( node ) );
554
+
555
+ return obj_nodes.get(node);
556
+ } else
557
+ return null;
558
+ }
559
+
560
+ // XMLHttpRequest
561
+ // Originally implemented by Yehuda Katz
562
+
563
+ window.XMLHttpRequest = function(){
564
+ this.headers = {};
565
+ this.responseHeaders = {};
566
+ };
567
+
568
+ XMLHttpRequest.prototype = {
569
+ open: function(method, url, async, user, password){
570
+ this.readyState = 1;
571
+ if (async)
572
+ this.async = true;
573
+ this.method = method || "GET";
574
+ this.url = url;
575
+ this.onreadystatechange();
576
+ },
577
+ setRequestHeader: function(header, value){
578
+ this.headers[header] = value;
579
+ },
580
+ getResponseHeader: function(header){ },
581
+ send: function(data){
582
+ var self = this;
583
+
584
+ function makeRequest(){
585
+ var url = new java.net.URL(curLocation, self.url);
586
+
587
+ if ( url.getProtocol() == "file" ) {
588
+ if ( self.method == "PUT" ) {
589
+ var out = new java.io.FileWriter(
590
+ new java.io.File( new java.net.URI( url.toString() ) ) ),
591
+ text = new java.lang.String( data || "" );
592
+
593
+ out.write( text, 0, text.length() );
594
+ out.flush();
595
+ out.close();
596
+ } else if ( self.method == "DELETE" ) {
597
+ var file = new java.io.File( new java.net.URI( url.toString() ) );
598
+ file["delete"]();
599
+ } else {
600
+ var connection = url.openConnection();
601
+ connection.connect();
602
+ handleResponse();
603
+ }
604
+ } else {
605
+ var connection = url.openConnection();
606
+
607
+ connection.setRequestMethod( self.method );
608
+
609
+ // Add headers to Java connection
610
+ for (var header in self.headers)
611
+ connection.addRequestProperty(header, self.headers[header]);
612
+
613
+ connection.connect();
614
+
615
+ // Stick the response headers into responseHeaders
616
+ for (var i = 0; ; i++) {
617
+ var headerName = connection.getHeaderFieldKey(i);
618
+ var headerValue = connection.getHeaderField(i);
619
+ if (!headerName && !headerValue) break;
620
+ if (headerName)
621
+ self.responseHeaders[headerName] = headerValue;
622
+ }
623
+
624
+ handleResponse();
625
+ }
626
+
627
+ function handleResponse(){
628
+ self.readyState = 4;
629
+ self.status = parseInt(connection.responseCode) || undefined;
630
+ self.statusText = connection.responseMessage || "";
631
+
632
+ var stream = new java.io.InputStreamReader(connection.getInputStream()),
633
+ buffer = new java.io.BufferedReader(stream), line;
634
+
635
+ while ((line = buffer.readLine()) != null)
636
+ self.responseText += line;
637
+
638
+ self.responseXML = null;
639
+
640
+ if ( self.responseText.match(/^\s*</) ) {
641
+ try {
642
+ self.responseXML = new DOMDocument(
643
+ new java.io.ByteArrayInputStream(
644
+ (new java.lang.String(
645
+ self.responseText)).getBytes("UTF8")));
646
+ } catch(e) {}
647
+ }
648
+ }
649
+
650
+ self.onreadystatechange();
651
+ }
652
+
653
+ if (this.async)
654
+ (new java.lang.Thread(new java.lang.Runnable({
655
+ run: makeRequest
656
+ }))).start();
657
+ else
658
+ makeRequest();
659
+ },
660
+ abort: function(){},
661
+ onreadystatechange: function(){},
662
+ getResponseHeader: function(header){
663
+ if (this.readyState < 3)
664
+ throw new Error("INVALID_STATE_ERR");
665
+ else {
666
+ var returnedHeaders = [];
667
+ for (var rHeader in this.responseHeaders) {
668
+ if (rHeader.match(new Regexp(header, "i")))
669
+ returnedHeaders.push(this.responseHeaders[rHeader]);
670
+ }
671
+
672
+ if (returnedHeaders.length)
673
+ return returnedHeaders.join(", ");
674
+ }
675
+
676
+ return null;
677
+ },
678
+ getAllResponseHeaders: function(header){
679
+ if (this.readyState < 3)
680
+ throw new Error("INVALID_STATE_ERR");
681
+ else {
682
+ var returnedHeaders = [];
683
+
684
+ for (var header in this.responseHeaders)
685
+ returnedHeaders.push( header + ": " + this.responseHeaders[header] );
686
+
687
+ return returnedHeaders.join("\r\n");
688
+ }
689
+ },
690
+ async: true,
691
+ readyState: 0,
692
+ responseText: "",
693
+ status: 0
694
+ };
695
+ })();