red 4.1.0 → 4.1.1
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/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
|