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,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
|