hobo 1.3.3 → 1.4.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. data/{CHANGES.txt → CHANGES-1.3.txt} +0 -0
  2. data/CHANGES-1.4.txt +678 -0
  3. data/Rakefile +13 -3
  4. data/TODO-1.4.txt +69 -0
  5. data/VERSION +1 -1
  6. data/app/helpers/hobo_debug_helper.rb +16 -0
  7. data/app/helpers/hobo_deprecated_helper.rb +45 -0
  8. data/app/helpers/hobo_helper_base.rb +8 -0
  9. data/app/helpers/hobo_permissions_helper.rb +136 -0
  10. data/app/helpers/hobo_route_helper.rb +196 -0
  11. data/{lib/hobo/helper/translations.rb → app/helpers/hobo_translations_helper.rb} +4 -7
  12. data/{lib/hobo/helper/translations/normalizer.rb → app/helpers/hobo_translations_normalizer_helper.rb} +3 -10
  13. data/app/helpers/hobo_type_helper.rb +24 -0
  14. data/app/helpers/hobo_view_hint_helper.rb +13 -0
  15. data/hobo.gemspec +3 -3
  16. data/lib/generators/hobo/admin_subsite/admin_subsite_generator.rb +0 -9
  17. data/lib/generators/hobo/admin_subsite/templates/application.dryml +2 -0
  18. data/lib/generators/hobo/admin_subsite/templates/gitkeep +0 -0
  19. data/lib/generators/hobo/admin_subsite/templates/site.css.erb +9 -0
  20. data/lib/generators/hobo/admin_subsite/templates/site.js.erb +10 -0
  21. data/lib/generators/hobo/assets/assets_generator.rb +16 -2
  22. data/lib/generators/hobo/assets/templates/application.css +9 -0
  23. data/lib/generators/hobo/assets/templates/application.dryml.erb +0 -5
  24. data/lib/generators/hobo/assets/templates/application.js +11 -0
  25. data/lib/generators/hobo/assets/templates/front.css +10 -0
  26. data/lib/generators/hobo/assets/templates/front.js +11 -0
  27. data/lib/generators/hobo/assets/templates/front_site.dryml.erb +6 -0
  28. data/lib/generators/hobo/assets/templates/gitkeep +0 -0
  29. data/lib/generators/hobo/dev_tweaks/dev_tweaks_generator.rb +31 -0
  30. data/lib/generators/hobo/i18n/templates/hobo.en.yml +1 -1
  31. data/lib/generators/hobo/install_plugin/USAGE +3 -0
  32. data/lib/generators/hobo/install_plugin/install_plugin_generator.rb +36 -0
  33. data/lib/generators/hobo/plugin.rb +112 -0
  34. data/lib/generators/hobo/setup_wizard/setup_wizard_generator.rb +31 -14
  35. data/lib/generators/hobo/subsite.rb +16 -2
  36. data/lib/generators/hobo/subsite/templates/gitkeep +0 -0
  37. data/lib/generators/hobo/subsite/templates/site.css.erb +9 -0
  38. data/lib/generators/hobo/subsite/templates/site.js.erb +10 -0
  39. data/lib/generators/hobo/subsite_taglib/templates/taglib.dryml.erb +0 -17
  40. data/lib/generators/hobo/test_framework/test_framework_generator.rb +1 -1
  41. data/lib/hobo.rb +3 -2
  42. data/lib/hobo/controller.rb +43 -24
  43. data/lib/hobo/controller/model.rb +63 -42
  44. data/lib/hobo/controller/user_base.rb +1 -3
  45. data/lib/hobo/engine.rb +1 -1
  46. data/lib/hobo/extensions/active_record/associations/association.rb +36 -0
  47. data/lib/hobo/extensions/active_record/associations/collection.rb +10 -19
  48. data/lib/hobo/extensions/active_record/associations/proxy.rb +3 -15
  49. data/lib/hobo/extensions/active_record/associations/scope.rb +2 -2
  50. data/lib/hobo/extensions/active_record/permissions.rb +32 -38
  51. data/lib/hobo/extensions/active_record/relation_with_origin.rb +5 -5
  52. data/lib/hobo/model.rb +12 -7
  53. data/lib/hobo/model/accessible_associations.rb +8 -15
  54. data/lib/hobo/model/lifecycles/creator.rb +1 -1
  55. data/lib/hobo/model/lifecycles/transition.rb +1 -1
  56. data/lib/hobo/model/permissions.rb +4 -4
  57. data/lib/hobo/model/scopes.rb +4 -17
  58. data/lib/hobo/model/scopes/automatic_scopes.rb +5 -13
  59. data/lib/hobo/rapid/helper.rb +1 -161
  60. data/lib/hobo/rapid/taglibs/rapid.dryml +3 -17
  61. data/test/doctest/hobo/hobo_helper.rdoctest +8 -44
  62. data/{doctests → test/doctest}/hobo/lifecycles.rdoctest +0 -0
  63. data/{doctests → test/doctest}/hobo/model.rdoctest +2 -4
  64. data/{doctests → test/doctest}/hobo/multi_model_forms.rdoctest +3 -24
  65. data/{doctests → test/doctest}/hobo/scopes.rdoctest +3 -53
  66. data/test/doctest/prepare_testapp.rb +11 -0
  67. data/test/irt/generators/admin_subsite.irt +1 -19
  68. data/test/irt/generators/assets.irt +4 -9
  69. data/test/irt/generators/controller.irt +0 -3
  70. data/test/irt/generators/front_controller.irt +0 -5
  71. data/test/irt/generators/{helper.rb → irt_helper.rb} +2 -2
  72. data/test/irt/generators/model.irt +1 -12
  73. data/test/irt/generators/partials/_account_user_model_tests.rb +0 -8
  74. data/test/irt/generators/partials/_accounts_users_controller_tests.rb +0 -2
  75. data/test/irt/generators/partials/_default_user_model_tests.rb +0 -8
  76. data/test/irt/generators/partials/_default_users_controller_tests.rb +0 -2
  77. data/test/irt/generators/partials/_house_controller_tests.rb +0 -2
  78. data/test/irt/generators/partials/_house_model_tests.rb +1 -9
  79. data/test/irt/generators/partials/_subsite_taglib_admin.rb +5 -2
  80. data/test/irt/generators/partials/_subsite_taglib_admin_invite_only.rb +1 -1
  81. data/test/irt/generators/partials/_subsite_taglib_noopt.rb +2 -2
  82. data/test/irt/generators/partials/_subsite_taglib_variables.rb +0 -15
  83. data/test/irt/generators/partials/_user_mailer_tests.rb +1 -3
  84. data/test/irt/generators/resource.irt +0 -3
  85. data/test/irt/generators/subsite.irt +6 -22
  86. data/test/irt/generators/subsite_taglib.irt +0 -18
  87. data/test/irt/generators/test_framework.irt +2 -5
  88. data/test/irt/generators/user_controller.irt +0 -3
  89. data/test/irt/generators/user_mailer.irt +0 -3
  90. data/test/irt/generators/user_model.irt +0 -3
  91. data/test/irt/generators/user_resource.irt +0 -3
  92. data/test/irt/readme.txt +6 -3
  93. metadata +116 -159
  94. data/app/controllers/dev_controller.rb +0 -25
  95. data/app/views/dev/summary.dryml +0 -102
  96. data/doctests/prepare_testapp.rb +0 -8
  97. data/lib/generators/hobo/admin_subsite/templates/admin.css +0 -20
  98. data/lib/generators/hobo/rapid/USAGE +0 -3
  99. data/lib/generators/hobo/rapid/rapid_generator.rb +0 -24
  100. data/lib/generators/hobo/rapid/templates/IE7.js +0 -2
  101. data/lib/generators/hobo/rapid/templates/blank.gif +0 -0
  102. data/lib/generators/hobo/rapid/templates/hobo-rapid.css +0 -94
  103. data/lib/generators/hobo/rapid/templates/hobo-rapid.js +0 -1015
  104. data/lib/generators/hobo/rapid/templates/ie7-recalc.js +0 -166
  105. data/lib/generators/hobo/rapid/templates/lowpro.js +0 -339
  106. data/lib/generators/hobo/rapid/templates/reset.css +0 -95
  107. data/lib/generators/hobo/rapid/templates/themes/clean/public/images/101-3B5F87-ACD3E6.png +0 -0
  108. data/lib/generators/hobo/rapid/templates/themes/clean/public/images/30-3E547A-242E42.png +0 -0
  109. data/lib/generators/hobo/rapid/templates/themes/clean/public/images/30-DBE1E5-FCFEF5.png +0 -0
  110. data/lib/generators/hobo/rapid/templates/themes/clean/public/images/300-ACD3E6-fff.png +0 -0
  111. data/lib/generators/hobo/rapid/templates/themes/clean/public/images/50-ACD3E6-fff.png +0 -0
  112. data/lib/generators/hobo/rapid/templates/themes/clean/public/images/fieldbg.gif +0 -0
  113. data/lib/generators/hobo/rapid/templates/themes/clean/public/images/pencil.png +0 -0
  114. data/lib/generators/hobo/rapid/templates/themes/clean/public/images/small_close.png +0 -0
  115. data/lib/generators/hobo/rapid/templates/themes/clean/public/images/spinner.gif +0 -0
  116. data/lib/generators/hobo/rapid/templates/themes/clean/public/stylesheets/clean.css +0 -327
  117. data/lib/generators/hobo/rapid/templates/themes/clean/public/stylesheets/rapid-ui.css +0 -102
  118. data/lib/generators/hobo/rapid/templates/themes/clean/views/clean.dryml +0 -10
  119. data/lib/hobo/helper.rb +0 -460
  120. data/lib/hobo/rapid/taglibs/rapid_core.dryml +0 -808
  121. data/lib/hobo/rapid/taglibs/rapid_document_tags.dryml +0 -56
  122. data/lib/hobo/rapid/taglibs/rapid_editing.dryml +0 -287
  123. data/lib/hobo/rapid/taglibs/rapid_forms.dryml +0 -1156
  124. data/lib/hobo/rapid/taglibs/rapid_generics.dryml +0 -48
  125. data/lib/hobo/rapid/taglibs/rapid_i18n.dryml +0 -173
  126. data/lib/hobo/rapid/taglibs/rapid_lifecycles.dryml +0 -96
  127. data/lib/hobo/rapid/taglibs/rapid_navigation.dryml +0 -108
  128. data/lib/hobo/rapid/taglibs/rapid_pages.dryml +0 -259
  129. data/lib/hobo/rapid/taglibs/rapid_plus.dryml +0 -247
  130. data/lib/hobo/rapid/taglibs/rapid_summary.dryml +0 -283
  131. data/lib/hobo/rapid/taglibs/rapid_support.dryml +0 -102
  132. data/lib/hobo/rapid/taglibs/rapid_user_pages.dryml +0 -182
  133. data/test/irt/generators/rapid.irt +0 -29
@@ -1,25 +0,0 @@
1
- class DevController < ActionController::Base
2
-
3
- hobo_controller
4
-
5
- before_filter :developer_modes_only
6
-
7
- def set_current_user
8
- model = params[:model] || Hobo::Model::UserBase.default_user_model
9
- self.current_user = if params[:login]
10
- model.where(model.login_attribute => params[:login]).first
11
- else
12
- model.find(params[:id])
13
- end
14
- redirect_to(request.env["HTTP_REFERER"] ? :back : home_page)
15
- end
16
-
17
- private
18
-
19
- def developer_modes_only
20
- # Belt and braces. In addition to this check, the routes only get
21
- # defined when developer_features is true
22
- render :text => "Permission Denied", :status => 403 unless Rails.application.config.hobo.developer_features
23
- end
24
-
25
- end
@@ -1,102 +0,0 @@
1
- <page>
2
- <content:>
3
- <div class="content-body">
4
- <h2>Application Summary</h2>
5
-
6
- <table class="app-summary">
7
- <tr> <th></th><th></th></tr>
8
- <tr> <td>Application Name</td> <td><app-name/></td> </tr>
9
- <tr> <td>Application Location</td> <td><rails-root/></td> </tr>
10
- <tr> <td>Rails Version</td> <td><rails-version/></td> </tr>
11
- <tr> <td>Mode</td> <td><rails-env/></td> </tr>
12
- </table>
13
-
14
- <h3>Change Control</h3>
15
- <table class="app-summary">
16
- <tr> <th></th><th></th></tr>
17
- <tr> <td>Method</td> <td><cms-method/></td> </tr>
18
- <if test="&cms_method.strip=='git'">
19
- <tr> <td>Version</td> <td><cms-version/></td> </tr>
20
- <tr> <td>Date</td> <td><cms-last-commit-time/></td> </tr>
21
- <tr> <td>Branch</td> <td><cms-branch/></td> </tr>
22
- <tr> <td>Clean?</td> <td><cms-clean/></td></tr>
23
- </if>
24
- </table>
25
-
26
-
27
- <h3>Bundled Gems</h3>
28
- <table class="app-summary">
29
- <with-gems>
30
- <tr if="&first_item?"><th></th><th>Version</th><th>Dependencies</th></tr>
31
- <tr>
32
- <td><gem-name/></td>
33
- <td><gem-version/></td>
34
- <td><gem-dependencies/></td>
35
- </tr>
36
- </with-gems>
37
- </table>
38
-
39
- <h3>Plugins</h3>
40
- <table class="app-summary">
41
- <with-plugins>
42
- <tr if="&first_item?"><th></th><th>Location</th><th>Method</th><th>Clean?</th><th>Version</th></tr>
43
- <tr>
44
- <td><plugin-name/></td>
45
- <td><plugin-location/></td>
46
- <td><plugin-method/></td>
47
- <td><plugin-clean/></td>
48
- <td><plugin-version/></td>
49
- </tr>
50
- </with-plugins>
51
- </table>
52
-
53
- <h3>Environments</h3>
54
- <table class="app-summary">
55
- <tr><th></th><th colspan='2'>database</th></tr>
56
- <with-environments>
57
- <tr>
58
- <td><environment-name /></td>
59
- <td><database-type /></td>
60
- <td><database-name /></td>
61
- </tr>
62
- </with-environments>
63
- </table>
64
-
65
- <h2>Models</h2>
66
- <table class="app-summary">
67
- <tr><th>Class</th><th>Table</th><th></th></tr>
68
- <with-models>
69
- <tr>
70
- <td><model-name/></td>
71
- <td><model-table-name/></td>
72
- <td><model-table-comment/></td>
73
- </tr>
74
- </with-models>
75
- </table>
76
-
77
- <with-models>
78
- <h3 if="&this.try.table_name"><model-name /></h3>
79
- <table class="app-summary">
80
- <with-model-columns>
81
- <tr if="&first_item?"><th>Column</th><th>Type</th><th></th></tr>
82
- <tr>
83
- <td><model-column-name/></td>
84
- <td><model-column-type/></td>
85
- <td><model-column-comment/></td>
86
- </tr>
87
- </with-model-columns>
88
- </table>
89
- <table class="app-summary">
90
- <with-model-associations>
91
- <tr if="&first_item?"><th>Association</th><th>Macro</th><th>Class</th></tr>
92
- <tr>
93
- <td><model-association-name/></td>
94
- <td><model-association-macro/></td>
95
- <td><model-association-class-name/></td>
96
- </tr>
97
- </with-model-associations>
98
- </table>
99
- </with-models>
100
- </div>
101
- </content:>
102
- </page>
@@ -1,8 +0,0 @@
1
- require 'fileutils'
2
- system %(rake test:prepare_testapp)
3
- TESTAPP_PATH = '/tmp/hobo_testapp'
4
- FileUtils.chdir TESTAPP_PATH
5
- require 'config/environment'
6
- require 'rails/generators'
7
- Rails::Generators.configure!
8
-
@@ -1,20 +0,0 @@
1
- body {
2
- background-color: #333;
3
- background-image: none;
4
- }
5
-
6
- .page-header {
7
- background: #555;
8
- }
9
-
10
- .page-header.sidemenu {
11
- background: none;
12
- }
13
-
14
- .page-header h1 a {
15
- color:#FCFFF5;
16
- }
17
-
18
- #main-nav-container {
19
- background:#555555
20
- }
@@ -1,3 +0,0 @@
1
- Description:
2
-
3
- Adds support for Rapid to your application.
@@ -1,24 +0,0 @@
1
- module Hobo
2
- class RapidGenerator < Rails::Generators::Base
3
- source_root File.expand_path('../templates', __FILE__)
4
-
5
- def self.banner
6
- "rails generate hobo:rapid"
7
- end
8
-
9
- def copy_rapid_files
10
- copy_file "hobo-rapid.js", "public/javascripts/hobo-rapid.js"
11
- copy_file "lowpro.js", "public/javascripts/lowpro.js"
12
- copy_file "IE7.js", "public/javascripts/IE7.js"
13
- copy_file "ie7-recalc.js", "public/javascripts/ie7-recalc.js"
14
- copy_file "blank.gif", "public/javascripts/blank.gif"
15
- copy_file "reset.css", "public/stylesheets/reset.css"
16
- copy_file "hobo-rapid.css", "public/stylesheets/hobo-rapid.css"
17
- directory "themes/clean/public","public/hobothemes/clean"
18
- directory "themes/clean/views", "app/views/taglibs/themes/clean"
19
- directory "themes/clean-sidemenu/public","public/hobothemes/clean-sidemenu"
20
- directory "themes/clean-sidemenu/views", "app/views/taglibs/themes/clean-sidemenu"
21
- end
22
-
23
- end
24
- end
@@ -1,2 +0,0 @@
1
- /* IE7/IE8.js - copyright 2004-2008, Dean Edwards */
2
- (function(){IE7={toString:function(){return"IE7 version 2.0 (beta4)"}};var k=IE7.appVersion=navigator.appVersion.match(/MSIE (\d\.\d)/)[1];if(/ie7_off/.test(top.location.search)||k<5)return;var Q=bG();var C=document.compatMode!="CSS1Compat";var bm=document.documentElement,v,s;var bA="!";var G=":link{ie7-link:link}:visited{ie7-link:visited}";var cj=/^[\w\.]+[^:]*$/;function W(a,b){if(cj.test(a))a=(b||"")+a;return a};function bn(a,b){a=W(a,b);return a.slice(0,a.lastIndexOf("/")+1)};var bB=document.scripts[document.scripts.length-1];var ck=bn(bB.src);try{var H=new ActiveXObject("Microsoft.XMLHTTP")}catch(e){}var X={};function cl(a,b){try{a=W(a,b);if(!X[a]){H.open("GET",a,false);H.send();if(H.status==0||H.status==200){X[a]=H.responseText}}}catch(e){}finally{return X[a]||""}};if(k<5.5){undefined=Q();bA="HTML:!";var cm=/(g|gi)$/;var cn=String.prototype.replace;String.prototype.replace=function(a,b){if(typeof b=="function"){if(a&&a.constructor==RegExp){var c=a;var d=c.global;if(d==null)d=cm.test(c);if(d)c=new RegExp(c.source)}else{c=new RegExp(bb(a))}var f,g=this,h="";while(g&&(f=c.exec(g))){h+=g.slice(0,f.index)+b.apply(this,f);g=g.slice(f.index+f[0].length);if(!d)break}return h+g}return cn.apply(this,arguments)};Array.prototype.pop=function(){if(this.length){var a=this[this.length-1];this.length--;return a}return undefined};Array.prototype.push=function(){for(var a=0;a<arguments.length;a++){this[this.length]=arguments[a]}return this.length};var co=this;Function.prototype.apply=function(a,b){if(a===undefined)a=co;else if(a==null)a=window;else if(typeof a=="string")a=new String(a);else if(typeof a=="number")a=new Number(a);else if(typeof a=="boolean")a=new Boolean(a);if(arguments.length==1)b=[];else if(b[0]&&b[0].writeln)b[0]=b[0].documentElement.document||b[0];var c="#ie7_apply",d;a[c]=this;switch(b.length){case 0:d=a[c]();break;case 1:d=a[c](b[0]);break;case 2:d=a[c](b[0],b[1]);break;case 3:d=a[c](b[0],b[1],b[2]);break;case 4:d=a[c](b[0],b[1],b[2],b[3]);break;case 5:d=a[c](b[0],b[1],b[2],b[3],b[4]);break;default:var f=[],g=b.length-1;do f[g]="a["+g+"]";while(g--);eval("r=o[$]("+f+")")}if(typeof a.valueOf=="function"){delete a[c]}else{a[c]=undefined;if(d&&d.writeln)d=d.documentElement.document||d}return d};Function.prototype.call=function(a){return this.apply(a,bC.apply(arguments,[1]))};G+="address,blockquote,body,dd,div,dt,fieldset,form,"+"frame,frameset,h1,h2,h3,h4,h5,h6,iframe,noframes,object,p,"+"hr,applet,center,dir,menu,pre,dl,li,ol,ul{display:block}"}var bC=Array.prototype.slice;var cJ=/%([1-9])/g;var cp=/^\s\s*/;var cq=/\s\s*$/;var cr=/([\/()[\]{}|*+-.,^$?\\])/g;var bD=/\bbase\b/;var bE=["constructor","toString"];var Y;function z(){};z.extend=function(a,b){Y=true;var c=new this;ba(c,a);Y=false;var d=c.constructor;function f(){if(!Y)d.apply(this,arguments)};c.constructor=f;f.extend=arguments.callee;ba(f,b);f.prototype=c;return f};z.prototype.extend=function(a){return ba(this,a)};var bo="#";var Z="~";var cs=/\\./g;var ct=/\(\?[:=!]|\[[^\]]+\]/g;var cu=/\(/g;var D=z.extend({constructor:function(a){this[Z]=[];this.merge(a)},exec:function(g){var h=this,p=this[Z];return String(g).replace(new RegExp(this,this.ignoreCase?"gi":"g"),function(){var a,b=1,c=0;while((a=h[bo+p[c++]])){var d=b+a.length+1;if(arguments[b]){var f=a.replacement;switch(typeof f){case"function":return f.apply(h,bC.call(arguments,b,d));case"number":return arguments[b+f];default:return f}}b=d}})},add:function(a,b){if(a instanceof RegExp){a=a.source}if(!this[bo+a])this[Z].push(String(a));this[bo+a]=new D.Item(a,b)},merge:function(a){for(var b in a)this.add(b,a[b])},toString:function(){return"("+this[Z].join(")|(")+")"}},{IGNORE:"$0",Item:z.extend({constructor:function(a,b){a=a instanceof RegExp?a.source:String(a);if(typeof b=="number")b=String(b);else if(b==null)b="";if(typeof b=="string"&&/\$(\d+)/.test(b)){if(/^\$\d+$/.test(b)){b=parseInt(b.slice(1))}else{var c=/'/.test(b.replace(/\\./g,""))?'"':"'";b=b.replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\$(\d+)/g,c+"+(arguments[$1]||"+c+c+")+"+c);b=new Function("return "+c+b.replace(/(['"])\1\+(.*)\+\1\1$/,"$1")+c)}}this.length=D.count(a);this.replacement=b;this.toString=bG(a)}}),count:function(a){a=String(a).replace(cs,"").replace(ct,"");return I(a,cu).length}});function ba(a,b){if(a&&b){var c=(typeof b=="function"?Function:Object).prototype;var d=bE.length,f;if(Y)while(f=bE[--d]){var g=b[f];if(g!=c[f]){if(bD.test(g)){bF(a,f,g)}else{a[f]=g}}}for(f in b)if(c[f]===undefined){var g=b[f];if(a[f]&&typeof g=="function"&&bD.test(g)){bF(a,f,g)}else{a[f]=g}}}return a};function bF(c,d,f){var g=c[d];c[d]=function(){var a=this.base;this.base=g;var b=f.apply(this,arguments);this.base=a;return b}};function cv(a,b){if(!b)b=a;var c={};for(var d in a)c[d]=b[d];return c};function i(c){var d=arguments;var f=new RegExp("%([1-"+arguments.length+"])","g");return String(c).replace(f,function(a,b){return b<d.length?d[b]:a})};function I(a,b){return String(a).match(b)||[]};function bb(a){return String(a).replace(cr,"\\$1")};function cK(a){return String(a).replace(cp,"").replace(cq,"")};function bG(a){return function(){return a}};var bH=D.extend({ignoreCase:true});var cw=/\x01(\d+)/g,cx=/'/g,cy=/^\x01/,cz=/\\([\da-fA-F]{1,4})/g;var bp=[];var cA=new bH({"<!\\-\\-|\\-\\->":"","\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\/":"","@(namespace|import)[^;\\n]+[;\\n]":"","'(\\\\.|[^'\\\\])*'":bJ,'"(\\\\.|[^"\\\\])*"':bJ,"\\s+":" "});function cB(a){return cA.exec(a)};function bI(c){return c.replace(cw,function(a,b){return bp[b-1]})};function bJ(c){return"\x01"+bp.push(c.replace(cz,function(a,b){return eval("'\\u"+"0000".slice(b.length)+b+"'")}).slice(1,-1).replace(cx,"\\'"))};function cC(a){return cy.test(a)?bp[a.slice(1)-1]:a};var cD=new D({Width:"Height",width:"height",Left:"Top",left:"top",Right:"Bottom",right:"bottom",onX:"onY"});function A(a){return cD.exec(a)};var bK=[];function bq(a){cF(a);w(window,"onresize",a)};function w(a,b,c){a.attachEvent(b,c);bK.push(arguments)};function cE(a,b,c){try{a.detachEvent(b,c)}catch(ignore){}};w(window,"onunload",function(){var a;while(a=bK.pop()){cE(a[0],a[1],a[2])}});function R(a,b,c){if(!a.elements)a.elements={};if(c)a.elements[b.uniqueID]=b;else delete a.elements[b.uniqueID];return c};w(window,"onbeforeprint",function(){if(!IE7.CSS.print)new bw("print");IE7.CSS.print.recalc()});var bL=/^\d+(px)?$/i;var J=/^\d+%$/;var E=function(a,b){if(bL.test(b))return parseInt(b);var c=a.style.left;var d=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;a.style.left=b||0;b=a.style.pixelLeft;a.style.left=c;a.runtimeStyle.left=d;return b};var br="ie7-";var bM=z.extend({constructor:function(){this.fixes=[];this.recalcs=[]},init:Q});var bs=[];function cF(a){bs.push(a)};IE7.recalc=function(){IE7.HTML.recalc();IE7.CSS.recalc();for(var a=0;a<bs.length;a++)bs[a]()};function bc(a){return a.currentStyle["ie7-position"]=="fixed"};function bt(a,b){return a.currentStyle[br+b]||a.currentStyle[b]};function K(a,b,c){if(a.currentStyle[br+b]==null){a.runtimeStyle[br+b]=a.currentStyle[b]}a.runtimeStyle[b]=c};function bN(a){var b=document.createElement(a||"object");b.style.cssText="position:absolute;padding:0;display:block;border:none;clip:rect(0 0 0 0);left:-9999";b.ie7_anon=true;return b};function B(a,b,c){if(!be[a]){F=[];var d="";var f=T.escape(a).split(",");for(var g=0;g<f.length;g++){o=m=x=0;S=f.length>1?2:0;var h=T.exec(f[g])||"if(0){";if(o){h+=i("if(e%1.nodeName!='!'){",m)}var p=S>1?bV:"";h+=i(p+bW,m);h+=Array(I(h,/\{/g).length+1).join("}");d+=h}eval(i(bX,F)+T.unescape(d)+"return s?null:r}");be[a]=_h}return be[a](b||document,c)};var bd=k<6;var bO=/^(href|src)$/;var bu={"class":"className","for":"htmlFor"};IE7._5=1;IE7._e=function(a,b){var c=a.all[b]||null;if(!c||c.id==b)return c;for(var d=0;d<c.length;d++){if(c[d].id==b)return c[d]}return null};IE7._f=function(a,b){if(b=="src"&&a.pngSrc)return a.pngSrc;var c=bd?(a.attributes[b]||a.attributes[bu[b.toLowerCase()]]):a.getAttributeNode(b);if(c&&(c.specified||b=="value")){if(bO.test(b)){return a.getAttribute(b,2)}else if(b=="class"){return a.className.replace(/\sie7_\w+/g,"")}else if(b=="style"){return a.style.cssText}else{return c.nodeValue}}return null};var bP="colSpan,rowSpan,vAlign,dateTime,accessKey,tabIndex,encType,maxLength,readOnly,longDesc";ba(bu,cv(bP.toLowerCase().split(","),bP.split(",")));IE7._a=function(a){while(a&&(a=a.nextSibling)&&(a.nodeType!=1||a.nodeName=="!"))continue;return a};IE7._b=function(a){while(a&&(a=a.previousSibling)&&(a.nodeType!=1||a.nodeName=="!"))continue;return a};var cG=/([\s>+~,]|[^(]\+|^)([#.:\[])/g,cH=/(^|,)([^\s>+~])/g,cI=/\s*([\s>+~(),]|^|$)\s*/g,bQ=/\s\*\s/g;var bR=D.extend({constructor:function(a){this.base(a);this.sorter=new D;this.sorter.add(/:not\([^)]*\)/,D.IGNORE);this.sorter.add(/([ >](\*|[\w-]+))([^: >+~]*)(:\w+-child(\([^)]+\))?)([^: >+~]*)/,"$1$3$6$4")},ignoreCase:true,escape:function(a){return this.optimise(this.format(a))},format:function(a){return a.replace(cI,"$1").replace(cH,"$1 $2").replace(cG,"$1*$2")},optimise:function(a){return this.sorter.exec(a.replace(bQ,">* "))},unescape:function(a){return bI(a)}});var bS={"":"%1!=null","=":"%1=='%2'","~=":/(^| )%1( |$)/,"|=":/^%1(-|$)/,"^=":/^%1/,"$=":/%1$/,"*=":/%1/};var bT={"first-child":"!IE7._b(e%1)","link":"e%1.currentStyle['ie7-link']=='link'","visited":"e%1.currentStyle['ie7-link']=='visited'"};var bv="var p%2=0,i%2,e%2,n%2=e%1.";var bU="e%1.sourceIndex";var bV="var g="+bU+";if(!p[g]){p[g]=1;";var bW="r[r.length]=e%1;if(s)return e%1;";var bX="var _h=function(e0,s){IE7._5++;var r=[],p={},reg=[%1],d=document;";var F;var m;var o;var x;var S;var be={};var T=new bR({" (\\*|[\\w-]+)#([\\w-]+)":function(a,b,c){o=false;var d="var e%2=IE7._e(d,'%4');if(e%2&&";if(b!="*")d+="e%2.nodeName=='%3'&&";d+="(e%1==d||e%1.contains(e%2))){";if(x)d+=i("i%1=n%1.length;",x);return i(d,m++,m,b.toUpperCase(),c)}," (\\*|[\\w-]+)":function(a,b){S++;o=b=="*";var c=bv;c+=(o&&bd)?"all":"getElementsByTagName('%3')";c+=";for(i%2=0;(e%2=n%2[i%2]);i%2++){";return i(c,m++,x=m,b.toUpperCase())},">(\\*|[\\w-]+)":function(a,b){var c=x;o=b=="*";var d=bv;d+=c?"children":"childNodes";if(!o&&c)d+=".tags('%3')";d+=";for(i%2=0;(e%2=n%2[i%2]);i%2++){";if(o){d+="if(e%2.nodeType==1){";o=bd}else{if(!c)d+="if(e%2.nodeName=='%3'){"}return i(d,m++,x=m,b.toUpperCase())},"\\+(\\*|[\\w-]+)":function(a,b){var c="";if(o)c+="if(e%1.nodeName!='!'){";o=false;c+="e%1=IE7._a(e%1);if(e%1";if(b!="*")c+="&&e%1.nodeName=='%2'";c+="){";return i(c,m,b.toUpperCase())},"~(\\*|[\\w-]+)":function(a,b){var c="";if(o)c+="if(e%1.nodeName!='!'){";o=false;S=2;c+="while(e%1=e%1.nextSibling){if(e%1.ie7_adjacent==IE7._5)break;if(";if(b=="*"){c+="e%1.nodeType==1";if(bd)c+="&&e%1.nodeName!='!'"}else c+="e%1.nodeName=='%2'";c+="){e%1.ie7_adjacent=IE7._5;";return i(c,m,b.toUpperCase())},"#([\\w-]+)":function(a,b){o=false;var c="if(e%1.id=='%2'){";if(x)c+=i("i%1=n%1.length;",x);return i(c,m,b)},"\\.([\\w-]+)":function(a,b){o=false;F.push(new RegExp("(^|\\s)"+bb(b)+"(\\s|$)"));return i("if(e%1.className&&reg[%2].test(e%1.className)){",m,F.length-1)},"\\[([\\w-]+)\\s*([^=]?=)?\\s*([^\\]]*)\\]":function(a,b,c,d){var f=bu[b]||b;if(c){var g="e%1.getAttribute('%2',2)";if(!bO.test(b)){g="e%1.%3||"+g}b=i("("+g+")",m,b,f)}else{b=i("IE7._f(e%1,'%2')",m,b)}var h=bS[c||""]||"0";if(h&&h.source){F.push(new RegExp(i(h.source,bb(T.unescape(d)))));h="reg[%2].test(%1)";d=F.length-1}return"if("+i(h,b,d)+"){"},":+([\\w-]+)(\\(([^)]+)\\))?":function(a,b,c,d){b=bT[b];return"if("+(b?i(b,m,d||""):"0")+"){"}});var bY=/a(#[\w-]+)?(\.[\w-]+)?:(hover|active)/i;var bZ=/\s*\{\s*/,ca=/\s*\}\s*/,cb=/\s*\,\s*/;var cc=/(.*)(:first-(line|letter))/;var y=document.styleSheets;IE7.CSS=new(bM.extend({parser:new bH,screen:"",print:"",styles:[],rules:[],pseudoClasses:k<7?"first\\-child":"",dynamicPseudoClasses:{toString:function(){var a=[];for(var b in this)a.push(b);return a.join("|")}},init:function(){var a="^\x01$";var b="\\[class=?[^\\]]*\\]";var c=[];if(this.pseudoClasses)c.push(this.pseudoClasses);var d=this.dynamicPseudoClasses.toString();if(d)c.push(d);c=c.join("|");var f=k<7?["[>+~[(]|([:.])\\w+\\1"]:[b];if(c)f.push(":("+c+")");this.UNKNOWN=new RegExp(f.join("|")||a,"i");var g=k<7?["\\[[^\\]]+\\]|[^\\s(\\[]+\\s*[+~]"]:[b];var h=g.concat();if(c)h.push(":("+c+")");n.COMPLEX=new RegExp(h.join("|")||a,"ig");if(this.pseudoClasses)g.push(":("+this.pseudoClasses+")");L.COMPLEX=new RegExp(g.join("|")||a,"i");L.MATCH=new RegExp(d?"(.*):("+d+")(.*)":a,"i");this.createStyleSheet();this.refresh()},addEventHandler:function(){w.apply(null,arguments)},addFix:function(a,b){this.parser.add(a,b)},addRecalc:function(c,d,f,g){d=new RegExp("([{;\\s])"+c+"\\s*:\\s*"+d+"[^;}]*");var h=this.recalcs.length;if(g)g=c+":"+g;this.addFix(d,function(a,b){return(g?b+g:a)+";ie7-"+a.slice(1)+";ie7_recalc"+h+":1"});this.recalcs.push(arguments);return h},apply:function(){this.getInlineStyles();new bw("screen");this.trash()},createStyleSheet:function(){this.styleSheet=document.createStyleSheet();this.styleSheet.ie7=true;this.styleSheet.owningElement.ie7=true;this.styleSheet.cssText=G},getInlineStyles:function(){var a=document.getElementsByTagName("style"),b;for(var c=a.length-1;(b=a[c]);c--){if(!b.disabled&&!b.ie7){this.styles.push(b.innerHTML)}}},getText:function(a,b){try{var c=a.cssText}catch(e){c=""}if(H)c=cl(a.href,b)||c;return c},recalc:function(){this.screen.recalc();var a=/ie7_recalc\d+/g;var b=G.match(/[{,]/g).length;var c=b+(this.screen.cssText.match(/\{/g)||"").length;var d=this.styleSheet.rules,f;var g,h,p,t,q,j,u,l;for(q=b;q<c;q++){f=d[q];var r=f.style.cssText;if(f&&(g=r.match(a))){p=B(f.selectorText);if(p.length)for(j=0;j<g.length;j++){l=g[j];h=IE7.CSS.recalcs[l.slice(10)][2];for(u=0;(t=p[u]);u++){if(t.currentStyle[l])h(t,r)}}}}},refresh:function(){this.styleSheet.cssText=G+this.screen+this.print},trash:function(){for(var a=0;a<y.length;a++){if(!y[a].ie7){try{var b=y[a].cssText}catch(e){b=""}if(b)y[a].cssText=""}}}}));var bw=z.extend({constructor:function(a){this.media=a;this.load();IE7.CSS[a]=this;IE7.CSS.refresh()},createRule:function(a,b){if(IE7.CSS.UNKNOWN.test(a)){var c;if(bf&&(c=a.match(bf.MATCH))){return new bf(c[1],c[2],b)}else if(c=a.match(L.MATCH)){if(!bY.test(c[0])||L.COMPLEX.test(c[0])){return new L(a,c[1],c[2],c[3],b)}}else return new n(a,b)}return a+" {"+b+"}"},getText:function(){var h=[].concat(IE7.CSS.styles);var p=/@media\s+([^{]*)\{([^@]+\})\s*\}/gi;var t=/\ball\b|^$/i,q=/\bscreen\b/i,j=/\bprint\b/i;function u(a,b){l.value=b;return a.replace(p,l)};function l(a,b,c){b=r(b);switch(b){case"screen":case"print":if(b!=l.value)return"";case"all":return c}return""};function r(a){if(t.test(a))return"all";else if(q.test(a))return(j.test(a))?"all":"screen";else if(j.test(a))return"print"};var N=this;function O(a,b,c,d){var f="";if(!d){c=r(a.media);d=0}if(c=="all"||c==N.media){if(d<3){for(var g=0;g<a.imports.length;g++){f+=O(a.imports[g],bn(a.href,b),c,d+1)}}f+=cB(a.href?cg(a,b):h.pop()||"");f=u(f,N.media)}return f};var bl={};function cg(a,b){var c=W(a.href,b);if(bl[c])return"";bl[c]=(a.disabled)?"":ci(IE7.CSS.getText(a,b),bn(a.href,b));return bl[c]};var ch=/(url\s*\(\s*['"]?)([\w\.]+[^:\)]*['"]?\))/gi;function ci(a,b){return a.replace(ch,"$1"+b.slice(0,b.lastIndexOf("/")+1)+"$2")};for(var P=0;P<y.length;P++){if(!y[P].disabled&&!y[P].ie7){this.cssText+=O(y[P])}}},load:function(){this.cssText="";this.getText();this.parse();this.cssText=bI(this.cssText);X={}},parse:function(){this.cssText=IE7.CSS.parser.exec(this.cssText);var a=IE7.CSS.rules.length;var b=this.cssText.split(ca),c;var d,f,g,h;for(g=0;g<b.length;g++){c=b[g].split(bZ);d=c[0].split(cb);f=c[1];for(h=0;h<d.length;h++){d[h]=f?this.createRule(d[h],f):""}b[g]=d.join("\n")}this.cssText=b.join("\n");this.rules=IE7.CSS.rules.slice(a)},recalc:function(){var a,b;for(b=0;(a=this.rules[b]);b++)a.recalc()},toString:function(){return"@media "+this.media+"{"+this.cssText+"}"}});var bf;var n=IE7.Rule=z.extend({constructor:function(a,b){this.id=IE7.CSS.rules.length;this.className=n.PREFIX+this.id;a=a.match(cc)||a||"*";this.selector=a[1]||a;this.selectorText=this.parse(this.selector)+(a[2]||"");this.cssText=b;this.MATCH=new RegExp("\\s"+this.className+"(\\s|$)","g");IE7.CSS.rules.push(this);this.init()},init:Q,add:function(a){a.className+=" "+this.className},recalc:function(){var a=B(this.selector);for(var b=0;b<a.length;b++)this.add(a[b])},parse:function(a){var b=a.replace(n.CHILD," ").replace(n.COMPLEX,"");if(k<7)b=b.replace(n.MULTI,"");var c=I(b,n.TAGS).length-I(a,n.TAGS).length;var d=I(b,n.CLASSES).length-I(a,n.CLASSES).length+1;while(d>0&&n.CLASS.test(b)){b=b.replace(n.CLASS,"");d--}while(c>0&&n.TAG.test(b)){b=b.replace(n.TAG,"$1*");c--}b+="."+this.className;d=Math.min(d,2);c=Math.min(c,2);var f=-10*d-c;if(f>0){b=b+","+n.MAP[f]+" "+b}return b},remove:function(a){a.className=a.className.replace(this.MATCH,"$1")},toString:function(){return i("%1 {%2}",this.selectorText,this.cssText)}},{CHILD:/>/g,CLASS:/\.[\w-]+/,CLASSES:/[.:\[]/g,MULTI:/(\.[\w-]+)+/g,PREFIX:"ie7_class",TAG:/^\w+|([\s>+~])\w+/,TAGS:/^\w|[\s>+~]\w/g,MAP:{1:"html",2:"html body",10:".ie7_html",11:"html.ie7_html",12:"html.ie7_html body",20:".ie7_html .ie7_body",21:"html.ie7_html .ie7_body",22:"html.ie7_html body.ie7_body"}});var L=n.extend({constructor:function(a,b,c,d,f){this.attach=b||"*";this.dynamicPseudoClass=IE7.CSS.dynamicPseudoClasses[c];this.target=d;this.base(a,f)},recalc:function(){var a=B(this.attach),b;for(var c=0;b=a[c];c++){var d=this.target?B(this.target,b):[b];if(d.length)this.dynamicPseudoClass.apply(b,d,this)}}});var cd=z.extend({constructor:function(a,b){this.name=a;this.apply=b;this.instances={};IE7.CSS.dynamicPseudoClasses[a]=this},register:function(a){var b=a[2];a.id=b.id+a[0].uniqueID;if(!this.instances[a.id]){var c=a[1],d;for(d=0;d<c.length;d++)b.add(c[d]);this.instances[a.id]=a}},unregister:function(a){if(this.instances[a.id]){var b=a[2];var c=a[1],d;for(d=0;d<c.length;d++)b.remove(c[d]);delete this.instances[a.id]}}});if(k<7){var U=new cd("hover",function(a){var b=arguments;IE7.CSS.addEventHandler(a,k<5.5?"onmouseover":"onmouseenter",function(){U.register(b)});IE7.CSS.addEventHandler(a,k<5.5?"onmouseout":"onmouseleave",function(){U.unregister(b)})});w(document,"onmouseup",function(){var a=U.instances;for(var b in a)if(!a[b][0].contains(event.srcElement))U.unregister(a[b])})}IE7.HTML=new(bM.extend({fixed:{},init:Q,addFix:function(){this.fixes.push(arguments)},apply:function(){for(var a=0;a<this.fixes.length;a++){var b=B(this.fixes[a][0]);var c=this.fixes[a][1];for(var d=0;d<b.length;d++)c(b[d])}},addRecalc:function(){this.recalcs.push(arguments)},recalc:function(){for(var a=0;a<this.recalcs.length;a++){var b=B(this.recalcs[a][0]);var c=this.recalcs[a][1],d;var f=Math.pow(2,a);for(var g=0;(d=b[g]);g++){var h=d.uniqueID;if((this.fixed[h]&f)==0){d=c(d)||d;this.fixed[h]|=f}}}}}));if(k<7){document.createElement("abbr");IE7.HTML.addRecalc("label",function(a){if(!a.htmlFor){var b=B("input,textarea",a,true);if(b){w(a,"onclick",function(){b.click()})}}})}var V="[.\\d]";new function(_){var layout=IE7.Layout=this;G+="*{boxSizing:content-box}";IE7.hasLayout=k<5.5?function(a){return a.clientWidth}:function(a){return a.currentStyle.hasLayout};layout.boxSizing=function(a){if(!IE7.hasLayout(a)){a.style.height="0cm";if(a.currentStyle.verticalAlign=="auto")a.runtimeStyle.verticalAlign="top";collapseMargins(a)}};function collapseMargins(a){if(a!=s&&a.currentStyle.position!="absolute"){collapseMargin(a,"marginTop");collapseMargin(a,"marginBottom")}};function collapseMargin(a,b){if(!a.runtimeStyle[b]){var c=a.parentElement;if(c&&IE7.hasLayout(c)&&!IE7[b=="marginTop"?"_b":"_a"](a))return;var d=B(">*:"+(b=="marginTop"?"first":"last")+"-child",a,true);if(d&&d.currentStyle.styleFloat=="none"&&IE7.hasLayout(d)){collapseMargin(d,b);margin=_9(a,a.currentStyle[b]);childMargin=_9(d,d.currentStyle[b]);if(margin<0||childMargin<0){a.runtimeStyle[b]=margin+childMargin}else{a.runtimeStyle[b]=Math.max(childMargin,margin)}d.runtimeStyle[b]="0px"}}};function _9(a,b){return b=="auto"?0:E(a,b)};var UNIT=/^[.\d][\w%]*$/,AUTO=/^(auto|0cm)$/;var applyWidth,applyHeight;IE7.Layout.borderBox=function(a){applyWidth(a);applyHeight(a)};var fixWidth=function(g){applyWidth=function(a){if(!J.test(a.currentStyle.width))h(a);collapseMargins(a)};function h(a,b){if(!a.runtimeStyle.fixedWidth){if(!b)b=a.currentStyle.width;a.runtimeStyle.fixedWidth=(UNIT.test(b))?Math.max(0,q(a,b)):b;K(a,"width",a.runtimeStyle.fixedWidth)}};function p(a){if(!bc(a)){var b=a.offsetParent;while(b&&!IE7.hasLayout(b))b=b.offsetParent}return(b||s).clientWidth};function t(a,b){if(J.test(b))return parseInt(parseFloat(b)/100*p(a));return E(a,b)};var q=function(a,b){var c=a.currentStyle["box-sizing"]=="border-box";var d=0;if(C&&!c)d+=j(a)+u(a,"padding");else if(!C&&c)d-=j(a)+u(a,"padding");return t(a,b)+d};function j(a){return a.offsetWidth-a.clientWidth};function u(a,b){return t(a,a.currentStyle[b+"Left"])+t(a,a.currentStyle[b+"Right"])};G+="*{minWidth:none;maxWidth:none;min-width:none;max-width:none}";layout.minWidth=function(a){if(a.currentStyle["min-width"]!=null){a.style.minWidth=a.currentStyle["min-width"]}if(R(arguments.callee,a,a.currentStyle.minWidth!="none")){layout.boxSizing(a);h(a);l(a)}};eval("IE7.Layout.maxWidth="+String(layout.minWidth).replace(/min/g,"max"));function l(a){var b=a.getBoundingClientRect();var c=b.right-b.left;if(a.currentStyle.minWidth!="none"&&c<=q(a,a.currentStyle.minWidth)){a.runtimeStyle.width=a.currentStyle.minWidth}else if(a.currentStyle.maxWidth!="none"&&c>=q(a,a.currentStyle.maxWidth)){a.runtimeStyle.width=a.currentStyle.maxWidth}else{a.runtimeStyle.width=a.runtimeStyle.fixedWidth}};function r(a){if(R(r,a,/^(fixed|absolute)$/.test(a.currentStyle.position)&&bt(a,"left")!="auto"&&bt(a,"right")!="auto"&&AUTO.test(bt(a,"width")))){N(a);IE7.Layout.boxSizing(a)}};IE7.Layout.fixRight=r;function N(a){var b=t(a,a.runtimeStyle._c||a.currentStyle.left);var c=p(a)-t(a,a.currentStyle.right)-b-u(a,"margin");if(parseInt(a.runtimeStyle.width)==c)return;a.runtimeStyle.width="";if(bc(a)||g||a.offsetWidth<c){if(!C)c-=j(a)+u(a,"padding");if(c<0)c=0;a.runtimeStyle.fixedWidth=c;K(a,"width",c)}};var O=0;bq(function(){if(!s)return;var a,b=(O<s.clientWidth);O=s.clientWidth;var c=layout.minWidth.elements;for(a in c){var d=c[a];var f=(parseInt(d.runtimeStyle.width)==q(d,d.currentStyle.minWidth));if(b&&f)d.runtimeStyle.width="";if(b==f)l(d)}var c=layout.maxWidth.elements;for(a in c){var d=c[a];var f=(parseInt(d.runtimeStyle.width)==q(d,d.currentStyle.maxWidth));if(!b&&f)d.runtimeStyle.width="";if(b!=f)l(d)}for(a in r.elements)N(r.elements[a])});if(C){IE7.CSS.addRecalc("width",V,applyWidth)}if(k<7){IE7.CSS.addRecalc("min-width",V,layout.minWidth);IE7.CSS.addRecalc("max-width",V,layout.maxWidth);IE7.CSS.addRecalc("right",V,r)}};eval("var fixHeight="+A(fixWidth));fixWidth();fixHeight(true)};var bg=W("blank.gif",ck);var bh="DXImageTransform.Microsoft.AlphaImageLoader";var bx="progid:"+bh+"(src='%1',sizingMethod='%2')";var bi;var M=[];function by(a){if(bi.test(a.src)){var b=new Image(a.width,a.height);b.onload=function(){a.width=b.width;a.height=b.height;b=null};b.src=a.src;a.pngSrc=a.src;bz(a)}};if(k>=5.5&&k<7){IE7.CSS.addFix(/background(-image)?\s*:\s*([^};]*)?url\(([^\)]+)\)([^;}]*)?/,function(a,b,c,d,f){d=cC(d);return bi.test(d)?"filter:"+i(bx,d,"crop")+";zoom:1;background"+(b||"")+":"+(c||"")+"none"+(f||""):a});IE7.HTML.addRecalc("img,input",function(a){if(a.tagName=="INPUT"&&a.type!="image")return;by(a);w(a,"onpropertychange",function(){if(!bj&&event.propertyName=="src"&&a.src.indexOf(bg)==-1)by(a)})});var bj=false;w(window,"onbeforeprint",function(){bj=true;for(var a=0;a<M.length;a++)ce(M[a])});w(window,"onafterprint",function(){for(var a=0;a<M.length;a++)bz(M[a]);bj=false})}function bz(a,b){var c=a.filters[bh];if(c){c.src=a.src;c.enabled=true}else{a.runtimeStyle.filter=i(bx,a.src,b||"scale");M.push(a)}a.src=bg};function ce(a){a.src=a.pngSrc;a.filters[bh].enabled=false};new function(_){if(k>=7)return;IE7.CSS.addRecalc("position","fixed",_6,"absolute");IE7.CSS.addRecalc("background(-attachment)?","[^};]*fixed",_2);var $viewport=C?"body":"documentElement";function _3(){if(v.currentStyle.backgroundAttachment!="fixed"){if(v.currentStyle.backgroundImage=="none"){v.runtimeStyle.backgroundRepeat="no-repeat";v.runtimeStyle.backgroundImage="url("+bg+")"}v.runtimeStyle.backgroundAttachment="fixed"}_3=Q};var _0=bN("img");function _1(a){return a?bc(a)||_1(a.parentElement):false};function _d(a,b,c){setTimeout("document.all."+a.uniqueID+".runtimeStyle.setExpression('"+b+"','"+c+"')",0)};function _2(a){if(R(_2,a,a.currentStyle.backgroundAttachment=="fixed"&&!a.contains(v))){_3();bgLeft(a);bgTop(a);_8(a)}};function _8(a){_0.src=a.currentStyle.backgroundImage.slice(5,-2);var b=a.canHaveChildren?a:a.parentElement;b.appendChild(_0);setOffsetLeft(a);setOffsetTop(a);b.removeChild(_0)};function bgLeft(a){a.style.backgroundPositionX=a.currentStyle.backgroundPositionX;if(!_1(a)){_d(a,"backgroundPositionX","(parseInt(runtimeStyle.offsetLeft)+document."+$viewport+".scrollLeft)||0")}};eval(A(bgLeft));function setOffsetLeft(a){var b=_1(a)?"backgroundPositionX":"offsetLeft";a.runtimeStyle[b]=getOffsetLeft(a,a.style.backgroundPositionX)-a.getBoundingClientRect().left-a.clientLeft+2};eval(A(setOffsetLeft));function getOffsetLeft(a,b){switch(b){case"left":case"top":return 0;case"right":case"bottom":return s.clientWidth-_0.offsetWidth;case"center":return(s.clientWidth-_0.offsetWidth)/2;default:if(J.test(b)){return parseInt((s.clientWidth-_0.offsetWidth)*parseFloat(b)/100)}_0.style.left=b;return _0.offsetLeft}};eval(A(getOffsetLeft));function _6(a){if(R(_6,a,bc(a))){K(a,"position","absolute");K(a,"left",a.currentStyle.left);K(a,"top",a.currentStyle.top);_3();IE7.Layout.fixRight(a);_4(a)}};function _4(a,b){positionTop(a,b);positionLeft(a,b,true);if(!a.runtimeStyle.autoLeft&&a.currentStyle.marginLeft=="auto"&&a.currentStyle.right!="auto"){var c=s.clientWidth-getPixelWidth(a,a.currentStyle.right)-getPixelWidth(a,a.runtimeStyle._c)-a.clientWidth;if(a.currentStyle.marginRight=="auto")c=parseInt(c/2);if(_1(a.offsetParent))a.runtimeStyle.pixelLeft+=c;else a.runtimeStyle.shiftLeft=c}clipWidth(a);clipHeight(a)};function clipWidth(a){var b=a.runtimeStyle.fixWidth;a.runtimeStyle.borderRightWidth="";a.runtimeStyle.width=b?getPixelWidth(a,b):"";if(a.currentStyle.width!="auto"){var c=a.getBoundingClientRect();var d=a.offsetWidth-s.clientWidth+c.left-2;if(d>=0){a.runtimeStyle.borderRightWidth="0px";d=Math.max(E(a,a.currentStyle.width)-d,0);K(a,"width",d);return d}}};eval(A(clipWidth));function positionLeft(a,b){if(!b&&J.test(a.currentStyle.width)){a.runtimeStyle.fixWidth=a.currentStyle.width}if(a.runtimeStyle.fixWidth){a.runtimeStyle.width=getPixelWidth(a,a.runtimeStyle.fixWidth)}a.runtimeStyle.shiftLeft=0;a.runtimeStyle._c=a.currentStyle.left;a.runtimeStyle.autoLeft=a.currentStyle.right!="auto"&&a.currentStyle.left=="auto";a.runtimeStyle.left="";a.runtimeStyle.screenLeft=getScreenLeft(a);a.runtimeStyle.pixelLeft=a.runtimeStyle.screenLeft;if(!b&&!_1(a.offsetParent)){_d(a,"pixelLeft","runtimeStyle.screenLeft+runtimeStyle.shiftLeft+document."+$viewport+".scrollLeft")}};eval(A(positionLeft));function getScreenLeft(a){var b=a.offsetLeft,c=1;if(a.runtimeStyle.autoLeft){b=s.clientWidth-a.offsetWidth-getPixelWidth(a,a.currentStyle.right)}if(a.currentStyle.marginLeft!="auto"){b-=getPixelWidth(a,a.currentStyle.marginLeft)}while(a=a.offsetParent){if(a.currentStyle.position!="static")c=-1;b+=a.offsetLeft*c}return b};eval(A(getScreenLeft));function getPixelWidth(a,b){return J.test(b)?parseInt(parseFloat(b)/100*s.clientWidth):E(a,b)};eval(A(getPixelWidth));function _g(){var a=_2.elements;for(var b in a)_8(a[b]);a=_6.elements;for(b in a){_4(a[b],true);_4(a[b],true)}_7=0};var _7;bq(function(){if(!_7)_7=setTimeout(_g,0)})};var bk={backgroundColor:"transparent",backgroundImage:"none",backgroundPositionX:null,backgroundPositionY:null,backgroundRepeat:null,borderTopWidth:0,borderRightWidth:0,borderBottomWidth:0,borderLeftStyle:"none",borderTopStyle:"none",borderRightStyle:"none",borderBottomStyle:"none",borderLeftWidth:0,height:null,marginTop:0,marginBottom:0,marginRight:0,marginLeft:0,width:"100%"};IE7.CSS.addRecalc("overflow","visible",function(a){if(a.parentNode.ie7_wrapped)return;if(IE7.Layout&&a.currentStyle["max-height"]!="auto"){IE7.Layout.maxHeight(a)}if(a.currentStyle.marginLeft=="auto")a.style.marginLeft=0;if(a.currentStyle.marginRight=="auto")a.style.marginRight=0;var b=document.createElement(bA);b.ie7_wrapped=a;for(var c in bk){b.style[c]=a.currentStyle[c];if(bk[c]!=null){a.runtimeStyle[c]=bk[c]}}b.style.display="block";b.style.position="relative";a.runtimeStyle.position="absolute";a.parentNode.insertBefore(b,a);b.appendChild(a)});function cf(){var f="xx-small,x-small,small,medium,large,x-large,xx-large".split(",");for(var g=0;g<f.length;g++){f[f[g]]=f[g-1]||"0.67em"}IE7.CSS.addFix(/(font(-size)?\s*:\s*)([\w.-]+)/,function(a,b,c,d){return b+(f[d]||d)});if(k<6){var h=/^\-/,p=/(em|ex)$/i;var t=/em$/i,q=/ex$/i;E=function(a,b){if(bL.test(b))return parseInt(b)||0;var c=h.test(b)?-1:1;if(p.test(b))c*=u(a);j.style.width=(c<0)?b.slice(1):b;v.appendChild(j);b=c*j.offsetWidth;j.removeNode();return parseInt(b)};var j=bN();function u(a){var b=1;j.style.fontFamily=a.currentStyle.fontFamily;j.style.lineHeight=a.currentStyle.lineHeight;while(a!=v){var c=a.currentStyle["ie7-font-size"];if(c){if(t.test(c))b*=parseFloat(c);else if(J.test(c))b*=(parseFloat(c)/100);else if(q.test(c))b*=(parseFloat(c)/2);else{j.style.fontSize=c;return 1}}a=a.parentElement}return b};IE7.CSS.addFix(/cursor\s*:\s*pointer/,"cursor:hand");IE7.CSS.addFix(/display\s*:\s*list-item/,"display:block")}function l(a){if(k<5.5)IE7.Layout.boxSizing(a.parentElement);var b=a.parentElement;var c=b.offsetWidth-a.offsetWidth-r(b);var d=(a.currentStyle["ie7-margin"]&&a.currentStyle.marginRight=="auto")||a.currentStyle["ie7-margin-right"]=="auto";switch(b.currentStyle.textAlign){case"right":c=d?parseInt(c/2):0;a.runtimeStyle.marginRight=c+"px";break;case"center":if(d)c=0;default:if(d)c/=2;a.runtimeStyle.marginLeft=parseInt(c)+"px"}};function r(a){return E(a,a.currentStyle.paddingLeft)+E(a,a.currentStyle.paddingRight)};IE7.CSS.addRecalc("margin(-left|-right)?","[^};]*auto",function(a){if(R(l,a,a.parentElement&&a.currentStyle.display=="block"&&a.currentStyle.marginLeft=="auto"&&a.currentStyle.position!="absolute")){l(a)}});bq(function(){for(var a in l.elements){var b=l.elements[a];b.runtimeStyle.marginLeft=b.runtimeStyle.marginRight="";l(b)}})};IE7.loaded=true;(function(){try{bm.doScroll("left")}catch(e){setTimeout(arguments.callee,1);return}try{eval(bB.innerHTML)}catch(e){}bi=new RegExp(bb(typeof IE7_PNG_SUFFIX=="string"?IE7_PNG_SUFFIX:"-trans.png")+"$","i");v=document.body;s=C?v:bm;v.className+=" ie7_body";bm.className+=" ie7_html";if(C)cf();IE7.CSS.init();IE7.HTML.init();IE7.HTML.apply();IE7.CSS.apply();IE7.recalc()})()})();
@@ -1,94 +0,0 @@
1
- /**** Default styling for Rapid ****/
2
-
3
- #ajax_progress {
4
- color: gray;
5
- float: right;
6
- margin: 20px;
7
- position: fixed;
8
- background: white;
9
- font-family: tahoma, sans-serif;
10
- display: none;
11
- z-index: 10;
12
- }
13
-
14
- #ajax_progress div {
15
- margin: 10px;
16
- padding: 3px;
17
- /* padding-top: -15px;*/
18
- }
19
-
20
- #ajax_progress img {
21
- padding-left: 6px;
22
- vertical-align: middle;
23
- }
24
-
25
-
26
- /* Scriptaculous Autocompleter ---*/
27
-
28
- div.completions_popup {
29
- position:absolute;
30
- width:250px;
31
- background-color:white;
32
- border:1px solid #888;
33
- margin:0px;
34
- padding:0px;
35
- z-index:100;
36
- }
37
- div.completions_popup ul {
38
- list-style-type:none;
39
- margin:0px;
40
- padding:0px;
41
- }
42
- div.completions_popup ul li.selected { background-color: #ffb;}
43
- div.completions_popup ul li {
44
- list-style-type:none;
45
- display:block;
46
- margin:0;
47
- padding:2px;
48
- cursor:pointer;
49
- }
50
-
51
-
52
- .field_list { width:95%; }
53
- .field_list td { padding: 5px; vertical-align: middle; }
54
- .field_list td.field_label {
55
- text-align: left; width: 1px; white-space: nowrap; vertical-align: top;
56
- padding-top: 10px; padding-bottom: 10px;
57
- }
58
- .field_list input[type=text] { width: 100%; }
59
- .field_list input, .field_list textarea { margin: -2px 0 0 0; }
60
- .field_list textarea { width: 100%; margin: 0; }
61
- /*
62
- td span.in_place_textfield_bhv, td span.in_place_textarea_bhv, td span.in_place_html_textarea_bhv {
63
- display: block; border: 1px solid #ddd;
64
- padding: 4px; background: #fafafa;
65
- }
66
- */
67
- table.login-table, table.login-table td {border: none;}
68
- .login_table td.field_label { vertical-align: middle; }
69
- /*table.login-table input {font-size: 16px; color: black;}*/
70
-
71
- input[type=text].wide { width: 100%; }
72
- textarea { height: 200px; }
73
- textarea.wide { width: 100%; }
74
- textarea.tall { height: 350px; }
75
-
76
- .field_list input.percentage {width: 25px; display: inline; margin-right: 5px; padding: 1px 3px;}
77
-
78
- /* rails error message */
79
- .error_messages {
80
- font-family: "Lucida Grande", arial, sans-serif;
81
- background: #9d0018;
82
- border: 1px solid #7a0013;
83
- padding: 20px;
84
- color: white;
85
- margin-bottom: 20px;
86
- }
87
- .error_messages h2 {
88
- text-transform: none;
89
- letter-spacing: normal;
90
- color: white;
91
- }
92
- .error_messages li {
93
- margin-left: 20px;
94
- }
@@ -1,1015 +0,0 @@
1
- Object.extend = function(destination) {
2
- $A(arguments).slice(1).each(function (src) {
3
- for (var property in src) {
4
- destination[property] = src[property];
5
- }
6
- })
7
- return destination
8
- }
9
-
10
- Object.merge = function() {
11
- return Object.extend.apply(this, [{}].concat($A(arguments)))
12
- }
13
-
14
- var Hobo = {
15
-
16
- searchRequest: null,
17
- uidCounter: 0,
18
- ipeOldValues: {},
19
- spinnerMinTime: 500, // milliseconds
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 = Hobo.getClassData(el, 'update')
29
- return updates ? updates.split(':') : []
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
- params = params + '&_method=PUT'
38
-
39
- var opts = Object.merge(options || {}, { params: params, message: el.getAttribute("hobo-ajax-message")})
40
- Hobo.ajaxRequest(Hobo.putUrl(el), updates, opts)
41
- },
42
-
43
- ajaxUpdateParams: function(updates, resultUpdates) {
44
- var params = []
45
- var i = 0
46
- if (updates.length > 0) {
47
- updates.each(function(id_or_el) {
48
- var el = $(id_or_el)
49
- if (el) { // ignore update of parts that do not exist
50
- var partDomId = el.id
51
- if (!hoboParts[partDomId]) { throw "Update of dom-id that is not a part: " + partDomId }
52
- params.push("render["+i+"][part_context]=" + encodeURIComponent(hoboParts[partDomId]))
53
- params.push("render["+i+"][id]=" + partDomId)
54
- i += 1
55
- }
56
- })
57
- params.push("page_path=" + encodeURIComponent(hoboPagePath))
58
- }
59
-
60
- if (resultUpdates) {
61
- resultUpdates.each(function (resultUpdate) {
62
- params.push("render["+i+"][id]=" + resultUpdate.id)
63
- params.push("render["+i+"][result]=" + resultUpdate.result)
64
- if (resultUpdate.func) {
65
- params.push("render["+i+"][function]=" + resultUpdate.func)
66
- }
67
- i += 1
68
- })
69
- }
70
- return params.join('&')
71
- },
72
-
73
- ajaxRequest: function(url_or_form, updates, options) {
74
- options = Object.merge({ asynchronous:true,
75
- evalScripts:true,
76
- resetForm: false,
77
- refocusForm: false,
78
- message: "Saving..."
79
- }, options)
80
- if (typeof url_or_form == "string") {
81
- var url = url_or_form
82
- var form = false
83
- } else {
84
- var form = url_or_form
85
- var url = form.action
86
- }
87
- var params = []
88
-
89
- if (typeof(formAuthToken) != "undefined") {
90
- params.push(formAuthToken.name + "=" + formAuthToken.value)
91
- }
92
-
93
- updateParams = Hobo.ajaxUpdateParams(updates, options.resultUpdate)
94
- if (updateParams != "") { params.push(updateParams) }
95
-
96
- if (options.params) {
97
- params.push(options.params)
98
- delete options.params
99
- }
100
-
101
- if (form) {
102
- params.push(Form.serialize(form))
103
- }
104
-
105
- if (options.message != false) Hobo.showSpinner(options.message, options.spinnerNextTo)
106
-
107
- var complete = function() {
108
- if (options.message != false) Hobo.hideSpinner();
109
- if (options.onComplete) options.onComplete.apply(this, arguments)
110
- if (form && options.refocusForm) Form.focusFirstElement(form)
111
- Event.addBehavior.reload()
112
- }
113
- var success = function() {
114
- if (options.onSuccess) options.onSuccess.apply(this, arguments)
115
- if (form && options.resetForm) form.reset();
116
- }
117
- if (options.method && options.method.toLowerCase() == "put") {
118
- delete options.method
119
- params.push("_method=PUT")
120
- }
121
-
122
- if (!options.onFailure) {
123
- options.onFailure = function(response) {
124
- alert(response.responseText)
125
- }
126
- }
127
-
128
- new Ajax.Request(url, Object.merge(options, { parameters: params.join("&"), onComplete: complete, onSuccess: success }))
129
- },
130
-
131
- hide: function() {
132
- for (i = 0; i < arguments.length; i++) {
133
- if ($(arguments[i])) {
134
- Element.addClassName(arguments[i], 'hidden')
135
- }
136
- }
137
- },
138
-
139
- show: function() {
140
- for (i = 0; i < arguments.length; i++) {
141
- if ($(arguments[i])) {
142
- Element.removeClassName(arguments[i], 'hidden')
143
- }
144
- }
145
- },
146
-
147
- toggle: function() {
148
- for (i = 0; i < arguments.length; i++) {
149
- if ($(arguments[i])) {
150
- if(Element.hasClassName(arguments[i], 'hidden')) {
151
- Element.removeClassName(arguments[i], 'hidden')
152
- } else {
153
- Element.addClassName(arguments[i], 'hidden')
154
- }
155
- }
156
- }
157
- },
158
-
159
- onFieldEditComplete: function(el, newValue) {
160
- el = $(el)
161
- var oldValue = Hobo.ipeOldValues[el.id]
162
- delete Hobo.ipeOldValues[el.id]
163
-
164
- var blank = el.getAttribute("hobo-blank-message")
165
- if (blank && newValue.strip().length == 0) {
166
- el.update(blank)
167
- } else {
168
- el.update(newValue)
169
- }
170
-
171
- var modelId = Hobo.getModelId(el)
172
- if (oldValue) {
173
- $$(".model:" + modelId).each(function(e) {
174
- if (e != el && e.innerHTML == oldValue) e.update(newValue)
175
- })
176
- }
177
- },
178
-
179
- _makeInPlaceEditor: function(el, options) {
180
- var old
181
- var updates = Hobo.updatesForElement(el)
182
- var id = el.id
183
- if (!id) { id = el.id = Hobo.uid() }
184
- var updateParams = Hobo.ajaxUpdateParams(updates, [{id: id,
185
- result: 'new_field_value',
186
- func: "Hobo.onFieldEditComplete"}])
187
- var opts = {okButton: false,
188
- cancelLink: false,
189
- submitOnBlur: true,
190
- evalScripts: true,
191
- htmlResponse: false,
192
- ajaxOptions: { method: "put" },
193
- onEnterHover: null,
194
- onLeaveHover: null,
195
- callback: function(form, val) {
196
- old = val
197
- el.setAttribute("hobo-edit-text", val)
198
- return (Hobo.fieldSetParam(el, val) + "&" + updateParams)
199
- },
200
- onFailure: function(_, resp) {
201
- alert(resp.responseText); el.innerHTML = old
202
- },
203
- onEnterEditMode: function() {
204
- var blank_message = el.getAttribute("hobo-blank-message")
205
- var editable_text = el.getAttribute("hobo-edit-text")
206
- if (editable_text) {
207
- el.innerHTML = editable_text
208
- }
209
- if (el.innerHTML.gsub("&nbsp;", " ") == blank_message) {
210
- el.innerHTML = ""
211
- } else {
212
- Hobo.ipeOldValues[el.id] = el.innerHTML
213
- }
214
- }
215
- }
216
- Object.extend(opts, options)
217
- return new Ajax.InPlaceEditor(el, Hobo.putUrl(el), opts)
218
- },
219
-
220
-
221
- doSearch: function(el) {
222
- el = $(el)
223
- var spinner = $(el.getAttribute("search-spinner") || "search-spinner")
224
- var search_results = $(el.getAttribute("search-results") || "search-results")
225
- var search_results_panel = $(el.getAttribute("search-results-panel") || "search-results-panel")
226
- var url = el.getAttribute("search-url") || (urlBase + "/search")
227
-
228
- var clear = function() { Hobo.hide(search_results_panel); el.clear() }
229
-
230
- // Close window on [Escape]
231
- Event.observe(el, 'keypress', function(ev) {
232
- if (ev.keyCode == 27) clear()
233
- });
234
-
235
- Event.observe(search_results_panel.down('.close-button'), 'click', clear)
236
-
237
- var value = $F(el)
238
- if (Hobo.searchRequest) { Hobo.searchRequest.transport.abort() }
239
- if (value.length >= 3) {
240
- if (spinner) Hobo.show(spinner);
241
- Hobo.searchRequest = new Ajax.Updater(search_results,
242
- url,
243
- { asynchronous:true,
244
- evalScripts:true,
245
- onSuccess:function(request) {
246
- if (spinner) Hobo.hide(spinner)
247
- if (search_results_panel) {
248
- Hobo.show(search_results_panel)
249
- }
250
- },
251
- method: "get",
252
- parameters:"query=" + value });
253
- } else {
254
- Hobo.updateElement(search_results, '')
255
- Hobo.hide(search_results_panel)
256
- }
257
- },
258
-
259
-
260
- putUrl: function(el) {
261
- /* we used to append _method=put here, but it doesn't work in Rails 3 */
262
- var spec = Hobo.modelSpecForElement(el)
263
- return urlBase + "/" + Hobo.pluralise(spec.name) + "/" + spec.id
264
- },
265
-
266
-
267
- urlForId: function(id) {
268
- var spec = Hobo.parseModelSpec(id)
269
- var url = urlBase + "/" + Hobo.pluralise(spec.name)
270
- if (spec.id) { url += "/" + spec.id }
271
- return url
272
- },
273
-
274
-
275
- fieldSetParam: function(el, val) {
276
- var spec = Hobo.modelSpecForElement(el)
277
- var res = spec.name + '[' + spec.field + ']=' + encodeURIComponent(val)
278
- if (typeof(formAuthToken) != "undefined") {
279
- res = res + "&" + formAuthToken.name + "=" + formAuthToken.value
280
- }
281
- return res
282
- },
283
-
284
-
285
- fadeObjectElement: function(el) {
286
- var fadeEl = Hobo.objectElementFor(el)
287
- new Effect.Fade(fadeEl, { duration: 0.5, afterFinish: function (ef) {
288
- ef.element.remove()
289
- } });
290
- Hobo.showEmptyMessageAfterLastRemove(fadeEl)
291
- },
292
-
293
-
294
- removeButton: function(el, url, updates, options) {
295
- if (options.fade == null) { options.fade = true; }
296
- if (options.confirm == null) { options.confirm = "Are you sure?"; }
297
-
298
- if (options.confirm == false || confirm(options.confirm)) {
299
- var objEl = Hobo.objectElementFor(el)
300
- Hobo.showSpinner('Removing');
301
- function complete() {
302
- if (options.fade) { Hobo.fadeObjectElement(objEl) }
303
- Hobo.hideSpinner()
304
- }
305
- if (updates && updates.length > 0) {
306
- new Hobo.ajaxRequest(url, updates, { method:'delete', message: "Removing...", onComplete: complete});
307
- } else {
308
- var ajaxOptions = {asynchronous:true, evalScripts:true, method:'delete', onComplete: complete}
309
- if (typeof(formAuthToken) != "undefined") {
310
- ajaxOptions.parameters = formAuthToken.name + "=" + formAuthToken.value
311
- }
312
- new Ajax.Request(url, ajaxOptions);
313
- }
314
- }
315
- },
316
-
317
-
318
- ajaxUpdateField: function(element, field, value, updates) {
319
- var objectElement = Hobo.objectElementFor(element)
320
- var url = Hobo.putUrl(objectElement)
321
- var spec = Hobo.modelSpecForElement(objectElement)
322
- var params = spec.name + '[' + field + ']=' + encodeURIComponent(value)
323
- new Hobo.ajaxRequest(url, updates, { method:'put', message: "Saving...", params: params });
324
- },
325
-
326
-
327
- showEmptyMessageAfterLastRemove: function(el) {
328
- var empty
329
- var container = $(el.parentNode)
330
- if (container.getElementsByTagName(el.nodeName).length == 1 &&
331
- (empty = container.next('.empty-collection-message'))) {
332
- new Effect.Appear(empty, {delay:0.3})
333
- }
334
- },
335
-
336
-
337
- getClassData: function(el, name) {
338
- var match = el.className.match(new RegExp("(^| )" + name + "::(\\S+)($| )"))
339
- return match && match[2]
340
- },
341
-
342
-
343
- getModelId: function(el) {
344
- return Hobo.getClassData(el, 'model')
345
- },
346
-
347
-
348
- modelSpecForElement: function(el) {
349
- var id = Hobo.getModelId(el)
350
- return id && Hobo.parseModelSpec(id)
351
- },
352
-
353
-
354
- parseModelSpec: function(id) {
355
- m = id.gsub('-', '_').match(/^([^:]+)(?::([^:]+)(?::([^:]+))?)?$/)
356
- if (m) return { name: m[1], id: m[2], field: m[3] }
357
- },
358
-
359
-
360
- objectElementFor: function(el) {
361
- var m
362
- while(el.getAttribute) {
363
- id = Hobo.getModelId(el)
364
- if (id) m = id.match(/^[^:]+:[^:]+$/);
365
- if (m) break;
366
- el = el.parentNode;
367
- }
368
- if (m) return el;
369
- },
370
-
371
- modelIdFor: function(el) {
372
- var e = Hobo.objectElementFor(el)
373
- return e && Hobo.getModelId(e)
374
- },
375
-
376
-
377
- showSpinner: function(message, nextTo) {
378
- clearTimeout(Hobo.spinnerTimer)
379
- Hobo.spinnerHideAt = new Date().getTime() + Hobo.spinnerMinTime;
380
- if (t = $('ajax-progress-text')) {
381
- if (!message || message.length == 0) {
382
- t.hide()
383
- } else {
384
- Element.update(t, message);
385
- t.show()
386
- }
387
- }
388
- if (e = $('ajax-progress')) {
389
- if (nextTo) {
390
- var e_nextTo = $(nextTo);
391
- var pos = e_nextTo.cumulativeOffset()
392
- e.style.top = pos.top - e_nextTo.offsetHeight + "px"
393
- e.style.left = (pos.left + e_nextTo.offsetWidth + 5) + "px"
394
- }
395
- e.style.display = "block";
396
- }
397
- },
398
-
399
-
400
- hideSpinner: function() {
401
- if (e = $('ajax-progress')) {
402
- var remainingTime = Hobo.spinnerHideAt - new Date().getTime()
403
- if (remainingTime <= 0) {
404
- e.visualEffect('Fade')
405
- } else {
406
- Hobo.spinnerTimer = setTimeout(function () { e.visualEffect('Fade') }, remainingTime)
407
- }
408
- }
409
- },
410
-
411
-
412
- updateElement: function(id, content) {
413
- Element.update(id, content)
414
- Element.fire($(id), "rapid:partupdated")
415
- },
416
-
417
- getStyle: function(el, styleProp) {
418
- if (el.currentStyle)
419
- var y = el.currentStyle[styleProp];
420
- else if (window.getComputedStyle)
421
- var y = document.defaultView.getComputedStyle(el, null).getPropertyValue(styleProp);
422
- return y;
423
- },
424
-
425
- partFor: function(el) {
426
- while (el) {
427
- if (el.id && hoboParts[el.id]) { return el }
428
- el = el.parentNode
429
- }
430
- return null
431
- },
432
-
433
- pluralise: function(s) {
434
- return pluralisations[s] || s + "s"
435
- },
436
-
437
- addUrlParams: function(params, options) {
438
- params = $H(window.location.search.toQueryParams()).merge(params)
439
-
440
- if (options.remove) {
441
- var remove = (options.remove instanceof Array) ? options.remove : [options.remove]
442
- remove.each(function(k) { params.unset(k) })
443
- }
444
-
445
- return window.location.href.sub(/(\?.*|$)/, "?" + params.toQueryString())
446
- },
447
-
448
-
449
- makeHtmlEditor: function(textarea) {
450
- // do nothing - plugins can overwrite this method
451
- }
452
-
453
-
454
- }
455
-
456
- Element.findContaining = function(el, tag) {
457
- el = $(el)
458
- tag = tag.toLowerCase()
459
- e = el.parentNode
460
- while (el) {
461
- if (el.nodeName.toLowerCase() == tag) {
462
- return el;
463
- }
464
- e = el.parentNode
465
- }
466
- return null;
467
- }
468
-
469
- Element.Methods.childWithClass = function(el, klass) {
470
- var ret=null;
471
- el.childElements().each(function(el2) {
472
- if(ret==null && el2.hasClassName(klass)) ret=el2;
473
- });
474
- return ret;
475
- }
476
-
477
- // Add an afterEnterEditMode hook to in-place-editor
478
- origEnterEditMode = Ajax.InPlaceEditor.prototype.enterEditMode
479
- Ajax.InPlaceEditor.prototype.enterEditMode = function(evt) {
480
- origEnterEditMode.bind(this)(evt)
481
- if (this.afterEnterEditMode) this.afterEnterEditMode()
482
- return false
483
- }
484
-
485
- // Fix Safari in-place-editor bug
486
- Ajax.InPlaceEditor.prototype.removeForm = function() {
487
- if (!this._form) return;
488
-
489
- if (this._form.parentNode) { try { Element.remove(this._form); } catch (e) {}}
490
- this._form = null;
491
- this._controls = { };
492
- }
493
-
494
- // Silence errors from IE :-(
495
- Field.scrollFreeActivate = function(field) {
496
- setTimeout(function() {
497
- try {
498
- Field.activate(field);
499
- } catch(e) {}
500
- }, 1);
501
- }
502
-
503
-
504
- Element.Methods.$$ = function(e, css) {
505
- return new Selector(css).findElements(e)
506
- }
507
-
508
-
509
- HoboBehavior = Class.create({
510
-
511
- initialize: function(mainSelector, features) {
512
- this.mainSelector = mainSelector
513
- this.features = features
514
- this.addEvents(mainSelector, features.events)
515
- if (features.initialize) {
516
- document.observe("dom:loaded", features.initialize);
517
- }
518
- },
519
-
520
- addEvents: function(parentSelector, events) {
521
- var self = this
522
-
523
- for (selector in events) {
524
- fullSelector = parentSelector + ' ' + selector
525
- var rhs = events[selector]
526
- if (Object.isString(rhs)) {
527
- this.addBehavior(fullSelector, this.features[rhs])
528
- } else {
529
- this.addEvents(fullSelector, rhs)
530
- }
531
- }
532
-
533
- },
534
-
535
- addBehavior: function(selector, handler) {
536
- var self = this
537
- behavior = {}
538
- behavior[selector] = function(ev) {
539
- self.features.element = this.up(self.mainSelector)
540
- handler.call(self.features, ev, this)
541
- }
542
- Event.addBehavior(behavior)
543
- }
544
-
545
- })
546
-
547
-
548
- HoboInputMany = {
549
-
550
- events: {
551
- "> li > div.buttons": {
552
- ".add-item:click": 'addOne',
553
- ".remove-item:click": 'removeOne'
554
- }
555
- },
556
-
557
- initialize: function(ev) {
558
- /* the second clause should be sufficient, but it isn't in IE7. See bug 603 */
559
- Element.select(ev.target, ".input-many-template").each(function (templ) {
560
- templ.select("input:hidden,select:hidden,textarea:hidden,button:hidden").each(function(input) {
561
- if(!input.disabled) {
562
- input.disabled = true;
563
- input.addClassName("input_many_template_input");
564
- }
565
- })
566
- });
567
-
568
- // disable all elements inside our template, and mark them so we can find them later.
569
- Element.select(ev.target, ".input-many-template").each(function (templ) {
570
- templ.select("input:enabled,select:enabled,textarea:enabled,button:enabled").each(function(input) {
571
- input.disabled = true;
572
- input.addClassName("input_many_template_input");
573
- });
574
- });
575
-
576
- Element.select(ev.target, ".sortable-input-many").each(function(el) {
577
- HoboInputMany.createSortable.call(el);
578
- });
579
-
580
- /* need to reinitialize after every change */
581
- Event.addBehavior({".sortable-input-many:rapid:change": function(ev) {
582
- HoboInputMany.createSortable.call(this);
583
- }});
584
-
585
- document.observe("rapid:partupdated", HoboInputMany.initialize);
586
- },
587
-
588
- createSortable: function() {
589
- Sortable.create(this.id, {
590
- constraint: 'vertical',
591
- handle: 'ordering-handle',
592
- overlap: 'vertical',
593
- scroll: 'window',
594
- onUpdate: function(list) {
595
- HoboInputMany.fixIndices.call(list);
596
- }
597
- });
598
- },
599
-
600
- // given this==the input-many, returns a lambda that updates the name & id for an element
601
- getNameUpdater: function(new_index) {
602
- var name_prefix = Hobo.getClassData(this, 'input-many-prefix');
603
- var id_prefix = name_prefix.replace(/\[/g, "_").replace(/\]/g, "");
604
- var name_re = RegExp("^" + RegExp.escape(name_prefix)+ "\[\-?[0-9]+\]");
605
- var name_sub = name_prefix + '[' + new_index.toString() + ']';
606
- var id_re = RegExp("^" + RegExp.escape(id_prefix)+ "_\-?[0-9]+");
607
- var id_sub = id_prefix + '_' + new_index.toString();
608
- var class_re = RegExp(RegExp.escape(name_prefix)+ "\[\-?[0-9]+\]");
609
- var class_sub = name_sub;
610
-
611
- return function() {
612
- if(this.name) {
613
- this.name = this.name.replace(name_re, name_sub);
614
- }
615
- if (id_prefix==this.id.slice(0, id_prefix.length)) {
616
- this.id = this.id.replace(id_re, id_sub);
617
- } else {
618
- // silly rails. text_area_tag and text_field_tag use different conventions for the id.
619
- if(name_prefix==this.id.slice(0, name_prefix.length)) {
620
- this.id = this.id.replace(name_re, name_sub);
621
- } /* else {
622
- hjq.util.log("hjq.input_many.update_id: id_prefix "+id_prefix+" didn't match input "+this.id);
623
- } */
624
- }
625
- if (class_re.test(this.className)) {
626
- this.className = this.className.replace(class_re, class_sub);
627
- }
628
- return this;
629
- };
630
- },
631
-
632
- // given this==an input-many item, get the submit index
633
- getIndex: function() {
634
- return Number(this.id.match(/_([-0-9]+)$/)[1]);
635
- },
636
-
637
- /* For some reason, select() and down() and all those useful functions aren't working for us. Roll our own replacement.
638
-
639
- this: element to recurse on.
640
- klass: class to filter on
641
- f: function to invoke
642
- */
643
- recurse_elements_with_class: function(klass,f ) {
644
- if(klass==null || this.hasClassName(klass)) {
645
- f(this);
646
- }
647
- this.childElements().each(function(el2) {HoboInputMany.recurse_elements_with_class.call(el2, klass, f);});
648
- },
649
-
650
- /* fixes the indices on an input-many so they're in order. */
651
- fixIndices: function() {
652
- var lis = this.immediateDescendants();
653
- var minimum = parseInt(Hobo.getClassData(this, 'minimum'));
654
- /* first two lis are hidden/disabled on an input-many */
655
- for(var i=0; i<lis.length-2; i++) {
656
- var il=i+2;
657
- if(i!=HoboInputMany.getIndex.call(lis[il])) {
658
- var updater = HoboInputMany.getNameUpdater.call(this, i);
659
- HoboInputMany.recurse_elements_with_class.call(lis[il], null, function(el) {
660
- updater.call(el);
661
- });
662
- var position=lis[il].childWithClass("sortable-position");
663
- if(position) position.value=i+1;
664
- if(i==minimum-1 && il==lis.length-1) {
665
- lis[il].childWithClass("buttons").childWithClass("remove-item").addClassName("hidden");
666
- } else {
667
- lis[il].childWithClass("buttons").childWithClass("remove-item").removeClassName("hidden");
668
- }
669
- if(il==lis.length-1) {
670
- lis[il].childWithClass("buttons").childWithClass("add-item").removeClassName("hidden");
671
- } else {
672
- lis[il].childWithClass("buttons").childWithClass("add-item").addClassName("hidden");
673
- }
674
- }
675
- }
676
- },
677
-
678
-
679
- addOne: function(ev, el) {
680
- Event.stop(ev);
681
- var ul = el.up('ul.input-many'), li = el.up('li.input-many-li');
682
-
683
- if(li.id.search(/_-1$/)>=0 && ul.immediateDescendants().length>2) {
684
- /* if(console) console.log("IE7 messed up again (bug 605)"); */
685
- return;
686
- }
687
-
688
- var template = ul.down("li.input-many-template");
689
- var clone = $(template.cloneNode(true));
690
- clone.removeClassName("input-many-template");
691
- // length-2 because ignore the template li and the empty li
692
- var name_updater = this.getNameUpdater.call(ul, ul.childElements().length-2);
693
-
694
- function reenable_inputs(el) {
695
- if(el.hasClassName("input_many_template_input")) {
696
- el.disabled = false;
697
- el.removeClassName("input_many_template_input");
698
- }
699
- el.childElements().each(function(el2) {
700
- if(!el2.hasClassName("input-many-template")) reenable_inputs(el2);
701
- });
702
- }
703
- reenable_inputs(clone);
704
-
705
- // update id & name
706
- HoboInputMany.recurse_elements_with_class.call(clone, null, function(el) {
707
- name_updater.call(el);
708
- });
709
-
710
- // do the add with anim
711
- clone.setStyle("display", "none")
712
- li.insert({after: clone});
713
- new Effect.BlindDown(clone, {duration: 0.3, afterFinish: function(ef) {
714
- Event.addBehavior.reload();
715
-
716
- ul.fire("rapid:add", { element: clone });
717
- ul.fire("rapid:change", { element: clone });
718
- }});
719
-
720
- // visibility
721
- if(li.hasClassName("empty")) {
722
- li.addClassName("hidden");
723
- li.childWithClass("empty-input").disabled = true;
724
- } else {
725
- // now that we've added an element after us, we should only have a '-' button
726
- li.childWithClass("buttons").childWithClass("remove-item").removeClassName("hidden");
727
- li.childWithClass("buttons").childWithClass("add-item").addClassName("hidden");
728
- }
729
-
730
- return;
731
- },
732
-
733
- removeOne: function(ev, el) {
734
- Event.stop(ev);
735
- var that = this;
736
- var ul = el.up('ul.input-many'), li = el.up('li.input-many-li')
737
- var minimum = parseInt(Hobo.getClassData(ul, 'minimum'));
738
-
739
- if(li.id.search(/_-1$/)>=0) {
740
- /* if(console) console.log("IE7 messed up again (bug 605)"); */
741
- return;
742
- }
743
-
744
- if(ul.fire("rapid:remove", { element: li }).stopped) return;
745
-
746
- // rename everybody from me onwards
747
- var i=this.getIndex.call(li)
748
- var n=li.next();
749
- for(; n; i+=1, n=n.next()) {
750
- var name_updater = this.getNameUpdater.call(ul, i);
751
- HoboInputMany.recurse_elements_with_class.call(n, null, function(el) {name_updater.call(el);});
752
- }
753
-
754
- // adjust +/- buttons on the button element as appropriate
755
- var last=ul.childElements()[ul.childElements().length-1];
756
- if(last==li) {
757
- last = last.previous();
758
- }
759
-
760
- if(last.hasClassName("empty")) {
761
- last.removeClassName("hidden");
762
- HoboInputMany.recurse_elements_with_class.call(last, "empty-input", function(el) {el.disabled=false;});
763
- } else {
764
- // if we've reached the minimum, we don't want to add the '-' button
765
- if(ul.childElements().length-3 <= minimum||0) {
766
- last.childWithClass("buttons").childWithClass("remove-item").addClassName("hidden");
767
- } else {
768
- last.childWithClass("buttons").childWithClass("remove-item").removeClassName("hidden");
769
- }
770
- last.childWithClass("buttons").childWithClass("add-item").removeClassName("hidden");
771
- }
772
-
773
- new Effect.BlindUp(li, { duration: 0.3, afterFinish: function (ef) {
774
- ul.fire("rapid:change")
775
- li.remove()
776
- } });
777
-
778
- }
779
-
780
-
781
-
782
- }
783
-
784
- new HoboBehavior("ul.input-many", HoboInputMany);
785
-
786
-
787
- SelectManyInput = Behavior.create({
788
-
789
- initialize : function() {
790
- // onchange doesn't bubble in IE6 so...
791
- Event.observe(this.element.down('select'), 'change', this.addOne.bind(this))
792
- },
793
-
794
- addOne : function() {
795
- var select = this.element.down('select')
796
- var selected = select.options[select.selectedIndex]
797
- if ($F(select) != "") {
798
- var newItem = $(DOM.Builder.fromHTML(this.element.down('.item-proto').innerHTML.strip()))
799
- this.element.down('.items').appendChild(newItem);
800
- newItem.down('span').innerHTML = selected.innerHTML
801
- this.itemAdded(newItem, selected)
802
- var optgroup = new Element("optgroup", {alt:selected.value, label:selected.text})
803
- optgroup.addClassName("disabled-option")
804
- selected.replace(optgroup)
805
- select.value = ""
806
- Event.addBehavior.reload()
807
- this.element.fire("rapid:add", { element: newItem })
808
- this.element.fire("rapid:change", { element: newItem })
809
- }
810
- },
811
-
812
- onclick : function(ev) {
813
- var el = Event.element(ev);
814
- if (el.match(".remove-item")) { this.removeOne(el.parentNode) }
815
- },
816
-
817
- removeOne : function(el) {
818
- var element = this.element
819
- new Effect.BlindUp(el,
820
- { duration: 0.3,
821
- afterFinish: function (ef) {
822
- ef.element.remove()
823
- element.fire("rapid:remove", { element: el })
824
- element.fire("rapid:change", { element: el })
825
- } } )
826
- var label = el.down('span').innerHTML
827
- var optgroup = element.down("optgroup[label="+label+"]")
828
- var option = new Element("option", {value:optgroup.readAttribute("alt")})
829
- option.innerHTML = optgroup.readAttribute("label")
830
- optgroup.replace(option)
831
- },
832
-
833
- itemAdded: function(item, option) {
834
- this.hiddenField(item).value = option.value
835
- },
836
-
837
- hiddenField: function(item) {
838
- return item.down('input[type=hidden]')
839
- //return item.getElementsByClassName("hidden-field")[0]
840
- }
841
-
842
-
843
- })
844
-
845
- NameManyInput = Object.extend(SelectManyInput, {
846
- addOne : function() {
847
- var select = this.element.down('select')
848
- var selected = select.options[select.selectedIndex]
849
- if (selected.value != "") {
850
- var newItem = $(DOM.Builder.fromHTML(this.element.down('.item-proto').innerHTML.strip()))
851
- this.element.down('.items').appendChild(newItem);
852
- newItem.down('span').innerHTML = selected.innerHTML
853
- this.itemAdded(newItem, selected)
854
- selected.disabled = true
855
- select.value = ""
856
- Event.addBehavior.reload()
857
- }
858
- }
859
- })
860
-
861
-
862
- AutocompleteBehavior = Behavior.create({
863
- initialize : function() {
864
- this.minChars = parseInt(Hobo.getClassData(this.element, "min-chars"));
865
- var match = this.element.className.match(/complete-on::([\S]+)/)
866
- var target = match[1].split('::')
867
- var typedId = target[0]
868
- var completer = target[1]
869
-
870
- var spec = Hobo.parseModelSpec(typedId)
871
- var url = urlBase + "/" + Hobo.pluralise(spec.name) + "/complete_" + completer
872
- var parameters = spec.id ? "id=" + spec.id : ""
873
- this.autocompleter = new Ajax.Autocompleter(this.element,
874
- this.element.next('.completions-popup'),
875
- url,
876
- {paramName:'query', method:'get', parameters: parameters, minChars: this.minChars,
877
- afterUpdateElement: this.afterUpdateElement});
878
- },
879
-
880
- onfocus: function() {
881
- if(this.element.hasClassName("nil-value")) {
882
- this.element.value = '';
883
- this.element.removeClassName("nil-value");
884
- }
885
- if(this.minChars==0) {
886
- this.autocompleter.activate();
887
- }
888
- },
889
-
890
- afterUpdateElement: function(input, li) {
891
- input.fire("rapid:autocomplete-assigned");
892
- }
893
-
894
- })
895
-
896
-
897
-
898
- Event.addBehavior.reassignAfterAjax = true;
899
- Event.addBehavior({
900
-
901
- 'div.select-many.input' : SelectManyInput(),
902
-
903
- 'textarea.html' : function() {
904
- Hobo.makeHtmlEditor(this)
905
- },
906
-
907
- 'form.filter-menu select:change': function(event) {
908
- var paramName = this.getAttribute('name')
909
- var params = {}
910
- var remove = [ 'page' ]
911
- if ($F(this) == '') {
912
- remove.push(paramName)
913
- } else {
914
- params[paramName] = $F(this)
915
- }
916
- location.href = Hobo.addUrlParams(params, {remove: remove})
917
- },
918
-
919
- '.autocompleter' : AutocompleteBehavior(),
920
-
921
- '.string.in-place-edit, .datetime.in-place-edit, .date.in-place-edit, .integer.in-place-edit, .float.in-place-edit, .decimal.in-place-edit' :
922
- function (ev) {
923
-
924
- var ipe = Hobo._makeInPlaceEditor(this)
925
- ipe.getText = function() {
926
- return this.element.innerHTML.gsub(/<br\s*\/?>/, "\n").unescapeHTML()
927
- }
928
- },
929
-
930
- '.text.in-place-edit, .markdown.in-place-edit, .textile.in-place-edit' : function (ev) {
931
- var ipe = Hobo._makeInPlaceEditor(this, {rows: 2})
932
- ipe.getText = function() {
933
- return this.element.innerHTML.gsub(/<br\s*\/?>/, "\n").unescapeHTML()
934
- }
935
- },
936
-
937
- ".html.in-place-edit" : function (ev) {
938
- if (Hobo.makeInPlaceHtmlEditor) {
939
- Hobo.makeInPlaceHtmlEditor(this)
940
- } else {
941
- var options = {
942
- rows: 2, handleLineBreaks: false, okButton: true, cancelLink: true, okText: "Save", submitOnBlur: false
943
- }
944
- var ipe = Hobo._makeInPlaceEditor(this, options)
945
- ipe.getText = function() {
946
- // Be careful! we're not calling unescapeHTML() here!
947
- return this.element.innerHTML
948
- }
949
- }
950
- },
951
-
952
- "select.integer.editor" : function(e) {
953
- var el = this
954
- el.onchange = function() {
955
- Hobo.ajaxSetFieldForElement(el, $F(el))
956
- }
957
- },
958
-
959
- "input.live-search[type=search]" : function(e) {
960
- var element = this
961
- new Form.Element.Observer(element, 1.0, function() { Hobo.doSearch(element) })
962
- }
963
-
964
-
965
- });
966
-
967
- ElementSet = Class.create(Enumerable, {
968
-
969
- initialize: function(array) {
970
- this.items = array
971
- },
972
-
973
- _each: function(fn) {
974
- return this.items.each(fn)
975
- },
976
-
977
- selectChildren: function(selector) {
978
- return new ElementSet(this.items.invoke('selectChildren', selector).pluck('items').flatten())
979
- },
980
-
981
- child: function(selector) {
982
- return this.selectChildren(selector).first()
983
- },
984
-
985
- select: function(selector) {
986
- return new ElementSet(this.items.invoke('select', selector).flatten())
987
- },
988
-
989
- down: function(selector) {
990
- for (var i = 0; i < this.items.length; i++) {
991
- var match = this.items[i].down(selector)
992
- if (match) return match
993
- }
994
- return null
995
- },
996
-
997
- size: function() {
998
- return this.items.length
999
- },
1000
-
1001
- first: function() {
1002
- return this.items.first()
1003
- },
1004
-
1005
- last: function() {
1006
- return this.items.last()
1007
- }
1008
-
1009
- })
1010
-
1011
- Element.addMethods({
1012
- selectChildren: function(element, selector) {
1013
- return new ElementSet(Selector.matchElements(element.childElements(), selector))
1014
- }
1015
- })