rhack 1.1.8 → 1.2.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.
Files changed (43) hide show
  1. checksums.yaml +6 -14
  2. data/Rakefile +2 -1
  3. data/config/rhack.yml.template +1 -0
  4. data/ext/curb-original/curb.c +977 -977
  5. data/ext/curb-original/curb.h +52 -52
  6. data/ext/curb-original/curb_config.h +238 -238
  7. data/ext/curb-original/curb_easy.c +3404 -3404
  8. data/ext/curb-original/curb_easy.h +90 -90
  9. data/ext/curb-original/curb_errors.c +647 -647
  10. data/ext/curb-original/curb_errors.h +129 -129
  11. data/ext/curb-original/curb_macros.h +159 -159
  12. data/ext/curb-original/curb_multi.c +633 -633
  13. data/ext/curb-original/curb_multi.h +26 -26
  14. data/ext/curb-original/curb_postfield.c +523 -523
  15. data/ext/curb-original/curb_postfield.h +40 -40
  16. data/ext/curb-original/curb_upload.c +80 -80
  17. data/ext/curb-original/curb_upload.h +30 -30
  18. data/ext/curb/curb.c +977 -977
  19. data/ext/curb/curb.h +52 -52
  20. data/ext/curb/curb_config.h +270 -270
  21. data/ext/curb/curb_easy.c +3434 -3434
  22. data/ext/curb/curb_easy.h +94 -94
  23. data/ext/curb/curb_errors.c +647 -647
  24. data/ext/curb/curb_errors.h +129 -129
  25. data/ext/curb/curb_macros.h +162 -162
  26. data/ext/curb/curb_multi.c +702 -702
  27. data/ext/curb/curb_multi.h +26 -26
  28. data/ext/curb/curb_postfield.c +523 -523
  29. data/ext/curb/curb_postfield.h +40 -40
  30. data/ext/curb/curb_upload.c +80 -80
  31. data/ext/curb/curb_upload.h +30 -30
  32. data/lib/rhack.rb +4 -1
  33. data/lib/rhack/clients/oauth.rb +1 -1
  34. data/lib/rhack/js/browser/env.js +697 -697
  35. data/lib/rhack/js/browser/jquery.js +7180 -7180
  36. data/lib/rhack/js/browser/xmlsax.js +1564 -1564
  37. data/lib/rhack/js/browser/xmlw3cdom_1.js +1443 -1443
  38. data/lib/rhack/js/browser/xmlw3cdom_2.js +2744 -2744
  39. data/lib/rhack/page.rb +6 -2
  40. data/lib/rhack/storage.rb +1 -1
  41. data/lib/rhack/version.rb +1 -1
  42. data/rhack.gemspec +1 -1
  43. metadata +16 -16
@@ -1,40 +1,40 @@
1
- /* curb_postfield.h - Field class for POST method
2
- * Copyright (c)2006 Ross Bamford.
3
- * Licensed under the Ruby License. See LICENSE for details.
4
- *
5
- * $Id: curb_postfield.h 4 2006-11-17 18:35:31Z roscopeco $
6
- */
7
- #ifndef __CURB_POSTFIELD_H
8
- #define __CURB_POSTFIELD_H
9
-
10
- #include "curb.h"
11
-
12
- /*
13
- * postfield doesn't actually wrap a curl_httppost - instead,
14
- * it just holds together some ruby objects and has a C-side
15
- * method to add it to a given form list during the perform.
16
- */
17
- typedef struct {
18
- /* Objects we associate */
19
- VALUE name;
20
- VALUE content;
21
- VALUE content_type;
22
- VALUE content_proc;
23
- VALUE local_file;
24
- VALUE remote_file;
25
-
26
- /* this will sometimes hold a string, which is the result
27
- * of the content_proc invocation. We need it to hang around.
28
- */
29
- VALUE buffer_str;
30
- } ruby_curl_postfield;
31
-
32
- extern VALUE cCurlPostField;
33
-
34
- void append_to_form(VALUE self,
35
- struct curl_httppost **first,
36
- struct curl_httppost **last);
37
-
38
- void init_curb_postfield();
39
-
40
- #endif
1
+ /* curb_postfield.h - Field class for POST method
2
+ * Copyright (c)2006 Ross Bamford.
3
+ * Licensed under the Ruby License. See LICENSE for details.
4
+ *
5
+ * $Id: curb_postfield.h 4 2006-11-17 18:35:31Z roscopeco $
6
+ */
7
+ #ifndef __CURB_POSTFIELD_H
8
+ #define __CURB_POSTFIELD_H
9
+
10
+ #include "curb.h"
11
+
12
+ /*
13
+ * postfield doesn't actually wrap a curl_httppost - instead,
14
+ * it just holds together some ruby objects and has a C-side
15
+ * method to add it to a given form list during the perform.
16
+ */
17
+ typedef struct {
18
+ /* Objects we associate */
19
+ VALUE name;
20
+ VALUE content;
21
+ VALUE content_type;
22
+ VALUE content_proc;
23
+ VALUE local_file;
24
+ VALUE remote_file;
25
+
26
+ /* this will sometimes hold a string, which is the result
27
+ * of the content_proc invocation. We need it to hang around.
28
+ */
29
+ VALUE buffer_str;
30
+ } ruby_curl_postfield;
31
+
32
+ extern VALUE cCurlPostField;
33
+
34
+ void append_to_form(VALUE self,
35
+ struct curl_httppost **first,
36
+ struct curl_httppost **last);
37
+
38
+ void init_curb_postfield();
39
+
40
+ #endif
@@ -1,80 +1,80 @@
1
- /* curb_upload.c - Curl upload handle
2
- * Copyright (c)2009 Todd A Fisher.
3
- * Licensed under the Ruby License. See LICENSE for details.
4
- */
5
- #include "curb_upload.h"
6
- extern VALUE mCurl;
7
- VALUE cCurlUpload;
8
-
9
- #ifdef RDOC_NEVER_DEFINED
10
- mCurl = rb_define_module("Curl");
11
- #endif
12
-
13
- static void curl_upload_mark(ruby_curl_upload *rbcu) {
14
- if (rbcu->stream && !NIL_P(rbcu->stream)) rb_gc_mark(rbcu->stream);
15
- }
16
- static void curl_upload_free(ruby_curl_upload *rbcu) {
17
- free(rbcu);
18
- }
19
-
20
- /*
21
- * call-seq:
22
- * internal class for sending large file uploads
23
- */
24
- VALUE ruby_curl_upload_new(VALUE klass) {
25
- VALUE upload;
26
- ruby_curl_upload *rbcu = ALLOC(ruby_curl_upload);
27
- rbcu->stream = Qnil;
28
- rbcu->offset = 0;
29
- upload = Data_Wrap_Struct(klass, curl_upload_mark, curl_upload_free, rbcu);
30
- return upload;
31
- }
32
-
33
- /*
34
- * call-seq:
35
- * internal class for sending large file uploads
36
- */
37
- VALUE ruby_curl_upload_stream_set(VALUE self, VALUE stream) {
38
- ruby_curl_upload *rbcu;
39
- Data_Get_Struct(self, ruby_curl_upload, rbcu);
40
- rbcu->stream = stream;
41
- return stream;
42
- }
43
- /*
44
- * call-seq:
45
- * internal class for sending large file uploads
46
- */
47
- VALUE ruby_curl_upload_stream_get(VALUE self) {
48
- ruby_curl_upload *rbcu;
49
- Data_Get_Struct(self, ruby_curl_upload, rbcu);
50
- return rbcu->stream;
51
- }
52
- /*
53
- * call-seq:
54
- * internal class for sending large file uploads
55
- */
56
- VALUE ruby_curl_upload_offset_set(VALUE self, VALUE offset) {
57
- ruby_curl_upload *rbcu;
58
- Data_Get_Struct(self, ruby_curl_upload, rbcu);
59
- rbcu->offset = FIX2LONG(offset);
60
- return offset;
61
- }
62
- /*
63
- * call-seq:
64
- * internal class for sending large file uploads
65
- */
66
- VALUE ruby_curl_upload_offset_get(VALUE self) {
67
- ruby_curl_upload *rbcu;
68
- Data_Get_Struct(self, ruby_curl_upload, rbcu);
69
- return INT2FIX(rbcu->offset);
70
- }
71
-
72
- /* =================== INIT LIB =====================*/
73
- void init_curb_upload() {
74
- cCurlUpload = rb_define_class_under(mCurl, "Upload", rb_cObject);
75
- rb_define_singleton_method(cCurlUpload, "new", ruby_curl_upload_new, 0);
76
- rb_define_method(cCurlUpload, "stream=", ruby_curl_upload_stream_set, 1);
77
- rb_define_method(cCurlUpload, "stream", ruby_curl_upload_stream_get, 0);
78
- rb_define_method(cCurlUpload, "offset=", ruby_curl_upload_offset_set, 1);
79
- rb_define_method(cCurlUpload, "offset", ruby_curl_upload_offset_get, 0);
80
- }
1
+ /* curb_upload.c - Curl upload handle
2
+ * Copyright (c)2009 Todd A Fisher.
3
+ * Licensed under the Ruby License. See LICENSE for details.
4
+ */
5
+ #include "curb_upload.h"
6
+ extern VALUE mCurl;
7
+ VALUE cCurlUpload;
8
+
9
+ #ifdef RDOC_NEVER_DEFINED
10
+ mCurl = rb_define_module("Curl");
11
+ #endif
12
+
13
+ static void curl_upload_mark(ruby_curl_upload *rbcu) {
14
+ if (rbcu->stream && !NIL_P(rbcu->stream)) rb_gc_mark(rbcu->stream);
15
+ }
16
+ static void curl_upload_free(ruby_curl_upload *rbcu) {
17
+ free(rbcu);
18
+ }
19
+
20
+ /*
21
+ * call-seq:
22
+ * internal class for sending large file uploads
23
+ */
24
+ VALUE ruby_curl_upload_new(VALUE klass) {
25
+ VALUE upload;
26
+ ruby_curl_upload *rbcu = ALLOC(ruby_curl_upload);
27
+ rbcu->stream = Qnil;
28
+ rbcu->offset = 0;
29
+ upload = Data_Wrap_Struct(klass, curl_upload_mark, curl_upload_free, rbcu);
30
+ return upload;
31
+ }
32
+
33
+ /*
34
+ * call-seq:
35
+ * internal class for sending large file uploads
36
+ */
37
+ VALUE ruby_curl_upload_stream_set(VALUE self, VALUE stream) {
38
+ ruby_curl_upload *rbcu;
39
+ Data_Get_Struct(self, ruby_curl_upload, rbcu);
40
+ rbcu->stream = stream;
41
+ return stream;
42
+ }
43
+ /*
44
+ * call-seq:
45
+ * internal class for sending large file uploads
46
+ */
47
+ VALUE ruby_curl_upload_stream_get(VALUE self) {
48
+ ruby_curl_upload *rbcu;
49
+ Data_Get_Struct(self, ruby_curl_upload, rbcu);
50
+ return rbcu->stream;
51
+ }
52
+ /*
53
+ * call-seq:
54
+ * internal class for sending large file uploads
55
+ */
56
+ VALUE ruby_curl_upload_offset_set(VALUE self, VALUE offset) {
57
+ ruby_curl_upload *rbcu;
58
+ Data_Get_Struct(self, ruby_curl_upload, rbcu);
59
+ rbcu->offset = FIX2LONG(offset);
60
+ return offset;
61
+ }
62
+ /*
63
+ * call-seq:
64
+ * internal class for sending large file uploads
65
+ */
66
+ VALUE ruby_curl_upload_offset_get(VALUE self) {
67
+ ruby_curl_upload *rbcu;
68
+ Data_Get_Struct(self, ruby_curl_upload, rbcu);
69
+ return INT2FIX(rbcu->offset);
70
+ }
71
+
72
+ /* =================== INIT LIB =====================*/
73
+ void init_curb_upload() {
74
+ cCurlUpload = rb_define_class_under(mCurl, "Upload", rb_cObject);
75
+ rb_define_singleton_method(cCurlUpload, "new", ruby_curl_upload_new, 0);
76
+ rb_define_method(cCurlUpload, "stream=", ruby_curl_upload_stream_set, 1);
77
+ rb_define_method(cCurlUpload, "stream", ruby_curl_upload_stream_get, 0);
78
+ rb_define_method(cCurlUpload, "offset=", ruby_curl_upload_offset_set, 1);
79
+ rb_define_method(cCurlUpload, "offset", ruby_curl_upload_offset_get, 0);
80
+ }
@@ -1,30 +1,30 @@
1
- /* curb_upload.h - Curl upload handle
2
- * Copyright (c)2009 Todd A Fisher.
3
- * Licensed under the Ruby License. See LICENSE for details.
4
- */
5
- #ifndef __CURB_UPLOAD_H
6
- #define __CURB_UPLOAD_H
7
-
8
- #include "curb.h"
9
-
10
- #include <curl/easy.h>
11
-
12
- /*
13
- * Maintain the state of an upload e.g. for putting large streams with very little memory
14
- * out to a server. via PUT requests
15
- */
16
- typedef struct {
17
- VALUE stream;
18
- size_t offset;
19
- } ruby_curl_upload;
20
-
21
- extern VALUE cCurlUpload;
22
- void init_curb_upload();
23
-
24
- VALUE ruby_curl_upload_new(VALUE klass);
25
- VALUE ruby_curl_upload_stream_set(VALUE self, VALUE stream);
26
- VALUE ruby_curl_upload_stream_get(VALUE self);
27
- VALUE ruby_curl_upload_offset_set(VALUE self, VALUE offset);
28
- VALUE ruby_curl_upload_offset_get(VALUE self);
29
-
30
- #endif
1
+ /* curb_upload.h - Curl upload handle
2
+ * Copyright (c)2009 Todd A Fisher.
3
+ * Licensed under the Ruby License. See LICENSE for details.
4
+ */
5
+ #ifndef __CURB_UPLOAD_H
6
+ #define __CURB_UPLOAD_H
7
+
8
+ #include "curb.h"
9
+
10
+ #include <curl/easy.h>
11
+
12
+ /*
13
+ * Maintain the state of an upload e.g. for putting large streams with very little memory
14
+ * out to a server. via PUT requests
15
+ */
16
+ typedef struct {
17
+ VALUE stream;
18
+ size_t offset;
19
+ } ruby_curl_upload;
20
+
21
+ extern VALUE cCurlUpload;
22
+ void init_curb_upload();
23
+
24
+ VALUE ruby_curl_upload_new(VALUE klass);
25
+ VALUE ruby_curl_upload_stream_set(VALUE self, VALUE stream);
26
+ VALUE ruby_curl_upload_stream_get(VALUE self);
27
+ VALUE ruby_curl_upload_offset_set(VALUE self, VALUE offset);
28
+ VALUE ruby_curl_upload_offset_get(VALUE self);
29
+
30
+ #endif
data/lib/rhack.rb CHANGED
@@ -19,6 +19,7 @@ module RHACK
19
19
 
20
20
  db = config.db || {}
21
21
  @@redis = nil
22
+
22
23
  if rcfg = db.redis
23
24
  begin
24
25
  require 'redis'
@@ -86,4 +87,6 @@ require "rhack/scout"
86
87
  require "rhack/scout_squad"
87
88
  require "rhack/frame"
88
89
  require "rhack/page"
89
- require "rhack/storage"
90
+ if defined? Redis::Objects
91
+ require "rhack/storage"
92
+ end
@@ -60,7 +60,7 @@ module RHACK
60
60
  end
61
61
 
62
62
  # @ state_params : [string<user_id>, (strings*",")<scope>]
63
- # persistent: state_params -> [string<token>, int<expires>]
63
+ # persistent: state_params -> [string token, int expires]
64
64
  def user_data(state_params, data=nil)
65
65
  key = "#{self.class.name.sub('RHACK::', '').underscore}:tokens"
66
66
  if data
@@ -1,697 +1,697 @@
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
- //Ruby.require("uri");
11
-
12
- print = function(txt) { Ruby.puts(txt); };
13
-
14
- (function(){
15
-
16
- // Browser Navigator
17
-
18
- window.navigator = {
19
- get userAgent(){
20
- return "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3";
21
- }
22
- };
23
- /*
24
- var fileToUrl = function(file) {
25
- return Ruby.URI.parse("file://" + Ruby.File.expand_path(file));
26
- };
27
-
28
- var curLocation = fileToUrl(".");
29
- /*
30
- window.__defineSetter__("location", function(url){
31
- var xhr = new XMLHttpRequest();
32
- xhr.open("GET", url);
33
- xhr.onreadystatechange = function(){
34
- curLocation = curLocation.merge(url);
35
- window.document = xhr.responseXML;
36
-
37
- if(window.document) {
38
- var event = document.createEvent();
39
- event.initEvent("load");
40
- window.dispatchEvent( event );
41
- }
42
- };
43
- xhr.send();
44
- });
45
-
46
- window.__defineGetter__("location", function(url){
47
- return {
48
- get protocol(){
49
- return curLocation.scheme() + ":";
50
- },
51
- get href(){
52
- return curLocation.toString();
53
- },
54
- toString: function(){
55
- return this.href.toString();
56
- }
57
- };
58
- });
59
- */
60
-
61
- // Timers
62
-
63
- var timers = [];
64
-
65
- window.setTimeout = function(fn, time){
66
- var num;
67
- return num = setInterval(function(){
68
- fn();
69
- clearInterval(num);
70
- }, time);
71
- };
72
-
73
- window.setInterval = function(fn, time){
74
- var num = timers.length;
75
-
76
- timers[num] = new Ruby.Thread(function() {
77
- while(true) {
78
- Ruby.sleep(time);
79
- fn();
80
- }
81
- });
82
-
83
- return num;
84
- };
85
-
86
- window.clearInterval = function(num){
87
- if ( timers[num] ) {
88
- timers[num].kill();
89
- delete timers[num];
90
- }
91
- };
92
-
93
- // Window Events
94
-
95
- var events = [{}];
96
-
97
- window.addEventListener = function(type, fn){
98
- if ( !this.uuid || this == window ) {
99
- this.uuid = events.length;
100
- events[this.uuid] = {};
101
- }
102
-
103
- if ( !events[this.uuid][type] )
104
- events[this.uuid][type] = [];
105
-
106
- if ( events[this.uuid][type].indexOf( fn ) < 0 )
107
- events[this.uuid][type].push( fn );
108
- };
109
-
110
- window.removeEventListener = function(type, fn){
111
- if ( !this.uuid || this == window ) {
112
- this.uuid = events.length;
113
- events[this.uuid] = {};
114
- }
115
-
116
- if ( !events[this.uuid][type] )
117
- events[this.uuid][type] = [];
118
-
119
- events[this.uuid][type] =
120
- events[this.uuid][type].filter(function(f){
121
- return f != fn;
122
- });
123
- };
124
-
125
- window.dispatchEvent = function(event){
126
- if ( event.type ) {
127
- if ( this.uuid && events[this.uuid][event.type] ) {
128
- var self = this;
129
-
130
- events[this.uuid][event.type].forEach(function(fn){
131
- fn.call( self, event );
132
- });
133
- }
134
-
135
- if ( this["on" + event.type] )
136
- this["on" + event.type].call( self, event );
137
- }
138
- };
139
-
140
- // DOM Document
141
-
142
- window.DOMDocument = function(file){
143
- this._file = file;
144
- var parser = new W3CDOMImplementation();
145
- try {
146
- this._dom = parser.loadXML(file);
147
- } catch(e) {
148
- Ruby.puts("*** wycats to fix: " + parser.translateErrCode(e.code));
149
- throw parser.translateErrCode(e.code);
150
- }
151
-
152
- if ( !obj_nodes["key?"]( this._dom ) )
153
- obj_nodes[this._dom] = this;
154
- };
155
-
156
- DOMDocument.prototype = {
157
- nodeType: 1,
158
- write: function(str) {
159
- if (typeof(write_output) != 'undefined')
160
- write_output += str;
161
- },
162
- createTextNode: function(text){
163
- return makeNode( this._dom.createTextNode(
164
- text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")) );
165
- },
166
- createElement: function(name){
167
- return makeNode( this._dom.createElement(name.toLowerCase()) );
168
- },
169
- getElementsByTagName: function(name){
170
- return new DOMNodeList( this._dom.getElementsByTagName(
171
- name.toLowerCase()) );
172
- },
173
- getElementById: function(id){
174
- return makeNode( this._dom.getElementById(id) );
175
- },
176
- get body(){
177
- return this.getElementsByTagName("body")[0];
178
- },
179
- get documentElement(){
180
- return makeNode( this._dom.getDocumentElement() );
181
- },
182
- get ownerDocument(){
183
- return null;
184
- },
185
- addEventListener: window.addEventListener,
186
- removeEventListener: window.removeEventListener,
187
- dispatchEvent: window.dispatchEvent,
188
- get nodeName() {
189
- return "#document";
190
- },
191
- importNode: function(node, deep){
192
- return makeNode( this._dom.importNode(node._dom, deep) );
193
- },
194
- toString: function(){
195
- return "Document" + (typeof this._file == "string" ?
196
- ": " + this._file : "");
197
- },
198
- get innerHTML(){
199
- return this.documentElement.outerHTML;
200
- },
201
-
202
- get defaultView(){
203
- return {
204
- getComputedStyle: function(elem){
205
- return {
206
- getPropertyValue: function(prop){
207
- prop = prop.replace(/\-(\w)/g,function(m,c){
208
- return c.toUpperCase();
209
- });
210
- var val = elem.style[prop];
211
-
212
- if ( prop === "opacity" && val === "" )
213
- val = "1";
214
-
215
- return val;
216
- }
217
- };
218
- }
219
- };
220
- },
221
-
222
- createEvent: function(){
223
- return {
224
- type: "",
225
- initEvent: function(type){
226
- this.type = type;
227
- }
228
- };
229
- }
230
- };
231
-
232
- function getDocument(node){
233
- return obj_nodes[node];
234
- }
235
-
236
- // DOM NodeList
237
-
238
- window.DOMNodeList = function(list){
239
- this._dom = list;
240
- this.length = list.getLength();
241
-
242
- for ( var i = 0; i < this.length; i++ ) {
243
- var node = list.item(i);
244
- this[i] = makeNode( node );
245
- }
246
- };
247
-
248
- DOMNodeList.prototype = {
249
- toString: function(){
250
- return "[ " +
251
- Array.prototype.join.call( this, ", " ) + " ]";
252
- },
253
- get outerHTML(){
254
- return Array.prototype.map.call(
255
- this, function(node){return node.outerHTML;}).join('');
256
- }
257
- };
258
-
259
- // DOM Node
260
-
261
- window.DOMNode = function(node){
262
- this._dom = node;
263
- };
264
-
265
- DOMNode.prototype = {
266
- get nodeType(){
267
- return this._dom.getNodeType();
268
- },
269
- get nodeValue(){
270
- return this._dom.getNodeValue();
271
- },
272
- get nodeName() {
273
- return this._dom.getNodeName();
274
- },
275
- cloneNode: function(deep){
276
- return makeNode( this._dom.cloneNode(deep) );
277
- },
278
- get ownerDocument(){
279
- return getDocument( this._dom.getOwnerDocument() );
280
- },
281
- get documentElement(){
282
- return makeNode( this._dom.getDocumentElement() );
283
- },
284
- get parentNode() {
285
- return makeNode( this._dom.getParentNode() );
286
- },
287
- get nextSibling() {
288
- return makeNode( this._dom.getNextSibling() );
289
- },
290
- get previousSibling() {
291
- return makeNode( this._dom.getPreviousSibling() );
292
- },
293
- toString: function(){
294
- return '"' + this.nodeValue + '"';
295
- },
296
- get outerHTML(){
297
- return this.nodeValue;
298
- }
299
- };
300
-
301
- // DOM Element
302
-
303
- window.DOMElement = function(elem){
304
- this._dom = elem;
305
- this.style = {
306
- get opacity(){ return this._opacity; },
307
- set opacity(val){ this._opacity = val + ""; }
308
- };
309
-
310
- // Load CSS info
311
- var styles = (this.getAttribute("style") || "").split(/\s*;\s*/);
312
-
313
- for ( var i = 0; i < styles.length; i++ ) {
314
- var style = styles[i].split(/\s*:\s*/);
315
- if ( style.length == 2 )
316
- this.style[ style[0] ] = style[1];
317
- }
318
- };
319
-
320
- DOMElement.prototype = extend( new DOMNode(), {
321
- get nodeName(){
322
- return this.tagName.toUpperCase();
323
- },
324
- get tagName(){
325
- return this._dom.getTagName().toUpperCase();
326
- },
327
- toString: function(){
328
- return "<" + this.tagName + (this.id ? "#" + this.id : "" ) + ">";
329
- },
330
- get outerHTML(){
331
- var ret = "<" + this.tagName, attr = this.attributes;
332
-
333
- for ( var i in attr )
334
- ret += " " + i + "='" + attr[i] + "'";
335
-
336
- if ( this.childNodes.length || this.nodeName == "SCRIPT" )
337
- ret += ">" + this.childNodes.outerHTML +
338
- "</" + this.tagName + ">";
339
- else
340
- ret += "/>";
341
-
342
- return ret;
343
- },
344
-
345
- get attributes(){
346
- var attr = {}, attrs = this._dom.getAttributes();
347
-
348
- for ( var i = 0; i < attrs.getLength(); i++ )
349
- attr[ attrs.item(i).nodeName ] = attrs.item(i).nodeValue;
350
-
351
- return attr;
352
- },
353
-
354
- get innerHTML(){
355
- return this.childNodes.outerHTML;
356
- },
357
- set innerHTML(html){
358
- html = html.replace(/<\/?([A-Z]+)/g, function(m){
359
- return m.toLowerCase();
360
- });
361
-
362
- var nodes = this.ownerDocument.importNode(
363
- new DOMDocument( html ).documentElement, true
364
- ).childNodes;
365
-
366
- while (this.firstChild)
367
- this.removeChild( this.firstChild );
368
-
369
- for ( var i = 0; i < nodes.length; i++ )
370
- this.appendChild( nodes[i] );
371
- },
372
-
373
- get textContent(){
374
- function nav(nodes){
375
- var str = "";
376
- for ( var i = 0; i < nodes.length; i++ ) {
377
- if ( nodes[i].nodeType == 3 )
378
- str += nodes[i].nodeValue;
379
- else if ( nodes[i].nodeType == 1 )
380
- str += nav(nodes[i].childNodes);
381
- }
382
- return str;
383
- }
384
-
385
- return nav(this.childNodes);
386
- },
387
- set textContent(text){
388
- while (this.firstChild)
389
- this.removeChild( this.firstChild );
390
- this.appendChild( this.ownerDocument.createTextNode(text) );
391
- },
392
-
393
- style: {},
394
- clientHeight: 0,
395
- clientWidth: 0,
396
- offsetHeight: 0,
397
- offsetWidth: 0,
398
-
399
- get disabled() {
400
- var val = this.getAttribute("disabled");
401
- return val != "false" && !!val;
402
- },
403
- set disabled(val) { return this.setAttribute("disabled",val); },
404
-
405
- get checked() {
406
- var val = this.getAttribute("checked");
407
- return val != "false" && !!val;
408
- },
409
- set checked(val) { return this.setAttribute("checked",val); },
410
-
411
- get selected() {
412
- if ( !this._selectDone ) {
413
- this._selectDone = true;
414
-
415
- if ( this.nodeName == "OPTION" && !this.parentNode.getAttribute("multiple") ) {
416
- var opt = this.parentNode.getElementsByTagName("option");
417
-
418
- if ( this == opt[0] ) {
419
- var select = true;
420
-
421
- for ( var i = 1; i < opt.length; i++ ) {
422
- if ( opt[i].selected ) {
423
- select = false;
424
- break;
425
- }
426
- }
427
-
428
- if ( select )
429
- this.selected = true;
430
- }
431
- }
432
- }
433
-
434
- var val = this.getAttribute("selected");
435
- return val != "false" && !!val;
436
- },
437
- set selected(val) { return this.setAttribute("selected",val); },
438
-
439
- get className() { return this.getAttribute("class") || ""; },
440
- set className(val) {
441
- return this.setAttribute("class",
442
- val.replace(/(^\s*|\s*$)/g,""));
443
- },
444
-
445
- get type() { return this.getAttribute("type") || ""; },
446
- set type(val) { return this.setAttribute("type",val); },
447
-
448
- get value() { return this.getAttribute("value") || ""; },
449
- set value(val) { return this.setAttribute("value",val); },
450
-
451
- get src() { return this.getAttribute("src") || ""; },
452
- set src(val) { return this.setAttribute("src",val); },
453
-
454
- get id() { return this.getAttribute("id") || ""; },
455
- set id(val) { return this.setAttribute("id",val); },
456
-
457
- getAttribute: function(name){
458
- return this._dom.hasAttribute(name) ?
459
- new String( this._dom.getAttribute(name) ) :
460
- null;
461
- },
462
- setAttribute: function(name,value){
463
- this._dom.setAttribute(name,value);
464
- },
465
- removeAttribute: function(name){
466
- this._dom.removeAttribute(name);
467
- },
468
-
469
- get childNodes(){
470
- return new DOMNodeList( this._dom.getChildNodes() );
471
- },
472
- get firstChild(){
473
- return makeNode( this._dom.getFirstChild() );
474
- },
475
- get lastChild(){
476
- return makeNode( this._dom.getLastChild() );
477
- },
478
- appendChild: function(node){
479
- this._dom.appendChild( node._dom );
480
- },
481
- insertBefore: function(node,before){
482
- this._dom.insertBefore( node._dom, before ? before._dom : before );
483
- },
484
- removeChild: function(node){
485
- this._dom.removeChild( node._dom );
486
- },
487
-
488
- getElementsByTagName: DOMDocument.prototype.getElementsByTagName,
489
-
490
- addEventListener: window.addEventListener,
491
- removeEventListener: window.removeEventListener,
492
- dispatchEvent: window.dispatchEvent,
493
-
494
- click: function(){
495
- var event = document.createEvent();
496
- event.initEvent("click");
497
- this.dispatchEvent(event);
498
- },
499
- submit: function(){
500
- var event = document.createEvent();
501
- event.initEvent("submit");
502
- this.dispatchEvent(event);
503
- },
504
- focus: function(){
505
- var event = document.createEvent();
506
- event.initEvent("focus");
507
- this.dispatchEvent(event);
508
- },
509
- blur: function(){
510
- var event = document.createEvent();
511
- event.initEvent("blur");
512
- this.dispatchEvent(event);
513
- },
514
- get elements(){
515
- return this.getElementsByTagName("*");
516
- },
517
- get contentWindow(){
518
- return this.nodeName == "IFRAME" ? {
519
- document: this.contentDocument
520
- } : null;
521
- },
522
- get contentDocument(){
523
- if ( this.nodeName == "IFRAME" ) {
524
- if ( !this._doc )
525
- this._doc = new DOMDocument(
526
- "<html><head><title></title></head><body></body></html>"
527
- );
528
- return this._doc;
529
- } else
530
- return null;
531
- }
532
- });
533
-
534
- DOMElement.prototype.toString = function() {
535
- return "<" + this.tagName + (this.className !== "" ? " class='" + this.className + "'" : "") +
536
- (this.id !== "" ? " id='" + this.id + "'" : "") + ">";
537
- };
538
-
539
- // Helper method for extending one object with another
540
-
541
- function extend(a,b) {
542
- for ( var i in b ) {
543
- var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i);
544
-
545
- if ( g || s ) {
546
- if ( g )
547
- a.__defineGetter__(i, g);
548
- if ( s )
549
- a.__defineSetter__(i, s);
550
- } else
551
- a[i] = b[i];
552
- }
553
- return a;
554
- }
555
-
556
- // Helper method for generating the right
557
- // DOM objects based upon the type
558
-
559
- var obj_nodes = new Ruby.Hash;
560
-
561
- function makeNode(node){
562
- if ( node ) {
563
- if ( !obj_nodes['key?']( node ) )
564
- obj_nodes[node] = node.getNodeType() ==
565
- W3CDOMNode.ELEMENT_NODE ?
566
- new DOMElement( node ) : new DOMNode( node );
567
-
568
- return obj_nodes[node];
569
- } else
570
- return null;
571
- }
572
-
573
- // XMLHttpRequest
574
- // Originally implemented by Yehuda Katz
575
-
576
- window.XMLHttpRequest = function(){
577
- this.headers = {};
578
- this.responseHeaders = {};
579
- };
580
-
581
- XMLHttpRequest.prototype = {
582
- open: function(method, url, async, user, password){
583
- this.readyState = 1;
584
- if (async)
585
- this.async = true;
586
- this.method = method || "GET";
587
- this.url = url;
588
- this.onreadystatechange();
589
- },
590
- setRequestHeader: function(header, value){
591
- this.headers[header] = value;
592
- },
593
- getResponseHeader: function(header){ },
594
- send: function(data){
595
- var self = this;
596
-
597
- function makeRequest(){
598
- var url = curLocation.merge(self.url);
599
- var connection;
600
-
601
- if ( url.scheme == "file" ) {
602
- if ( self.method == "PUT" ) {
603
- var out = new Ruby.File(url.path);
604
- var text = data || "";
605
-
606
- out.puts( text );
607
- out.flush();
608
- out.close();
609
- } else if ( self.method == "DELETE" ) {
610
- var file = new Ruby.File(url.path());
611
- file["delete"]();
612
- } else if ( self.method == "GET" ) {
613
- var file = Ruby.File.read(url.path);
614
- connection = {
615
- code: "200",
616
- message: "Ok",
617
- body: file,
618
- }
619
- handleResponse();
620
- } else {
621
- connection = Ruby.Net.HTTP.start(url.host, url.port, function(http) {
622
- http.get(url.path);
623
- });
624
- handleResponse();
625
- }
626
- } else {
627
- var http = Ruby.Net.HTTP.new(url.host, url.port);
628
- var request = new Ruby.Net.HTTP.Get(url.path);
629
- for (var header in self.headers)
630
- request.add_field(header, self.headers[header]);
631
-
632
- var connection = http.request(request);
633
- connection.each_header(function(k,v) {
634
- self.responseHeaders[k] = v;
635
- });
636
-
637
- handleResponse();
638
- }
639
-
640
- function handleResponse(){
641
- self.readyState = 4;
642
- self.status = parseInt(connection.code) || undefined;
643
- self.statusText = connection.message || "";
644
-
645
- self.responseText = connection.body;
646
-
647
- self.responseXML = null;
648
-
649
- if ( self.responseText.match(/^\s*</) ) {
650
- self.responseXML = new DOMDocument( self.responseText );
651
- }
652
- }
653
-
654
- self.onreadystatechange();
655
- }
656
-
657
- if (this.async)
658
- new Ruby.Thread(function() { makeRequest(); });
659
- else
660
- makeRequest();
661
- },
662
- abort: function(){},
663
- onreadystatechange: function(){},
664
- getResponseHeader: function(header){
665
- if (this.readyState < 3)
666
- throw new Error("INVALID_STATE_ERR");
667
- else {
668
- var returnedHeaders = [];
669
- for (var rHeader in this.responseHeaders) {
670
- if (rHeader.match(new Regexp(header, "i")))
671
- returnedHeaders.push(this.responseHeaders[rHeader]);
672
- }
673
-
674
- if (returnedHeaders.length)
675
- return returnedHeaders.join(", ");
676
- }
677
-
678
- return null;
679
- },
680
- getAllResponseHeaders: function(header){
681
- if (this.readyState < 3)
682
- throw new Error("INVALID_STATE_ERR");
683
- else {
684
- var returnedHeaders = [];
685
-
686
- for (var aHeader in this.responseHeaders)
687
- returnedHeaders.push( aHeader + ": " + this.responseHeaders[aHeader] );
688
-
689
- return returnedHeaders.join("\r\n");
690
- }
691
- },
692
- async: true,
693
- readyState: 0,
694
- responseText: "",
695
- status: 0
696
- };
697
- })();
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
+ //Ruby.require("uri");
11
+
12
+ print = function(txt) { Ruby.puts(txt); };
13
+
14
+ (function(){
15
+
16
+ // Browser Navigator
17
+
18
+ window.navigator = {
19
+ get userAgent(){
20
+ return "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3";
21
+ }
22
+ };
23
+ /*
24
+ var fileToUrl = function(file) {
25
+ return Ruby.URI.parse("file://" + Ruby.File.expand_path(file));
26
+ };
27
+
28
+ var curLocation = fileToUrl(".");
29
+ /*
30
+ window.__defineSetter__("location", function(url){
31
+ var xhr = new XMLHttpRequest();
32
+ xhr.open("GET", url);
33
+ xhr.onreadystatechange = function(){
34
+ curLocation = curLocation.merge(url);
35
+ window.document = xhr.responseXML;
36
+
37
+ if(window.document) {
38
+ var event = document.createEvent();
39
+ event.initEvent("load");
40
+ window.dispatchEvent( event );
41
+ }
42
+ };
43
+ xhr.send();
44
+ });
45
+
46
+ window.__defineGetter__("location", function(url){
47
+ return {
48
+ get protocol(){
49
+ return curLocation.scheme() + ":";
50
+ },
51
+ get href(){
52
+ return curLocation.toString();
53
+ },
54
+ toString: function(){
55
+ return this.href.toString();
56
+ }
57
+ };
58
+ });
59
+ */
60
+
61
+ // Timers
62
+
63
+ var timers = [];
64
+
65
+ window.setTimeout = function(fn, time){
66
+ var num;
67
+ return num = setInterval(function(){
68
+ fn();
69
+ clearInterval(num);
70
+ }, time);
71
+ };
72
+
73
+ window.setInterval = function(fn, time){
74
+ var num = timers.length;
75
+
76
+ timers[num] = new Ruby.Thread(function() {
77
+ while(true) {
78
+ Ruby.sleep(time);
79
+ fn();
80
+ }
81
+ });
82
+
83
+ return num;
84
+ };
85
+
86
+ window.clearInterval = function(num){
87
+ if ( timers[num] ) {
88
+ timers[num].kill();
89
+ delete timers[num];
90
+ }
91
+ };
92
+
93
+ // Window Events
94
+
95
+ var events = [{}];
96
+
97
+ window.addEventListener = function(type, fn){
98
+ if ( !this.uuid || this == window ) {
99
+ this.uuid = events.length;
100
+ events[this.uuid] = {};
101
+ }
102
+
103
+ if ( !events[this.uuid][type] )
104
+ events[this.uuid][type] = [];
105
+
106
+ if ( events[this.uuid][type].indexOf( fn ) < 0 )
107
+ events[this.uuid][type].push( fn );
108
+ };
109
+
110
+ window.removeEventListener = function(type, fn){
111
+ if ( !this.uuid || this == window ) {
112
+ this.uuid = events.length;
113
+ events[this.uuid] = {};
114
+ }
115
+
116
+ if ( !events[this.uuid][type] )
117
+ events[this.uuid][type] = [];
118
+
119
+ events[this.uuid][type] =
120
+ events[this.uuid][type].filter(function(f){
121
+ return f != fn;
122
+ });
123
+ };
124
+
125
+ window.dispatchEvent = function(event){
126
+ if ( event.type ) {
127
+ if ( this.uuid && events[this.uuid][event.type] ) {
128
+ var self = this;
129
+
130
+ events[this.uuid][event.type].forEach(function(fn){
131
+ fn.call( self, event );
132
+ });
133
+ }
134
+
135
+ if ( this["on" + event.type] )
136
+ this["on" + event.type].call( self, event );
137
+ }
138
+ };
139
+
140
+ // DOM Document
141
+
142
+ window.DOMDocument = function(file){
143
+ this._file = file;
144
+ var parser = new W3CDOMImplementation();
145
+ try {
146
+ this._dom = parser.loadXML(file);
147
+ } catch(e) {
148
+ Ruby.puts("*** wycats to fix: " + parser.translateErrCode(e.code));
149
+ throw parser.translateErrCode(e.code);
150
+ }
151
+
152
+ if ( !obj_nodes["key?"]( this._dom ) )
153
+ obj_nodes[this._dom] = this;
154
+ };
155
+
156
+ DOMDocument.prototype = {
157
+ nodeType: 1,
158
+ write: function(str) {
159
+ if (typeof(write_output) != 'undefined')
160
+ write_output += str;
161
+ },
162
+ createTextNode: function(text){
163
+ return makeNode( this._dom.createTextNode(
164
+ text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")) );
165
+ },
166
+ createElement: function(name){
167
+ return makeNode( this._dom.createElement(name.toLowerCase()) );
168
+ },
169
+ getElementsByTagName: function(name){
170
+ return new DOMNodeList( this._dom.getElementsByTagName(
171
+ name.toLowerCase()) );
172
+ },
173
+ getElementById: function(id){
174
+ return makeNode( this._dom.getElementById(id) );
175
+ },
176
+ get body(){
177
+ return this.getElementsByTagName("body")[0];
178
+ },
179
+ get documentElement(){
180
+ return makeNode( this._dom.getDocumentElement() );
181
+ },
182
+ get ownerDocument(){
183
+ return null;
184
+ },
185
+ addEventListener: window.addEventListener,
186
+ removeEventListener: window.removeEventListener,
187
+ dispatchEvent: window.dispatchEvent,
188
+ get nodeName() {
189
+ return "#document";
190
+ },
191
+ importNode: function(node, deep){
192
+ return makeNode( this._dom.importNode(node._dom, deep) );
193
+ },
194
+ toString: function(){
195
+ return "Document" + (typeof this._file == "string" ?
196
+ ": " + this._file : "");
197
+ },
198
+ get innerHTML(){
199
+ return this.documentElement.outerHTML;
200
+ },
201
+
202
+ get defaultView(){
203
+ return {
204
+ getComputedStyle: function(elem){
205
+ return {
206
+ getPropertyValue: function(prop){
207
+ prop = prop.replace(/\-(\w)/g,function(m,c){
208
+ return c.toUpperCase();
209
+ });
210
+ var val = elem.style[prop];
211
+
212
+ if ( prop === "opacity" && val === "" )
213
+ val = "1";
214
+
215
+ return val;
216
+ }
217
+ };
218
+ }
219
+ };
220
+ },
221
+
222
+ createEvent: function(){
223
+ return {
224
+ type: "",
225
+ initEvent: function(type){
226
+ this.type = type;
227
+ }
228
+ };
229
+ }
230
+ };
231
+
232
+ function getDocument(node){
233
+ return obj_nodes[node];
234
+ }
235
+
236
+ // DOM NodeList
237
+
238
+ window.DOMNodeList = function(list){
239
+ this._dom = list;
240
+ this.length = list.getLength();
241
+
242
+ for ( var i = 0; i < this.length; i++ ) {
243
+ var node = list.item(i);
244
+ this[i] = makeNode( node );
245
+ }
246
+ };
247
+
248
+ DOMNodeList.prototype = {
249
+ toString: function(){
250
+ return "[ " +
251
+ Array.prototype.join.call( this, ", " ) + " ]";
252
+ },
253
+ get outerHTML(){
254
+ return Array.prototype.map.call(
255
+ this, function(node){return node.outerHTML;}).join('');
256
+ }
257
+ };
258
+
259
+ // DOM Node
260
+
261
+ window.DOMNode = function(node){
262
+ this._dom = node;
263
+ };
264
+
265
+ DOMNode.prototype = {
266
+ get nodeType(){
267
+ return this._dom.getNodeType();
268
+ },
269
+ get nodeValue(){
270
+ return this._dom.getNodeValue();
271
+ },
272
+ get nodeName() {
273
+ return this._dom.getNodeName();
274
+ },
275
+ cloneNode: function(deep){
276
+ return makeNode( this._dom.cloneNode(deep) );
277
+ },
278
+ get ownerDocument(){
279
+ return getDocument( this._dom.getOwnerDocument() );
280
+ },
281
+ get documentElement(){
282
+ return makeNode( this._dom.getDocumentElement() );
283
+ },
284
+ get parentNode() {
285
+ return makeNode( this._dom.getParentNode() );
286
+ },
287
+ get nextSibling() {
288
+ return makeNode( this._dom.getNextSibling() );
289
+ },
290
+ get previousSibling() {
291
+ return makeNode( this._dom.getPreviousSibling() );
292
+ },
293
+ toString: function(){
294
+ return '"' + this.nodeValue + '"';
295
+ },
296
+ get outerHTML(){
297
+ return this.nodeValue;
298
+ }
299
+ };
300
+
301
+ // DOM Element
302
+
303
+ window.DOMElement = function(elem){
304
+ this._dom = elem;
305
+ this.style = {
306
+ get opacity(){ return this._opacity; },
307
+ set opacity(val){ this._opacity = val + ""; }
308
+ };
309
+
310
+ // Load CSS info
311
+ var styles = (this.getAttribute("style") || "").split(/\s*;\s*/);
312
+
313
+ for ( var i = 0; i < styles.length; i++ ) {
314
+ var style = styles[i].split(/\s*:\s*/);
315
+ if ( style.length == 2 )
316
+ this.style[ style[0] ] = style[1];
317
+ }
318
+ };
319
+
320
+ DOMElement.prototype = extend( new DOMNode(), {
321
+ get nodeName(){
322
+ return this.tagName.toUpperCase();
323
+ },
324
+ get tagName(){
325
+ return this._dom.getTagName().toUpperCase();
326
+ },
327
+ toString: function(){
328
+ return "<" + this.tagName + (this.id ? "#" + this.id : "" ) + ">";
329
+ },
330
+ get outerHTML(){
331
+ var ret = "<" + this.tagName, attr = this.attributes;
332
+
333
+ for ( var i in attr )
334
+ ret += " " + i + "='" + attr[i] + "'";
335
+
336
+ if ( this.childNodes.length || this.nodeName == "SCRIPT" )
337
+ ret += ">" + this.childNodes.outerHTML +
338
+ "</" + this.tagName + ">";
339
+ else
340
+ ret += "/>";
341
+
342
+ return ret;
343
+ },
344
+
345
+ get attributes(){
346
+ var attr = {}, attrs = this._dom.getAttributes();
347
+
348
+ for ( var i = 0; i < attrs.getLength(); i++ )
349
+ attr[ attrs.item(i).nodeName ] = attrs.item(i).nodeValue;
350
+
351
+ return attr;
352
+ },
353
+
354
+ get innerHTML(){
355
+ return this.childNodes.outerHTML;
356
+ },
357
+ set innerHTML(html){
358
+ html = html.replace(/<\/?([A-Z]+)/g, function(m){
359
+ return m.toLowerCase();
360
+ });
361
+
362
+ var nodes = this.ownerDocument.importNode(
363
+ new DOMDocument( html ).documentElement, true
364
+ ).childNodes;
365
+
366
+ while (this.firstChild)
367
+ this.removeChild( this.firstChild );
368
+
369
+ for ( var i = 0; i < nodes.length; i++ )
370
+ this.appendChild( nodes[i] );
371
+ },
372
+
373
+ get textContent(){
374
+ function nav(nodes){
375
+ var str = "";
376
+ for ( var i = 0; i < nodes.length; i++ ) {
377
+ if ( nodes[i].nodeType == 3 )
378
+ str += nodes[i].nodeValue;
379
+ else if ( nodes[i].nodeType == 1 )
380
+ str += nav(nodes[i].childNodes);
381
+ }
382
+ return str;
383
+ }
384
+
385
+ return nav(this.childNodes);
386
+ },
387
+ set textContent(text){
388
+ while (this.firstChild)
389
+ this.removeChild( this.firstChild );
390
+ this.appendChild( this.ownerDocument.createTextNode(text) );
391
+ },
392
+
393
+ style: {},
394
+ clientHeight: 0,
395
+ clientWidth: 0,
396
+ offsetHeight: 0,
397
+ offsetWidth: 0,
398
+
399
+ get disabled() {
400
+ var val = this.getAttribute("disabled");
401
+ return val != "false" && !!val;
402
+ },
403
+ set disabled(val) { return this.setAttribute("disabled",val); },
404
+
405
+ get checked() {
406
+ var val = this.getAttribute("checked");
407
+ return val != "false" && !!val;
408
+ },
409
+ set checked(val) { return this.setAttribute("checked",val); },
410
+
411
+ get selected() {
412
+ if ( !this._selectDone ) {
413
+ this._selectDone = true;
414
+
415
+ if ( this.nodeName == "OPTION" && !this.parentNode.getAttribute("multiple") ) {
416
+ var opt = this.parentNode.getElementsByTagName("option");
417
+
418
+ if ( this == opt[0] ) {
419
+ var select = true;
420
+
421
+ for ( var i = 1; i < opt.length; i++ ) {
422
+ if ( opt[i].selected ) {
423
+ select = false;
424
+ break;
425
+ }
426
+ }
427
+
428
+ if ( select )
429
+ this.selected = true;
430
+ }
431
+ }
432
+ }
433
+
434
+ var val = this.getAttribute("selected");
435
+ return val != "false" && !!val;
436
+ },
437
+ set selected(val) { return this.setAttribute("selected",val); },
438
+
439
+ get className() { return this.getAttribute("class") || ""; },
440
+ set className(val) {
441
+ return this.setAttribute("class",
442
+ val.replace(/(^\s*|\s*$)/g,""));
443
+ },
444
+
445
+ get type() { return this.getAttribute("type") || ""; },
446
+ set type(val) { return this.setAttribute("type",val); },
447
+
448
+ get value() { return this.getAttribute("value") || ""; },
449
+ set value(val) { return this.setAttribute("value",val); },
450
+
451
+ get src() { return this.getAttribute("src") || ""; },
452
+ set src(val) { return this.setAttribute("src",val); },
453
+
454
+ get id() { return this.getAttribute("id") || ""; },
455
+ set id(val) { return this.setAttribute("id",val); },
456
+
457
+ getAttribute: function(name){
458
+ return this._dom.hasAttribute(name) ?
459
+ new String( this._dom.getAttribute(name) ) :
460
+ null;
461
+ },
462
+ setAttribute: function(name,value){
463
+ this._dom.setAttribute(name,value);
464
+ },
465
+ removeAttribute: function(name){
466
+ this._dom.removeAttribute(name);
467
+ },
468
+
469
+ get childNodes(){
470
+ return new DOMNodeList( this._dom.getChildNodes() );
471
+ },
472
+ get firstChild(){
473
+ return makeNode( this._dom.getFirstChild() );
474
+ },
475
+ get lastChild(){
476
+ return makeNode( this._dom.getLastChild() );
477
+ },
478
+ appendChild: function(node){
479
+ this._dom.appendChild( node._dom );
480
+ },
481
+ insertBefore: function(node,before){
482
+ this._dom.insertBefore( node._dom, before ? before._dom : before );
483
+ },
484
+ removeChild: function(node){
485
+ this._dom.removeChild( node._dom );
486
+ },
487
+
488
+ getElementsByTagName: DOMDocument.prototype.getElementsByTagName,
489
+
490
+ addEventListener: window.addEventListener,
491
+ removeEventListener: window.removeEventListener,
492
+ dispatchEvent: window.dispatchEvent,
493
+
494
+ click: function(){
495
+ var event = document.createEvent();
496
+ event.initEvent("click");
497
+ this.dispatchEvent(event);
498
+ },
499
+ submit: function(){
500
+ var event = document.createEvent();
501
+ event.initEvent("submit");
502
+ this.dispatchEvent(event);
503
+ },
504
+ focus: function(){
505
+ var event = document.createEvent();
506
+ event.initEvent("focus");
507
+ this.dispatchEvent(event);
508
+ },
509
+ blur: function(){
510
+ var event = document.createEvent();
511
+ event.initEvent("blur");
512
+ this.dispatchEvent(event);
513
+ },
514
+ get elements(){
515
+ return this.getElementsByTagName("*");
516
+ },
517
+ get contentWindow(){
518
+ return this.nodeName == "IFRAME" ? {
519
+ document: this.contentDocument
520
+ } : null;
521
+ },
522
+ get contentDocument(){
523
+ if ( this.nodeName == "IFRAME" ) {
524
+ if ( !this._doc )
525
+ this._doc = new DOMDocument(
526
+ "<html><head><title></title></head><body></body></html>"
527
+ );
528
+ return this._doc;
529
+ } else
530
+ return null;
531
+ }
532
+ });
533
+
534
+ DOMElement.prototype.toString = function() {
535
+ return "<" + this.tagName + (this.className !== "" ? " class='" + this.className + "'" : "") +
536
+ (this.id !== "" ? " id='" + this.id + "'" : "") + ">";
537
+ };
538
+
539
+ // Helper method for extending one object with another
540
+
541
+ function extend(a,b) {
542
+ for ( var i in b ) {
543
+ var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i);
544
+
545
+ if ( g || s ) {
546
+ if ( g )
547
+ a.__defineGetter__(i, g);
548
+ if ( s )
549
+ a.__defineSetter__(i, s);
550
+ } else
551
+ a[i] = b[i];
552
+ }
553
+ return a;
554
+ }
555
+
556
+ // Helper method for generating the right
557
+ // DOM objects based upon the type
558
+
559
+ var obj_nodes = new Ruby.Hash;
560
+
561
+ function makeNode(node){
562
+ if ( node ) {
563
+ if ( !obj_nodes['key?']( node ) )
564
+ obj_nodes[node] = node.getNodeType() ==
565
+ W3CDOMNode.ELEMENT_NODE ?
566
+ new DOMElement( node ) : new DOMNode( node );
567
+
568
+ return obj_nodes[node];
569
+ } else
570
+ return null;
571
+ }
572
+
573
+ // XMLHttpRequest
574
+ // Originally implemented by Yehuda Katz
575
+
576
+ window.XMLHttpRequest = function(){
577
+ this.headers = {};
578
+ this.responseHeaders = {};
579
+ };
580
+
581
+ XMLHttpRequest.prototype = {
582
+ open: function(method, url, async, user, password){
583
+ this.readyState = 1;
584
+ if (async)
585
+ this.async = true;
586
+ this.method = method || "GET";
587
+ this.url = url;
588
+ this.onreadystatechange();
589
+ },
590
+ setRequestHeader: function(header, value){
591
+ this.headers[header] = value;
592
+ },
593
+ getResponseHeader: function(header){ },
594
+ send: function(data){
595
+ var self = this;
596
+
597
+ function makeRequest(){
598
+ var url = curLocation.merge(self.url);
599
+ var connection;
600
+
601
+ if ( url.scheme == "file" ) {
602
+ if ( self.method == "PUT" ) {
603
+ var out = new Ruby.File(url.path);
604
+ var text = data || "";
605
+
606
+ out.puts( text );
607
+ out.flush();
608
+ out.close();
609
+ } else if ( self.method == "DELETE" ) {
610
+ var file = new Ruby.File(url.path());
611
+ file["delete"]();
612
+ } else if ( self.method == "GET" ) {
613
+ var file = Ruby.File.read(url.path);
614
+ connection = {
615
+ code: "200",
616
+ message: "Ok",
617
+ body: file,
618
+ }
619
+ handleResponse();
620
+ } else {
621
+ connection = Ruby.Net.HTTP.start(url.host, url.port, function(http) {
622
+ http.get(url.path);
623
+ });
624
+ handleResponse();
625
+ }
626
+ } else {
627
+ var http = Ruby.Net.HTTP.new(url.host, url.port);
628
+ var request = new Ruby.Net.HTTP.Get(url.path);
629
+ for (var header in self.headers)
630
+ request.add_field(header, self.headers[header]);
631
+
632
+ var connection = http.request(request);
633
+ connection.each_header(function(k,v) {
634
+ self.responseHeaders[k] = v;
635
+ });
636
+
637
+ handleResponse();
638
+ }
639
+
640
+ function handleResponse(){
641
+ self.readyState = 4;
642
+ self.status = parseInt(connection.code) || undefined;
643
+ self.statusText = connection.message || "";
644
+
645
+ self.responseText = connection.body;
646
+
647
+ self.responseXML = null;
648
+
649
+ if ( self.responseText.match(/^\s*</) ) {
650
+ self.responseXML = new DOMDocument( self.responseText );
651
+ }
652
+ }
653
+
654
+ self.onreadystatechange();
655
+ }
656
+
657
+ if (this.async)
658
+ new Ruby.Thread(function() { makeRequest(); });
659
+ else
660
+ makeRequest();
661
+ },
662
+ abort: function(){},
663
+ onreadystatechange: function(){},
664
+ getResponseHeader: function(header){
665
+ if (this.readyState < 3)
666
+ throw new Error("INVALID_STATE_ERR");
667
+ else {
668
+ var returnedHeaders = [];
669
+ for (var rHeader in this.responseHeaders) {
670
+ if (rHeader.match(new Regexp(header, "i")))
671
+ returnedHeaders.push(this.responseHeaders[rHeader]);
672
+ }
673
+
674
+ if (returnedHeaders.length)
675
+ return returnedHeaders.join(", ");
676
+ }
677
+
678
+ return null;
679
+ },
680
+ getAllResponseHeaders: function(header){
681
+ if (this.readyState < 3)
682
+ throw new Error("INVALID_STATE_ERR");
683
+ else {
684
+ var returnedHeaders = [];
685
+
686
+ for (var aHeader in this.responseHeaders)
687
+ returnedHeaders.push( aHeader + ": " + this.responseHeaders[aHeader] );
688
+
689
+ return returnedHeaders.join("\r\n");
690
+ }
691
+ },
692
+ async: true,
693
+ readyState: 0,
694
+ responseText: "",
695
+ status: 0
696
+ };
697
+ })();