mack-javascript 0.8.2 → 0.8.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/mack-javascript/generators/manifest.yml +3 -15
- data/lib/mack-javascript/generators/templates/javascripts/jquery.js.template +110 -23
- data/lib/mack-javascript/generators/templates/javascripts/prototype.js.template +438 -4219
- data/lib/mack-javascript/helpers/jquery_helper.rb +536 -60
- data/lib/mack-javascript/helpers/prototype_helper.rb +407 -39
- data/lib/mack-javascript/helpers/script_generator.rb +151 -14
- data/lib/mack-javascript/rendering/engine/rjs.rb +6 -2
- data/lib/mack-javascript/view_helpers/html_helpers.rb +18 -5
- data/lib/mack-javascript.rb +2 -11
- metadata +2 -7
- data/lib/mack-javascript/generators/templates/javascripts/controls.js.template +0 -963
- data/lib/mack-javascript/generators/templates/javascripts/dragdrop.js.template +0 -972
- data/lib/mack-javascript/generators/templates/javascripts/effects.js.template +0 -1120
- data/lib/mack-javascript/generators/templates/javascripts/jquery-fx.js.template +0 -28
- data/lib/mack-javascript/generators/templates/javascripts/jquery-ui.js.template +0 -85
@@ -1,64 +1,13 @@
|
|
1
|
+
require File.join_from_here('script_generator')
|
2
|
+
|
1
3
|
module Mack
|
2
4
|
module JavaScript # :nodoc:
|
3
5
|
module Framework # :nodoc:
|
4
|
-
class
|
6
|
+
class JqueryAjax
|
5
7
|
class << self
|
6
|
-
|
7
|
-
insertion = position.to_s.downcase
|
8
|
-
insertion = 'append' if insertion == 'bottom'
|
9
|
-
insertion = 'prepend' if insertion == 'top'
|
10
|
-
"$(\'##{id}\').#{insertion}('#{html}')"
|
11
|
-
end
|
12
|
-
|
13
|
-
def replace_html(id, html)
|
14
|
-
insert_html(:html, id, html)
|
15
|
-
end
|
16
|
-
|
17
|
-
def replace(id, html)
|
18
|
-
"$(\'##{id}\').replaceWith('#{html}')"
|
19
|
-
end
|
20
|
-
|
21
|
-
def remove(*ids)
|
22
|
-
"$(\'##{ids.join(',#')}\').remove()"
|
23
|
-
end
|
24
|
-
|
25
|
-
def show(*ids)
|
26
|
-
"$(\'##{ids.join(',#')}\').show()"
|
27
|
-
end
|
28
|
-
|
29
|
-
def hide(*ids)
|
30
|
-
"$(\'##{ids.join(',#')}\').hide()"
|
31
|
-
end
|
32
|
-
|
33
|
-
def toggle(*ids)
|
34
|
-
"$(\'##{ids.join(',#')}\').toggle()"
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
|
-
# def draggable(id, options = {})
|
39
|
-
# record @context.send(:draggable_element_js, id, options)
|
40
|
-
# end
|
41
|
-
#
|
42
|
-
# def visual_effect(name, id = nil, options = {})
|
43
|
-
# record @context.send(:visual_effect, name, id, options)
|
44
|
-
# end
|
45
|
-
#
|
46
|
-
# def drop_receiving(id, options = {})
|
47
|
-
# record @context.send(:drop_receiving_element_js, id, options)
|
48
|
-
# end
|
49
|
-
#
|
8
|
+
|
50
9
|
def remote_function(options)
|
51
10
|
javascript_options = options_for_ajax(options)
|
52
|
-
update = ''
|
53
|
-
if options[:update] && options[:update].is_a?(Hash)
|
54
|
-
update = []
|
55
|
-
update << "success:'#{options[:update][:success]}'" if options[:update][:success]
|
56
|
-
update << "failure:'#{options[:update][:failure]}'" if options[:update][:failure]
|
57
|
-
update = '{' + update.join(',') + '}'
|
58
|
-
elsif options[:update]
|
59
|
-
update << "'#{options[:update]}'"
|
60
|
-
end
|
61
|
-
|
62
11
|
function = "$.ajax(#{javascript_options})"
|
63
12
|
|
64
13
|
function = "#{options[:before]}; #{function}" if options[:before]
|
@@ -72,19 +21,43 @@ module Mack
|
|
72
21
|
def options_for_ajax(options)
|
73
22
|
js_options = build_callbacks(options)
|
74
23
|
js_options['url'] = "'#{options[:url]}'"
|
75
|
-
js_options['async'] = options[:type] != :synchronous
|
76
|
-
|
24
|
+
js_options['async'] = options[:type] != :synchronous
|
25
|
+
|
26
|
+
|
77
27
|
js_options['dataType'] = options[:datatype] ? "'#{options[:datatype]}'" : (options[:update] ? nil : "'script'")
|
78
|
-
|
28
|
+
|
29
|
+
|
79
30
|
if options[:form]
|
80
31
|
js_options['data'] = "$.param($(this).serializeArray())"
|
81
|
-
elsif options[:submit]
|
82
|
-
js_options['data'] = "$(\"##{options[:submit]}\").serializeArray()"
|
83
32
|
elsif options[:with]
|
84
33
|
js_options['data'] = options[:with].gsub('Form.serialize(this.form)','$.param($(this.form).serializeArray())')
|
85
34
|
end
|
35
|
+
|
36
|
+
if options[:method].nil? || options[:method].to_sym != :get
|
37
|
+
js_options['type'] = "'post'"
|
38
|
+
else
|
39
|
+
js_options['type'] = "'get'"
|
40
|
+
end
|
41
|
+
|
42
|
+
if options[:method] && options[:method].to_sym == :put || options[:method] == :delete
|
43
|
+
js_options['data'] = append_ajax_data(js_options['data'], "_method=#{options[:method]}")
|
44
|
+
end
|
45
|
+
|
46
|
+
if js_options['type'] == "'post'" && options[:authenticity_token]
|
47
|
+
js_options['data'] = append_ajax_data(js_options['data'], "__authenticity_token=#{options.delete(:authenticity_token)}")
|
48
|
+
end
|
49
|
+
|
86
50
|
options_for_javascript(js_options.reject {|key, value| value.nil?})
|
87
51
|
end
|
52
|
+
|
53
|
+
def append_ajax_data(data, new_data)
|
54
|
+
if data
|
55
|
+
data << " + '&"
|
56
|
+
else
|
57
|
+
data = "'"
|
58
|
+
end
|
59
|
+
data << "#{new_data}'"
|
60
|
+
end
|
88
61
|
|
89
62
|
def options_for_javascript(options)
|
90
63
|
'{' + options.map {|k, v| "#{k}:#{v}"}.sort.join(', ') + '}'
|
@@ -120,6 +93,509 @@ module Mack
|
|
120
93
|
end
|
121
94
|
|
122
95
|
end
|
96
|
+
|
97
|
+
class JquerySelector < Mack::JavaScript::Selector
|
98
|
+
|
99
|
+
def select
|
100
|
+
"$(#{@selector})"
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
|
106
|
+
#--- Tree Walking ---#
|
107
|
+
|
108
|
+
# Will give you the immediate children underneath the selected elements
|
109
|
+
#
|
110
|
+
#
|
111
|
+
# Example:
|
112
|
+
# say you have the following html:
|
113
|
+
#
|
114
|
+
# <div class='rakim'>
|
115
|
+
# <ul>
|
116
|
+
# ...
|
117
|
+
# </ul>
|
118
|
+
# </div>
|
119
|
+
#
|
120
|
+
# <div class='rakim'>
|
121
|
+
# <p>Eric B</p>
|
122
|
+
# <div id='technique'>
|
123
|
+
# ...
|
124
|
+
# </div>
|
125
|
+
# </div>
|
126
|
+
#
|
127
|
+
# page.select('.rakim').children would give you a collection consisting of
|
128
|
+
# the ul element, the p element, and the div with id 'technique'
|
129
|
+
def children
|
130
|
+
add "children()"
|
131
|
+
end
|
132
|
+
|
133
|
+
# returns a collection of the immediate parent of each selected element
|
134
|
+
def parent
|
135
|
+
add "parent()"
|
136
|
+
end
|
137
|
+
|
138
|
+
# returns a collection of every parent up the chain to the root of the document
|
139
|
+
# for each selected element. This method also takes an optional selector as an argument.
|
140
|
+
#
|
141
|
+
# Example:
|
142
|
+
#
|
143
|
+
# for the html
|
144
|
+
#
|
145
|
+
# <div class='big_daddy_kane'>
|
146
|
+
# <div id='long_live'>
|
147
|
+
# <ul class='raw'>
|
148
|
+
# <li id='featuring'>with Kool G Rap</li>
|
149
|
+
# </ul>
|
150
|
+
# </div>
|
151
|
+
# </div>
|
152
|
+
#
|
153
|
+
# page.select('#featuring').ancestors will give you a collection consisting
|
154
|
+
# of both divs and the ul.
|
155
|
+
# page.select('#featuring').ancestors('#long_live') will give you the div with
|
156
|
+
# id 'long_live'
|
157
|
+
def ancestors(selector = nil)
|
158
|
+
add "parents(#{optional_selector(selector)})"
|
159
|
+
end
|
160
|
+
|
161
|
+
# gets all siblings for each element selected
|
162
|
+
# Takes an optional selector as an argument
|
163
|
+
def siblings(selector = nil)
|
164
|
+
add "siblings(#{optional_selector(selector)})"
|
165
|
+
end
|
166
|
+
|
167
|
+
# gets the next immediate sibling for each element selected
|
168
|
+
# Takes an optional selector as an argument
|
169
|
+
def next(selector = nil)
|
170
|
+
add "next(#{optional_selector(selector)})"
|
171
|
+
end
|
172
|
+
|
173
|
+
# gets the previous immediate sibling for each element selected
|
174
|
+
# Takes an optional selector as an argument
|
175
|
+
def previous(selector = nil)
|
176
|
+
add "prev(#{optional_selector(selector)})"
|
177
|
+
end
|
178
|
+
|
179
|
+
# gets every next sibling for each element selected
|
180
|
+
# Takes an optional selector as an argument
|
181
|
+
def all_next(selector = nil)
|
182
|
+
add "nextAll(#{optional_selector(selector)})"
|
183
|
+
end
|
184
|
+
|
185
|
+
# gets every previous sibling for each element selected
|
186
|
+
# Takes an optional selector as an argument
|
187
|
+
def all_previous(selector = nil)
|
188
|
+
add "prevAll(#{optional_selector(selector)})"
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
|
193
|
+
|
194
|
+
|
195
|
+
#-- Attributes --#
|
196
|
+
|
197
|
+
def add_class(klass)
|
198
|
+
add "addClass('#{klass}')"
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
def remove_class(klass = '')
|
203
|
+
add "removeClass('#{klass}')"
|
204
|
+
end
|
205
|
+
|
206
|
+
def set_attribute(name, value)
|
207
|
+
value = "'#{value}'" if value.is_a? String
|
208
|
+
add "attr('#{name}', #{value})"
|
209
|
+
end
|
210
|
+
|
211
|
+
def remove_attribute(name)
|
212
|
+
add "removeAttr('#{name}')"
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
|
217
|
+
|
218
|
+
#-- DOM Manipulation --#
|
219
|
+
|
220
|
+
# inserts html into the selected place for the specfied elemets
|
221
|
+
#
|
222
|
+
# +position+ may be one of:
|
223
|
+
#
|
224
|
+
# <tt>:top</tt>:: HTML is inserted inside the element, before the
|
225
|
+
# element's existing content.
|
226
|
+
# <tt>:bottom</tt>:: HTML is inserted inside the element, after the
|
227
|
+
# element's existing content.
|
228
|
+
# <tt>:before</tt>:: HTML is inserted immediately preceding the element.
|
229
|
+
# <tt>:after</tt>:: HTML is inserted immediately following the element.
|
230
|
+
#
|
231
|
+
#
|
232
|
+
# Example
|
233
|
+
#
|
234
|
+
# <div class='rakim'>
|
235
|
+
# <ul>
|
236
|
+
# ...
|
237
|
+
# </ul>
|
238
|
+
# </div>
|
239
|
+
#
|
240
|
+
# <div class='rakim'>
|
241
|
+
# <p>Eric B</p>
|
242
|
+
# <div id='technique'>
|
243
|
+
# ...
|
244
|
+
# </div>
|
245
|
+
# </div>
|
246
|
+
#
|
247
|
+
# page.select('.rakim').insert(:before, "<h1> The R </h1>") would result in:
|
248
|
+
#
|
249
|
+
# <h1> The R </h2>
|
250
|
+
# <div class='rakim'>
|
251
|
+
# <ul>
|
252
|
+
# ...
|
253
|
+
# </ul>
|
254
|
+
# </div>
|
255
|
+
#
|
256
|
+
# <h1> The R </h2>
|
257
|
+
# <div class='rakim'>
|
258
|
+
# <p>Eric B</p>
|
259
|
+
# <div id='technique'>
|
260
|
+
# ...
|
261
|
+
# </div>
|
262
|
+
# </div>
|
263
|
+
#
|
264
|
+
#
|
265
|
+
# Tip: use this with a partial containing your html:
|
266
|
+
# page.select('.rakim').insert(:before, render(:partial, 'the_r', :format => :html))
|
267
|
+
def insert(position, html)
|
268
|
+
position = {:bottom => 'append', :top => 'prepend'}[position.to_sym] || position.to_s
|
269
|
+
add "#{position}('#{escape_javascript(html)}')"
|
270
|
+
end
|
271
|
+
|
272
|
+
|
273
|
+
# replaces the selected html.
|
274
|
+
#
|
275
|
+
# +repace+ may be:
|
276
|
+
#
|
277
|
+
# <tt>:inner</tt>:: The inner html of the selected elements
|
278
|
+
# are replaced
|
279
|
+
# <tt>:outer</tt>:: the selected elements themselves are replaced
|
280
|
+
#
|
281
|
+
# Example
|
282
|
+
#
|
283
|
+
# <div class='rakim'>
|
284
|
+
# <p>Dont Sweat the Techinique</p>
|
285
|
+
# </div>
|
286
|
+
# <div class='rakim'>
|
287
|
+
# <p>Follow the Leader</p>
|
288
|
+
# </div>
|
289
|
+
#
|
290
|
+
# page.select('.rakim').replace(:inner, "<p>Paid in Full</p>") would result in
|
291
|
+
#
|
292
|
+
# <div class='rakim'>
|
293
|
+
# <p>Paid in Full</p>
|
294
|
+
# </div>
|
295
|
+
# <div class='rakim'>
|
296
|
+
# <p>Paid in Full</p>
|
297
|
+
# </div>
|
298
|
+
#
|
299
|
+
# if we then did:
|
300
|
+
# page.select('.rakim').replace(:outer, "<div class='schoolyD'><p>SaturdayNight</p></div>")
|
301
|
+
# the result would be
|
302
|
+
#
|
303
|
+
# <div class='schoolyD'>
|
304
|
+
# <p>SaturdayNight</p>
|
305
|
+
# </div>
|
306
|
+
# <div class='schoolyD'>
|
307
|
+
# <p>SaturdayNight</p>
|
308
|
+
# </div>
|
309
|
+
def replace(replace, html)
|
310
|
+
function = {:inner =>"html",:outer => 'replaceWith'}[replace.to_sym]
|
311
|
+
add "#{function}('#{escape_javascript(html)}')"
|
312
|
+
end
|
313
|
+
|
314
|
+
#removes the selected elements from the DOM
|
315
|
+
def remove
|
316
|
+
add "remove()"
|
317
|
+
end
|
318
|
+
|
319
|
+
|
320
|
+
|
321
|
+
#-- Effects --#
|
322
|
+
#
|
323
|
+
# All five effects methods in JquerySelector (morph, effect, show, hide, toggle)
|
324
|
+
# take the same options hash. This can consist of:
|
325
|
+
#
|
326
|
+
# <tt>:duration</tt>:: The duration of the effect in ms.
|
327
|
+
# <tt>:easing</tt>:: see below
|
328
|
+
# <tt>:callback</tt>:: see below
|
329
|
+
# <tt>:queue</tt>:: If false, the animation isn’t queued and begins running
|
330
|
+
# immediately.
|
331
|
+
#
|
332
|
+
#
|
333
|
+
# --Easing--
|
334
|
+
# This determines the mathematical function your effect will use while transitioning.
|
335
|
+
# For instance, if you do page.select(.rakim).effect(:slideUp, :easing => 'easeOutBounce'),
|
336
|
+
# every element with class 'rakim' will slide up and when it reaches the top, they will
|
337
|
+
# bounce back down a little then go back up. To visualize this better, see
|
338
|
+
# http://www.robertpenner.com/easing/easing_demo.html
|
339
|
+
#
|
340
|
+
# The full list of jquery easing options:
|
341
|
+
# linear, swing, easeInQuad, easeOutQuad, easeInOutQuad, easeInCubic, easeOutCubic,
|
342
|
+
# easeInOutCubic, easeInQuart, easeOutQuart, easeInOutQuart, easeInQuint, easeOutQuint,
|
343
|
+
# easeInOutQuint, easeInSine, easeOutSine, easeInOutSine, easeInExpo, easeOutExpo,
|
344
|
+
# easeInOutExpo, easeInCirc, easeOutCirc, easeInOutCirc, easeInElastic, easeOutElastic,
|
345
|
+
# easeInOutElastic, easeInBack, easeOutBack, easeInOutBack, easeInBounce, easeOutBounce,
|
346
|
+
# easeInOutBounce:
|
347
|
+
#
|
348
|
+
# --Callback--
|
349
|
+
#
|
350
|
+
# this is a function that will get called when your effect is done. You can use
|
351
|
+
# page.function to build it. Note: This function gets called for each element selected.
|
352
|
+
# For instance, in the following example, if there are 10 elements with the class 'rakim'
|
353
|
+
# then the function will be called 10 times. If you want to target each of the 10 elements
|
354
|
+
# in the callback function, use page.select('this')
|
355
|
+
#
|
356
|
+
# func = page.function.body do |p|
|
357
|
+
# p.select('this').insert(:top, '<h1>Cool Effects</h1>').effect(:highlight)
|
358
|
+
# end
|
359
|
+
# page.select('.rakim').effect(:slide_down, :callback => func)
|
360
|
+
#
|
361
|
+
# The above code will make every element with class 'rakim' slide down. When they are done
|
362
|
+
# sliding, the h1 tag will be inserted in the top of each element, and each element will
|
363
|
+
# be highlighted. Instead of this, you could do the following
|
364
|
+
# page.select('.rakim').effect(:slide_down).insert(:top, '<h1>Cool Effects</h1>').effect(:highlight)
|
365
|
+
# But this way, the insertion won't wait for the first animation to be done before occurring.
|
366
|
+
|
367
|
+
|
368
|
+
|
369
|
+
# Takes a hash of css properties you want the selected elements to 'morph' into.
|
370
|
+
# Say you want all elements with class rakim to transition to only having half
|
371
|
+
# the opacity and having a red background, and you want the transition to last 4
|
372
|
+
# seconds
|
373
|
+
# page.select('.rakim').morph({:opacity => 0.5, :backgroundColor => '#f00'}, :duration => 4000)
|
374
|
+
# You can see a list of css properties here http://www.w3schools.com/CSS/css_reference.asp
|
375
|
+
# The properties in your hash should be camelcase: :backgroundColor instead of
|
376
|
+
# background-color
|
377
|
+
def morph(hsh, options = nil)
|
378
|
+
options[:complete] = options.delete(:callback) if options && options[:callback]
|
379
|
+
args = [options_for_javascript(hsh), options_for_effects(options)]
|
380
|
+
add "animate(#{args.compact.join(',')})"
|
381
|
+
end
|
382
|
+
|
383
|
+
#This general mapping taken from the awesome JRails plugin
|
384
|
+
@@effects = {
|
385
|
+
:appear => {:function => 'fadeIn'},
|
386
|
+
:blind_down => {:mode => 'blind', :function => 'show', :options => {:direction => 'vertical'}},
|
387
|
+
:blind_up => {:mode => 'blind', :function => 'hide', :options => {:direction => 'vertical'}},
|
388
|
+
:blind_right => {:mode => 'blind', :function => 'show', :options => {:direction => 'horizontal'}},
|
389
|
+
:blind_left => {:mode => 'blind', :function => 'hide', :options => {:direction => 'horizontal'}},
|
390
|
+
:bounce_in => {:mode => 'bounce', :function => 'show', :options => {:direction => 'up'}},
|
391
|
+
:bounce_out => {:mode => 'bounce', :function => 'hide', :options => {:direction => 'up'}},
|
392
|
+
:drop_in => {:mode => 'drop', :function => 'show', :options => {:direction => 'up'}},
|
393
|
+
:drop_out => {:mode => 'drop', :function => 'hide', :options => {:direction => 'down'}},
|
394
|
+
:fade => {:function => 'fadeOut'},
|
395
|
+
:fold_in => {:mode => 'fold', :function => 'hide'},
|
396
|
+
:fold_out => {:mode => 'fold', :function => 'show'},
|
397
|
+
:grow => {:mode => 'scale', :function => 'show'},
|
398
|
+
:highlight => {:mode => 'highlight', :function => 'show'},
|
399
|
+
:puff => {:mode => 'puff', :function => 'hide'},
|
400
|
+
:pulsate => {:mode => 'pulsate', :function => 'show'},
|
401
|
+
:shake => {:mode => 'shake', :function => 'show'},
|
402
|
+
:shrink => {:mode => 'scale', :function => 'hide'},
|
403
|
+
:slide_down => {:mode => 'slide', :function => 'show', :options => {:direction => 'up'}},
|
404
|
+
:slide_up => {:mode => 'slide', :function => 'hide', :options => {:direction => 'up'}},
|
405
|
+
:slide_right => {:mode => 'slide', :function => 'show', :options => {:direction => 'left'}},
|
406
|
+
:slide_left => {:mode => 'slide', :function => 'hide', :options => {:direction => 'left'}},
|
407
|
+
:squish => {:mode => 'scale', :function => 'hide', :options => {:origin => "['top','left']"}},
|
408
|
+
:switch_on => {:mode => 'clip', :function => 'show', :options => {:direction => 'vertical'}},
|
409
|
+
:switch_off => {:mode => 'clip', :function => 'hide', :options => {:direction => 'vertical'}},
|
410
|
+
:toggle_appear => {:function => 'fadeToggle'},
|
411
|
+
:toggle_slide => {:mode => 'slide', :function => 'toggle', :options => {:direction => 'up'}},
|
412
|
+
:toggle_blind => {:mode => 'blind', :function => 'toggle', :options => {:direction => 'vertical'}},
|
413
|
+
}
|
414
|
+
|
415
|
+
#custom effects. 'name' corresponds to the keys of the hash above
|
416
|
+
def effect(name, options = nil)
|
417
|
+
effect = @@effects[name]
|
418
|
+
args = [effect[:mode] ? "'#{effect[:mode]}'" : nil,
|
419
|
+
options_for_effects((effect[:options] || {}).merge(options || {}))]
|
420
|
+
add "#{effect[:function]}(#{args.compact.join(',')})"
|
421
|
+
end
|
422
|
+
|
423
|
+
# show() shows an element, hide() hides it, and toggle() shows a hidden and hides a shown.
|
424
|
+
#
|
425
|
+
# The first parameter, fx, can be any one of the following: blind, bounce, clip, core,
|
426
|
+
# drop, explode, fold, highlight, pulsate, scale, shake, slide.
|
427
|
+
# You can see above that the majority of the custom effects are built using either
|
428
|
+
# show or hide paired with an fx
|
429
|
+
# Note: the arguments for the following three methods are unique to jquery
|
430
|
+
def show(fx = nil, options = nil)
|
431
|
+
args = [fx ? "'#{fx}'" : nil, options_for_effects(options)]
|
432
|
+
add "show(#{args.compact.join(',')})"
|
433
|
+
end
|
434
|
+
|
435
|
+
def hide(fx = nil, options = nil)
|
436
|
+
args = [fx ? "'#{fx}'" : nil, options_for_effects(options)]
|
437
|
+
add "hide(#{args.compact.join(',')})"
|
438
|
+
end
|
439
|
+
|
440
|
+
def toggle(fx = nil, options = nil)
|
441
|
+
args = [fx ? "'#{fx}'" : nil, options_for_effects(options)]
|
442
|
+
add "toggle(#{args.compact.join(',')})"
|
443
|
+
end
|
444
|
+
|
445
|
+
|
446
|
+
|
447
|
+
|
448
|
+
|
449
|
+
#-- Events --#
|
450
|
+
|
451
|
+
# adds an event listener to the selected elements. If options[:prevent_default] == true
|
452
|
+
# the default behavior of the event isn't taken
|
453
|
+
#
|
454
|
+
# Example
|
455
|
+
#
|
456
|
+
# page.select('.rakim a').peep 'click', :prevent_default => true do |p|
|
457
|
+
# p.select('#sucka_mcs').effect(:fade)
|
458
|
+
# end
|
459
|
+
#
|
460
|
+
# After running this code, if you click any a tag under any element with the
|
461
|
+
# class 'rakim', the element with id "sucka_mcs" will fade. Because of the option
|
462
|
+
# :prevent_default => true, the default action when clicking the a tag (the browser
|
463
|
+
# goes to its href url) isn't done.
|
464
|
+
# This can also be used in conjunction with trigger to make and call custom events.
|
465
|
+
def peep(event_name, options = {}, &block)
|
466
|
+
add "bind('#{event_name}', #{event_function(options[:prevent_default], &block)})"
|
467
|
+
end
|
468
|
+
|
469
|
+
#takes away any event listeners on the 'event_name' event fot the selected elements
|
470
|
+
def stop_peeping(event_name)
|
471
|
+
add "unbind('#{event_name}')"
|
472
|
+
end
|
473
|
+
|
474
|
+
# triggers the 'event_name' event on the selected elements.
|
475
|
+
def trigger(event_name)
|
476
|
+
add "trigger('#{event_name}')"
|
477
|
+
end
|
478
|
+
|
479
|
+
|
480
|
+
|
481
|
+
|
482
|
+
|
483
|
+
#-- Drag and Drop --#
|
484
|
+
|
485
|
+
# Makes the selected elements draggable.
|
486
|
+
#
|
487
|
+
# options can be a hash or a string. The following strings are supported
|
488
|
+
#
|
489
|
+
# <tt>disable</tt>:: temporarily disables dragging functionality
|
490
|
+
# <tt>enable</tt>:: re-enables dragging functionality
|
491
|
+
# <tt>destroy</tt>:: disables dragging functionality
|
492
|
+
#
|
493
|
+
# The options hash has many...well, options, the full list of which
|
494
|
+
# can be found here: http://docs.jquery.com/UI/Draggable/draggable#toptions
|
495
|
+
# Some usefule ones include:
|
496
|
+
#
|
497
|
+
# <tt>:opacity</tt>:: opacity of the element once dragging starts
|
498
|
+
# <tt>:scroll</tt>:: if true, container auto-scrolls while dragging.
|
499
|
+
# <tt>:zIndex</tt>:: z-index for the helper while being dragged.
|
500
|
+
# <tt>:helper</tt>:: Possible values: 'original', 'clone'. The 'clone'
|
501
|
+
# option will produce the 'ghosting' effect.
|
502
|
+
# <tt>:revert</tt>:: if set to true, the element will return to its
|
503
|
+
# start position when dragging stops. Also accepts the
|
504
|
+
# strings "valid" and "invalid": If set to invalid, revert
|
505
|
+
# will only occur if the draggable has not been dropped on
|
506
|
+
# a droppable. For valid, it's the other way around.
|
507
|
+
def draggable(options = nil)
|
508
|
+
add "draggable(#{drag_and_drop_options(options)})"
|
509
|
+
end
|
510
|
+
|
511
|
+
|
512
|
+
# Makes the selected elements droppable.
|
513
|
+
#
|
514
|
+
# options can be a hash or a string. The following strings are supported
|
515
|
+
#
|
516
|
+
# <tt>disable</tt>:: temporarily disables dropping functionality
|
517
|
+
# <tt>enable</tt>:: re-enables dropping functionality
|
518
|
+
# <tt>destroy</tt>:: disables dropping functionality
|
519
|
+
#
|
520
|
+
# all options are at http://docs.jquery.com/UI/Droppables/droppable
|
521
|
+
# Some useful ones include:
|
522
|
+
# <tt>:accept</tt>:: a css selector that defines what type of draggable
|
523
|
+
# elements it accepts. For instance, if :accept => '.block',
|
524
|
+
# only draggable objects with the class 'block' will be selected
|
525
|
+
# <tt>:activeClass</tt>:: The class that should be added to the droppable while
|
526
|
+
# an acceptable draggable is being dragged.
|
527
|
+
# <tt>:hoverClass</tt>:: The class that should be added to the droppable while
|
528
|
+
# being hovered by an acceptable draggable.
|
529
|
+
# <tt>:tolerance</tt>:: Specifies which mode to use for testing whether a draggable
|
530
|
+
# is 'over' a droppable. Possible values: 'fit', 'intersect',
|
531
|
+
# 'pointer', 'touch'. Default value: 'intersect'.
|
532
|
+
# <tt>:remote</tt>:: takes a hash of ajax options, the same as given to page.ajax
|
533
|
+
# if this options is, an ajax call is made using the specified
|
534
|
+
# options along. Added to the url is an id parameter which
|
535
|
+
# has the id of the element that was dropped
|
536
|
+
#
|
537
|
+
# if a block is given, the blocks code will be executed when a succesful drop is done.
|
538
|
+
#
|
539
|
+
# Example
|
540
|
+
#
|
541
|
+
# options = {:accept => '.trash', :remote => {:url => '/stuff'}}
|
542
|
+
# page.select('#bucket').droppable options do |p|
|
543
|
+
# p.alert('you dropped it!')
|
544
|
+
# end
|
545
|
+
#
|
546
|
+
# This code will make the element with id 'bucket' droppable. If an element with
|
547
|
+
# class 'trash' is dropped onto it, an ajax call to the url '/stuff' will be
|
548
|
+
# sent with an id parameter of the id of the dropped element. Then an js alert
|
549
|
+
# box with the message 'you dropped it' will appear.
|
550
|
+
def droppable(options = nil, &block)
|
551
|
+
remote_options = options.delete(:remote)
|
552
|
+
if remote_options || block_given?
|
553
|
+
func = Mack::JavaScript::Function.new(session_id, 'ev', 'ui')
|
554
|
+
if remote_options
|
555
|
+
remote_options[:with] ||= "'id=' + $(ui.draggable).attr('id')"
|
556
|
+
func << Mack::JavaScript::ScriptGenerator.new(session_id).ajax(remote_options)
|
557
|
+
end
|
558
|
+
func.body(&block) if block_given?
|
559
|
+
options.merge!(:drop => func)
|
560
|
+
end
|
561
|
+
add "droppable(#{drag_and_drop_options(options)})"
|
562
|
+
end
|
563
|
+
|
564
|
+
|
565
|
+
private
|
566
|
+
|
567
|
+
def build_multiple_selector_string(selector)
|
568
|
+
"'#{selector.join(', ')}'"
|
569
|
+
end
|
570
|
+
|
571
|
+
def drag_and_drop_options(options)
|
572
|
+
options = options.is_a?(String) ? "'#{options}'" : options_for_effects(options)
|
573
|
+
end
|
574
|
+
|
575
|
+
def options_for_effects(options)
|
576
|
+
options && !options.empty? ? options_for_javascript(options) : nil
|
577
|
+
end
|
578
|
+
|
579
|
+
def optional_selector(selector)
|
580
|
+
return "'#{selector}'" if selector
|
581
|
+
nil
|
582
|
+
end
|
583
|
+
|
584
|
+
def options_for_javascript(options)
|
585
|
+
options = options.collect do |key, value|
|
586
|
+
value = "'#{value}'" unless !value.is_a?(String) || value =~ /^function/
|
587
|
+
"#{key}: #{value}"
|
588
|
+
end
|
589
|
+
"{#{options.join(',')}}"
|
590
|
+
end
|
591
|
+
|
592
|
+
def event_function(prevent_default = false, &block)
|
593
|
+
func = Mack::JavaScript::Function.new(session_id, 'event')
|
594
|
+
func << "event.preventDefault()" if prevent_default
|
595
|
+
func.body(&block)
|
596
|
+
end
|
597
|
+
|
598
|
+
end
|
123
599
|
end
|
124
600
|
end
|
125
601
|
end
|