opal-jquery 0.3.0.beta1 → 0.3.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,205 @@
1
+ require 'opal/jquery/constants'
2
+
3
+ # {Event} wraps native jQuery events into a ruby api. Instances of events
4
+ # can be accessed by {#to_n}.
5
+ #
6
+ # {Event} instances should not be created directly, as they are usually
7
+ # created by one of the dom event handlers in {Element}.
8
+ #
9
+ # element.on :click do |event|
10
+ # puts event
11
+ # end
12
+ #
13
+ # # => #<Event:0x0000000>
14
+ #
15
+ # ## Usage
16
+ #
17
+ # {Event} exposes a slightly different API than jQuery, as {Event} tries to
18
+ # add some more ruby flavour to the object.
19
+ #
20
+ # ### Accessing element triggering event
21
+ #
22
+ # Unlike jQuery, the context of an event handler is not set to the triggering
23
+ # element. Instead, the element triggering the event can be accessed from the
24
+ # {Event} instance.
25
+ #
26
+ # #### Current Target
27
+ #
28
+ # To access the current element in the bubbling phase, {#element} or
29
+ # {#current_target} can be used which is the same as `currentTarget` or `this`
30
+ # from jQuery.
31
+ #
32
+ # element.on :click do |event|
33
+ # puts "element clicked: #{event.element}
34
+ # end
35
+ #
36
+ # # => "element clicked: #<Element: [<div>]>
37
+ #
38
+ # #### Target
39
+ #
40
+ # The {#target} of an event is the actual dom element that triggered the event,
41
+ # and this will be the same element through all phases of event bubbling. This
42
+ # is the same as the `event.target` jQuery property.
43
+ #
44
+ # element.on :click do |event|
45
+ # puts "actual element: #{event.target}"
46
+ # end
47
+ #
48
+ # # => "actual element: #<Element: [<div>]>
49
+ #
50
+ # ### Controlling Event Bubbling
51
+ #
52
+ # Propagation and default behaviour can be controlled on events using {#prevent}
53
+ # and {#stop}, which will prevent the browser default and stop event propagation
54
+ # respectively.
55
+ #
56
+ # element.on :click do |event|
57
+ # event.prevent # prevent browser default
58
+ # event.stop # stop event propagation
59
+ # end
60
+ #
61
+ # If you want to trigger both methods, which is usually the case, then {#kill}
62
+ # can be used as a shorthand.
63
+ #
64
+ # element.on :click do |event|
65
+ # event.kill
66
+ # puts event.prevented?
67
+ # puts event.stopped?
68
+ # end
69
+ #
70
+ # # => true
71
+ # # => true
72
+ #
73
+ class Event
74
+ `var $ = #{JQUERY_SELECTOR.to_n}` # cache $ for SPEED
75
+
76
+ # @private
77
+ # @param native [JSObject] native jquery/javascript event
78
+ def initialize(native)
79
+ @native = native
80
+ end
81
+
82
+ # Returns native javascript event created by jQuery.
83
+ #
84
+ # @return [JSObject]
85
+ def to_n
86
+ @native
87
+ end
88
+
89
+ def [](name)
90
+ `#@native[name]`
91
+ end
92
+
93
+ def type
94
+ `#@native.type`
95
+ end
96
+
97
+ # Returns the current element in the bubbling cycle of the event. This is
98
+ # not the same as the actual dom event that triggered the event, but is
99
+ # usually the context element the event was registered with, or the target
100
+ # of the css selector used in newer event styles.
101
+ #
102
+ # @return [Element]
103
+ def element
104
+ `$(#@native.currentTarget)`
105
+ end
106
+
107
+ alias current_target element
108
+
109
+ # Returns the actual element that triggered the dom event.
110
+ #
111
+ # @return [Element]
112
+ def target
113
+ `$(#@native.target)`
114
+ end
115
+
116
+ # Returns `true` if this event has had its default browser behaviour
117
+ # prevented, `false` otherwise.
118
+ #
119
+ # @return [Boolean]
120
+ def prevented?
121
+ `#@native.isDefaultPrevented()`
122
+ end
123
+
124
+ # Prevent this event from triggering its default browser behaviour.
125
+ def prevent
126
+ `#@native.preventDefault()`
127
+ end
128
+
129
+ # Returns `true` if the propagation/bubbling of this event has been stopped,
130
+ # `false` otherwise.
131
+ #
132
+ # @return [Boolean]
133
+ def stopped?
134
+ `#@native.isPropagationStopped()`
135
+ end
136
+
137
+ # Stop further propagaion of this event.
138
+ def stop
139
+ `#@native.stopPropagation()`
140
+ end
141
+
142
+ def stop_immediate
143
+ `#@native.stopImmediatePropagation()`
144
+ end
145
+
146
+ # Stops propagation and prevents default action.
147
+ #
148
+ # @see {#prevent}
149
+ # @see {#stop}
150
+ def kill
151
+ stop
152
+ prevent
153
+ end
154
+
155
+ ##
156
+ # Keyboard/Mouse/Touch
157
+
158
+ def page_x
159
+ `#@native.pageX`
160
+ end
161
+
162
+ def page_y
163
+ `#@native.pageY`
164
+ end
165
+
166
+ def touch_x
167
+ `#@native.originalEvent.touches[0].pageX`
168
+ end
169
+
170
+ def touch_y
171
+ `#@native.originalEvent.touches[0].pageY`
172
+ end
173
+
174
+ def ctrl_key
175
+ `#@native.ctrlKey`
176
+ end
177
+
178
+ def meta_key
179
+ `#@native.metaKey`
180
+ end
181
+
182
+ def alt_key
183
+ `#@native.altKey`
184
+ end
185
+
186
+ def shift_key
187
+ `#@native.shiftKey`
188
+ end
189
+
190
+ def key_code
191
+ `#@native.keyCode`
192
+ end
193
+
194
+ def which
195
+ `#@native.which`
196
+ end
197
+
198
+ # @deprecated These will be removed soon
199
+ alias default_prevented? prevented?
200
+ alias prevent_default prevent
201
+ alias propagation_stopped? stopped?
202
+ alias stop_propagation stop
203
+ alias stop_immediate_propagation stop_immediate
204
+
205
+ end
@@ -0,0 +1,270 @@
1
+ require 'json'
2
+ require 'native'
3
+ require 'promise'
4
+ require 'opal/jquery/constants'
5
+
6
+ # {HTTP} is used to perform a `XMLHttpRequest` in ruby. It is a simple wrapper
7
+ # around jQuerys' `$.ajax` call. `XMLHttpRequest` is not wrapped directly as
8
+ # jquery provides some cross browser fixes.
9
+ #
10
+ # # Making requests
11
+ #
12
+ # To create a simple request, {HTTP} exposes class level methods to specify
13
+ # the HTTP action you wish to perform. Each action accepts the url for the
14
+ # request, as well as optional arguments passed as a hash:
15
+ #
16
+ # HTTP.get("/users/1.json")
17
+ # HTTP.post("/users", payload: data)
18
+ #
19
+ # The supported `HTTP` actions are:
20
+ #
21
+ # * {HTTP.get}
22
+ # * {HTTP.post}
23
+ # * {HTTP.put}
24
+ # * {HTTP.delete}
25
+ # * {HTTP.patch}
26
+ # * {HTTP.head}
27
+ #
28
+ # # Handling responses
29
+ #
30
+ # Responses can be handled using either a simple block callback, or using a
31
+ # {Promise} returned by the request.
32
+ #
33
+ # ## Using a block
34
+ #
35
+ # All HTTP action methods accept a block which can be used as a simple
36
+ # handler for the request. The block will be called for both successful as well
37
+ # as unsuccessful requests.
38
+ #
39
+ # HTTP.get("/users/1") do |request|
40
+ # puts "the request has completed!"
41
+ # end
42
+ #
43
+ # This `request` object will simply be the instance of the {HTTP} class which
44
+ # wraps the native `XMLHttpRequest`. {HTTP#ok?} can be used to quickly determine
45
+ # if the request was successful.
46
+ #
47
+ # HTTP.get("/users/1") do |request|
48
+ # if request.ok?
49
+ # puts "request was success"
50
+ # else
51
+ # puts "something went wrong with request"
52
+ # end
53
+ # end
54
+ #
55
+ # The {HTTP} instance will always be the only object passed to the block.
56
+ #
57
+ # ## Using a Promise
58
+ #
59
+ # If no block is given to one of the action methods, then a {Promise} is
60
+ # returned instead. See the standard library for more information on Promises.
61
+ #
62
+ # HTTP.get("/users/1").then do |req|
63
+ # puts "response ok!"
64
+ # end.fail do |req|
65
+ # puts "response was not ok"
66
+ # end
67
+ #
68
+ # When using a {Promise}, both success and failure handlers will be passed the
69
+ # {HTTP} instance.
70
+ #
71
+ # # Accessing Response Data
72
+ #
73
+ # All data returned from an HTTP request can be accessed via the {HTTP} object
74
+ # passed into the block or promise handlers.
75
+ #
76
+ # - {#ok?} - returns `true` or `false`, if request was a success (or not).
77
+ # - {#body} - returns the raw text response of the request
78
+ # - {#status_code} - returns the raw {HTTP} status code as integer
79
+ # - {#json} - tries to convert the body response into a JSON object
80
+ class HTTP
81
+ `var $ = #{JQUERY_SELECTOR.to_n}` # cache $ for SPEED
82
+
83
+ # All valid {HTTP} action methods this class accepts.
84
+ #
85
+ # @see HTTP.get
86
+ # @see HTTP.post
87
+ # @see HTTP.put
88
+ # @see HTTP.delete
89
+ # @see HTTP.patch
90
+ # @see HTTP.head
91
+ ACTIONS = %w[get post put delete patch head]
92
+
93
+ # @!method self.get(url, options = {}, &block)
94
+ #
95
+ # Create a {HTTP} `get` request.
96
+ #
97
+ # @example
98
+ # HTTP.get("/foo") do |req|
99
+ # puts "got data: #{req.data}"
100
+ # end
101
+ #
102
+ # @param url [String] url for request
103
+ # @param options [Hash] any request options
104
+ # @yield [self] optional block to handle response
105
+ # @return [Promise, nil] optionally returns a promise
106
+
107
+ # @!method self.post(url, options = {}, &block)
108
+ #
109
+ # Create a {HTTP} `post` request. Post data can be supplied using the
110
+ # `payload` options. Usually this will be a hash which will get serialized
111
+ # into a native javascript object.
112
+ #
113
+ # @example
114
+ # HTTP.post("/bar", payload: data) do |req|
115
+ # puts "got response"
116
+ # end
117
+ #
118
+ # @param url [String] url for request
119
+ # @param options [Hash] optional request options
120
+ # @yield [self] optional block to yield for response
121
+ # @return [Promise, nil] returns a {Promise} unless block given
122
+
123
+ # @!method self.put(url, options = {}, &block)
124
+
125
+ # @!method self.delete(url, options = {}, &block)
126
+
127
+ # @!method self.patch(url, options = {}, &block)
128
+
129
+ # @!method self.head(url, options = {}, &block)
130
+
131
+ ACTIONS.each do |action|
132
+ define_singleton_method(action) do |url, options = {}, &block|
133
+ new.send(action, url, options, block)
134
+ end
135
+
136
+ define_method(action) do |url, options = {}, &block|
137
+ send(action, url, options, block)
138
+ end
139
+ end
140
+
141
+ def self.setup
142
+ Hash.new(`$.ajaxSetup()`)
143
+ end
144
+
145
+ def self.setup= settings
146
+ `$.ajaxSetup(#{settings.to_n})`
147
+ end
148
+
149
+ attr_reader :body, :error_message, :method, :status_code, :url, :xhr
150
+
151
+ def initialize
152
+ @settings = {}
153
+ @ok = true
154
+ end
155
+
156
+ def send(method, url, options, block)
157
+ @method = method
158
+ @url = url
159
+ @payload = options.delete :payload
160
+ @handler = block
161
+
162
+ @settings.update options
163
+
164
+ settings, payload = @settings.to_n, @payload
165
+
166
+ %x{
167
+ if (typeof(#{payload}) === 'string') {
168
+ #{settings}.data = payload;
169
+ }
170
+ else if (payload != nil) {
171
+ settings.data = payload.$to_json();
172
+ settings.contentType = 'application/json';
173
+ }
174
+
175
+ settings.url = #@url;
176
+ settings.type = #{@method.upcase};
177
+
178
+ settings.success = function(data, status, xhr) {
179
+ return #{ succeed `data`, `status`, `xhr` };
180
+ };
181
+
182
+ settings.error = function(xhr, status, error) {
183
+ return #{ fail `xhr`, `status`, `error` };
184
+ };
185
+
186
+ $.ajax(settings);
187
+ }
188
+
189
+ @handler ? self : promise
190
+ end
191
+
192
+ # Parses the http response body through json. If the response is not
193
+ # valid JSON then an error will very likely be thrown.
194
+ #
195
+ # @example Getting JSON content
196
+ # HTTP.get("api.json") do |response|
197
+ # puts response.json
198
+ # end
199
+ #
200
+ # # => {"key" => 1, "bar" => 2, ... }
201
+ #
202
+ # @return [Hash, Array] returns the parsed json
203
+ def json
204
+ @json ||= JSON.parse(@body)
205
+ end
206
+
207
+ # Returns true if the request succeeded, false otherwise.
208
+ #
209
+ # @example
210
+ # HTTP.get("/some/url") do |response|
211
+ # if response.ok?
212
+ # alert "Yay!"
213
+ # else
214
+ # alert "Aww :("
215
+ # end
216
+ #
217
+ # @return [true, false] true if request was successful
218
+ def ok?
219
+ @ok
220
+ end
221
+
222
+ # Returns the value of the specified response header.
223
+ #
224
+ # @param key [String] name of the header to get
225
+ # @return [String] value of the header
226
+ def get_header(key)
227
+ `#@xhr.getResponseHeader(#{key});`
228
+ end
229
+
230
+ private
231
+
232
+ def promise
233
+ return @promise if @promise
234
+
235
+ @promise = Promise.new.tap { |promise|
236
+ @handler = proc { |res|
237
+ if res.ok?
238
+ promise.resolve res
239
+ else
240
+ promise.reject res
241
+ end
242
+ }
243
+ }
244
+ end
245
+
246
+ def succeed(data, status, xhr)
247
+ %x{
248
+ #@body = data;
249
+ #@xhr = xhr;
250
+ #@status_code = xhr.status;
251
+
252
+ if (typeof(data) === 'object') {
253
+ #@json = #{ JSON.from_object `data` };
254
+ }
255
+ }
256
+
257
+ @handler.call self if @handler
258
+ end
259
+
260
+ def fail(xhr, status, error)
261
+ %x{
262
+ #@body = xhr.responseText;
263
+ #@xhr = xhr;
264
+ #@status_code = xhr.status;
265
+ }
266
+
267
+ @ok = false
268
+ @handler.call self if @handler
269
+ end
270
+ end