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,150 @@
|
|
1
|
+
# The +Browser+ module contains methods for checking the current platform and
|
2
|
+
# rendering engine.
|
3
|
+
#
|
4
|
+
module Browser
|
5
|
+
Plugins = {}
|
6
|
+
|
7
|
+
# call-seq:
|
8
|
+
# Browser.engine -> hash
|
9
|
+
#
|
10
|
+
# Returns a hash containing the name and version of the current rendering
|
11
|
+
# engine.
|
12
|
+
#
|
13
|
+
# Browser.engine #=> {:name => "gecko", :version => 19}
|
14
|
+
#
|
15
|
+
def self.engine
|
16
|
+
{:name => Engine.instance_variable_get('@name'), :version => Engine.instance_variable_get('@version')}
|
17
|
+
end
|
18
|
+
|
19
|
+
# call-seq:
|
20
|
+
# Browser.platform -> string
|
21
|
+
#
|
22
|
+
# Returns the name of the current platform as a string.
|
23
|
+
#
|
24
|
+
# Browser.platform #=> "mac"
|
25
|
+
#
|
26
|
+
def self.platform
|
27
|
+
@platform ||= `$q(window.orientation==undefined?(navigator.platform.match(/mac|win|linux/i)||['other'])[0].toLowerCase():'ipod')`
|
28
|
+
end
|
29
|
+
|
30
|
+
# The +Features+ module mixes in methods to check for browser features such
|
31
|
+
# as XPath and Adobe AIR.
|
32
|
+
#
|
33
|
+
module Features
|
34
|
+
`c$Browser.c$Features.__xpath__=!!(document.evaluate)`
|
35
|
+
`c$Browser.c$Features.__air__=!!(window.runtime)`
|
36
|
+
`c$Browser.c$Features.__query__=!!(document.querySelector)`
|
37
|
+
|
38
|
+
# call-seq:
|
39
|
+
# xpath? -> true or false
|
40
|
+
#
|
41
|
+
# Returns +true+ if XPath is available, +false+ otherwise.
|
42
|
+
#
|
43
|
+
def xpath?
|
44
|
+
`c$Browser.c$Features.__xpath__`
|
45
|
+
end
|
46
|
+
|
47
|
+
# call-seq:
|
48
|
+
# air? -> true or false
|
49
|
+
#
|
50
|
+
# Returns +true+ if Adobe AIR is available, +false+ otherwise.
|
51
|
+
#
|
52
|
+
def air?
|
53
|
+
`c$Browser.c$Features.__air__`
|
54
|
+
end
|
55
|
+
|
56
|
+
# call-seq:
|
57
|
+
# query? -> true or false
|
58
|
+
#
|
59
|
+
# Returns +true+ if the W3C Selectors API is available, +false+ otherwise.
|
60
|
+
#
|
61
|
+
def query?
|
62
|
+
`c$Browser.c$Features.__query__`
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# The +Engine+ module mixes in methods to check the current browser's
|
67
|
+
# rendering engine and its version.
|
68
|
+
#
|
69
|
+
module Engine
|
70
|
+
if `window.opera`
|
71
|
+
@name = 'presto'
|
72
|
+
@version = `document.getElementsByClassName` ? 950 : 925
|
73
|
+
elsif `window.ActiveXObject`
|
74
|
+
@name = 'trident'
|
75
|
+
@version = `window.XMLHttpRequest` ? 5 : 4
|
76
|
+
elsif `!navigator.taintEnabled`
|
77
|
+
@name = 'webkit'
|
78
|
+
@version = `#{Browser::Features}.__xpath__` ? (`#{Browser::Features}.__query__` ? 525 : 420) : 419
|
79
|
+
elsif `document.getBoxObjectFor != null`
|
80
|
+
@name = 'gecko'
|
81
|
+
@version = `document.getElementsByClassName` ? 19 : 18
|
82
|
+
else
|
83
|
+
@name = 'unknown'
|
84
|
+
@version = 0
|
85
|
+
end
|
86
|
+
|
87
|
+
# call-seq:
|
88
|
+
# gecko? -> true or false
|
89
|
+
# gecko?(num) -> true or false
|
90
|
+
#
|
91
|
+
# Returns +true+ if the current browser is Firefox. Optionally checks for
|
92
|
+
# version _num_.
|
93
|
+
#
|
94
|
+
# gecko? #=> true
|
95
|
+
# gecko?(18) #=> false
|
96
|
+
#
|
97
|
+
def gecko?(version)
|
98
|
+
self.browser?('gecko', version)
|
99
|
+
end
|
100
|
+
|
101
|
+
# call-seq:
|
102
|
+
# presto? -> true or false
|
103
|
+
# presto?(num) -> true or false
|
104
|
+
#
|
105
|
+
# Returns +true+ if the current browser is Opera. Optionally checks for
|
106
|
+
# version _num_.
|
107
|
+
#
|
108
|
+
# presto? #=> true
|
109
|
+
# presto?(925) #=> false
|
110
|
+
#
|
111
|
+
def presto?(version)
|
112
|
+
self.browser?('presto', version)
|
113
|
+
end
|
114
|
+
|
115
|
+
# call-seq:
|
116
|
+
# trident? -> true or false
|
117
|
+
# trident?(num) -> true or false
|
118
|
+
#
|
119
|
+
# Returns +true+ if the current browser is Internet Explorer. Optionally
|
120
|
+
# checks for version _num_.
|
121
|
+
#
|
122
|
+
# trident? #=> true
|
123
|
+
# trident?(4) #=> false
|
124
|
+
#
|
125
|
+
def trident?(version)
|
126
|
+
self.browser?('trident', version)
|
127
|
+
end
|
128
|
+
|
129
|
+
# call-seq:
|
130
|
+
# webkit? -> true or false
|
131
|
+
# webkit?(num) -> true or false
|
132
|
+
#
|
133
|
+
# Returns +true+ if the current browser is Safari, Mobile Safari, or
|
134
|
+
# Google Chrome. Optionally checks for version _num_.
|
135
|
+
#
|
136
|
+
# webkit? #=> true
|
137
|
+
# webkit?(419) #=> false
|
138
|
+
#
|
139
|
+
def webkit?(version)
|
140
|
+
self.browser?('webkit', version)
|
141
|
+
end
|
142
|
+
|
143
|
+
def browser?(name, version) # :nodoc:
|
144
|
+
Engine.instance_variable_get('@name') == name && (version ? Engine.instance_variable_get('@version') == version : true)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
include Browser::Engine
|
150
|
+
include Browser::Features
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Classes including module +Chainable+ gain the ability to cache a stack of
|
2
|
+
# +Proc+ objects. These blocks of code can later be executed one at a time, in
|
3
|
+
# the order of their insertion.
|
4
|
+
#
|
5
|
+
# class Foo
|
6
|
+
# include Chainable
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
# foo = Foo.new
|
10
|
+
# foo.chain {|x| puts "x: " + x }.chain {|y,z| puts ["y: %s","z: %s"].join("\n") % [y,z] }
|
11
|
+
#
|
12
|
+
# foo.call_chain('called 1st')
|
13
|
+
# foo.call_chain('called 2nd', 'called 2nd also')
|
14
|
+
#
|
15
|
+
# produces:
|
16
|
+
#
|
17
|
+
# x: called 1st
|
18
|
+
# y: called 2nd
|
19
|
+
# z: called 2nd also
|
20
|
+
#
|
21
|
+
module Chainable
|
22
|
+
# call-seq:
|
23
|
+
# chainable.call_chain(arg, ...) -> object or false
|
24
|
+
#
|
25
|
+
# Removes the foremost +Proc+ from _chainable_'s chain and calls it,
|
26
|
+
# returning the result. Returns +false+ if the chain was empty.
|
27
|
+
#
|
28
|
+
# chainable.chain {|x,y,z| x * (y + z) }
|
29
|
+
#
|
30
|
+
# chainable.call_chain(4,5,6) #=> 44
|
31
|
+
# chainable.call_chain #=> false
|
32
|
+
#
|
33
|
+
def call_chain(*args)
|
34
|
+
@chain ||= []
|
35
|
+
return `#{@chain.shift}.__block__.apply(this,args)` unless @chain.empty?
|
36
|
+
return false
|
37
|
+
end
|
38
|
+
|
39
|
+
# call-seq:
|
40
|
+
# chainable.chain { |arg,...| block } -> chainable
|
41
|
+
#
|
42
|
+
# Adds _block_ to the end of _chainable_'s chain, then returns _chainable_.
|
43
|
+
#
|
44
|
+
# chainable.chain { puts 1; return 'called 1' }.chain { puts 2; return 'called 2' }
|
45
|
+
#
|
46
|
+
# chainable.call_chain #=> "called 1"
|
47
|
+
# chainable.call_chain #=> "called 2"
|
48
|
+
# chainable.call_chain #=> false
|
49
|
+
#
|
50
|
+
# produces:
|
51
|
+
#
|
52
|
+
# 1
|
53
|
+
# 2
|
54
|
+
#
|
55
|
+
def chain(&block)
|
56
|
+
@chain ||= []
|
57
|
+
@chain << block
|
58
|
+
return self
|
59
|
+
end
|
60
|
+
|
61
|
+
# call-seq:
|
62
|
+
# chainable.clear_chain -> chainable
|
63
|
+
#
|
64
|
+
# Returns _chainable_ with its chain emptied.
|
65
|
+
#
|
66
|
+
# chainable.chain { 1 + 1 }
|
67
|
+
#
|
68
|
+
# chainable.clear_chain.call_chain #=> false
|
69
|
+
#
|
70
|
+
def clear_chain
|
71
|
+
@chain ||= []
|
72
|
+
@chain.clear
|
73
|
+
return self
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
# Module +CodeEvents+ enables event-driven programming by giving objects of
|
2
|
+
# the including class the ability to define custom observers and callbacks.
|
3
|
+
#
|
4
|
+
# class Looper
|
5
|
+
# include CodeEvents
|
6
|
+
#
|
7
|
+
# def initialize(range)
|
8
|
+
# @range = range
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# def run(min, max)
|
12
|
+
# self.fire(:start)
|
13
|
+
# @range.each do |i|
|
14
|
+
# self.fire(:minimum, 0, i) && next if i == min
|
15
|
+
# self.fire(:maximum, 0, i) && next if i == max
|
16
|
+
# puts i
|
17
|
+
# end
|
18
|
+
# return self
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# looper = Looper.new(1..10) #=> #<Looper:0x34fe78>
|
23
|
+
#
|
24
|
+
# looper.upon :start do
|
25
|
+
# puts "The loop has begun"
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# min_proc = Proc.new {|i| puts "Minimum amount reached: %s" % i } #=> #<Proc:0x3e72a9>
|
29
|
+
# max_proc = Proc.new {|i| puts "Maximum amount reached: %s" % i } #=> #<Proc:0x3ea147>
|
30
|
+
# looper.upon(:minimum => min_proc, :maximum => max_proc) #=> #<Looper:0x34fe78>
|
31
|
+
#
|
32
|
+
# looper.run(3,8) #=> #<Looper:0x34fe78>
|
33
|
+
#
|
34
|
+
# produces:
|
35
|
+
#
|
36
|
+
# The loop has begun
|
37
|
+
# 1
|
38
|
+
# 2
|
39
|
+
# Minimum amount reached: 3
|
40
|
+
# 4
|
41
|
+
# 5
|
42
|
+
# 6
|
43
|
+
# 7
|
44
|
+
# Maximum amount reached: 8
|
45
|
+
# 9
|
46
|
+
# 10
|
47
|
+
#
|
48
|
+
module CodeEvents
|
49
|
+
# call-seq:
|
50
|
+
# obj.fire(sym) -> obj
|
51
|
+
# obj.fire(sym, delay, arg, ...) -> obj
|
52
|
+
#
|
53
|
+
# Instructs _obj_ to call the +Proc+ objects associated with the event
|
54
|
+
# _sym_, then returns _obj_. Optionally delays the firing of the event by
|
55
|
+
# _delay_ milliseconds. The second form allows passing of arguments to the
|
56
|
+
# event's +Proc+ objects, but if any arguments are passed, the first must be
|
57
|
+
# the _delay_ argument.
|
58
|
+
#
|
59
|
+
# obj.upon(:A) {|x| puts x } #=> obj
|
60
|
+
# obj.upon(:B) {|y| puts y } #=> obj
|
61
|
+
# obj.upon(:C) { puts 'fire 3' } #=> obj
|
62
|
+
#
|
63
|
+
# obj.fire(:A, 500, 'fire 1').fire(:B, 0, 'fire 2').fire(:C)
|
64
|
+
#
|
65
|
+
# produces:
|
66
|
+
#
|
67
|
+
# fire 2
|
68
|
+
# fire 3
|
69
|
+
# fire 1
|
70
|
+
#
|
71
|
+
def fire(sym, delay, *args)
|
72
|
+
name = sym.to_sym
|
73
|
+
return self unless @code_events && events_group = @code_events[name]
|
74
|
+
events_group.each {|proc| proc.process_event(self, delay, args) }
|
75
|
+
return self
|
76
|
+
end
|
77
|
+
|
78
|
+
# call-seq:
|
79
|
+
# obj.ignore -> obj
|
80
|
+
# obj.ignore(sym) -> obj
|
81
|
+
# obj.ignore(sym, &proc) -> obj
|
82
|
+
#
|
83
|
+
# Instructs _obj_ to ignore the specified event, then returns _obj_.
|
84
|
+
#
|
85
|
+
# In the first form, all event-related +Proc+ objects not marked
|
86
|
+
# as "unignorable" are removed from _obj_.
|
87
|
+
#
|
88
|
+
# obj.upon(:A, true) { puts '1st executed' } #=> obj
|
89
|
+
# obj.upon(:A) { puts '2nd executed' } #=> obj
|
90
|
+
# obj.upon(:B) { puts '3rd executed' } #=> obj
|
91
|
+
#
|
92
|
+
# obj.ignore #=> obj
|
93
|
+
# obj.fire(:A).fire(:B) #=> obj
|
94
|
+
#
|
95
|
+
# produces:
|
96
|
+
#
|
97
|
+
# 1st executed
|
98
|
+
#
|
99
|
+
# In the second form, only the ignorable +Proc+ objects associated with the
|
100
|
+
# event _sym_ are removed.
|
101
|
+
#
|
102
|
+
# obj.upon(:A, true) { puts '1st executed' } #=> obj
|
103
|
+
# obj.upon(:A) { puts '2nd executed' } #=> obj
|
104
|
+
# obj.upon(:B) { puts '3rd executed' } #=> obj
|
105
|
+
#
|
106
|
+
# obj.ignore(:A) #=> obj
|
107
|
+
# obj.fire(:A).fire(:B) #=> obj
|
108
|
+
#
|
109
|
+
# produces:
|
110
|
+
#
|
111
|
+
# 1st executed
|
112
|
+
# 3rd executed
|
113
|
+
#
|
114
|
+
# In the third form, only the +Proc+ object passed in as <i>&proc</i> is
|
115
|
+
# removed.
|
116
|
+
#
|
117
|
+
# proc_1 = Proc.new { puts 'Proc 1 executed' } #=> #<Proc:0x3e78ee>
|
118
|
+
# proc_2 = Proc.new { puts 'Proc 2 executed' } #=> #<Proc:0x3e888a>
|
119
|
+
#
|
120
|
+
# obj.upon(:A, &proc_1) #=> obj
|
121
|
+
# obj.upon(:A, &proc_2) #=> obj
|
122
|
+
#
|
123
|
+
# obj.ignore(:A, &proc_1) #=> obj
|
124
|
+
# obj.fire(:A) #=> obj
|
125
|
+
#
|
126
|
+
# produces:
|
127
|
+
#
|
128
|
+
# Proc 2 executed
|
129
|
+
#
|
130
|
+
def ignore(sym, &block)
|
131
|
+
if sym
|
132
|
+
name = sym.to_sym
|
133
|
+
return self unless @code_events && events_group = @code_events[name]
|
134
|
+
if block
|
135
|
+
events_group.delete(block) unless `block.__block__.__unignorable__`
|
136
|
+
else
|
137
|
+
events_group.each {|proc| self.disregard(name, &proc) }
|
138
|
+
end
|
139
|
+
else
|
140
|
+
@code_events.each_key {|name| self.disregard(name) }
|
141
|
+
end
|
142
|
+
return self
|
143
|
+
end
|
144
|
+
|
145
|
+
# call-seq:
|
146
|
+
# obj.upon(sym, unignorable = false) { |arg,...| block } -> obj
|
147
|
+
# obj.upon(hash) -> obj
|
148
|
+
#
|
149
|
+
# Stores a number of +Proc+ objects to be called when the event _sym_ is
|
150
|
+
# fired.
|
151
|
+
#
|
152
|
+
# The first form adds _block_ to the array of +Proc+ objects executed when
|
153
|
+
# the event _sym_ is fired, then returns _obj_. If _unignorable_ is set to
|
154
|
+
# +true+, the _block_ will be executed when _sym_ fires, regardless of
|
155
|
+
# whether it has been ignored.
|
156
|
+
#
|
157
|
+
# obj.upon(:A, true) { puts '1st executed' } #=> obj
|
158
|
+
# obj.upon(:A, true) { puts '2nd executed' } #=> obj
|
159
|
+
# obj.upon(:A) { puts '3rd executed' } #=> obj
|
160
|
+
#
|
161
|
+
# obj.ignore(:A) #=> obj
|
162
|
+
# obj.fire(:A) #=> obj
|
163
|
+
#
|
164
|
+
# produces:
|
165
|
+
#
|
166
|
+
# 1st executed
|
167
|
+
# 2nd executed
|
168
|
+
#
|
169
|
+
# The second form takes a hash of +Proc+ objects keyed by event name,
|
170
|
+
# running <tt>obj.upon(name, &proc)</tt> on each key-value pair, then
|
171
|
+
# returns _obj_.
|
172
|
+
#
|
173
|
+
# proc_1 = Proc.new { puts '1st executed' } #=> #<Proc:0x3e78ee>
|
174
|
+
# proc_2 = Proc.new { puts '2nd executed' } #=> #<Proc:0x3e888a>
|
175
|
+
#
|
176
|
+
# obj.upon(:A => proc_1, :B => proc_2) #=> obj
|
177
|
+
# obj.fire(:B) #=> obj
|
178
|
+
#
|
179
|
+
# produces
|
180
|
+
#
|
181
|
+
# 2nd executed
|
182
|
+
#
|
183
|
+
def upon(sym_or_hash, unignorable, &block)
|
184
|
+
if sym_or_hash.instance_of?(Hash)
|
185
|
+
sym_or_hash.each {|name,proc| self.upon(name, &proc) }
|
186
|
+
return self
|
187
|
+
else
|
188
|
+
name = sym_or_hash.to_sym
|
189
|
+
@code_events ||= {}
|
190
|
+
@code_events[name] ||= []
|
191
|
+
@code_events[name] << block
|
192
|
+
`block.__block__.__unignorable__=typeof(unignorable)=='function'?false:unignorable`
|
193
|
+
return self
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class ::Proc # :nodoc:
|
198
|
+
def process_event(context, delay, args_array) # :nodoc:
|
199
|
+
`var f=this.__block__.__unbound__,event_function=function(){return f.apply(context,args_array);}`
|
200
|
+
`if(delay){return setTimeout(event_function,delay);}`
|
201
|
+
`event_function()`
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# Class +Cookie+ governs the writing and accessing of cookies in the browser.
|
2
|
+
#
|
3
|
+
# A cookie is a key-value pair stored by your browser as text data. If you
|
4
|
+
# know a cookie's key, you can read or overwrite its value, or reassign any of
|
5
|
+
# a number of parameters.
|
6
|
+
#
|
7
|
+
# Instances of class +Cookie+ are temporary holders for browser-based cookie
|
8
|
+
# data. When you create a new +Cookie+ object using <tt>Cookie.new</tt> or
|
9
|
+
# update an existing +Cookie+ object using <tt>Cookie#update</tt>, class
|
10
|
+
# +Cookie+ writes the key-value pair and the cookie's parameters to the
|
11
|
+
# browser's cookie file. You can then read the value of the cookie immediately
|
12
|
+
# or during subsequent visits using <tt>Cookie.read</tt>.
|
13
|
+
#
|
14
|
+
# The following parameters can be set for a +Cookie+ object:
|
15
|
+
#
|
16
|
+
# *Required*
|
17
|
+
# _key_:: The unique (per domain) identifier by which you identify a cookie.
|
18
|
+
# _value_:: The string of data associated with a given key.
|
19
|
+
#
|
20
|
+
# *Optional*
|
21
|
+
# _duration_:: The amount of time (in days) before the cookie should expire.
|
22
|
+
# _domain_:: The domain to which the cookie should be sent.
|
23
|
+
# _path_:: The path, relative to the domain, where the cookie is active.
|
24
|
+
# _secure_:: If +true+, the browser will use SSL when sending the cookie.
|
25
|
+
#
|
26
|
+
# The browser can hold up to 20 cookies from a single domain.
|
27
|
+
#
|
28
|
+
class Cookie
|
29
|
+
OPTIONS = {
|
30
|
+
:duration => nil,
|
31
|
+
:domain => nil,
|
32
|
+
:path => nil,
|
33
|
+
:secure => false,
|
34
|
+
:document => Document
|
35
|
+
}
|
36
|
+
|
37
|
+
attr_accessor :key, :value, :duration, :domain, :path, :secure, :document
|
38
|
+
|
39
|
+
# call-seq:
|
40
|
+
# Cookie.new(key, value, options = {}) -> cookie
|
41
|
+
#
|
42
|
+
# Returns a new +Cookie+ object with the given parameters and stores the
|
43
|
+
# data in the browser as cookie data. If the browser already has a cookie
|
44
|
+
# that matches _key_, that cookie's parameters will be overwritten.
|
45
|
+
#
|
46
|
+
# Cookie.new(:user_jds, '2237115568') #=> #<Cookie: @key="user_jds" @value="2237115568">
|
47
|
+
# Cookie.read(:user_jds) #=> '2237115568'
|
48
|
+
#
|
49
|
+
# Cookie.new(:user_jds, '8557acb0') #=> #<Cookie: @key="user_jds" @value="8557acb0">
|
50
|
+
# Cookie.read(:user_jds) #=> '8557acb0'
|
51
|
+
#
|
52
|
+
def initialize(key, value, options = {})
|
53
|
+
self.key = key
|
54
|
+
self.update(value, OPTIONS.merge(options))
|
55
|
+
end
|
56
|
+
|
57
|
+
# call-seq:
|
58
|
+
# Cookie.read(key) -> string
|
59
|
+
#
|
60
|
+
# Returns the string value of the cookie named _key_, or +nil+ if no such
|
61
|
+
# cookie exists.
|
62
|
+
#
|
63
|
+
# c = Cookie.new(:user_jds, '2237115568', :domain => '.example.com')
|
64
|
+
#
|
65
|
+
# Cookie.read(:user_jds) #=> '2237115568'
|
66
|
+
#
|
67
|
+
# This method can be used to test whether a cookie with the name _key_
|
68
|
+
# exists in the browser.
|
69
|
+
#
|
70
|
+
# Cookie.new(:user_jds, '8557acb0') unless Cookie.read(:user_jds)
|
71
|
+
#
|
72
|
+
def self.read(key)
|
73
|
+
value = `#{OPTIONS[:document].native}.cookie.match('(?:^|;)\\s*' + #{Regexp.escape(key)}.__value__ + '=([^;]*)')`
|
74
|
+
return value ? `$q(decodeURIComponent(value[1]))` : nil
|
75
|
+
end
|
76
|
+
|
77
|
+
# call-seq:
|
78
|
+
# Cookie.store(cookie) -> cookie
|
79
|
+
#
|
80
|
+
# Writes the given cookie to the browser, then returns _cookie_. This method
|
81
|
+
# is called internally by <tt>Cookie.new</tt> and <tt>Cookie#update</tt>.
|
82
|
+
#
|
83
|
+
def self.store(cookie)
|
84
|
+
`var str = cookie.m$key().__value__ + '=' + encodeURIComponent(cookie.m$value().__value__)`
|
85
|
+
`str += '; domain=' + cookie.m$domain().__value__` if cookie.domain
|
86
|
+
`str += '; path=' + cookie.m$path().__value__` if cookie.path
|
87
|
+
if cookie.duration
|
88
|
+
`date = new Date()`
|
89
|
+
`date.setTime(date.getTime() + cookie.m$duration() * 86400000)`
|
90
|
+
`str += '; expires=' + date.toGMTString()`
|
91
|
+
end
|
92
|
+
`str += '; secure'` if cookie.secure
|
93
|
+
|
94
|
+
`#{cookie.document.native}.cookie = str`
|
95
|
+
return cookie
|
96
|
+
end
|
97
|
+
|
98
|
+
# call-seq:
|
99
|
+
# cookie.destroy -> true
|
100
|
+
#
|
101
|
+
# Expires _cookie_, then returns +true+.
|
102
|
+
#
|
103
|
+
# c = Cookie.new(:user_jds, '2237115568', :duration => 14)
|
104
|
+
#
|
105
|
+
# c.destroy #=> true
|
106
|
+
# Cookie.read(:user_jds) #=> nil
|
107
|
+
#
|
108
|
+
def destroy
|
109
|
+
self.update('',:duration => -1)
|
110
|
+
end
|
111
|
+
|
112
|
+
# call-seq:
|
113
|
+
# cookie.inspect -> string
|
114
|
+
#
|
115
|
+
# Returns a string representing _cookie_ and its key-value data.
|
116
|
+
#
|
117
|
+
# c = Cookie.new(:user_jds, '2237115568', :duration => 14)
|
118
|
+
#
|
119
|
+
# c.inspect #=> #<Cookie: @key="user_jds" @value="2237115568">
|
120
|
+
#
|
121
|
+
def inspect
|
122
|
+
"#<Cookie: @key=#{self.key.inspect} @value=#{self.value.inspect}>"
|
123
|
+
end
|
124
|
+
|
125
|
+
# call-seq:
|
126
|
+
# cookie.update(value, options = {}) -> cookie
|
127
|
+
#
|
128
|
+
# Updates _cookie_ with the given parameters, then writes the cookie data to
|
129
|
+
# the browser.
|
130
|
+
#
|
131
|
+
# c = Cookie.new(:user_jds, '2237115568', :duration => 14)
|
132
|
+
#
|
133
|
+
# Cookie.read(:user_jds) #=> '2237115568'
|
134
|
+
# c.update('8557acb0') #=> #<Cookie: @key="user_jds" @value="8557acb0">
|
135
|
+
# Cookie.read(:user_jds) #=> '8557acb0'
|
136
|
+
#
|
137
|
+
def update(value, options = {})
|
138
|
+
self.value = value
|
139
|
+
options.each {|k,v| self.send("#{k}=",v) }
|
140
|
+
Cookie.store(self)
|
141
|
+
end
|
142
|
+
end
|