hobo 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/LICENSE.txt +22 -0
  2. data/README.txt +18 -0
  3. data/bin/hobo +81 -0
  4. data/hobo_files/plugin/CHANGES.txt +963 -0
  5. data/hobo_files/plugin/LICENSE.txt +22 -0
  6. data/hobo_files/plugin/README +4 -0
  7. data/hobo_files/plugin/Rakefile +11 -0
  8. data/hobo_files/plugin/generators/hobo/hobo_generator.rb +37 -0
  9. data/hobo_files/plugin/generators/hobo/templates/application.dryml +2 -0
  10. data/hobo_files/plugin/generators/hobo/templates/guest.rb +31 -0
  11. data/hobo_files/plugin/generators/hobo_front_controller/USAGE +11 -0
  12. data/hobo_files/plugin/generators/hobo_front_controller/hobo_front_controller_generator.rb +90 -0
  13. data/hobo_files/plugin/generators/hobo_front_controller/templates/controller.rb +51 -0
  14. data/hobo_files/plugin/generators/hobo_front_controller/templates/functional_test.rb +18 -0
  15. data/hobo_files/plugin/generators/hobo_front_controller/templates/helper.rb +2 -0
  16. data/hobo_files/plugin/generators/hobo_front_controller/templates/index.dryml +43 -0
  17. data/hobo_files/plugin/generators/hobo_front_controller/templates/login.dryml +44 -0
  18. data/hobo_files/plugin/generators/hobo_front_controller/templates/search.dryml +18 -0
  19. data/hobo_files/plugin/generators/hobo_front_controller/templates/signup.dryml +45 -0
  20. data/hobo_files/plugin/generators/hobo_model/USAGE +26 -0
  21. data/hobo_files/plugin/generators/hobo_model/hobo_model_generator.rb +38 -0
  22. data/hobo_files/plugin/generators/hobo_model/templates/fixtures.yml +11 -0
  23. data/hobo_files/plugin/generators/hobo_model/templates/migration.rb +13 -0
  24. data/hobo_files/plugin/generators/hobo_model/templates/model.rb +24 -0
  25. data/hobo_files/plugin/generators/hobo_model/templates/unit_test.rb +10 -0
  26. data/hobo_files/plugin/generators/hobo_model_controller/USAGE +30 -0
  27. data/hobo_files/plugin/generators/hobo_model_controller/hobo_model_controller_generator.rb +43 -0
  28. data/hobo_files/plugin/generators/hobo_model_controller/templates/controller.rb +5 -0
  29. data/hobo_files/plugin/generators/hobo_model_controller/templates/functional_test.rb +18 -0
  30. data/hobo_files/plugin/generators/hobo_model_controller/templates/helper.rb +2 -0
  31. data/hobo_files/plugin/generators/hobo_model_controller/templates/view.rhtml +2 -0
  32. data/hobo_files/plugin/generators/hobo_rapid/hobo_rapid_generator.rb +51 -0
  33. data/hobo_files/plugin/generators/hobo_rapid/templates/hobo_rapid.js +436 -0
  34. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/default_mapping.rb +11 -0
  35. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/banner.gif +0 -0
  36. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_bodytop.gif +0 -0
  37. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_01.gif +0 -0
  38. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_02.gif +0 -0
  39. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_03.gif +0 -0
  40. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_corner_04.gif +0 -0
  41. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_bottom.gif +0 -0
  42. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_left.gif +0 -0
  43. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_right.gif +0 -0
  44. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/bkg_shadow_top.gif +0 -0
  45. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_blue.gif +0 -0
  46. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_dblue.gif +0 -0
  47. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_green.gif +0 -0
  48. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_purple.gif +0 -0
  49. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/header_red.gif +0 -0
  50. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/logo.gif +0 -0
  51. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/spinner.gif +0 -0
  52. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_dblue.gif +0 -0
  53. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_green.gif +0 -0
  54. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_purple.gif +0 -0
  55. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/txt_list_img_red.gif +0 -0
  56. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_01.gif +0 -0
  57. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_02.gif +0 -0
  58. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_03.gif +0 -0
  59. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_corner_04.gif +0 -0
  60. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_bottom.gif +0 -0
  61. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_left.gif +0 -0
  62. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_right.gif +0 -0
  63. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/images/window_shadow_top.gif +0 -0
  64. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/public/stylesheets/application.css +390 -0
  65. data/hobo_files/plugin/generators/hobo_rapid/templates/themes/default/views/application.dryml +104 -0
  66. data/hobo_files/plugin/generators/hobo_user_model/USAGE +26 -0
  67. data/hobo_files/plugin/generators/hobo_user_model/hobo_user_model_generator.rb +38 -0
  68. data/hobo_files/plugin/generators/hobo_user_model/templates/fixtures.yml +11 -0
  69. data/hobo_files/plugin/generators/hobo_user_model/templates/migration.rb +15 -0
  70. data/hobo_files/plugin/generators/hobo_user_model/templates/model.rb +58 -0
  71. data/hobo_files/plugin/generators/hobo_user_model/templates/unit_test.rb +10 -0
  72. data/hobo_files/plugin/init.rb +44 -0
  73. data/hobo_files/plugin/lib/action_view_extensions/base.rb +14 -0
  74. data/hobo_files/plugin/lib/active_record/has_many_association.rb +54 -0
  75. data/hobo_files/plugin/lib/active_record/has_many_through_association.rb +22 -0
  76. data/hobo_files/plugin/lib/active_record/table_definition.rb +34 -0
  77. data/hobo_files/plugin/lib/extensions.rb +245 -0
  78. data/hobo_files/plugin/lib/extensions/test_case.rb +130 -0
  79. data/hobo_files/plugin/lib/hobo.rb +353 -0
  80. data/hobo_files/plugin/lib/hobo/HtmlString +3 -0
  81. data/hobo_files/plugin/lib/hobo/authenticated_user.rb +106 -0
  82. data/hobo_files/plugin/lib/hobo/authentication_support.rb +108 -0
  83. data/hobo_files/plugin/lib/hobo/composite_model.rb +66 -0
  84. data/hobo_files/plugin/lib/hobo/controller.rb +134 -0
  85. data/hobo_files/plugin/lib/hobo/controller_helpers.rb +135 -0
  86. data/hobo_files/plugin/lib/hobo/core.rb +475 -0
  87. data/hobo_files/plugin/lib/hobo/define_tags.rb +56 -0
  88. data/hobo_files/plugin/lib/hobo/dryml.rb +161 -0
  89. data/hobo_files/plugin/lib/hobo/dryml/dryml_builder.rb +126 -0
  90. data/hobo_files/plugin/lib/hobo/dryml/tag_module.rb +9 -0
  91. data/hobo_files/plugin/lib/hobo/dryml/taglib.rb +57 -0
  92. data/hobo_files/plugin/lib/hobo/dryml/template.rb +586 -0
  93. data/hobo_files/plugin/lib/hobo/dryml/template_environment.rb +302 -0
  94. data/hobo_files/plugin/lib/hobo/dryml/template_handler.rb +19 -0
  95. data/hobo_files/plugin/lib/hobo/generator.rb +25 -0
  96. data/hobo_files/plugin/lib/hobo/html_string.rb +3 -0
  97. data/hobo_files/plugin/lib/hobo/lazy_hash.rb +28 -0
  98. data/hobo_files/plugin/lib/hobo/mapping_tags.rb +262 -0
  99. data/hobo_files/plugin/lib/hobo/markdown_string.rb +7 -0
  100. data/hobo_files/plugin/lib/hobo/model.rb +391 -0
  101. data/hobo_files/plugin/lib/hobo/model_controller.rb +676 -0
  102. data/hobo_files/plugin/lib/hobo/model_queries.rb +92 -0
  103. data/hobo_files/plugin/lib/hobo/model_support.rb +44 -0
  104. data/hobo_files/plugin/lib/hobo/password_string.rb +3 -0
  105. data/hobo_files/plugin/lib/hobo/predicate_dispatch.rb +78 -0
  106. data/hobo_files/plugin/lib/hobo/proc_binding.rb +32 -0
  107. data/hobo_files/plugin/lib/hobo/rapid.rb +447 -0
  108. data/hobo_files/plugin/lib/hobo/static_tags +92 -0
  109. data/hobo_files/plugin/lib/hobo/text.rb +3 -0
  110. data/hobo_files/plugin/lib/hobo/textile_string.rb +13 -0
  111. data/hobo_files/plugin/lib/hobo/undefined.rb +41 -0
  112. data/hobo_files/plugin/lib/hobo/undefined_access_error.rb +5 -0
  113. data/hobo_files/plugin/lib/hobo/where_fragment.rb +23 -0
  114. data/hobo_files/plugin/lib/rexml.rb +345 -0
  115. data/hobo_files/plugin/tags/core.dryml +6 -0
  116. data/hobo_files/plugin/tags/rapid.dryml +177 -0
  117. data/hobo_files/plugin/tags/rapid_editing.dryml +168 -0
  118. data/hobo_files/plugin/tags/rapid_navigation.dryml +95 -0
  119. data/hobo_files/plugin/tags/rapid_pages.dryml +175 -0
  120. data/hobo_files/plugin/tasks/environments.rake +19 -0
  121. data/hobo_files/plugin/tasks/hobo_tasks.rake +4 -0
  122. data/hobo_files/plugin/test/hobo_dryml_template_test.rb +7 -0
  123. data/hobo_files/plugin/test/hobo_test.rb +7 -0
  124. data/hobo_files/plugin/uninstall.rb +1 -0
  125. metadata +206 -0
@@ -0,0 +1,26 @@
1
+ Description:
2
+ The model generator creates stubs for a new model.
3
+
4
+ The generator takes a model name as its argument. The model name may be given in CamelCase or under_score and
5
+ should not be suffixed with 'Model'.
6
+
7
+ As additional parameters, the generator will take attribute pairs described by name and type. These attributes will
8
+ be used to prepopulate the migration to create the table for the model and give you a set of predefined fixture.
9
+ You don't have to think up all attributes up front, but it's a good idea of adding just the baseline of what's
10
+ needed to start really working with the resource.
11
+
12
+ The generator creates a model class in app/models, a test suite in test/unit, test fixtures in
13
+ test/fixtures/singular_name.yml, and a migration in db/migrate.
14
+
15
+ Examples:
16
+ ./script/generate model account
17
+
18
+ This will create an Account model:
19
+ Model: app/models/account.rb
20
+ Test: test/unit/account_test.rb
21
+ Fixtures: test/fixtures/accounts.yml
22
+ Migration: db/migrate/XXX_add_accounts.rb
23
+
24
+ ./script/generate model post title:string created_on:date body:text published:boolean
25
+
26
+ Creates post model with predefined attributes.
@@ -0,0 +1,38 @@
1
+ class HoboModelGenerator < Rails::Generator::NamedBase
2
+ default_options :skip_migration => false
3
+
4
+ def manifest
5
+ record do |m|
6
+ # Check for class naming collisions.
7
+ m.class_collisions class_path, class_name, "#{class_name}Test"
8
+
9
+ # Model, test, and fixture directories.
10
+ m.directory File.join('app/models', class_path)
11
+ m.directory File.join('test/unit', class_path)
12
+ m.directory File.join('test/fixtures', class_path)
13
+
14
+ # Model class, unit test, and fixtures.
15
+ m.template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
16
+ m.template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb")
17
+ m.template 'fixtures.yml', File.join('test/fixtures', class_path, "#{table_name}.yml")
18
+
19
+ unless options[:skip_migration]
20
+ m.migration_template 'migration.rb', 'db/migrate', :assigns => {
21
+ :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}"
22
+ }, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
23
+ end
24
+ end
25
+ end
26
+
27
+ protected
28
+ def banner
29
+ "Usage: #{$0} generate ModelName [field:type, field:type]"
30
+ end
31
+
32
+ def add_options!(opt)
33
+ opt.separator ''
34
+ opt.separator 'Options:'
35
+ opt.on("--skip-migration",
36
+ "Don't generate a migration file for this model") { |v| options[:skip_migration] = v }
37
+ end
38
+ end
@@ -0,0 +1,11 @@
1
+ # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2
+ one:
3
+ id: 1
4
+ <% for attribute in attributes -%>
5
+ <%= attribute.name %>: <%= attribute.default %>
6
+ <% end -%>
7
+ two:
8
+ id: 2
9
+ <% for attribute in attributes -%>
10
+ <%= attribute.name %>: <%= attribute.default %>
11
+ <% end -%>
@@ -0,0 +1,13 @@
1
+ class <%= migration_name %> < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :<%= table_name %> do |t|
4
+ <% for attribute in attributes -%>
5
+ t.column :<%= attribute.name %>, :<%= attribute.type %>
6
+ <% end -%>
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ drop_table :<%= table_name %>
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ class <%= class_name %> < ActiveRecord::Base
2
+
3
+ hobo_model
4
+
5
+
6
+ # --- Hobo Permissions --- #
7
+
8
+ def creatable_by?(creator)
9
+ false
10
+ end
11
+
12
+ def updatable_by?(updater, new)
13
+ false
14
+ end
15
+
16
+ def deletable_by?(deleter)
17
+ false
18
+ end
19
+
20
+ def viewable_by?(viewer, field)
21
+ true
22
+ end
23
+
24
+ end
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper'
2
+
3
+ class <%= class_name %>Test < Test::Unit::TestCase
4
+ fixtures :<%= table_name %>
5
+
6
+ # Replace this with your real tests.
7
+ def test_truth
8
+ assert true
9
+ end
10
+ end
@@ -0,0 +1,30 @@
1
+ Description:
2
+ The controller generator creates stubs for a new controller and its views.
3
+
4
+ The generator takes a controller name and a list of views as arguments.
5
+ The controller name may be given in CamelCase or under_score and should
6
+ not be suffixed with 'Controller'. To create a controller within a
7
+ module, specify the controller name as 'module/controller'.
8
+
9
+ The generator creates a controller class in app/controllers with view
10
+ templates in app/views/controller_name, a helper class in app/helpers,
11
+ and a functional test suite in test/functional.
12
+
13
+ Example:
14
+ ./script/generate controller CreditCard open debit credit close
15
+
16
+ Credit card controller with URLs like /credit_card/debit.
17
+ Controller: app/controllers/credit_card_controller.rb
18
+ Views: app/views/credit_card/debit.rhtml [...]
19
+ Helper: app/helpers/credit_card_helper.rb
20
+ Test: test/functional/credit_card_controller_test.rb
21
+
22
+ Modules Example:
23
+ ./script/generate controller 'admin/credit_card' suspend late_fee
24
+
25
+ Credit card admin controller with URLs /admin/credit_card/suspend.
26
+ Controller: app/controllers/admin/credit_card_controller.rb
27
+ Views: app/views/admin/credit_card/debit.rhtml [...]
28
+ Helper: app/helpers/admin/credit_card_helper.rb
29
+ Test: test/functional/admin/credit_card_controller_test.rb
30
+
@@ -0,0 +1,43 @@
1
+ class HoboModelControllerGenerator < Rails::Generator::NamedBase
2
+
3
+ def initialize(args, options)
4
+ args[0] = args[0].pluralize
5
+ super(args, options)
6
+ end
7
+
8
+ def manifest
9
+ record do |m|
10
+ # Check for class naming collisions.
11
+ m.class_collisions class_path, "#{class_name}Controller", "#{class_name}ControllerTest", "#{class_name}Helper"
12
+
13
+ # Controller, helper, views, and test directories.
14
+ m.directory File.join('app/controllers', class_path)
15
+ m.directory File.join('app/helpers', class_path)
16
+ m.directory File.join('app/views', class_path, file_name)
17
+ m.directory File.join('test/functional', class_path)
18
+
19
+ # Controller class, functional test, and helper class.
20
+ m.template 'controller.rb',
21
+ File.join('app/controllers',
22
+ class_path,
23
+ "#{file_name}_controller.rb")
24
+
25
+ m.template 'functional_test.rb',
26
+ File.join('test/functional',
27
+ class_path,
28
+ "#{file_name}_controller_test.rb")
29
+
30
+ m.template 'helper.rb',
31
+ File.join('app/helpers',
32
+ class_path,
33
+ "#{file_name}_helper.rb")
34
+
35
+ # View template for each action.
36
+ actions.each do |action|
37
+ path = File.join('app/views', class_path, file_name, "#{action}.rhtml")
38
+ m.template 'view.rhtml', path,
39
+ :assigns => { :action => action, :path => path }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,5 @@
1
+ class <%= class_name %>Controller < ApplicationController
2
+
3
+ hobo_model_controller
4
+
5
+ end
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper'
2
+ require '<%= file_path %>_controller'
3
+
4
+ # Re-raise errors caught by the controller.
5
+ class <%= class_name %>Controller; def rescue_action(e) raise e end; end
6
+
7
+ class <%= class_name %>ControllerTest < Test::Unit::TestCase
8
+ def setup
9
+ @controller = <%= class_name %>Controller.new
10
+ @request = ActionController::TestRequest.new
11
+ @response = ActionController::TestResponse.new
12
+ end
13
+
14
+ # Replace this with your real tests.
15
+ def test_truth
16
+ assert true
17
+ end
18
+ end
@@ -0,0 +1,2 @@
1
+ module <%= class_name %>Helper
2
+ end
@@ -0,0 +1,2 @@
1
+ <h1><%= class_name %>#<%= action %></h1>
2
+ <p>Find me in <%= path %></p>
@@ -0,0 +1,51 @@
1
+ require 'find'
2
+
3
+ class HoboRapidGenerator < Hobo::Generator
4
+
5
+ default_options :import_tags => false
6
+
7
+ def manifest
8
+ if options[:command] == :create
9
+ import_tags if options[:import_tags]
10
+ end
11
+
12
+ record do |m|
13
+ m.file "hobo_rapid.js", "public/javascripts/hobo_rapid.js"
14
+ m.file "themes/default/default_mapping.rb", "app/views/hobolib/default_mapping.rb"
15
+ create_all(m, "themes/default/public", "public/hobothemes/default")
16
+ create_all(m, "themes/default/views", "app/views/hobolib/themes/default")
17
+ end
18
+ end
19
+
20
+ def import_tags
21
+ path = File.join(RAILS_ROOT, "app/views/hobolib/application.dryml")
22
+
23
+ tag = "<taglib src=\"plugins/hobo/tags/rapid\"/>\n\n<set_theme name=\"default\"/>\n"
24
+
25
+ src = File.read(path)
26
+ return if src.include?(tag)
27
+
28
+ # first try putting it before the first tag
29
+ done = src.sub!(/<(?!!)/, tag + "\n<")
30
+
31
+ # otherwise append it
32
+ src << tag unless done
33
+
34
+ File.open(path, 'w') {|f| f.write(src) }
35
+ end
36
+
37
+
38
+ protected
39
+ def banner
40
+ "Usage: #{$0} generate [--import-tags]"
41
+ end
42
+
43
+ def add_options!(opt)
44
+ opt.separator ''
45
+ opt.separator 'Options:'
46
+ opt.on("--import-tags",
47
+ "Modify hobolib/application.dryml to import hobo-rapid and theme tags ") do |v|
48
+ options[:import_tags] = true
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,436 @@
1
+
2
+ Object.extend = function(destination) {
3
+ $A(arguments).slice(1).each(function (src) {
4
+ for (var property in src) {
5
+ destination[property] = src[property];
6
+ }
7
+ })
8
+ return destination
9
+ }
10
+
11
+ Object.merge = function() {
12
+ return Object.extend.apply(this, [{}].concat($A(arguments)))
13
+ }
14
+
15
+ var Hobo = {
16
+
17
+ searchRequest: null,
18
+ uidCounter: 0,
19
+ ipeOldValues: {},
20
+
21
+ uid: function() {
22
+ Hobo.uidCounter += 1
23
+ return "uid" + Hobo.uidCounter
24
+ },
25
+
26
+ updatesForElement: function(el) {
27
+ el = $(el)
28
+ var updates = el.getAttribute("hobo_update")
29
+ return updates ? updates.split(/\s*,\s*/) : []
30
+ },
31
+
32
+ ajaxSetFieldForElement: function(el, val, options) {
33
+ var updates = Hobo.updatesForElement(el)
34
+ var params = Hobo.fieldSetParam(el, val)
35
+ var p = el.getAttribute("hobo_ajax_params")
36
+ if (p) params = params + "&" + p
37
+
38
+ var opts = Object.merge(options || {}, { params: params})
39
+ Hobo.ajaxRequest(Hobo.putUrl(el),
40
+ el.getAttribute("hobo_ajax_message") || "Changing...",
41
+ updates,
42
+ opts)
43
+ },
44
+
45
+ ajaxUpdateParams: function(updates, resultUpdates) {
46
+ var params = []
47
+ var i = 0
48
+ if (updates.length > 0) {
49
+ updates.each(function(dom_id) {
50
+ params.push("render["+i+"][part]=" + hoboParts[dom_id][0])
51
+ params.push("render["+i+"][id]=" + dom_id)
52
+ params.push("render["+i+"][object]=" + hoboParts[dom_id][1])
53
+ i += 1
54
+ })
55
+ params.push("part_page=" + hoboPartPage)
56
+ }
57
+
58
+ if (resultUpdates) {
59
+ resultUpdates.each(function (resultUpdate) {
60
+ params.push("render["+i+"][id]=" + resultUpdate.id)
61
+ params.push("render["+i+"][result]=" + resultUpdate.result)
62
+ if (resultUpdate.func) {
63
+ params.push("render["+i+"][function]=" + resultUpdate.func)
64
+ }
65
+ i += 1
66
+ })
67
+ }
68
+ return params.join('&')
69
+ },
70
+
71
+ ajaxRequest: function(url_or_form, message, updates, options) {
72
+ options = Object.merge({ asynchronous:true,
73
+ evalScripts:true,
74
+ resetForm: true,
75
+ refocusForm: true
76
+ }, options)
77
+ if (typeof url_or_form == "string") {
78
+ var url = url_or_form
79
+ var form = false
80
+ } else {
81
+ var form = url_or_form
82
+ var url = form.action
83
+ }
84
+ var params = []
85
+
86
+ updateParams = Hobo.ajaxUpdateParams(updates, options.resultUpdate)
87
+ if (updateParams != "") { params.push(updateParams) }
88
+
89
+ if (options.params) {
90
+ params.push(options.params)
91
+ delete options.params
92
+ }
93
+
94
+ if (form) {
95
+ params.push(Form.serialize(form))
96
+ }
97
+
98
+ Hobo.showSpinner(message)
99
+ var complete = function() {
100
+ if (form && options.resetForm) form.reset();
101
+ Hobo.hideSpinner();
102
+
103
+ if (options.onComplete)
104
+ options.onComplete.apply(this, arguments)
105
+ if (form && options) Form.focusFirstElement(form)
106
+ }
107
+ if (options.method && options.method.toLowerCase() == "put") {
108
+ delete options.method
109
+ params.push("_method=PUT")
110
+ }
111
+
112
+ if (!options.onFailure) {
113
+ options.onFailure = function(response) {
114
+ alert(response.responseText)
115
+ }
116
+ }
117
+
118
+ new Ajax.Request(url, Object.merge(options, { parameters: params.join("&"), onComplete: complete }))
119
+ },
120
+
121
+ hide: function() {
122
+ for (i = 0; i < arguments.length; i++) {
123
+ if ($(arguments[i])) {
124
+ Element.addClassName(arguments[i], 'hidden')
125
+ }
126
+ }
127
+ },
128
+
129
+ show: function() {
130
+ for (i = 0; i < arguments.length; i++) {
131
+ if ($(arguments[i])) {
132
+ Element.removeClassName(arguments[i], 'hidden')
133
+ }
134
+ }
135
+ },
136
+
137
+ toggle: function() {
138
+ for (i = 0; i < arguments.length; i++) {
139
+ if ($(arguments[i])) {
140
+ if(Element.hasClassName(arguments[i], 'hidden')) {
141
+ Element.removeClassName(arguments[i], 'hidden')
142
+ } else {
143
+ Element.addClassName(arguments[i], 'hidden')
144
+ }
145
+ }
146
+ }
147
+ },
148
+
149
+ onFieldEditComplete: function(el, newValue) {
150
+ el = $(el)
151
+ var oldValue = Hobo.ipeOldValues[el.id]
152
+ delete Hobo.ipeOldValues[el.id]
153
+
154
+ var blank = el.getAttribute("hobo_blank_message")
155
+ if (blank && newValue.strip().length == 0) {
156
+ el.update(blank)
157
+ } else {
158
+ el.update(newValue)
159
+ }
160
+
161
+ var modelId = el.getAttribute('hobo_model_id')
162
+ if (oldValue) {
163
+ $$("*[hobo_model_id=" + modelId + "]").each(function(e) {
164
+ if (e != el && e.innerHTML == oldValue) e.update(newValue)
165
+ })
166
+ }
167
+ },
168
+
169
+ _makeInPlaceEditor: function(el, options) {
170
+ var old
171
+ var spec = Hobo.parseFieldId(el)
172
+ var updates = Hobo.updatesForElement(el)
173
+ var id = el.id
174
+ if (!id) { id = el.id = Hobo.uid() }
175
+ var updateParams = Hobo.ajaxUpdateParams(updates, [{id: id,
176
+ result: 'new_field_value',
177
+ func: "Hobo.onFieldEditComplete"}])
178
+ opts = {okButton: false,
179
+ cancelLink: false,
180
+ submitOnBlur: true,
181
+ callback: function(form, val) {
182
+ old = val
183
+ return (Hobo.fieldSetParam(el, val) + "&" + updateParams)
184
+ },
185
+ highlightcolor: '#ffffff',
186
+ highlightendcolor: Hobo.backgroundColor(el),
187
+ onFailure: function(resp) { alert(resp.responseText); el.innerHTML = old },
188
+ evalScripts: true
189
+ }
190
+ Object.extend(opts, options)
191
+ var ipe = new Ajax.InPlaceEditor(el, Hobo.putUrl(el), opts)
192
+ ipe.onEnterEditMode = function() {
193
+ var blank_message = el.getAttribute("hobo_blank_message")
194
+ if (el.innerHTML.gsub("&nbsp;", " ") == blank_message) {
195
+ el.innerHTML = ""
196
+ } else {
197
+ Hobo.ipeOldValues[el.id] = el.innerHTML
198
+ }
199
+ }
200
+ return ipe
201
+ },
202
+
203
+ applyEvents: function(root) {
204
+ root = $(root)
205
+ function select(p) {
206
+ return new Selector(p).findElements(root)
207
+ }
208
+
209
+ select(".in_place_textfield_bhv").each(function (el) {
210
+ ipe = Hobo._makeInPlaceEditor(el)
211
+ ipe.getText = function() {
212
+ return this.element.innerHTML.gsub(/<br\s*\/?>/, "\n").unescapeHTML()
213
+ }
214
+ })
215
+
216
+ select(".in_place_textarea_bhv").each(function (el) {
217
+ ipe = Hobo._makeInPlaceEditor(el, {rows: 2})
218
+ ipe.getText = function() {
219
+ return this.element.innerHTML.gsub(/<br\s*\/?>/, "\n").unescapeHTML()
220
+ }
221
+ })
222
+
223
+ select(".in_place_html_textarea_bhv").each(function (el) {
224
+ var ipe = Hobo._makeInPlaceEditor(el, {rows: 2, handleLineBreaks: false})
225
+ if (typeof(tinyMCE) != "undefined") {
226
+ ipe.afterEnterEditMode = function() {
227
+ var id = this.form.id = Hobo.uid()
228
+
229
+ // 'orrible 'ack
230
+ // What is the correct way to individually configure a tinyMCE instace?
231
+ var old = tinyMCE.settings.theme_advanced_buttons1
232
+ tinyMCE.settings.theme_advanced_buttons1 += ", separator, save"
233
+ tinyMCE.addMCEControl(this.editField, id);
234
+ tinyMCE.settings.theme_advanced_buttons1 = old
235
+
236
+ this.form.onsubmit = function() {
237
+ tinyMCE.removeMCEControl(ipe.form.id)
238
+ setTimeout(ipe.onSubmit.bind(ipe), 10)
239
+ return false
240
+ }
241
+ }
242
+ }
243
+ })
244
+
245
+ select("select.number_editor_bhv").each(function(el) {
246
+ el.onchange = function() {
247
+ Hobo.ajaxSetFieldForElement(el, el.value)
248
+ }
249
+ })
250
+
251
+ select(".autocomplete_bhv").each(function (el) {
252
+ options = {paramName: "query", minChars: 3, method: 'get' }
253
+ if (el.hasClassName("autosubmit")) {
254
+ options.afterUpdateElement = function(el, item) { el.form.onsubmit(); }
255
+ }
256
+ new Ajax.Autocompleter(el, el.id + "_completions", el.getAttribute("autocomplete_url"),
257
+ options);
258
+ });
259
+
260
+ select(".search_bhv").each(function(el) {
261
+ new Form.Element.Observer(el, 1.0, function() { Hobo.doSearch(el) })
262
+ });
263
+ },
264
+
265
+
266
+ doSearch: function(el) {
267
+ el = $(el)
268
+ var spinner = $(el.getAttribute("search_spinner") || "search_spinner")
269
+ var search_results = $(el.getAttribute("search_results") || "search_results")
270
+ var search_results_panel = $(el.getAttribute("search_results_panel") || "search_results_panel")
271
+ var url = el.getAttribute("search_url") || (urlBase + "/search")
272
+
273
+ el.focus();
274
+ var value = $F(el)
275
+ if (Hobo.searchRequest) { Hobo.searchRequest.transport.abort() }
276
+ if (value.length >= 3) {
277
+ if (spinner) Hobo.show(spinner);
278
+ Hobo.searchRequest = new Ajax.Updater(search_results,
279
+ url,
280
+ { asynchronous:true,
281
+ evalScripts:true,
282
+ onSuccess:function(request) {
283
+ if (spinner) Hobo.hide(spinner)
284
+ if (search_results_panel) {
285
+ Hobo.show(search_results_panel)
286
+ }
287
+ },
288
+ parameters:"query=" + value });
289
+ } else {
290
+ Hobo.updateElement(search_results, '')
291
+ Hobo.hide(search_results_panel)
292
+ }
293
+ },
294
+
295
+
296
+ putUrl: function(el) {
297
+ spec = Hobo.parseFieldId(el)
298
+ return urlBase + "/" + controllerNames[spec.name] + "/" + spec.id + "?_method=PUT"
299
+ },
300
+
301
+
302
+ fieldSetParam: function(el, val) {
303
+ spec = Hobo.parseFieldId(el)
304
+ return spec.name + '[' + spec.field + ']=' + escape(val)
305
+ },
306
+
307
+ fadeObjectElement: function(el) {
308
+ new Effect.Fade(Hobo.objectElementFor(el),
309
+ { duration: 0.5,
310
+ afterFinish: function (ef) { ef.element.remove() } });
311
+ },
312
+
313
+ removeButton: function(el, url, updates, fade) {
314
+ if (fade == null) { fade = true; }
315
+ if (confirm("Are you sure?")) {
316
+ objEl = Hobo.objectElementFor(el)
317
+ Hobo.showSpinner('Removing');
318
+ function complete() {
319
+ if (fade) { Hobo.fadeObjectElement(el) }
320
+ Hobo.hideSpinner()
321
+ }
322
+ if (updates && updates.length > 0) {
323
+ new Hobo.ajaxRequest(url, "Removing", updates, { method:'delete',
324
+ onComplete: complete});
325
+ } else {
326
+ new Ajax.Request(url, {asynchronous:true, evalScripts:true, method:'delete',
327
+ onComplete: complete});
328
+ }
329
+ }
330
+ },
331
+
332
+
333
+ parseFieldId: function(el) {
334
+ id = el.getAttribute("hobo_model_id")
335
+ if (!id) return
336
+ m = id.match(/^([a-z_]+)_([0-9]+)_([a-z_]+)$/)
337
+ if (m) return { name: m[1], id: m[2], field: m[3] }
338
+ },
339
+
340
+ appendRow: function(el, rowSrc) {
341
+ // IE friendly method to add a <tr> (from html source) to a table
342
+ // el should be an element that contains *only* a table
343
+ el = $(el);
344
+ el.innerHTML = el.innerHTML.replace("</table>", "") + rowSrc + "</table>";
345
+ Hobo.applyEvents(el)
346
+ },
347
+
348
+ objectElementFor: function(el) {
349
+ var m
350
+ while(el.getAttribute) {
351
+ id = el.getAttribute("hobo_model_id");
352
+ if (id) m = id.match(/^([a-z_]+)_([0-9]+)(_[a-z0-9_]*)?$/);
353
+ if (m) break;
354
+ el = el.parentNode;
355
+ }
356
+ if (m) return el;
357
+ },
358
+
359
+
360
+ showSpinner: function(message) {
361
+ if(t = $('ajax_progress_text')) Element.update(t, message);
362
+ if(e = $('ajax_progress')) e.style.display = "block";
363
+ },
364
+
365
+
366
+ hideSpinner: function() {
367
+ if(e = $('ajax_progress')) e.style.display = "none";
368
+ },
369
+
370
+
371
+ updateElement: function(id, content) {
372
+ Element.update(id, content)
373
+ Hobo.applyEvents(id)
374
+ },
375
+
376
+ rgbColorToHex: function(color) {
377
+ parts = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)/.exec(color)
378
+ function hexPart(s) {
379
+ var res = (s * 1).toString(16)
380
+ return res.length == 1 ? '0' + res : res
381
+ }
382
+ if (parts) {
383
+ return '#' + hexPart(parts[1]) + hexPart(parts[2]) + hexPart(parts[3])
384
+ } else {
385
+ return color
386
+ }
387
+ },
388
+
389
+ getStyle: function(el, styleProp) {
390
+ if (el.currentStyle)
391
+ var y = el.currentStyle[styleProp];
392
+ else if (window.getComputedStyle)
393
+ var y = document.defaultView.getComputedStyle(el, null).getPropertyValue(styleProp);
394
+ return y;
395
+ },
396
+
397
+ backgroundColor: function(el) {
398
+ return Hobo.rgbColorToHex(Hobo.getStyle(el, 'background-color'))
399
+ }
400
+
401
+ }
402
+
403
+ Element.findContaining = function(el, tag) {
404
+ el = $(el)
405
+ tag = tag.toLowerCase()
406
+ e = el.parentNode
407
+ while (el) {
408
+ if (el.nodeName.toLowerCase() == tag) {
409
+ return el;
410
+ }
411
+ e = el.parentNode
412
+ }
413
+ return null;
414
+ }
415
+
416
+ // Fix scriptaculous - don't remove <p> tags please!
417
+ Ajax.InPlaceEditor.prototype.convertHTMLLineBreaks = function(string) {
418
+ return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n");
419
+ }
420
+
421
+
422
+ origEnterEditMode = Ajax.InPlaceEditor.prototype.enterEditMode
423
+ Ajax.InPlaceEditor.prototype.enterEditMode = function(evt) {
424
+ origEnterEditMode.bind(this)(evt)
425
+ if (this.afterEnterEditMode) this.afterEnterEditMode()
426
+ return false
427
+ }
428
+
429
+ // Silence errors from IE :-(
430
+ Field.scrollFreeActivate = function(field) {
431
+ setTimeout(function() {
432
+ try {
433
+ Field.activate(field);
434
+ } catch(e) {}
435
+ }, 1);
436
+ }