bivouac 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/README +9 -0
  2. data/bin/bivouac +15 -19
  3. data/doc/rdoc/classes/BivouacHelpers.html +117 -0
  4. data/doc/rdoc/classes/BivouacHelpers/BaseView.html +140 -0
  5. data/doc/rdoc/classes/BivouacHelpers/FormView.html +398 -0
  6. data/doc/rdoc/classes/BivouacHelpers/HtmlView.html +274 -0
  7. data/doc/rdoc/classes/BivouacHelpers/JavaScriptView.html +573 -0
  8. data/doc/rdoc/classes/BivouacHelpers/ScriptAculoUsView.html +258 -0
  9. data/doc/rdoc/classes/BivouacHelpers/TooltipView.html +158 -0
  10. data/doc/rdoc/classes/JavaScriptGenerator.html +564 -0
  11. data/doc/rdoc/created.rid +1 -1
  12. data/doc/rdoc/files/AUTHORS.html +14 -0
  13. data/doc/rdoc/files/COPYING.html +14 -0
  14. data/doc/rdoc/files/README.html +40 -1
  15. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/base_rb.html +109 -0
  16. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/form_rb.html +109 -0
  17. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/html_rb.html +109 -0
  18. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/javascript_rb.html +113 -0
  19. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/scriptaculous_rb.html +113 -0
  20. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/tooltip_rb.html +109 -0
  21. data/examples/bivouac_sample/app/bivouac_sample.rb +61 -0
  22. data/examples/bivouac_sample/app/controllers/autocomplete.rb +24 -0
  23. data/examples/bivouac_sample/app/controllers/drag_and_drop.rb +11 -0
  24. data/examples/bivouac_sample/app/controllers/index.rb +7 -0
  25. data/examples/bivouac_sample/app/controllers/observe.rb +14 -0
  26. data/examples/bivouac_sample/app/controllers/periodically_call.rb +12 -0
  27. data/examples/bivouac_sample/app/controllers/remote_form.rb +10 -0
  28. data/examples/bivouac_sample/app/controllers/remote_link.rb +11 -0
  29. data/examples/bivouac_sample/app/controllers/submit_remote.rb +17 -0
  30. data/examples/bivouac_sample/app/controllers/toggle.rb +10 -0
  31. data/examples/bivouac_sample/app/controllers/toggle_sortable.rb +11 -0
  32. data/examples/bivouac_sample/app/helpers/_helpers.rb +25 -0
  33. data/examples/bivouac_sample/app/helpers/source.rb +25 -0
  34. data/examples/bivouac_sample/app/views/_autocomplete_result.rb +9 -0
  35. data/examples/bivouac_sample/app/views/_drag_and_drop_result.rb +5 -0
  36. data/examples/bivouac_sample/app/views/_observe_result.rb +17 -0
  37. data/examples/bivouac_sample/app/views/_periodically_call_result.rb +5 -0
  38. data/examples/bivouac_sample/app/views/_remote_link_result.rb +5 -0
  39. data/examples/bivouac_sample/app/views/_sortable_result.rb +5 -0
  40. data/examples/bivouac_sample/app/views/_submit_remote_result.rb +5 -0
  41. data/examples/bivouac_sample/app/views/autocomplete.rb +28 -0
  42. data/examples/bivouac_sample/app/views/drag_and_drop.rb +35 -0
  43. data/examples/bivouac_sample/app/views/index.rb +19 -0
  44. data/examples/bivouac_sample/app/views/observe.rb +19 -0
  45. data/examples/bivouac_sample/app/views/periodically_call.rb +17 -0
  46. data/examples/bivouac_sample/app/views/remote_form.rb +19 -0
  47. data/examples/bivouac_sample/app/views/remote_link.rb +20 -0
  48. data/examples/bivouac_sample/app/views/submit_remote.rb +21 -0
  49. data/examples/bivouac_sample/app/views/toggle.rb +44 -0
  50. data/examples/bivouac_sample/app/views/toggle_sortable.rb +52 -0
  51. data/examples/bivouac_sample/config/environment.rb +37 -0
  52. data/examples/bivouac_sample/config/postamble.rb +62 -0
  53. data/examples/bivouac_sample/log/BivouacSample.log +77 -0
  54. data/examples/bivouac_sample/public/images/camping.png +0 -0
  55. data/examples/bivouac_sample/public/index.html +242 -0
  56. data/examples/bivouac_sample/public/javascripts/builder.js +131 -0
  57. data/examples/bivouac_sample/public/javascripts/controls.js +835 -0
  58. data/examples/bivouac_sample/public/javascripts/dragdrop.js +944 -0
  59. data/examples/bivouac_sample/public/javascripts/effects.js +1090 -0
  60. data/examples/bivouac_sample/public/javascripts/prototype.js +2515 -0
  61. data/examples/bivouac_sample/public/javascripts/scriptaculous.js +51 -0
  62. data/examples/bivouac_sample/public/javascripts/slider.js +278 -0
  63. data/examples/bivouac_sample/public/javascripts/tooltip.js +208 -0
  64. data/examples/bivouac_sample/public/javascripts/unittest.js +564 -0
  65. data/examples/bivouac_sample/public/stylesheets/autocomplete.css +22 -0
  66. data/examples/bivouac_sample/public/stylesheets/coderay.css +104 -0
  67. data/examples/bivouac_sample/script/generate +3 -0
  68. data/examples/bivouac_sample/script/server +5 -0
  69. data/lib/bivouac/helpers/view/goh/base.rb +16 -0
  70. data/lib/bivouac/helpers/view/goh/form.rb +170 -0
  71. data/lib/bivouac/helpers/view/goh/html.rb +138 -0
  72. data/lib/bivouac/helpers/view/goh/javascript.rb +532 -0
  73. data/lib/bivouac/helpers/view/goh/scriptaculous.rb +133 -0
  74. data/lib/bivouac/helpers/view/goh/tooltip.rb +33 -0
  75. data/lib/bivouac/template.rb +3 -3
  76. data/lib/bivouac/template/application/helpers_erb.rb +11 -0
  77. data/lib/bivouac/template/application/helpers_goh.rb +25 -0
  78. data/lib/bivouac/template/application/postamble.rb +62 -0
  79. data/lib/bivouac/template/application_erb.rb +4 -0
  80. data/lib/bivouac/template/application_goh.rb +4 -0
  81. data/lib/bivouac/template/environment.rb +19 -5
  82. data/lib/bivouac/template/server.rb +1 -1
  83. data/lib/bivouac/template/static/autocomplete.css +22 -0
  84. data/lib/bivouac/template/static/builder.js +131 -0
  85. data/lib/bivouac/template/static/controls.js +835 -0
  86. data/lib/bivouac/template/static/dragdrop.js +944 -0
  87. data/lib/bivouac/template/static/effects.js +1090 -0
  88. data/lib/bivouac/template/static/prototype.js +2515 -0
  89. data/lib/bivouac/template/static/scriptaculous.js +51 -0
  90. data/lib/bivouac/template/static/slider.js +278 -0
  91. data/lib/bivouac/template/static/tooltip.js +208 -0
  92. data/lib/bivouac/template/static/unittest.js +564 -0
  93. metadata +124 -7
  94. data/lib/bivouac/template/application/postamble_cgi.rb +0 -8
  95. data/lib/bivouac/template/application/postamble_fastcgi.rb +0 -8
  96. data/lib/bivouac/template/application/postamble_mongrel.rb +0 -19
  97. data/lib/bivouac/template/application/postamble_none.rb +0 -1
  98. data/lib/bivouac/template/application/postamble_webrick.rb +0 -19
@@ -0,0 +1,133 @@
1
+ # bivouac/helpers/view/scriptaculous
2
+ require 'active_support'
3
+
4
+ module BivouacHelpers
5
+ module ScriptAculoUsView
6
+ unless const_defined? :TOGGLE_EFFECTS
7
+ TOGGLE_EFFECTS = [:toggle_appear, :toggle_slide, :toggle_blind]
8
+ end
9
+
10
+ # Returns a JavaScript snippet to be used on the Ajax callbacks for starting visual effects.
11
+ def visual_effect(name, element_id = false, js_options = {})
12
+ element = element_id ? element_id : "element"
13
+
14
+ js_options[:queue] = if js_options[:queue].is_a?(Hash)
15
+ '{' + js_options[:queue].map {|k, v| k == :limit ? "#{k}:#{v}" : "#{k}:'#{v}'" }.join(',') + '}'
16
+ elsif js_options[:queue]
17
+ "'#{js_options[:queue]}'"
18
+ end if js_options[:queue]
19
+
20
+ if TOGGLE_EFFECTS.include? name.to_sym
21
+ %(Effect.toggle(#{element.inspect},'#{name.to_s.gsub(/^toggle_/,'')}',#{options_for_javascript(js_options)}))
22
+ else
23
+ %(new Effect.#{name.to_s.camelize}('#{element}',#{options_for_javascript(js_options)}))
24
+ end
25
+ end
26
+
27
+ # Makes the element with the DOM ID specified by +element_id+ sortable
28
+ # by drag-and-drop and make an Ajax call whenever the sort order has
29
+ # changed. By default, the action called gets the serialized sortable
30
+ # element as parameters.
31
+ #
32
+ # See http://script.aculo.us for avalaible options.
33
+ #
34
+ # If you wan't to use +onChange+ and/or +onUpdate+ you can pass a javascript string
35
+ # or a Hash, if you want to call a remote function.
36
+ #
37
+ # Example:
38
+ # ul( :id => 'my_list' ) do
39
+ # li "Google"
40
+ # li "Yahoo"
41
+ # li "Accoona"
42
+ # li "Ask.com"
43
+ # li "Baidu"
44
+ # li "Exalead"
45
+ # li "Voila"
46
+ # li "Lycos"
47
+ # end
48
+ # sortable_element( 'my_list',
49
+ # :onChange => {
50
+ # :url => R(SaveListOrder),
51
+ # :success => visual_effect( :highlight, 'my_list' )
52
+ # }
53
+ # )
54
+ def sortable_element( element_id, options = {} )
55
+ javascript_tag( sortable_element_js( element_id, options ) + ";\n" )
56
+ end
57
+
58
+ def sortable_element_js( element_id, options = {} ) #:nodoc:
59
+ if options[:onUpdate].is_a?( Hash )
60
+ options[:onUpdate][:with] ||= "Sortable.serialize('#{element_id}')"
61
+ options[:onUpdate] = "function(){" + remote_function(options[:onUpdate]) + "}"
62
+ elsif options[:onUpdate].is_a?( String )
63
+ options[:onUpdate] = "function(){" + options[:onUpdate] + ";}"
64
+ end
65
+
66
+ if options[:onChange].is_a?( Hash )
67
+ options[:onChange][:with] ||= "Sortable.serialize('#{element_id}')"
68
+ options[:onChange] = "function(){" + remote_function(options[:onChange]) + "}"
69
+ elsif options[:onChange].is_a?( String )
70
+ options[:onChange] = "function(){" + options[:onChange] + ";}"
71
+ end
72
+
73
+ [:tag, :overlap, :constraint, :handle].each do |option|
74
+ options[option] = "'#{options[option]}'" if options[option]
75
+ end
76
+
77
+ options[:containment] = array_or_string_for_javascript(options[:containment]) if options[:containment]
78
+ options[:only] = array_or_string_for_javascript(options[:only]) if options[:only]
79
+
80
+ %(Sortable.create(#{element_id.inspect}, #{options_for_javascript(options)}))
81
+ end
82
+
83
+ def unsortable_element_js( element_id ) #:nodoc:
84
+ %(Sortable.destroy(#{element_id.inspect}))
85
+ end
86
+
87
+ # Makes the element with the DOM ID specified by +element_id+ draggable.
88
+ #
89
+ # Example:
90
+ # draggable_element("my_image", :revert => true)
91
+ #
92
+ # You can change the behaviour with various options, see
93
+ # http://script.aculo.us for more documentation.
94
+ def draggable_element(element_id, options = {})
95
+ javascript_tag(draggable_element_js(element_id, options) + ";\n")
96
+ end
97
+
98
+ def draggable_element_js(element_id, options = {}) #:nodoc:
99
+ %(new Draggable(#{element_id.inspect}, #{options_for_javascript(options)}))
100
+ end
101
+
102
+ # Makes the element with the DOM ID specified by +element_id+ receive
103
+ # dropped draggable elements (created by draggable_element).
104
+ # and make an AJAX call. By default, the action called gets the DOM ID
105
+ # of the element as parameter.
106
+ #
107
+ # Example:
108
+ # drop_receiving_element("my_cart", :onDrop => {
109
+ # :url => R(CartAdd),
110
+ # :update => 'drop-info'
111
+ # } )
112
+ #
113
+ # You can change the behaviour with various options, see
114
+ # http://script.aculo.us for more documentation.
115
+ def drop_receiving_element(element_id, options = {})
116
+ javascript_tag(drop_receiving_element_js(element_id, options) + ";\n")
117
+ end
118
+
119
+ def drop_receiving_element_js(element_id, options = {}) #:nodoc:
120
+ if options[:onDrop].is_a?( Hash)
121
+ options[:onDrop][:with] = "'id=' + encodeURIComponent(element.id)"
122
+ options[:onDrop] = "function(element){" + remote_function(options[:onDrop]) + "}"
123
+ elsif options[:onDrop].is_a?( String )
124
+ options[:onDrop] = "function(){" + options[:onDrop] + ";}"
125
+ end
126
+
127
+ options[:accept] = array_or_string_for_javascript(options[:accept]) if options[:accept]
128
+ options[:hoverclass] = "'#{options[:hoverclass]}'" if options[:hoverclass]
129
+
130
+ %(Droppables.add(#{element_id.inspect}, #{options_for_javascript(options)}))
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,33 @@
1
+ # bivouac/helpers/view/html
2
+
3
+ module BivouacHelpers
4
+ module TooltipView
5
+ # Returns an html div (id +name+) as a tooltip for +element+.
6
+ #
7
+ # div( id => "tooltip_me" ) do
8
+ # "Hello World"
9
+ # end
10
+ # tooltip( "i_m_the_tooltip", "tooltip_me" ) do
11
+ # "Content of the tooltip"
12
+ # end # =>
13
+ # <div id="tooltip_me">
14
+ # Hello World
15
+ # </div>
16
+ # <div id = "i_m_the_tooltip" style = "display:none;">
17
+ # Content of the tooltip
18
+ # </div>
19
+ # <script>
20
+ # var i_m_the_tooltip = new Tooltip( 'tooltip_me', 'i_m_the_tooltip' )
21
+ # </script>
22
+ #
23
+ # See http://blog.innerewut.de/tooltip for more information about tooltip
24
+ def tooltip( name, element, &block )
25
+ div( :id => name, :style => "display:none;" ) do
26
+ yield( )
27
+ end
28
+ script do
29
+ "var #{name} = new Tooltip( '#{element}', '#{name}' )"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -55,10 +55,10 @@ module Bivouac
55
55
  end
56
56
 
57
57
  def copyTemplate( file, dest )
58
- if File.exist?( dest + "/" + file )
59
- puts "\tskip #{File.expand_path( dest + "/" + file )}: already exist"
58
+ if File.exist?( dest + "/" + File.basename( file ) )
59
+ puts "\tskip #{File.expand_path( dest + "/" + File.basename( file ) )}: already exist"
60
60
  else
61
- puts "\tcreate #{File.expand_path( dest )}"
61
+ puts "\tcreate #{File.expand_path( dest ) + "/" + File.basename( file )}"
62
62
  src = File.dirname(__FILE__) + "/template/" + file
63
63
  FileUtils::cp( src, dest )
64
64
  end
@@ -0,0 +1,11 @@
1
+ #
2
+ # Project <%= @appname %>
3
+ #
4
+ # Created using bivouac on <%= Time.now %>.
5
+ # Copyright (c) <%= Time.now.year %> __My__. All rights reserved.
6
+ #
7
+ # DO NOT EDIT THIS FILE OR YOU REALLY KNOW WHAT YOU ARE DOING
8
+ # USE script/generate helper my_helper
9
+ #
10
+
11
+ # TODO
@@ -0,0 +1,25 @@
1
+ #
2
+ # Project <%= @appname %>
3
+ #
4
+ # Created using bivouac on <%= Time.now %>.
5
+ # Copyright (c) <%= Time.now.year %> __My__. All rights reserved.
6
+ #
7
+ # DO NOT EDIT THIS FILE OR YOU REALLY KNOW WHAT YOU ARE DOING
8
+ # USE script/generate helper my_helper
9
+ #
10
+ require 'bivouac/helpers/view/goh/base'
11
+ require 'bivouac/helpers/view/goh/html'
12
+ require 'bivouac/helpers/view/goh/form'
13
+ require 'bivouac/helpers/view/goh/scriptaculous'
14
+ require 'bivouac/helpers/view/goh/javascript'
15
+ require 'bivouac/helpers/view/goh/tooltip'
16
+
17
+ helpers = [
18
+ BivouacHelpers::BaseView,
19
+ BivouacHelpers::HtmlView,
20
+ BivouacHelpers::FormView,
21
+ BivouacHelpers::ScriptAculoUsView,
22
+ BivouacHelpers::JavaScriptView,
23
+ BivouacHelpers::TooltipView
24
+ ]
25
+ <%= @appname %>.module_eval "class Mab < Markaby::Builder; include #{helpers.join(', ')}; end"
@@ -0,0 +1,62 @@
1
+ #
2
+ # Project <%= @appname %>
3
+ #
4
+ # Created using bivouac on <%= Time.now %>.
5
+ # Copyright (c) <%= Time.now.year %> __My__. All rights reserved.
6
+ #
7
+
8
+ require 'simple-daemon'
9
+
10
+ DIRNAME = File.expand_path( File.dirname(__FILE__) )
11
+ SimpleDaemon::WorkingDirectory = DIRNAME + "/../log/"
12
+ class <%= @appname %>Daemon < SimpleDaemon::Base
13
+ @@server = nil
14
+
15
+ def self.start
16
+ config = Bivouac::Environment.new( )
17
+
18
+ <%= @appname %>::Models::Base.establish_connection :adapter => 'sqlite3', :database => DIRNAME + "/../db/<%= @appname %>.db"
19
+ <%= @appname %>::Models::Base.logger = Logger.new(DIRNAME + "/../log/<%= @appname %>.log")
20
+ <%= @appname %>::Models::Base.threaded_connections = false
21
+ <%= @appname %>.create if <%= @appname %>.respond_to? :create
22
+
23
+ trap(:INT) do
24
+ stop
25
+ end
26
+
27
+ begin
28
+ require 'mongrel/camping'
29
+
30
+ @@server = Mongrel::Camping.start( config.environment.address, config.environment.port, "/", <%= @appname %>)
31
+ puts "** <%= @appname %> is running at http://#{config.environment.address}:#{config.environment.port}"
32
+ @@server.run.join
33
+ rescue LoadError => e
34
+ require 'webrick/httpserver'
35
+ require 'camping/webrick'
36
+
37
+ @@server = WEBrick::HTTPServer.new :BindAddress => config.environment.address, :Port => config.environment.port
38
+ puts "** <%= @appname %> is running at http://#{config.environment.address}:#{config.environment.port}"
39
+ @@server.mount "/", WEBrick::CampingHandler, <%= @appname %>
40
+ end
41
+ end
42
+
43
+ def self.stop
44
+ begin
45
+ @@server.stop
46
+ rescue
47
+ @@server.shutdown
48
+ end
49
+ @@server = nil
50
+ end
51
+ end
52
+
53
+ deamonize = ARGV.shift
54
+ case deamonize
55
+ when '-d'
56
+ <%= @appname %>Daemon.daemonize
57
+ when '-h'
58
+ puts "script/server [-d start|stop|restart] [-h]"
59
+ exit
60
+ else
61
+ <%= @appname %>Daemon.start
62
+ end
@@ -67,3 +67,7 @@ end
67
67
  # Load create
68
68
  files( '../db' ) { |file| require( file ) }
69
69
 
70
+ # Load postamble and configuration
71
+ if __FILE__ == $0
72
+ files( '../config' ) { |file| require( file ) }
73
+ end
@@ -55,3 +55,7 @@ end
55
55
  # Load create
56
56
  files( '../db' ) { |file| require( file ) }
57
57
 
58
+ # Load postamble and configuration
59
+ if __FILE__ == $0
60
+ files( '../config' ) { |file| require( file ) }
61
+ end
@@ -4,8 +4,6 @@
4
4
  # Created using bivouac on <%= Time.now %>.
5
5
  # Copyright (c) <%= Time.now.year %> __My__. All rights reserved.
6
6
  #
7
- # DO NOT EDIT THIS FILE, OR YOU REALLY KNOW WHAT YOU ARE DOING !
8
- #
9
7
 
10
8
  require 'ostruct'
11
9
 
@@ -15,9 +13,25 @@ module Bivouac
15
13
  attr_reader :environment
16
14
 
17
15
  def initialize
18
- @environment = OpenStruct.new( )
19
- <% @conf.to_hash.each do |k, v| %>
20
- @environment.<%= k %> = "<%= v %>"<% end %>
16
+ @environment = OpenStruct.new(
17
+ # Address to bind to
18
+ :address => "<%= @conf.address %>",
19
+
20
+ # Application port
21
+ :port => <%= @conf.port %>,
22
+
23
+ # Name of the application
24
+ # DO NOT CHANGE IT, OR YOU REALLY KNOW WHAT YOU ARE DOING!
25
+ :appname => "<%= @conf.appname %>",
26
+
27
+ # Path of the application
28
+ # DO NOT CHANGE IT, OR YOU REALLY KNOW WHAT YOU ARE DOING!
29
+ :appdir => "<%= @conf.appdir %>",
30
+
31
+ # Organisation type of the application
32
+ # DO NOT CHANGE IT, OR YOU REALLY KNOW WHAT YOU ARE DOING!
33
+ :orgtype => "<%= @conf.orgtype %>"
34
+ )
21
35
  end
22
36
  end
23
37
  end
@@ -2,4 +2,4 @@
2
2
  require 'rubygems'
3
3
  app = File.dirname(__FILE__) + "/../app/<%= @conf.appdir %>.rb"
4
4
 
5
- system "ruby #{app}"
5
+ system "ruby #{app} #{ARGV.join(' ')}"
@@ -0,0 +1,22 @@
1
+ div.autocomplete {
2
+ position:absolute;
3
+ width:250px;
4
+ background-color:white;
5
+ border:1px solid #888;
6
+ margin:0px;
7
+ padding:0px;
8
+ }
9
+ div.autocomplete ul {
10
+ list-style-type:none;
11
+ margin:0px;
12
+ padding:0px;
13
+ }
14
+ div.autocomplete ul li.selected { background-color: #ffb;}
15
+ div.autocomplete ul li {
16
+ list-style-type:none;
17
+ display:block;
18
+ margin:0;
19
+ padding:2px;
20
+ height:32px;
21
+ cursor:pointer;
22
+ }
@@ -0,0 +1,131 @@
1
+ // script.aculo.us builder.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
2
+
3
+ // Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
+ //
5
+ // script.aculo.us is freely distributable under the terms of an MIT-style license.
6
+ // For details, see the script.aculo.us web site: http://script.aculo.us/
7
+
8
+ var Builder = {
9
+ NODEMAP: {
10
+ AREA: 'map',
11
+ CAPTION: 'table',
12
+ COL: 'table',
13
+ COLGROUP: 'table',
14
+ LEGEND: 'fieldset',
15
+ OPTGROUP: 'select',
16
+ OPTION: 'select',
17
+ PARAM: 'object',
18
+ TBODY: 'table',
19
+ TD: 'table',
20
+ TFOOT: 'table',
21
+ TH: 'table',
22
+ THEAD: 'table',
23
+ TR: 'table'
24
+ },
25
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
26
+ // due to a Firefox bug
27
+ node: function(elementName) {
28
+ elementName = elementName.toUpperCase();
29
+
30
+ // try innerHTML approach
31
+ var parentTag = this.NODEMAP[elementName] || 'div';
32
+ var parentElement = document.createElement(parentTag);
33
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
34
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
35
+ } catch(e) {}
36
+ var element = parentElement.firstChild || null;
37
+
38
+ // see if browser added wrapping tags
39
+ if(element && (element.tagName.toUpperCase() != elementName))
40
+ element = element.getElementsByTagName(elementName)[0];
41
+
42
+ // fallback to createElement approach
43
+ if(!element) element = document.createElement(elementName);
44
+
45
+ // abort if nothing could be created
46
+ if(!element) return;
47
+
48
+ // attributes (or text)
49
+ if(arguments[1])
50
+ if(this._isStringOrNumber(arguments[1]) ||
51
+ (arguments[1] instanceof Array)) {
52
+ this._children(element, arguments[1]);
53
+ } else {
54
+ var attrs = this._attributes(arguments[1]);
55
+ if(attrs.length) {
56
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
57
+ parentElement.innerHTML = "<" +elementName + " " +
58
+ attrs + "></" + elementName + ">";
59
+ } catch(e) {}
60
+ element = parentElement.firstChild || null;
61
+ // workaround firefox 1.0.X bug
62
+ if(!element) {
63
+ element = document.createElement(elementName);
64
+ for(attr in arguments[1])
65
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
66
+ }
67
+ if(element.tagName.toUpperCase() != elementName)
68
+ element = parentElement.getElementsByTagName(elementName)[0];
69
+ }
70
+ }
71
+
72
+ // text, or array of children
73
+ if(arguments[2])
74
+ this._children(element, arguments[2]);
75
+
76
+ return element;
77
+ },
78
+ _text: function(text) {
79
+ return document.createTextNode(text);
80
+ },
81
+
82
+ ATTR_MAP: {
83
+ 'className': 'class',
84
+ 'htmlFor': 'for'
85
+ },
86
+
87
+ _attributes: function(attributes) {
88
+ var attrs = [];
89
+ for(attribute in attributes)
90
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
91
+ '="' + attributes[attribute].toString().escapeHTML() + '"');
92
+ return attrs.join(" ");
93
+ },
94
+ _children: function(element, children) {
95
+ if(typeof children=='object') { // array can hold nodes and text
96
+ children.flatten().each( function(e) {
97
+ if(typeof e=='object')
98
+ element.appendChild(e)
99
+ else
100
+ if(Builder._isStringOrNumber(e))
101
+ element.appendChild(Builder._text(e));
102
+ });
103
+ } else
104
+ if(Builder._isStringOrNumber(children))
105
+ element.appendChild(Builder._text(children));
106
+ },
107
+ _isStringOrNumber: function(param) {
108
+ return(typeof param=='string' || typeof param=='number');
109
+ },
110
+ build: function(html) {
111
+ var element = this.node('div');
112
+ $(element).update(html.strip());
113
+ return element.down();
114
+ },
115
+ dump: function(scope) {
116
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
117
+
118
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
119
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
120
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
121
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
122
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
123
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
124
+
125
+ tags.each( function(tag){
126
+ scope[tag] = function() {
127
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
128
+ }
129
+ });
130
+ }
131
+ }