hobo 0.5.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.
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
+ }