[webui] update jrails plugin to a version maintained
[opensuse:build-service.git] / src / webui / vendor / plugins / jrails / lib / jrails / jrails.rb
1 module JRails
2   @@config = {
3     :google           => false,
4     :jquery_version   => "1.4.4",
5     :jqueryui_version => "1.8.6",
6     :compressed       => true
7   }
8
9   def self.load_config
10     config_file = File.join("./", "config", "jrails.yml")
11     if File.exist? config_file
12       loaded_config = YAML.load_file(config_file) 
13       if loaded_config and loaded_config.key? Rails.env
14         @@config.merge!(loaded_config[Rails.env].symbolize_keys) 
15         if google?
16           @@jquery_path   = "http://ajax.googleapis.com/ajax/libs/jquery/#{@@config[:jquery_version]}/jquery#{".min" if compressed?}.js"
17           @@jqueryui_path = "http://ajax.googleapis.com/ajax/libs/jqueryui/#{@@config[:jqueryui_version]}/jquery-ui#{".min" if compressed?}.js"
18           @@jqueryui_i18n_path = "http://ajax.googleapis.com/ajax/libs/jqueryui/#{@@config[:jqueryui_version]}/i18n/jquery-ui-i18n#{".min" if compressed?}.js"
19         end
20       else
21         raise Exception.new "Failed finding '#{Rails.env}' environment in config. check your 'config/jrails.yml' or delete that file "
22       end
23     end
24   end
25
26   def self.config        ; @@config              ; end
27   def self.google?       ; @@config[:google]     ; end
28   def self.compressed?   ; @@config[:compressed] ; end
29   def self.jquery_path   ; @@jquery_path         ; end
30   def self.jqueryui_path ; @@jqueryui_path       ; end
31   def self.jqueryui_i18n_path ; @@jqueryui_i18n_path  ; end
32 end
33
34
35
36 module ActionView
37   module Helpers
38     
39     module JavaScriptHelper
40       
41       # This function can be used to render rjs inline
42       #
43       # <%= javascript_function do |page|
44       #   page.replace_html :list, :partial => 'list', :object => @list
45       # end %>
46       #
47       def javascript_function(*args, &block)
48         html_options = args.extract_options!
49         function = args[0] || ''
50
51         html_options.symbolize_keys!
52         function = update_page(&block) if block_given?
53         javascript_tag(function)
54       end
55       
56       def jquery_id(id)
57         id.to_s.count('#.*,>+~:[/ ') == 0 ? "##{id}" : id
58       end
59           
60       def jquery_ids(ids)
61         Array(ids).map{|id| jquery_id(id)}.join(',')
62       end
63
64     end
65     
66     module PrototypeHelper
67       
68       USE_PROTECTION = const_defined?(:DISABLE_JQUERY_FORGERY_PROTECTION) ? !DISABLE_JQUERY_FORGERY_PROTECTION : true
69
70       unless const_defined? :JQUERY_VAR
71         JQUERY_VAR = 'jQuery'
72       end
73           
74       unless const_defined? :JQCALLBACKS
75         JQCALLBACKS = Set.new([ :beforeSend, :complete, :error, :success ] + (100..599).to_a)
76         #instance_eval { remove_const :AJAX_OPTIONS }
77         remove_const(:AJAX_OPTIONS) if const_defined?(:AJAX_OPTIONS)
78         AJAX_OPTIONS = Set.new([ :before, :after, :condition, :url,
79                          :asynchronous, :method, :insertion, :position,
80                          :form, :with, :update, :script ]).merge(JQCALLBACKS)
81       end
82       
83       def periodically_call_remote(options = {})
84         frequency = options[:frequency] || 10 # every ten seconds by default
85         code = "setInterval(function() {#{remote_function(options)}}, #{frequency} * 1000)"
86         javascript_tag(code)
87       end
88       
89       def remote_function(options)
90         javascript_options = options_for_ajax(options)
91
92         update = ''
93         if options[:update] && options[:update].is_a?(Hash)
94           update  = []
95           update << "success:'#{options[:update][:success]}'" if options[:update][:success]
96           update << "failure:'#{options[:update][:failure]}'" if options[:update][:failure]
97           update  = '{' + update.join(',') + '}'
98         elsif options[:update]
99           update << "'#{options[:update]}'"
100         end
101
102         function = "#{JQUERY_VAR}.ajax(#{javascript_options})"
103
104         function = "#{options[:before]}; #{function}" if options[:before]
105         function = "#{function}; #{options[:after]}"  if options[:after]
106         function = "if (#{options[:condition]}) { #{function}; }" if options[:condition]
107         function = "if (confirm('#{escape_javascript(options[:confirm])}')) { #{function}; }" if options[:confirm]
108         return function
109       end
110       
111       class JavaScriptGenerator
112         module GeneratorMethods
113           
114           def insert_html(position, id, *options_for_render)
115             insertion = position.to_s.downcase
116             insertion = 'append' if insertion == 'bottom'
117             insertion = 'prepend' if insertion == 'top'
118             call "#{JQUERY_VAR}(\"#{jquery_id(id)}\").#{insertion}", render(*options_for_render)
119           end
120           
121           def replace_html(id, *options_for_render)
122             insert_html(:html, id, *options_for_render)
123           end
124           
125           def replace(id, *options_for_render)
126             call "#{JQUERY_VAR}(\"#{jquery_id(id)}\").replaceWith", render(*options_for_render)
127           end
128           
129           def remove(*ids)
130             call "#{JQUERY_VAR}(\"#{jquery_ids(ids)}\").remove"
131           end
132           
133           def show(*ids)
134             call "#{JQUERY_VAR}(\"#{jquery_ids(ids)}\").show"
135           end
136           
137           def hide(*ids)
138             call "#{JQUERY_VAR}(\"#{jquery_ids(ids)}\").hide"
139           end
140
141           def toggle(*ids)
142             call "#{JQUERY_VAR}(\"#{jquery_ids(ids)}\").toggle"
143           end
144           
145           def jquery_id(id)
146             id.to_s.count('#.*,>+~:[/ ') == 0 ? "##{id}" : id
147           end
148           
149           def jquery_ids(ids)
150             Array(ids).map{|id| jquery_id(id)}.join(',')
151           end
152           
153         end
154       end
155       
156     protected
157       def options_for_ajax(options)
158         js_options = build_callbacks(options)
159         
160         url_options = options[:url]
161         url_options = url_options.merge(:escape => false) if url_options.is_a?(Hash)
162         js_options['url'] = "'#{url_for(url_options)}'"
163         js_options['async'] = false if options[:type] == :synchronous
164         js_options['type'] = options[:method] ? method_option_to_s(options[:method]) : ( options[:form] ? "'post'" : nil )
165         js_options['dataType'] = options[:datatype] ? "'#{options[:datatype]}'" : (options[:update] ? nil : "'script'")
166         
167         if options[:form]
168           js_options['data'] = "#{JQUERY_VAR}.param(#{JQUERY_VAR}(this).serializeArray())"
169         elsif options[:submit]
170           js_options['data'] = "#{JQUERY_VAR}(\"##{options[:submit]} :input\").serialize()"
171         elsif options[:with]
172           js_options['data'] = options[:with].gsub("Form.serialize(this.form)","#{JQUERY_VAR}.param(#{JQUERY_VAR}(this.form).serializeArray())")
173         end
174         
175         js_options['type'] ||= "'post'"
176         if options[:method]
177           if method_option_to_s(options[:method]) == "'put'" || method_option_to_s(options[:method]) == "'delete'"
178             js_options['type'] = "'post'"
179             if js_options['data']
180               js_options['data'] << " + '&"
181             else
182               js_options['data'] = "'"
183             end
184             js_options['data'] << "_method=#{options[:method]}'"
185           end
186         end
187         
188         if USE_PROTECTION && respond_to?('protect_against_forgery?') && protect_against_forgery?
189           if js_options['data']
190             js_options['data'] << " + '&"
191           else
192             js_options['data'] = "'"
193           end
194           js_options['data'] << "#{request_forgery_protection_token}=' + encodeURIComponent('#{escape_javascript form_authenticity_token}')"
195         end
196         js_options['data'] = "''" if js_options['type'] == "'post'" && js_options['data'].nil?
197         options_for_javascript(js_options.reject {|key, value| value.nil?})
198       end
199       
200       def build_update_for_success(html_id, insertion=nil)
201         insertion = build_insertion(insertion)
202         "#{JQUERY_VAR}('#{jquery_id(html_id)}').#{insertion}(request);"
203       end
204
205       def build_update_for_error(html_id, insertion=nil)
206         insertion = build_insertion(insertion)
207         "#{JQUERY_VAR}('#{jquery_id(html_id)}').#{insertion}(request.responseText);"
208       end
209
210       def build_insertion(insertion)
211         insertion = insertion ? insertion.to_s.downcase : 'html'
212         insertion = 'append' if insertion == 'bottom'
213         insertion = 'prepend' if insertion == 'top'
214         insertion
215       end
216
217       def build_observer(klass, name, options = {})
218         if options[:with] && (options[:with] !~ /[\{=(.]/)
219           options[:with] = "'#{options[:with]}=' + value"
220         else
221           options[:with] ||= 'value' unless options[:function]
222         end
223
224         callback = options[:function] || remote_function(options)
225         javascript  = "#{JQUERY_VAR}('#{jquery_id(name)}').delayedObserver("
226         javascript << "#{options[:frequency] || 0}, "
227         javascript << "function(element, value) {"
228         javascript << "#{callback}}"
229         #javascript << ", '#{options[:on]}'" if options[:on]
230         javascript << ")"
231         javascript_tag(javascript)
232       end
233       
234       def build_callbacks(options)
235         callbacks = {}
236         options[:beforeSend] = '';
237         [:uninitialized,:loading].each do |key|
238           options[:beforeSend] << (options[key].last == ';' ? options.delete(key) : options.delete(key) << ';') if options[key]
239         end
240         options.delete(:beforeSend) if options[:beforeSend].blank?
241         options[:complete] = options.delete(:loaded) if options[:loaded] 
242         options[:error] = options.delete(:failure) if options[:failure]
243         if options[:update]
244           if options[:update].is_a?(Hash)
245             options[:update][:error] = options[:update].delete(:failure) if options[:update][:failure]
246             if options[:update][:success]
247               options[:success] = build_update_for_success(options[:update][:success], options[:position]) << (options[:success] ? options[:success] : '')
248             end
249             if options[:update][:error]
250               options[:error] = build_update_for_error(options[:update][:error], options[:position]) << (options[:error] ? options[:error] : '')
251             end
252           else
253             options[:success] = build_update_for_success(options[:update], options[:position]) << (options[:success] ? options[:success] : '')
254           end
255         end
256         options.each do |callback, code|
257           if JQCALLBACKS.include?(callback)
258             callbacks[callback] = "function(request){#{code}}"
259           end
260         end
261         callbacks
262       end
263       
264     end
265     
266     class JavaScriptElementProxy < JavaScriptProxy #:nodoc:
267       
268       unless const_defined? :JQUERY_VAR
269         JQUERY_VAR = PrototypeHelper::JQUERY_VAR
270       end
271       
272       def initialize(generator, id)
273         id = id.to_s.count('#.*,>+~:[/ ') == 0 ? "##{id}" : id
274         @id = id
275         super(generator, "#{JQUERY_VAR}(\"#{id}\")")
276       end
277       
278       def replace_html(*options_for_render)
279         call 'html', @generator.send(:render, *options_for_render)
280       end
281
282       def replace(*options_for_render)
283         call 'replaceWith', @generator.send(:render, *options_for_render)
284       end
285       
286       def reload(options_for_replace={})
287         replace(options_for_replace.merge({ :partial => @id.to_s.sub(/^#/,'') }))
288       end
289       
290       def value()
291         call 'val()'
292       end
293
294       def value=(value)
295         call 'val', value
296       end
297       
298     end
299     
300     class JavaScriptElementCollectionProxy < JavaScriptCollectionProxy #:nodoc:\
301       
302       unless const_defined? :JQUERY_VAR
303         JQUERY_VAR = PrototypeHelper::JQUERY_VAR
304       end
305       
306       def initialize(generator, pattern)
307         super(generator, "#{JQUERY_VAR}(#{pattern.to_json})")
308       end
309     end
310     
311     module ScriptaculousHelper
312       
313       unless const_defined? :JQUERY_VAR
314         JQUERY_VAR = PrototypeHelper::JQUERY_VAR
315       end
316       
317       unless const_defined? :SCRIPTACULOUS_EFFECTS
318         SCRIPTACULOUS_EFFECTS = {
319           :appear => {:method => 'fadeIn'},
320           :blind_down => {:method => 'blind', :mode => 'show', :options => {:direction => 'vertical'}},
321           :blind_up => {:method => 'blind', :mode => 'hide', :options => {:direction => 'vertical'}},
322           :blind_right => {:method => 'blind', :mode => 'show', :options => {:direction => 'horizontal'}},
323           :blind_left => {:method => 'blind', :mode => 'hide', :options => {:direction => 'horizontal'}},
324           :bounce_in => {:method => 'bounce', :mode => 'show', :options => {:direction => 'up'}},
325           :bounce_out => {:method => 'bounce', :mode => 'hide', :options => {:direction => 'up'}},
326           :drop_in => {:method => 'drop', :mode => 'show', :options => {:direction => 'up'}},
327           :drop_out => {:method => 'drop', :mode => 'hide', :options => {:direction => 'down'}},
328           :fade => {:method => 'fadeOut'},
329           :fold_in => {:method => 'fold', :mode => 'hide'},
330           :fold_out => {:method => 'fold', :mode => 'show'},
331           :grow => {:method => 'scale', :mode => 'show'},
332           :shrink => {:method => 'scale', :mode => 'hide'},
333           :slide_down => {:method => 'slide', :mode => 'show', :options => {:direction => 'up'}},
334           :slide_up => {:method => 'slide', :mode => 'hide', :options => {:direction => 'up'}},
335           :slide_right => {:method => 'slide', :mode => 'show', :options => {:direction => 'left'}},
336           :slide_left => {:method => 'slide', :mode => 'hide', :options => {:direction => 'left'}},
337           :squish => {:method => 'scale', :mode => 'hide', :options => {:origin => "['top','left']"}},
338           :switch_on => {:method => 'clip', :mode => 'show', :options => {:direction => 'vertical'}},
339           :switch_off => {:method => 'clip', :mode => 'hide', :options => {:direction => 'vertical'}},
340           :toggle_appear => {:method => 'fadeToggle'},
341           :toggle_slide => {:method => 'slide', :mode => 'toggle', :options => {:direction => 'up'}},
342           :toggle_blind => {:method => 'blind', :mode => 'toggle', :options => {:direction => 'vertical'}},
343         }
344       end
345       
346       def visual_effect(name, element_id = false, js_options = {})
347         element = element_id ? element_id : "this"
348         
349         if SCRIPTACULOUS_EFFECTS.has_key? name.to_sym
350           effect = SCRIPTACULOUS_EFFECTS[name.to_sym]
351           name = effect[:method]
352           mode = effect[:mode]
353           js_options = js_options.merge(effect[:options]) if effect[:options]
354         end
355         
356         [:color, :direction, :startcolor, :endcolor].each do |option|
357           js_options[option] = "'#{js_options[option]}'" if js_options[option]
358         end
359         
360         if js_options.has_key? :duration
361           speed = js_options.delete :duration
362           speed = (speed * 1000).to_i unless speed.nil?
363         else
364           speed = js_options.delete :speed
365         end
366         
367         if ['fadeIn','fadeOut','fadeToggle'].include?(name)
368           #     090905 - Jake - changed ' to \" so it passes assert_select_rjs with an id
369           javascript = "#{JQUERY_VAR}(\"#{jquery_id(element_id)}\").#{name}("
370           javascript << "#{speed}" unless speed.nil?
371           javascript << ");"
372         else
373           #     090905 - Jake - changed ' to \" so it passes "assert_select_rjs :effect, ID"
374           javascript = "#{JQUERY_VAR}(\"#{jquery_id(element_id)}\").#{mode || 'effect'}('#{name}'"
375           javascript << ",#{options_for_javascript(js_options)}" unless speed.nil? && js_options.empty?
376           javascript << ",#{speed}" unless speed.nil?
377           javascript << ");"
378         end
379         
380       end
381       
382       def sortable_element_js(element_id, options = {}) #:nodoc:
383         #convert similar attributes
384         options[:handle] = ".#{options[:handle]}" if options[:handle]
385         if options[:tag] || options[:only]
386           options[:items] = "> "
387           options[:items] << options.delete(:tag) if options[:tag]
388           options[:items] << ".#{options.delete(:only)}" if options[:only]
389         end
390         options[:connectWith] = options.delete(:containment).map {|x| "##{x}"} if options[:containment]
391         options[:containment] = options.delete(:container) if options[:container]
392         options[:dropOnEmpty] = false unless options[:dropOnEmpty]
393         options[:helper] = "'clone'" if options[:ghosting] == true
394         options[:axis] = case options.delete(:constraint)
395           when "vertical", :vertical
396             "y"
397           when "horizontal", :horizontal
398             "x"
399           when false
400             nil
401           when nil
402             "y"
403         end
404         options.delete(:axis) if options[:axis].nil?
405         options.delete(:overlap)
406         options.delete(:ghosting)
407         
408         if options[:onUpdate] || options[:url]
409           if options[:format]
410             options[:with] ||= "#{JQUERY_VAR}(this).sortable('serialize',{key:'#{element_id}[]', expression:#{options[:format]}})"
411             options.delete(:format)
412           else
413             options[:with] ||= "#{JQUERY_VAR}(this).sortable('serialize',{key:'#{element_id}[]'})"
414           end
415           
416           options[:onUpdate] ||= "function(){" + remote_function(options) + "}"
417         end
418         
419         options.delete_if { |key, value| PrototypeHelper::AJAX_OPTIONS.include?(key) }
420         options[:update] = options.delete(:onUpdate) if options[:onUpdate]
421         
422         [:axis, :cancel, :containment, :cursor, :handle, :tolerance, :items, :placeholder].each do |option|
423           options[option] = "'#{options[option]}'" if options[option]
424         end
425         
426         options[:connectWith] = array_or_string_for_javascript(options[:connectWith]) if options[:connectWith]
427         
428         %(#{JQUERY_VAR}('#{jquery_id(element_id)}').sortable(#{options_for_javascript(options)});)
429       end
430       
431       def draggable_element_js(element_id, options = {})
432         %(#{JQUERY_VAR}("#{jquery_id(element_id)}").draggable(#{options_for_javascript(options)});)
433       end
434       
435       def drop_receiving_element_js(element_id, options = {})
436         #convert similar options
437         options[:hoverClass] = options.delete(:hoverclass) if options[:hoverclass]
438         options[:drop] = options.delete(:onDrop) if options[:onDrop]
439         
440         if options[:drop] || options[:url]
441           options[:with] ||= "'id=' + encodeURIComponent(#{JQUERY_VAR}(ui.draggable).attr('id'))"
442           options[:drop] ||= "function(ev, ui){" + remote_function(options) + "}"
443         end
444         
445         options.delete_if { |key, value| PrototypeHelper::AJAX_OPTIONS.include?(key) }
446
447         options[:accept] = array_or_string_for_javascript(options[:accept]) if options[:accept]    
448         [:activeClass, :hoverClass, :tolerance].each do |option|
449           options[option] = "'#{options[option]}'" if options[option]
450         end
451         
452         %(#{JQUERY_VAR}('#{jquery_id(element_id)}').droppable(#{options_for_javascript(options)});)
453       end
454       
455     end
456     
457   end
458 end