red 4.1.0 → 4.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +25 -0
- data/lib/red/version.rb +1 -1
- data/lib/source/redshift/accessors.rb +580 -0
- data/lib/source/redshift/browser.rb +150 -0
- data/lib/source/redshift/chainable.rb +75 -0
- data/lib/source/redshift/code_events.rb +204 -0
- data/lib/source/redshift/cookie.rb +142 -0
- data/lib/source/redshift/document.rb +216 -0
- data/lib/source/redshift/element.rb +417 -0
- data/lib/source/redshift/event.rb +312 -0
- data/lib/source/redshift/redshift.red +5 -0
- data/lib/source/redshift/request.rb +276 -0
- data/lib/source/redshift/selectors.rb +374 -0
- data/lib/source/redshift/situated.rb +328 -0
- data/lib/source/redshift/store.rb +48 -0
- data/lib/source/redshift/transform.rb +199 -0
- data/lib/source/redshift/tween.rb +66 -0
- data/lib/source/redshift/user_events.rb +215 -0
- data/lib/source/redshift/validator.rb +21 -0
- data/lib/source/redshift/window.rb +11 -0
- data/lib/source/redspec/index.html +11 -0
- data/lib/source/redspec/lib/red_spec/red_spec.red +525 -0
- data/lib/source/redspec/lib/stylesheets/specs.sass +290 -0
- metadata +27 -2
@@ -0,0 +1,312 @@
|
|
1
|
+
`function $v(event){
|
2
|
+
var doc=$u,result=$u,type=$u,target=$u,code=$u,key=$u,f_key=$u,wheel=$u,right_click=$u,page=$u,client=$u,related_target=$u;
|
3
|
+
event = event || window.event;
|
4
|
+
doc = document;
|
5
|
+
if(!event){return nil;};
|
6
|
+
result=c$Event.m$new(null);
|
7
|
+
type = event.type;
|
8
|
+
target = event.target || event.srcElement;
|
9
|
+
while(target&&target.nodeType==3){target=event.parentNode;};
|
10
|
+
if(/key/.test(type)){
|
11
|
+
code=event.which || event.keyCode;
|
12
|
+
key=c$Event.c$KEYS.m$_brac(code);
|
13
|
+
if(type=='keydown'){f_key=code-111;if(f_key>0&&f_key<13){key=$s('f'+f_key);};};
|
14
|
+
key=$T(key)?key:$s(String.fromCharCode(code).toLowerCase());
|
15
|
+
}else{
|
16
|
+
if(type.match(/(click|mouse|menu)/i)){
|
17
|
+
doc=(!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
|
18
|
+
wheel=(type.match(/DOMMouseScroll|mousewheel/) ? (event.wheelDelta ? event.wheelDelta/40 : -(event.detail||0)) : nil);
|
19
|
+
right_click=event.which==3||event.button==2;
|
20
|
+
page={x:(event.pageX || event.clientX + doc.scrollLeft),y:(event.pageY || event.clientY + doc.scrollTop)};
|
21
|
+
client={x:(event.pageX ? event.pageX - window.pageXOffset : event.clientX),y:(event.pageY ? event.pageY - window.pageYOffset : event.clientY)};
|
22
|
+
if(type.match(/over|out/)){
|
23
|
+
switch(type){
|
24
|
+
case 'mouseover':related_target=event.relatedTarget || event.fromElement;break;
|
25
|
+
case 'mouseout':related_target=event.relatedTarget || event.toElement;break;
|
26
|
+
};
|
27
|
+
if(window.m$gecko_bool()){
|
28
|
+
try{while(related_target&&related_target.nodeType==3){related_target=related_target.parentNode;};}catch(e){related_target=false;};
|
29
|
+
}else{while(related_target&&related_target.nodeType==3){related_target.parentNode;};};
|
30
|
+
};
|
31
|
+
};
|
32
|
+
};
|
33
|
+
result.__native__=event;result.__code__=code;result.__key__=key;result.__type__=type;result.__target__=target;result.__wheel__=wheel;result.__right_click__=right_click;result.__related_target__=related_target;
|
34
|
+
result.__page__=page||{x:nil,y:nil};result.__client__=client||{x:nil,y:nil};
|
35
|
+
result.__shift__=event.shiftKey;result.__ctrl__=event.ctrlKey;result.__alt__=event.altKey;result.__meta__=event.metaKey;
|
36
|
+
return result;
|
37
|
+
}`
|
38
|
+
|
39
|
+
# +Event+ objects represent user interactions with the browser. Attempting to
|
40
|
+
# create an +Event+ object by calling <tt>Event.new</tt> results in
|
41
|
+
# +NewEventError+.
|
42
|
+
#
|
43
|
+
# +Event+ objects are handled by the methods in the +UserEvents+ module.
|
44
|
+
#
|
45
|
+
class Event
|
46
|
+
KEYS = {
|
47
|
+
8 => :backspace,
|
48
|
+
9 => :tab,
|
49
|
+
13 => :enter,
|
50
|
+
27 => :esc,
|
51
|
+
32 => :space,
|
52
|
+
37 => :left,
|
53
|
+
38 => :up,
|
54
|
+
39 => :right,
|
55
|
+
40 => :down,
|
56
|
+
46 => :delete
|
57
|
+
}
|
58
|
+
|
59
|
+
# Exception raised by calling <tt>Event.new</tt>.
|
60
|
+
#
|
61
|
+
class NewEventError < Exception
|
62
|
+
end
|
63
|
+
|
64
|
+
def initialize(raise_error) # :nodoc:
|
65
|
+
raise(NewEventError, 'Events can only be initialized by user interactions with the browser') unless `raise_error === null`
|
66
|
+
end
|
67
|
+
|
68
|
+
# call-seq:
|
69
|
+
# evnt.alt? -> true or false
|
70
|
+
#
|
71
|
+
# Returns +true+ if the alt key was depressed during the event, +false+
|
72
|
+
# otherwise.
|
73
|
+
#
|
74
|
+
# Document['#example'].listen(:click) {|element, event| puts "alt-clicked" if event.alt? }
|
75
|
+
#
|
76
|
+
# alt-clicking element '#example' produces:
|
77
|
+
#
|
78
|
+
# alt-clicked
|
79
|
+
#
|
80
|
+
def alt?
|
81
|
+
`this.__alt__`
|
82
|
+
end
|
83
|
+
|
84
|
+
# call-seq:
|
85
|
+
# evnt.base_type -> symbol
|
86
|
+
#
|
87
|
+
# Returns a symbol representing _evnt_'s event type, or +:base+ type if
|
88
|
+
# _evnt_ is a defined event.
|
89
|
+
#
|
90
|
+
# UserEvents.define(:shift_click, :base => 'click', :condition => proc {|element,event| event.shift? })
|
91
|
+
# Document['#example'].listen(:click) {|element, event| puts event.base_type }
|
92
|
+
# Document['#example'].listen(:shift_click) {|element, event| puts event.base_type }
|
93
|
+
#
|
94
|
+
# clicking or shift-clicking on element '#example' produces:
|
95
|
+
#
|
96
|
+
# click
|
97
|
+
#
|
98
|
+
def base_type
|
99
|
+
`$s(this.__type__)`
|
100
|
+
end
|
101
|
+
|
102
|
+
# call-seq:
|
103
|
+
# evnt.client -> {:x => integer, :y => integer}
|
104
|
+
#
|
105
|
+
# Returns a hash representing _evnt_'s distance in pixels from the left
|
106
|
+
# (_x_) and top (_y_) edges of the browser viewport.
|
107
|
+
#
|
108
|
+
# Document['#example'].listen(:click) {|element,event| puts event.client.inspect }
|
109
|
+
#
|
110
|
+
# clicking element '#example' at position (35,45) produces:
|
111
|
+
#
|
112
|
+
# {:x => 35, :y => 45}
|
113
|
+
#
|
114
|
+
def client
|
115
|
+
{:x => `this.__client__.x`, :y => `this.__client__.y`}
|
116
|
+
end
|
117
|
+
|
118
|
+
# call-seq:
|
119
|
+
# evnt.code -> integer or nil
|
120
|
+
#
|
121
|
+
# If _evnt_ involved a keystroke, returns the ASCII code of the key pressed,
|
122
|
+
# otherwise returns +nil+.
|
123
|
+
#
|
124
|
+
# Document['#example'].listen(:keypress) {|element, event| puts event.code }
|
125
|
+
#
|
126
|
+
# typing "test\n" into textarea '#example produces:
|
127
|
+
#
|
128
|
+
# 116
|
129
|
+
# 101
|
130
|
+
# 115
|
131
|
+
# 116
|
132
|
+
# 13
|
133
|
+
#
|
134
|
+
def code
|
135
|
+
`this.__code__ || nil`
|
136
|
+
end
|
137
|
+
|
138
|
+
# call-seq:
|
139
|
+
# evnt.ctrl? -> true or false
|
140
|
+
#
|
141
|
+
# Returns +true+ if the control key was depressed during the event, +false+
|
142
|
+
# otherwise.
|
143
|
+
#
|
144
|
+
# Document['#example'].listen(:click) {|element, event| puts "ctrl-clicked" if event.ctrl? }
|
145
|
+
#
|
146
|
+
# ctrl-clicking element '#example' produces:
|
147
|
+
#
|
148
|
+
# ctrl-clicked
|
149
|
+
#
|
150
|
+
def ctrl?
|
151
|
+
`this.__ctrl__`
|
152
|
+
end
|
153
|
+
|
154
|
+
# call-seq:
|
155
|
+
# evnt.key -> symbol or nil
|
156
|
+
#
|
157
|
+
# If _evnt_ involved a keystroke, returns a symbol representing the key
|
158
|
+
# pressed, otherwise returns +nil+.
|
159
|
+
#
|
160
|
+
# Document['#example'].listen(:keypress) {|element, event| puts event.key.inspect }
|
161
|
+
#
|
162
|
+
# typing "test\n" into textarea '#example produces:
|
163
|
+
#
|
164
|
+
# :t
|
165
|
+
# :e
|
166
|
+
# :s
|
167
|
+
# :t
|
168
|
+
# :enter
|
169
|
+
#
|
170
|
+
def key
|
171
|
+
`this.__key__ || nil`
|
172
|
+
end
|
173
|
+
|
174
|
+
# call-seq:
|
175
|
+
# evnt.kill! -> evnt
|
176
|
+
#
|
177
|
+
# Stops the event in place, preventing the default action as well as any
|
178
|
+
# further propagation, then returns _evnt_.
|
179
|
+
#
|
180
|
+
def kill!
|
181
|
+
self.stop_propagation.prevent_default
|
182
|
+
end
|
183
|
+
|
184
|
+
# call-seq:
|
185
|
+
# evnt.meta? -> true or false
|
186
|
+
#
|
187
|
+
# Returns +true+ if the meta key was depressed during the event, +false+
|
188
|
+
# otherwise.
|
189
|
+
#
|
190
|
+
# Document['#example'].listen(:click) {|element, event| puts "meta-clicked" if event.meta? }
|
191
|
+
#
|
192
|
+
# meta-clicking element '#example' produces:
|
193
|
+
#
|
194
|
+
# meta-clicked
|
195
|
+
#
|
196
|
+
def meta?
|
197
|
+
`this.__meta__`
|
198
|
+
end
|
199
|
+
|
200
|
+
# call-seq:
|
201
|
+
# evnt.page -> {:x => numeric, :y => numeric}
|
202
|
+
#
|
203
|
+
# Returns a hash representing _evnt_'s distance in pixels from the left
|
204
|
+
# (_x_) and top (_y_) edges of the current page, including pixels that may
|
205
|
+
# have scrolled out of view.
|
206
|
+
#
|
207
|
+
# Document['#example'].listen(:click) {|element,event| puts event.page.inspect }
|
208
|
+
#
|
209
|
+
# clicking element '#example' at position (35,45) after scrolling down 100
|
210
|
+
# pixels produces:
|
211
|
+
#
|
212
|
+
# {:x => 35, :y => 145}
|
213
|
+
#
|
214
|
+
def page
|
215
|
+
{:x => `this.__page__.x`, :y => `this.__page__.y`}
|
216
|
+
end
|
217
|
+
|
218
|
+
# call-seq:
|
219
|
+
# evnt.prevent_default -> evnt
|
220
|
+
#
|
221
|
+
# Instructs the event to abandon its default browser action, then returns
|
222
|
+
# _evnt_.
|
223
|
+
#
|
224
|
+
def prevent_default
|
225
|
+
native = `this.__native__`
|
226
|
+
`native.preventDefault?native.preventDefault():native.returnValue=false`
|
227
|
+
return self
|
228
|
+
end
|
229
|
+
|
230
|
+
# call-seq:
|
231
|
+
# evnt.right_click? -> true or false
|
232
|
+
#
|
233
|
+
# Returns +true+ if the event was a right click.
|
234
|
+
#
|
235
|
+
# elem = Document['#example'].listen(:click) {|element, event| puts "right-clicked" if event.right_click? }
|
236
|
+
#
|
237
|
+
# right-clicking element '#example' produces:
|
238
|
+
#
|
239
|
+
# right-clicked
|
240
|
+
#
|
241
|
+
def right_click?
|
242
|
+
`this.__right_click__`
|
243
|
+
end
|
244
|
+
|
245
|
+
# call-seq:
|
246
|
+
# evnt.shift? -> true or false
|
247
|
+
#
|
248
|
+
# Returns +true+ if the shift key was depressed during the event, +false+
|
249
|
+
# otherwise.
|
250
|
+
#
|
251
|
+
# Document['#example'].listen(:click) {|element, event| puts "shift-clicked" if event.shift? }
|
252
|
+
#
|
253
|
+
# shift-clicking element '#example' produces:
|
254
|
+
#
|
255
|
+
# shift-clicked
|
256
|
+
#
|
257
|
+
def shift?
|
258
|
+
`this.__shift__`
|
259
|
+
end
|
260
|
+
|
261
|
+
# call-seq:
|
262
|
+
# evnt.stop_propagation -> evnt
|
263
|
+
#
|
264
|
+
# Instructs the event to stop propagating, then returns _evnt_.
|
265
|
+
#
|
266
|
+
def stop_propagation
|
267
|
+
native = `this.__native__`
|
268
|
+
`native.stopPropagation?native.stopPropagation():native.cancelBubble=true`
|
269
|
+
return self
|
270
|
+
end
|
271
|
+
|
272
|
+
# call-seq:
|
273
|
+
# evnt.target -> element
|
274
|
+
#
|
275
|
+
# Returns the DOM element targeted by _evnt_, or +nil+ if no element was
|
276
|
+
# targeted. The target of an event may be a different element than _elem_.
|
277
|
+
#
|
278
|
+
# elem = Document['#outer']
|
279
|
+
#
|
280
|
+
# elem.listen :click do |element, event|
|
281
|
+
# puts "%s was clicked" % event.target.inspect
|
282
|
+
# puts "%s was indirectly clicked" % element.inspect
|
283
|
+
# end
|
284
|
+
#
|
285
|
+
# clicking element '#inner' inside '#outer' produces:
|
286
|
+
#
|
287
|
+
# #<Element: DIV id="inner"> was clicked
|
288
|
+
# #<Element: DIV id="outer"> was indirectly clicked
|
289
|
+
#
|
290
|
+
def target
|
291
|
+
`$E(this.__target__)`
|
292
|
+
end
|
293
|
+
|
294
|
+
# call-seq:
|
295
|
+
# evnt.wheel -> numeric or nil
|
296
|
+
#
|
297
|
+
# Returns a floating point number representing the velocity of the wheel
|
298
|
+
# movement executed during _evnt_. Positive values indicate upward
|
299
|
+
# scrolling, negative values indicate downward scrolling. Returns +nil+ if
|
300
|
+
# _evnt_ did not involve the mouse wheel.
|
301
|
+
#
|
302
|
+
# Document['#example'].listen(:mouse_wheel) {|element, event| puts event.wheel }
|
303
|
+
#
|
304
|
+
# wheeling the mousewheel downward by a single "click" over element
|
305
|
+
# '#example' produces:
|
306
|
+
#
|
307
|
+
# -1
|
308
|
+
#
|
309
|
+
def wheel
|
310
|
+
`this.__wheel__`
|
311
|
+
end
|
312
|
+
end
|
@@ -0,0 +1,276 @@
|
|
1
|
+
require 'chainable'
|
2
|
+
require 'code_events'
|
3
|
+
|
4
|
+
class Request
|
5
|
+
include CodeEvents
|
6
|
+
include Chainable
|
7
|
+
|
8
|
+
METHODS = %w(GET POST PUT DELETE)
|
9
|
+
OPTIONS = {
|
10
|
+
:url => '',
|
11
|
+
:data => {},
|
12
|
+
:link => 'ignore',
|
13
|
+
:async => true,
|
14
|
+
:format => nil,
|
15
|
+
:method => 'post',
|
16
|
+
:encoding => 'utf-8',
|
17
|
+
:is_success => nil,
|
18
|
+
:emulation => true,
|
19
|
+
:url_encoded => true,
|
20
|
+
:eval_scripts => false,
|
21
|
+
:eval_response => false,
|
22
|
+
:headers => {
|
23
|
+
'X-Requested-With' => 'XMLHttpRequest',
|
24
|
+
'Accept' => 'text/javascript, text/html, application/xml, text/xml, */*'
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
# call-seq:
|
29
|
+
# Request.new(options = {}) -> request
|
30
|
+
#
|
31
|
+
# Returns a new _request_ with the given options.
|
32
|
+
#
|
33
|
+
def initialize(options = {})
|
34
|
+
`this.__xhr__ = typeof(ActiveXObject)=='undefined' ? new XMLHttpRequest : new ActiveXObject('MSXML2.XMLHTTP')`
|
35
|
+
@options = OPTIONS.merge(options)
|
36
|
+
`#{@options[:headers]}.__xhr__=this.__xhr__` # MooTools sets the ResponseHeaders in the xhr
|
37
|
+
#def (@options[:headers]).[](name) # only during execution, but allows you to get
|
38
|
+
# `this.__xhr__.getResponseHeader(name)` # at them at any time. I'm not sure whether it
|
39
|
+
#end # is necessary for us to emulate this exactly.
|
40
|
+
end
|
41
|
+
|
42
|
+
# call-seq:
|
43
|
+
# req.cancel -> req
|
44
|
+
#
|
45
|
+
# Cancels the request, fires its "cancel" callback, and returns _req_.
|
46
|
+
#
|
47
|
+
def cancel
|
48
|
+
return self unless @running
|
49
|
+
@running = false
|
50
|
+
`this.__xhr__.abort`
|
51
|
+
`this.__xhr__.onreadystatechange=function(){;}`
|
52
|
+
`this.__xhr__=typeof(ActiveXObject)=='undefined' ? new XMLHttpRequest : new ActiveXObject('MSXML2.XMLHTTP')`
|
53
|
+
self.fire(:cancel)
|
54
|
+
return self
|
55
|
+
end
|
56
|
+
|
57
|
+
# call-seq:
|
58
|
+
# req.check(arg, ...) { |request,args_array| block } -> true or false
|
59
|
+
#
|
60
|
+
# returns +true+ when Request object is not running or gets cancelled, otherwise returns false.
|
61
|
+
# also, seems equipped to 'chain' some additional function after itself
|
62
|
+
#
|
63
|
+
def check(*args, &block)
|
64
|
+
return true unless @running
|
65
|
+
case @options[:link]
|
66
|
+
when 'cancel'
|
67
|
+
self.cancel
|
68
|
+
return true
|
69
|
+
when 'chain'
|
70
|
+
# self.chain(&block(self,args))
|
71
|
+
return false
|
72
|
+
end
|
73
|
+
return false
|
74
|
+
end
|
75
|
+
|
76
|
+
# call-seq:
|
77
|
+
# req.execute(options = {}) -> req
|
78
|
+
#
|
79
|
+
# Returns +req+ immediately if the request is already running. Otherwise,
|
80
|
+
# opens a connection and sends the data provided with the specified options.
|
81
|
+
#
|
82
|
+
def execute(options = {})
|
83
|
+
# return self unless self.check(options)
|
84
|
+
@options.update(options)
|
85
|
+
raise(TypeError, 'can\'t convert %s to a String' % @options[:url].inspect) unless [String].include?(@options[:url].class)
|
86
|
+
raise(TypeError, 'can\'t convert %s to a String' % @options[:method].inspect) unless [String, Symbol].include?(@options[:method].class)
|
87
|
+
raise(TypeError, 'can\'t convert %s to a Hash' % @options[:data].inspect) unless [Hash].include?(@options[:data].class)
|
88
|
+
raise(HttpMethodError, 'invalid HTTP method "%s" for %s' % [@options[:method],self]) unless METHODS.include?(method = @options[:method].to_s.upcase)
|
89
|
+
|
90
|
+
@running = true
|
91
|
+
data = @options[:data].to_query_string
|
92
|
+
url = @options[:url]
|
93
|
+
|
94
|
+
if @options[:format]
|
95
|
+
format = "format=%s" % @options[:format]
|
96
|
+
data = data.empty? ? format : [format, data].join('&')
|
97
|
+
end
|
98
|
+
|
99
|
+
if @options[:emulation] && %w(PUT DELETE).include?(method)
|
100
|
+
_method = "_method=%s" % method
|
101
|
+
data = data.empty? ? _method : [_method, data].join('&')
|
102
|
+
method = 'POST'
|
103
|
+
end
|
104
|
+
|
105
|
+
if @options[:url_encoded] && method == 'POST'
|
106
|
+
encoding = @options[:encoding] ? "; charset=%s" % @options[:encoding] : ""
|
107
|
+
self.headers['Content-type'] = "application/x-www-form-urlencoded" + encoding
|
108
|
+
end
|
109
|
+
|
110
|
+
if data && method == 'GET'
|
111
|
+
separator = url.include?('?') ? "&" : "?"
|
112
|
+
url = [url, data].join(separator)
|
113
|
+
data = nil
|
114
|
+
end
|
115
|
+
|
116
|
+
`this.__xhr__.open(method.__value__, url.__value__, #{@options[:async]})`
|
117
|
+
`this.__xhr__.onreadystatechange = #{self.on_state_change}.__block__`
|
118
|
+
|
119
|
+
@options[:headers].each do |k,v|
|
120
|
+
`this.__xhr__.setRequestHeader(k.__value__,v.__value__)`
|
121
|
+
# raise(HeaderError, "#{k} => #{v}")
|
122
|
+
end
|
123
|
+
|
124
|
+
self.fire(:request)
|
125
|
+
`this.__xhr__.send($T(data)?data.__value__:'')`
|
126
|
+
self.on_state_change.call unless @options[:async]
|
127
|
+
return self
|
128
|
+
end
|
129
|
+
|
130
|
+
# call-seq:
|
131
|
+
# req.failure! -> req
|
132
|
+
#
|
133
|
+
# Fires _req_'s "response" and "failure" callbacks, then returns _req_.
|
134
|
+
#
|
135
|
+
def failure!
|
136
|
+
self.fire(:response).fire(:failure, @xhr);
|
137
|
+
end
|
138
|
+
|
139
|
+
# call-seq:
|
140
|
+
# req.headers -> hash
|
141
|
+
#
|
142
|
+
# Returns _req_'s HTTP headers as a +Hash+.
|
143
|
+
#
|
144
|
+
def headers
|
145
|
+
@options[:headers]
|
146
|
+
end
|
147
|
+
|
148
|
+
# call-seq:
|
149
|
+
# req.on_state_change -> proc
|
150
|
+
#
|
151
|
+
# Returns a +Proc+ object
|
152
|
+
#
|
153
|
+
def on_state_change
|
154
|
+
Proc.new do
|
155
|
+
`var xhr=this.__xhr__`
|
156
|
+
`if(xhr.readyState!=4||!#{@running}){return nil;}`
|
157
|
+
|
158
|
+
@running = false
|
159
|
+
@status = 0
|
160
|
+
|
161
|
+
`try{#{@status}=xhr.status}catch(e){;}`
|
162
|
+
|
163
|
+
if self.success?
|
164
|
+
@response = {:text => `$q(xhr.responseText)`, :xml => `xhr.responseXML`}
|
165
|
+
self.success!(self.process_scripts(@response[:text]), @response[:xml])
|
166
|
+
else
|
167
|
+
@response = {:text => nil, :xml => nil};
|
168
|
+
self.failure!
|
169
|
+
end
|
170
|
+
|
171
|
+
`xhr.onreadystatechange=function(){;}`
|
172
|
+
|
173
|
+
return nil
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# call-seq:
|
178
|
+
# req.process_scripts(str) -> string or object
|
179
|
+
#
|
180
|
+
# If the HTTP response consists of JavaScript alone or if _req_'s
|
181
|
+
# <tt>eval_response</tt> option is set to +true+, evaluates the entire
|
182
|
+
# text of the response as JavaScript and returns the result.
|
183
|
+
#
|
184
|
+
# Otherwise, returns a copy of _str_ with any <tt><script></tt> tags and
|
185
|
+
# their content removed. If _req_'s <tt>eval_scripts</tt> option is set to
|
186
|
+
# +true+, evaluates the removed scripts.
|
187
|
+
#
|
188
|
+
def process_scripts(str)
|
189
|
+
return Document.execute_js(str) if @options[:eval_response] || `/(ecma|java)script/.test(this.__xhr__.getResponseHeader('Content-Type'))`
|
190
|
+
return str.strip_scripts(@options[:eval_scripts])
|
191
|
+
end
|
192
|
+
|
193
|
+
# call-seq:
|
194
|
+
# req.success!(text, xml) -> req
|
195
|
+
#
|
196
|
+
# Fires _req_'s "response" and "success" callbacks, then returns _req_.
|
197
|
+
#
|
198
|
+
def success!(text, xml)
|
199
|
+
self.fire(:response, [text, xml]).fire(:success, [text, xml]).call_chain
|
200
|
+
end
|
201
|
+
|
202
|
+
# call-seq:
|
203
|
+
# req.success? -> true or false
|
204
|
+
#
|
205
|
+
# Returns +true+ if _req_'s status is in the 200s, +false+ otherwise.
|
206
|
+
#
|
207
|
+
def success?
|
208
|
+
`#{@status}>=200&&#{@status}<300`
|
209
|
+
end
|
210
|
+
|
211
|
+
# +HeaderError+ is raised when a +Request+ is executed with headers that are
|
212
|
+
# rejected by the XMLHTTPRequest object.
|
213
|
+
#
|
214
|
+
class HeaderError < StandardError
|
215
|
+
end
|
216
|
+
|
217
|
+
# +HttpMethodError+ is raised when a +Request+ object's HTTP method is not
|
218
|
+
# one of +GET+, +POST+, +PUT+, or +DELETE+.
|
219
|
+
#
|
220
|
+
class HttpMethodError < StandardError
|
221
|
+
end
|
222
|
+
|
223
|
+
class ::String
|
224
|
+
# call-seq:
|
225
|
+
# str.strip_scripts(evaluate = false) -> string
|
226
|
+
#
|
227
|
+
# Returns a copy of _str_ with the contents of any <tt><script></tt> tags
|
228
|
+
# removed. If _evaluate_ is set to true, the stripped scripts will be
|
229
|
+
# evaluated.
|
230
|
+
#
|
231
|
+
def strip_scripts(evaluate = false)
|
232
|
+
scripts = ''
|
233
|
+
result = `this.__value__.replace(/<script[^>]*>([\\s\\S]*?)<\\/script>/gi,function(){scripts.__value__+=arguments[1]+'\\n';return '';})`
|
234
|
+
Document.execute_js(scripts) if evaluate
|
235
|
+
return result
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
class ::Hash
|
240
|
+
# call-seq:
|
241
|
+
# hsh.to_query_string -> string
|
242
|
+
#
|
243
|
+
# Returns a string representing _hsh_ formatted as HTTP data.
|
244
|
+
#
|
245
|
+
def to_query_string(base = '')
|
246
|
+
query_string = []
|
247
|
+
self.each do |k,v|
|
248
|
+
next if v.nil?
|
249
|
+
k = base.empty? ? k.to_s : "%s[%s]" % [base,k]
|
250
|
+
case v
|
251
|
+
when Hash
|
252
|
+
result = v.to_query_string(k)
|
253
|
+
when Array
|
254
|
+
qs = {}
|
255
|
+
`for(var i=0,l=v.length;i<l;i++){#{qs[i] = v[i]}}`
|
256
|
+
#v.each_with_index do |v,i|
|
257
|
+
# qs[i] = v
|
258
|
+
#end
|
259
|
+
result = qs.to_query_string(k)
|
260
|
+
else
|
261
|
+
result = "%s=%s" % [k, `$q(encodeURIComponent(v))`]
|
262
|
+
end
|
263
|
+
query_string.push(result)
|
264
|
+
end
|
265
|
+
return query_string.join('&')
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
class HTML
|
270
|
+
|
271
|
+
end
|
272
|
+
|
273
|
+
class JSON
|
274
|
+
|
275
|
+
end
|
276
|
+
end
|