rhack 0.2.2
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/.gemtest +0 -0
- data/CURB-LICENSE +51 -0
- data/Gemfile +4 -0
- data/History.txt +4 -0
- data/LICENSE +51 -0
- data/License.txt +17 -0
- data/Manifest.txt +61 -0
- data/README.txt +12 -0
- data/Rakefile +34 -0
- data/ext/curb-original/curb.c +977 -0
- data/ext/curb-original/curb.h +52 -0
- data/ext/curb-original/curb_config.h +235 -0
- data/ext/curb-original/curb_easy.c +3455 -0
- data/ext/curb-original/curb_easy.h +90 -0
- data/ext/curb-original/curb_errors.c +647 -0
- data/ext/curb-original/curb_errors.h +129 -0
- data/ext/curb-original/curb_macros.h +159 -0
- data/ext/curb-original/curb_multi.c +704 -0
- data/ext/curb-original/curb_multi.h +26 -0
- data/ext/curb-original/curb_postfield.c +523 -0
- data/ext/curb-original/curb_postfield.h +40 -0
- data/ext/curb-original/curb_upload.c +80 -0
- data/ext/curb-original/curb_upload.h +30 -0
- data/ext/curb/Makefile +157 -0
- data/ext/curb/curb.c +977 -0
- data/ext/curb/curb.h +52 -0
- data/ext/curb/curb_config.h +235 -0
- data/ext/curb/curb_easy.c +3430 -0
- data/ext/curb/curb_easy.h +94 -0
- data/ext/curb/curb_errors.c +647 -0
- data/ext/curb/curb_errors.h +129 -0
- data/ext/curb/curb_macros.h +159 -0
- data/ext/curb/curb_multi.c +710 -0
- data/ext/curb/curb_multi.h +26 -0
- data/ext/curb/curb_postfield.c +523 -0
- data/ext/curb/curb_postfield.h +40 -0
- data/ext/curb/curb_upload.c +80 -0
- data/ext/curb/curb_upload.h +30 -0
- data/ext/curb/extconf.rb +399 -0
- data/lib/cache.rb +44 -0
- data/lib/curl-global.rb +151 -0
- data/lib/extensions/browser/env.js +697 -0
- data/lib/extensions/browser/jquery.js +7180 -0
- data/lib/extensions/browser/xmlsax.js +1564 -0
- data/lib/extensions/browser/xmlw3cdom_1.js +1444 -0
- data/lib/extensions/browser/xmlw3cdom_2.js +2744 -0
- data/lib/extensions/curb.rb +125 -0
- data/lib/extensions/declarative.rb +153 -0
- data/lib/extensions/johnson.rb +63 -0
- data/lib/frame.rb +766 -0
- data/lib/init.rb +36 -0
- data/lib/rhack.rb +16 -0
- data/lib/rhack.yml.template +19 -0
- data/lib/rhack/proxy/checker.rb +226 -0
- data/lib/rhack/proxy/list.rb +196 -0
- data/lib/rhack/services.rb +445 -0
- data/lib/rhack_in.rb +2 -0
- data/lib/scout.rb +591 -0
- data/lib/words.rb +37 -0
- data/test/test_frame.rb +107 -0
- data/test/test_rhack.rb +5 -0
- data/test/test_scout.rb +53 -0
- metadata +195 -0
data/lib/cache.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module HTTPAccessKit
|
3
|
+
|
4
|
+
class Cache < ActiveRecord::Base
|
5
|
+
declare CacheTable do |t|
|
6
|
+
t.integer :url_hash
|
7
|
+
t.string :url
|
8
|
+
t.string :path
|
9
|
+
t.string :date
|
10
|
+
t.string :ext
|
11
|
+
t.timestamps
|
12
|
+
end if DB
|
13
|
+
RAMCache = {}
|
14
|
+
|
15
|
+
def self.clean(time=7.days)
|
16
|
+
destroy_all("created_at < '#{time.ago}'").each {|c|
|
17
|
+
FileUtils.remove c.path if c.path and File.file?(c.path)}
|
18
|
+
end
|
19
|
+
CacheTTL and clean CacheTTL
|
20
|
+
|
21
|
+
def self.save(url, data, cache_data=true)
|
22
|
+
new(url, data).save
|
23
|
+
RAMCache[url.href] = data if cache_data
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.load(url, cache_data=true)
|
27
|
+
if data = RAMCache[url.href]
|
28
|
+
data
|
29
|
+
elsif file = first(:select => 'date, path', :conditions => {:url_hash => url.href.hash})
|
30
|
+
RAMCache[url.href] = read(file.path) if cache_data
|
31
|
+
file
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(url, data)
|
36
|
+
t = Time.now
|
37
|
+
path = "#{CacheDir}/#{t.to_i}-#{File.split(url.path)[1]}"
|
38
|
+
rw path, data
|
39
|
+
super :url => url.href, :url_hash => url.href.hash, :date => t.httpdate, :path => path, :ext => url.ext
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/lib/curl-global.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Curl
|
3
|
+
|
4
|
+
def execute
|
5
|
+
# если ты ищешь, откуда оно запускается, то это наверное
|
6
|
+
# lib/extensions/johnson.rb:37:in `set_browser_for_curl'
|
7
|
+
if $CarierThread and s = $CarierThread.status
|
8
|
+
L.debug "Carier thread allready started and has status #{s}"
|
9
|
+
else
|
10
|
+
if s = Curl.status(false) then L.warn s end
|
11
|
+
L.debug($CarierThread ? "Resetting Carier thread" : "Setting Carier thread up")
|
12
|
+
$CarierThread = Thread.new {
|
13
|
+
error = nil
|
14
|
+
begin
|
15
|
+
# "why Thread#value is raising since it never raised before?"
|
16
|
+
yield if block_given?
|
17
|
+
rescue => error
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
loop {
|
21
|
+
begin
|
22
|
+
# with true argument (idle) it would break only if no requests to perform
|
23
|
+
break unless $Carier.perform true
|
24
|
+
L.debug "Nothing to perform; idling..."
|
25
|
+
rescue => error
|
26
|
+
break
|
27
|
+
# but ruby mystically crashes if next sequence occur:
|
28
|
+
# Multi performs and can't see any requests so entering idle mode
|
29
|
+
# we add some requests and multi load them
|
30
|
+
# one of requests' callbacks raises error in *main* thread
|
31
|
+
# so we can't allow any raises here, instead, keep them in 'wait' section
|
32
|
+
end
|
33
|
+
} unless error
|
34
|
+
error
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
alias :run :execute
|
39
|
+
module_function :execute, :run
|
40
|
+
|
41
|
+
def wait
|
42
|
+
if $CarierThread
|
43
|
+
if !(within = Thread.current == $CarierThread)
|
44
|
+
# We can't set `perform' timeout lesser than 1 second in the curl binding
|
45
|
+
# because in that case thread status would always be "run"
|
46
|
+
# so here we wait for exactly 1 sec
|
47
|
+
sleep 1
|
48
|
+
end
|
49
|
+
# Also, if thread do Kernel.sleep, it would skip Curl.wait here
|
50
|
+
if !$Carier.sheduled and ($CarierThread.status == 'sleep' or within && $Carier.reqs.empty?)
|
51
|
+
L.debug "No shedule to wait"
|
52
|
+
else
|
53
|
+
L.log "Waiting for Carier to complete in #{within ? 'it\'s thread' : Thread.main == Thread.current ? 'main thread' : 'thread '+Thread.current.object_id}"
|
54
|
+
begin
|
55
|
+
L.log { "Trying to change $CarierThreadIsJoined #{$CarierThreadIsJoined} -> true from #{within ? 'it\'s thread' : Thread.main == Thread.current ? 'main thread' : 'thread '+Thread.current.object_id}" }
|
56
|
+
if within
|
57
|
+
L.debug "calling this from one of callbacks to wait for the rest to complete"
|
58
|
+
begin
|
59
|
+
$Carier.perform
|
60
|
+
rescue RuntimeError => e
|
61
|
+
L.warn [e, e.message]
|
62
|
+
L.info "$Carier $Carier.sheduled $CarierThread $CarierThread.status", binding
|
63
|
+
L.warn "Failed to run Multi#perform: nothing to perform"
|
64
|
+
end
|
65
|
+
else
|
66
|
+
$CarierThreadIsJoined = true
|
67
|
+
$CarierThread.join
|
68
|
+
end
|
69
|
+
rescue (defined?(IRB) ? IRB::Abort : NilClass)
|
70
|
+
recall!
|
71
|
+
L.info "Carier thread recalled by keyboard"
|
72
|
+
ensure
|
73
|
+
L.log "trying to change $CarierThreadIsJoined #{$CarierThreadIsJoined} -> false from #{within ? 'it\'s' : 'main'} thread"
|
74
|
+
if !within
|
75
|
+
$CarierThreadIsJoined = false
|
76
|
+
if $CarierThread and e = $CarierThread.value
|
77
|
+
# this will raise thread-safely in main thread
|
78
|
+
# in case of unrescued error in CarierThread
|
79
|
+
recall!
|
80
|
+
raise e
|
81
|
+
end
|
82
|
+
execute
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
else
|
87
|
+
L.debug "No thread to wait"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
module_function :wait
|
91
|
+
|
92
|
+
def recall
|
93
|
+
L.debug caller
|
94
|
+
if $CarierThread
|
95
|
+
L.debug "Recalling Carier thread"
|
96
|
+
$CarierThread.kill
|
97
|
+
sleep 1
|
98
|
+
else
|
99
|
+
L.debug "No thread to recall"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
alias :stop :recall
|
103
|
+
|
104
|
+
def recall!
|
105
|
+
if $CarierThread
|
106
|
+
L.info "Recalling thread and resetting Carier!!!"
|
107
|
+
$CarierThread.kill
|
108
|
+
$CarierThread = nil
|
109
|
+
$Carier.reset
|
110
|
+
else
|
111
|
+
L.debug "No thread to recall!"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
alias :stop! :recall!
|
115
|
+
module_function :recall!, :stop!, :recall, :stop
|
116
|
+
|
117
|
+
def reset
|
118
|
+
recall
|
119
|
+
execute
|
120
|
+
end
|
121
|
+
|
122
|
+
def reset!
|
123
|
+
recall!
|
124
|
+
execute
|
125
|
+
end
|
126
|
+
module_function :reset!, :reset
|
127
|
+
|
128
|
+
def status(raise_e=true)
|
129
|
+
if $CarierThread and (s = $CarierThread.status)
|
130
|
+
L.log "Carier thread responding with status #{s}"
|
131
|
+
s
|
132
|
+
elsif $CarierThread
|
133
|
+
if e = $CarierThread.value
|
134
|
+
if raise_e
|
135
|
+
recall!
|
136
|
+
raise e
|
137
|
+
else
|
138
|
+
L.log "Carier Thread returned #{e.inspect}"
|
139
|
+
e
|
140
|
+
end
|
141
|
+
else
|
142
|
+
L.debug "Carier Thread is exited without error"
|
143
|
+
end
|
144
|
+
else
|
145
|
+
L.debug "There is no Carier Thread atm"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
alias :st :status
|
149
|
+
module_function :status, :st
|
150
|
+
|
151
|
+
end
|
@@ -0,0 +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, "&").replace(/</g, "<").replace(/>/g, ">")) );
|
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
|
+
})();
|