]> projects.mako.cc - selectricity/blob - vendor/plugins/engines/lib/bundles/require_resource.rb
3469c635ca7fbbe17721c13ecb21fff111c429bf
[selectricity] / vendor / plugins / engines / lib / bundles / require_resource.rb
1 # RequireResource v.1.4 by Duane Johnson
2 #
3 # Makes inclusion of javascript and stylesheet resources easier via automatic or explicit
4 # calls.  e.g. require_javascript 'popup' is an explicit call.
5 #
6 # The simplest way to make use of this functionality is to add
7 #   <%= resource_tags %>
8 # to your layout (usually in the <head></head> section).  This will automatically add
9 # bundle support to your application, as well as enable simple javascript and stylesheet
10 # dependencies for your views.
11 #
12 # Note that this can easily be turned in to a helper on its own.
13 module RequireResource
14   mattr_accessor :path_prefix
15
16   # Write out all javascripts & stylesheets, including default javascripts (unless :defaults => false)
17   def resource_tags(options = {})
18     options = {:auto => true, :defaults => true}.update(options)
19     require_defaults if options[:defaults]
20     stylesheet_auto_link_tags(:auto => options[:auto]) +
21     javascript_auto_include_tags(:auto => options[:auto])
22   end
23   
24   # Write out the <link> tags themselves based on the array of stylesheets to be included
25   def stylesheet_auto_link_tags(options = {})
26     options = {:auto => true}.update(options)
27     ensure_resource_is_initialized(:stylesheet)
28     autorequire(:stylesheet) if options[:auto]
29     @stylesheets.uniq.inject("") do |buffer, css|
30       buffer << stylesheet_link_tag(css) + "\n    "
31     end
32   end
33
34   # Write out the <script> tags themselves based on the array of javascripts to be included
35   def javascript_auto_include_tags(options = {})
36     options = {:auto => true}.update(options)
37     ensure_resource_is_initialized(:javascript)
38     autorequire(:javascript) if options[:auto]
39     @javascripts.uniq.inject("") do |buffer, js|
40       buffer << javascript_include_tag(js) + "\n    "
41     end
42   end
43
44   # Bundle the defaults together for easy inclusion
45   def require_defaults
46     require_javascript(:prototype)
47     require_javascript(:controls)
48     require_javascript(:effects)
49     require_javascript(:dragdrop)
50   end
51   
52   # Adds a javascript to the array of javascripts that will be included in the layout by
53   # either your call to 'javascript_auto_include_tags' or 'resource_tags'.
54   def require_javascript(*scripts)
55     scripts.each do |script|
56       require_resource(:javascript, RequireResource.path_prefix.to_s + script.to_s)
57     end
58   end
59
60   # Adds a stylesheet to the array of stylesheets that will be included in the layout by
61   # either your call to 'stylesheet_auto_link_tags' or 'resource_tags'.
62   def require_stylesheet(*sheets)
63     sheets.each do |sheet|
64       require_resource(:stylesheet, RequireResource.path_prefix.to_s + sheet.to_s)
65     end
66   end
67   
68   # Changes the RequireResource.path_prefix within the scope of a block.  This is
69   # particularly useful when requiring several resources within a directory.  For example,
70   # bundles can take advantage of this by calling
71   #   require_relative_to Engines.current.public_dir do
72   #     require_javascript '...'
73   #     require_stylesheet '...'
74   #     # ...
75   #   end
76   def require_relative_to(path)
77     former_prefix = RequireResource.path_prefix
78     RequireResource.path_prefix = path
79     yield
80     RequireResource.path_prefix = former_prefix
81   end
82   
83   protected
84     # Adds resources such as stylesheet or javascript files to the corresponding array of
85     # resources that will be 'required' by the layout. The +resource_type+ is either
86     # :javascript or :stylesheet. The +extension+ is optional, and should normally correspond
87     # with the resource type, e.g. 'css' for :stylesheet and 'js' for :javascript.
88     def autorequire(resource_type, extension = nil)
89       extensions = {:stylesheet => 'css', :javascript => 'js'}
90       extension ||= extensions[resource_type]
91       candidates = []
92       class_iterator = controller.class
93       resource_path = "#{RAILS_ROOT}/public/#{resource_type.to_s.pluralize}/" 
94
95       while ![ActionController::Base].include? class_iterator
96         controller_path = class_iterator.to_s.underscore.sub('controllers/', '').sub('_controller', '')
97         candidates |= [ "#{controller_path}", "#{controller_path}/#{controller.action_name}" ]
98         class_iterator = class_iterator.superclass
99       end
100       
101       for candidate in candidates
102         if FileTest.exist?("#{resource_path}/#{candidate}.#{extension}")
103           require_resource(resource_type, candidate)
104         end
105       end
106     end
107
108     # Adds a resource (e.g. a javascript) to the appropriate array (e.g. @javascripts)
109     # ONLY if the resource is not already included.
110     def require_resource(type, name)
111       variable = type.to_s.pluralize
112       new_resource_array = (instance_variable_get("@#{variable}") || []) | [name.to_s]
113       instance_variable_set("@#{variable}", new_resource_array)
114     end
115
116     # Ensures that a resource array (e.g. @javascripts) is not nil--uses [] if so
117     def ensure_resource_is_initialized(type)
118       variable = type.to_s.pluralize
119       new_resource_array = (instance_variable_get("@#{variable}") || [])
120       instance_variable_set("@#{variable}", new_resource_array)      
121     end
122 end
123
124 ActionView::Base.send(:include, RequireResource)

Benjamin Mako Hill || Want to submit a patch?