mack-javascript 0.8.2 → 0.8.3
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/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
|