imagine_cms 3.0.0.beta6 → 3.0.0.beta7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (278) hide show
  1. data/README.rdoc +1 -1
  2. data/app/assets/images/codepress/line-numbers.png +0 -0
  3. data/app/assets/images/cropper/marqueeHoriz.gif +0 -0
  4. data/app/assets/images/cropper/marqueeVert.gif +0 -0
  5. data/app/assets/images/management/btn_add.gif +0 -0
  6. data/app/assets/images/management/btn_archive.gif +0 -0
  7. data/app/assets/images/management/btn_delete.gif +0 -0
  8. data/app/assets/images/management/btn_duplicate.gif +0 -0
  9. data/app/assets/images/management/btn_edit.gif +0 -0
  10. data/app/assets/images/management/btn_help.gif +0 -0
  11. data/app/assets/images/management/btn_new_page.gif +0 -0
  12. data/app/assets/images/management/btn_preview.gif +0 -0
  13. data/app/assets/images/management/btn_properties.gif +0 -0
  14. data/app/assets/images/management/btn_restore.gif +0 -0
  15. data/app/assets/images/management/btn_top_delete.gif +0 -0
  16. data/app/assets/images/management/btn_top_duplicate.gif +0 -0
  17. data/app/assets/images/management/btn_top_edit.gif +0 -0
  18. data/app/assets/images/management/btn_top_new.gif +0 -0
  19. data/app/assets/images/management/btn_top_preview.gif +0 -0
  20. data/app/assets/images/management/btn_top_properties.gif +0 -0
  21. data/app/assets/{manage → images/management}/bullet.gif +0 -0
  22. data/app/assets/images/management/cvv2_graphic.gif +0 -0
  23. data/app/assets/images/management/error.gif +0 -0
  24. data/app/assets/images/management/gallery_index.gif +0 -0
  25. data/app/assets/images/management/gallery_preview_overlay.png +0 -0
  26. data/app/assets/images/management/gallery_small_drag_overlay.png +0 -0
  27. data/app/assets/images/management/gallery_small_overlay.png +0 -0
  28. data/app/assets/images/management/gallery_sort.gif +0 -0
  29. data/app/assets/images/management/icon_download.gif +0 -0
  30. data/app/assets/images/management/icon_locked.png +0 -0
  31. data/app/assets/images/management/icon_page.gif +0 -0
  32. data/app/assets/images/management/icon_time.gif +0 -0
  33. data/app/assets/images/management/icon_unlocked.png +0 -0
  34. data/app/assets/images/management/page_loading.gif +0 -0
  35. data/app/assets/{manage → images/management}/start.gif +0 -0
  36. data/app/assets/images/management/vcard.gif +0 -0
  37. data/app/assets/javascripts/builder.js +101 -0
  38. data/app/assets/javascripts/codepress/codepress.html +36 -0
  39. data/app/assets/javascripts/codepress/codepress.js +130 -0
  40. data/app/assets/javascripts/codepress/engines/gecko.js +240 -0
  41. data/{vendor/gems/acts_as_tree/test/abstract_unit.rb → app/assets/javascripts/codepress/engines/khtml.js} +0 -0
  42. data/app/assets/javascripts/codepress/engines/msie.js +263 -0
  43. data/{vendor/gems/acts_as_tree/test/database.yml → app/assets/javascripts/codepress/engines/older.js} +0 -0
  44. data/app/assets/javascripts/codepress/engines/opera.js +259 -0
  45. data/app/assets/javascripts/codepress/languages/css.js +23 -0
  46. data/app/assets/javascripts/codepress/languages/generic.js +25 -0
  47. data/app/assets/javascripts/codepress/languages/html.js +63 -0
  48. data/app/assets/javascripts/codepress/languages/java.js +24 -0
  49. data/app/assets/javascripts/codepress/languages/javascript.js +30 -0
  50. data/app/assets/javascripts/codepress/languages/perl.js +27 -0
  51. data/app/assets/javascripts/codepress/languages/php.js +60 -0
  52. data/app/assets/javascripts/codepress/languages/ruby.js +26 -0
  53. data/app/assets/javascripts/codepress/languages/sql.js +30 -0
  54. data/app/assets/javascripts/codepress/languages/text.js +9 -0
  55. data/app/assets/javascripts/cropper.js +568 -0
  56. data/app/assets/javascripts/dojo/dojo.js +14155 -0
  57. data/app/assets/javascripts/dojo/src/html/images/shadowB.png +0 -0
  58. data/app/assets/javascripts/dojo/src/html/images/shadowBL.png +0 -0
  59. data/app/assets/javascripts/dojo/src/html/images/shadowBR.png +0 -0
  60. data/app/assets/javascripts/dojo/src/html/images/shadowL.png +0 -0
  61. data/app/assets/javascripts/dojo/src/html/images/shadowR.png +0 -0
  62. data/app/assets/javascripts/dojo/src/html/images/shadowT.png +0 -0
  63. data/app/assets/javascripts/dojo/src/html/images/shadowTL.png +0 -0
  64. data/app/assets/javascripts/dojo/src/html/images/shadowTR.png +0 -0
  65. data/app/assets/javascripts/dojo/src/widget/templates/Editor2/showtableborder_gecko.css +19 -0
  66. data/app/assets/javascripts/dojo/src/widget/templates/HslColorPicker.svg +30 -0
  67. data/app/assets/javascripts/dojo/src/widget/templates/buttons/aggregate.gif +0 -0
  68. data/app/assets/javascripts/dojo/src/widget/templates/buttons/aggregate.psd +0 -0
  69. data/app/assets/javascripts/dojo/src/widget/templates/buttons/backcolor.gif +0 -0
  70. data/app/assets/javascripts/dojo/src/widget/templates/buttons/bg-fade.png +0 -0
  71. data/app/assets/javascripts/dojo/src/widget/templates/buttons/bold.gif +0 -0
  72. data/app/assets/javascripts/dojo/src/widget/templates/buttons/cancel.gif +0 -0
  73. data/app/assets/javascripts/dojo/src/widget/templates/buttons/copy.gif +0 -0
  74. data/app/assets/javascripts/dojo/src/widget/templates/buttons/createlink.gif +0 -0
  75. data/app/assets/javascripts/dojo/src/widget/templates/buttons/cut.gif +0 -0
  76. data/app/assets/javascripts/dojo/src/widget/templates/buttons/delete.gif +0 -0
  77. data/app/assets/javascripts/dojo/src/widget/templates/buttons/forecolor.gif +0 -0
  78. data/app/assets/javascripts/dojo/src/widget/templates/buttons/hilitecolor.gif +0 -0
  79. data/app/assets/javascripts/dojo/src/widget/templates/buttons/indent.gif +0 -0
  80. data/app/assets/javascripts/dojo/src/widget/templates/buttons/inserthorizontalrule.gif +0 -0
  81. data/app/assets/javascripts/dojo/src/widget/templates/buttons/insertimage.gif +0 -0
  82. data/app/assets/javascripts/dojo/src/widget/templates/buttons/insertorderedlist.gif +0 -0
  83. data/app/assets/javascripts/dojo/src/widget/templates/buttons/inserttable.gif +0 -0
  84. data/app/assets/javascripts/dojo/src/widget/templates/buttons/insertunorderedlist.gif +0 -0
  85. data/app/assets/javascripts/dojo/src/widget/templates/buttons/italic.gif +0 -0
  86. data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifycenter.gif +0 -0
  87. data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifyfull.gif +0 -0
  88. data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifyleft.gif +0 -0
  89. data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifyright.gif +0 -0
  90. data/app/assets/javascripts/dojo/src/widget/templates/buttons/left_to_right.gif +0 -0
  91. data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_bullet_indent.gif +0 -0
  92. data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_bullet_outdent.gif +0 -0
  93. data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_num_indent.gif +0 -0
  94. data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_num_outdent.gif +0 -0
  95. data/app/assets/javascripts/dojo/src/widget/templates/buttons/outdent.gif +0 -0
  96. data/app/assets/javascripts/dojo/src/widget/templates/buttons/paste.gif +0 -0
  97. data/app/assets/javascripts/dojo/src/widget/templates/buttons/redo.gif +0 -0
  98. data/app/assets/javascripts/dojo/src/widget/templates/buttons/removeformat.gif +0 -0
  99. data/app/assets/javascripts/dojo/src/widget/templates/buttons/right_to_left.gif +0 -0
  100. data/app/assets/javascripts/dojo/src/widget/templates/buttons/save.gif +0 -0
  101. data/app/assets/javascripts/dojo/src/widget/templates/buttons/sep.gif +0 -0
  102. data/app/assets/javascripts/dojo/src/widget/templates/buttons/space.gif +0 -0
  103. data/app/assets/javascripts/dojo/src/widget/templates/buttons/strikethrough.gif +0 -0
  104. data/app/assets/javascripts/dojo/src/widget/templates/buttons/subscript.gif +0 -0
  105. data/app/assets/javascripts/dojo/src/widget/templates/buttons/superscript.gif +0 -0
  106. data/app/assets/javascripts/dojo/src/widget/templates/buttons/underline.gif +0 -0
  107. data/app/assets/javascripts/dojo/src/widget/templates/buttons/undo.gif +0 -0
  108. data/app/assets/javascripts/dojo/src/widget/templates/buttons/wikiword.gif +0 -0
  109. data/app/assets/javascripts/dojo/src/widget/templates/check.gif +0 -0
  110. data/app/assets/javascripts/dojo/src/widget/templates/decrementMonth.gif +0 -0
  111. data/app/assets/javascripts/dojo/src/widget/templates/decrementWeek.gif +0 -0
  112. data/app/assets/javascripts/dojo/src/widget/templates/grabCorner.gif +0 -0
  113. data/app/assets/javascripts/dojo/src/widget/templates/images/floatingPaneClose.gif +0 -0
  114. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaAccordionOff.gif +0 -0
  115. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaAccordionSelected.gif +0 -0
  116. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaActive-c.gif +0 -0
  117. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaActive-l.gif +0 -0
  118. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaActive-r.gif +0 -0
  119. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaBarBg.gif +0 -0
  120. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaButton-c.gif +0 -0
  121. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaButton-l.gif +0 -0
  122. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaButton-r.gif +0 -0
  123. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaDisabled-c.gif +0 -0
  124. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaDisabled-l.gif +0 -0
  125. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaDisabled-r.gif +0 -0
  126. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaMenuBg.gif +0 -0
  127. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaPressed-c.gif +0 -0
  128. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaPressed-l.gif +0 -0
  129. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaPressed-r.gif +0 -0
  130. data/app/assets/javascripts/dojo/src/widget/templates/images/tab_close.gif +0 -0
  131. data/app/assets/javascripts/dojo/src/widget/templates/images/toolbar-bg.gif +0 -0
  132. data/app/assets/javascripts/dojo/src/widget/templates/incrementMonth.gif +0 -0
  133. data/app/assets/javascripts/dojo/src/widget/templates/incrementWeek.gif +0 -0
  134. data/app/assets/javascripts/dojo/src/widget/templates/richtextframe.html +24 -0
  135. data/app/assets/javascripts/imagine.js +1385 -0
  136. data/app/assets/javascripts/jquery_no_conflict.js +9405 -0
  137. data/app/assets/stylesheets/codepress/codepress.css +7 -0
  138. data/app/assets/stylesheets/codepress/languages/css.css +10 -0
  139. data/app/assets/stylesheets/codepress/languages/generic.css +9 -0
  140. data/app/assets/stylesheets/codepress/languages/html.css +18 -0
  141. data/app/assets/stylesheets/codepress/languages/java.css +7 -0
  142. data/app/assets/stylesheets/codepress/languages/javascript.css +8 -0
  143. data/app/assets/stylesheets/codepress/languages/perl.css +11 -0
  144. data/app/assets/stylesheets/codepress/languages/php.css +12 -0
  145. data/app/assets/stylesheets/codepress/languages/ruby.css +10 -0
  146. data/app/assets/stylesheets/codepress/languages/sql.css +10 -0
  147. data/app/assets/stylesheets/codepress/languages/text.css +5 -0
  148. data/app/assets/stylesheets/cropper.css +182 -0
  149. data/app/assets/stylesheets/management.css +96 -0
  150. data/app/assets/stylesheets/reset.css +58 -0
  151. data/app/controllers/cms/content_controller.rb +318 -2
  152. data/app/controllers/management/cms_controller.rb +1669 -0
  153. data/app/controllers/management/user_controller.rb +4 -4
  154. data/app/controllers/management/users_controller.rb +18 -4
  155. data/app/controllers/util_controller.rb +45 -0
  156. data/app/helpers/cms_application_helper.rb +662 -15
  157. data/app/models/cms_content_sweeper.rb +21 -0
  158. data/app/models/cms_page.rb +126 -0
  159. data/app/models/cms_page_object.rb +23 -0
  160. data/app/models/cms_page_tag.rb +5 -0
  161. data/app/models/cms_page_version.rb +3 -0
  162. data/app/models/cms_snippet.rb +16 -0
  163. data/app/models/cms_template.rb +29 -0
  164. data/app/models/user.rb +6 -3
  165. data/app/views/management/cms/_complete_gallery.html.erb +5 -0
  166. data/app/views/management/cms/_create_file_link.html.erb +21 -0
  167. data/app/views/management/cms/_crop_feature_image.html.erb +188 -0
  168. data/app/views/management/cms/_crop_image.html.erb +188 -0
  169. data/app/views/management/cms/_crop_results.html.erb +1 -0
  170. data/app/views/management/cms/_crop_results_feature_image.html.erb +1 -0
  171. data/app/views/management/cms/_crop_results_thumb.html.erb +1 -0
  172. data/app/views/management/cms/_crop_thumb.html.erb +188 -0
  173. data/app/views/management/cms/_dialogs.html.erb +39 -0
  174. data/app/views/management/cms/_edit_page.html.erb +176 -0
  175. data/app/views/management/cms/_gallery_index.html.erb +10 -0
  176. data/app/views/management/cms/_gallery_setup.html.erb +22 -0
  177. data/app/views/management/cms/_image.html.erb +3 -0
  178. data/app/views/management/cms/_image_details.html.erb +26 -0
  179. data/app/views/management/cms/_image_draggable.html.erb +4 -0
  180. data/app/views/management/cms/_list_page.html.erb +8 -0
  181. data/app/views/management/cms/_list_page_select.html.erb +8 -0
  182. data/app/views/management/cms/_list_pages.html.erb +1 -0
  183. data/app/views/management/cms/_list_pages_select.html.erb +1 -0
  184. data/app/views/management/cms/_page_attribute.html.erb +6 -0
  185. data/app/views/management/cms/_page_list.html.erb +171 -0
  186. data/app/views/management/cms/_page_list_source_folder.html.erb +20 -0
  187. data/app/views/management/cms/_page_list_source_tag.html.erb +18 -0
  188. data/app/views/management/cms/_select_gallery.html.erb +117 -0
  189. data/app/views/management/cms/_snippet.html.erb +3 -0
  190. data/app/views/management/cms/_sort_images.html.erb +15 -0
  191. data/app/views/management/cms/_temp.html.erb +3 -0
  192. data/app/views/management/cms/_template_options.html.erb +21 -0
  193. data/app/views/management/cms/_template_reference.html.erb +42 -0
  194. data/app/views/management/cms/_upload_feature_image.html.erb +35 -0
  195. data/app/views/management/cms/_upload_file.html.erb +31 -0
  196. data/app/views/management/cms/_upload_image.html.erb +74 -0
  197. data/app/views/management/cms/_upload_thumb.html.erb +35 -0
  198. data/app/views/management/cms/edit_master.html.erb +48 -0
  199. data/app/views/management/cms/edit_page_content.html.erb +4 -0
  200. data/app/views/management/cms/edit_snippet.html.erb +47 -0
  201. data/app/views/management/cms/edit_template.html.erb +48 -0
  202. data/app/views/management/cms/gallery_management.html.erb +108 -0
  203. data/app/views/management/cms/index.html.erb +20 -0
  204. data/app/views/management/cms/page_tags_for_lookup.html.erb +5 -0
  205. data/app/views/management/cms/pages.html.erb +99 -0
  206. data/app/views/management/cms/permission_denied.html.erb +1 -0
  207. data/app/views/management/cms/select_page.html.erb +57 -0
  208. data/app/views/management/cms/snippets.html.erb +14 -0
  209. data/app/views/management/cms/templates.html.erb +14 -0
  210. data/app/views/management/cms/toolbar_edit.html.erb +269 -0
  211. data/app/views/management/cms/toolbar_preview.html.erb +109 -0
  212. data/app/views/util/_calendar_days.html.erb +72 -0
  213. data/app/views/util/_calendar_month_year.html.erb +1 -0
  214. data/app/views/util/_date_picker.html.erb +56 -0
  215. data/app/views/util/_message.html.erb +1 -0
  216. data/app/views/util/_show_message.js.erb +6 -0
  217. data/app/views/util/_tab.html.erb +4 -0
  218. data/config/routes.rb +4 -1
  219. data/imagine_cms.gemspec +4 -0
  220. data/{vendor/gems → lib}/acts_as_versioned/.document +0 -0
  221. data/{vendor/gems → lib}/acts_as_versioned/.gitignore +2 -0
  222. data/{vendor/gems → lib}/acts_as_versioned/CHANGELOG +0 -0
  223. data/lib/acts_as_versioned/Gemfile +7 -0
  224. data/{vendor/gems → lib}/acts_as_versioned/MIT-LICENSE +0 -0
  225. data/{vendor/gems → lib}/acts_as_versioned/README +0 -0
  226. data/{vendor/gems → lib}/acts_as_versioned/RUNNING_UNIT_TESTS +0 -0
  227. data/{vendor/gems → lib}/acts_as_versioned/Rakefile +1 -1
  228. data/{vendor/gems → lib}/acts_as_versioned/acts_as_versioned.gemspec +4 -4
  229. data/{vendor/gems → lib}/acts_as_versioned/init.rb +0 -0
  230. data/{vendor/gems → lib}/acts_as_versioned/lib/acts_as_versioned.rb +109 -107
  231. data/{vendor/gems → lib}/acts_as_versioned/test/abstract_unit.rb +0 -0
  232. data/{vendor/gems → lib}/acts_as_versioned/test/database.yml +0 -0
  233. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/authors.yml +0 -0
  234. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/landmark.rb +0 -0
  235. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/landmark_versions.yml +0 -0
  236. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/landmarks.yml +0 -0
  237. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/locked_pages.yml +0 -0
  238. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/locked_pages_revisions.yml +0 -0
  239. data/{vendor/gems/acts_as_versioned/test/fixtures/migrations/1_add_versioned_tables.rb → lib/acts_as_versioned/test/fixtures/migrations/2_add_versioned_tables.rb} +0 -0
  240. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/page.rb +0 -0
  241. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/page_versions.yml +0 -0
  242. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/pages.yml +0 -0
  243. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/widget.rb +0 -0
  244. data/{vendor/gems → lib}/acts_as_versioned/test/migration_test.rb +0 -1
  245. data/{vendor/gems → lib}/acts_as_versioned/test/schema.rb +0 -0
  246. data/{vendor/gems → lib}/acts_as_versioned/test/versioned_test.rb +0 -0
  247. data/lib/extensions/action_controller.rb +154 -143
  248. data/lib/imagine_cms/engine.rb +33 -12
  249. data/lib/imagine_cms/version.rb +1 -1
  250. data/lib/imagine_cms.rb +30 -6
  251. data/lib/prototype_legacy_helper/README.markdown +13 -0
  252. data/lib/prototype_legacy_helper/init.rb +1 -0
  253. data/lib/prototype_legacy_helper/lib/prototype_legacy_helper.rb +430 -0
  254. data/lib/prototype_legacy_helper/test/test_prototype_helper.rb +297 -0
  255. data/lib/upload_progress/CHANGELOG +5 -0
  256. data/lib/upload_progress/MIT-LICENSE +20 -0
  257. data/lib/upload_progress/README +45 -0
  258. data/{vendor/gems/acts_as_tree → lib/upload_progress}/Rakefile +6 -5
  259. data/lib/upload_progress/init.rb +7 -0
  260. data/lib/upload_progress/lib/multipart_progress.rb +176 -0
  261. data/lib/upload_progress/lib/progress.rb +145 -0
  262. data/lib/upload_progress/lib/upload_progress.rb +303 -0
  263. data/lib/upload_progress/lib/upload_progress_helper.rb +425 -0
  264. data/lib/upload_progress/public/stylesheets/upload_progress.css +21 -0
  265. data/lib/upload_progress/test/multipart_progress_testx.rb +364 -0
  266. data/lib/upload_progress/test/upload_progress_helper_testx.rb +134 -0
  267. data/lib/upload_progress/test/upload_progress_testx.rb +88 -0
  268. metadata +305 -43
  269. data/app/assets/manage/btn_delete.gif +0 -0
  270. data/vendor/gems/.DS_Store +0 -0
  271. data/vendor/gems/acts_as_tree/README +0 -26
  272. data/vendor/gems/acts_as_tree/init.rb +0 -1
  273. data/vendor/gems/acts_as_tree/lib/active_record/acts/tree.rb +0 -96
  274. data/vendor/gems/acts_as_tree/test/acts_as_tree_test.rb +0 -219
  275. data/vendor/gems/acts_as_tree/test/fixtures/mixin.rb +0 -0
  276. data/vendor/gems/acts_as_tree/test/fixtures/mixins.yml +0 -0
  277. data/vendor/gems/acts_as_tree/test/schema.rb +0 -0
  278. data/vendor/gems/acts_as_versioned/Gemfile +0 -7
@@ -0,0 +1,297 @@
1
+ if ENV['RAILS_ROOT']
2
+ environment = File.expand_path('vendor/gems/environment', ENV['RAILS_ROOT'])
3
+ require environment if File.exist?("#{environment}.rb")
4
+ end
5
+
6
+ $:.unshift File.expand_path('../../lib', __FILE__)
7
+
8
+ require 'test/unit'
9
+ require 'action_view'
10
+ require 'action_controller'
11
+ require 'active_model'
12
+ require 'prototype_helper'
13
+
14
+ class Bunny < Struct.new(:Bunny, :id)
15
+ end
16
+
17
+ class Author
18
+ extend ActiveModel::Naming
19
+
20
+ attr_reader :id
21
+ def save; @id = 1 end
22
+ def new_record?; @id.nil? end
23
+ def name
24
+ @id.nil? ? 'new author' : "author ##{@id}"
25
+ end
26
+ end
27
+
28
+ class Article
29
+ extend ActiveModel::Naming
30
+
31
+ attr_reader :id
32
+ attr_reader :author_id
33
+ def save; @id = 1; @author_id = 1 end
34
+ def new_record?; @id.nil? end
35
+ def name
36
+ @id.nil? ? 'new article' : "article ##{@id}"
37
+ end
38
+ end
39
+
40
+ class Author::Nested < Author; end
41
+
42
+ class PrototypeHelperTest < ActionView::TestCase
43
+ attr_accessor :formats, :output_buffer, :template_format
44
+
45
+ def _evaluate_assigns_and_ivars() end
46
+
47
+ def reset_formats(format)
48
+ @format = format
49
+ end
50
+
51
+ def setup
52
+ @record = @author = Author.new
53
+ @article = Article.new
54
+ super
55
+ @template = self
56
+ @controller = Class.new do
57
+ def url_for(options)
58
+ if options.is_a?(String)
59
+ options
60
+ else
61
+ url = "http://www.example.com/"
62
+ url << options[:action].to_s if options and options[:action]
63
+ url << "?a=#{options[:a]}" if options && options[:a]
64
+ url << "&b=#{options[:b]}" if options && options[:a] && options[:b]
65
+ url
66
+ end
67
+ end
68
+ end.new
69
+ end
70
+
71
+
72
+ def test_observe_form
73
+ assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Observer('cart', 2, function(element, value) {new Ajax.Request('http://www.example.com/cart_changed', {asynchronous:true, evalScripts:true, parameters:value})})\n//]]>\n</script>),
74
+ observe_form("cart", :frequency => 2, :url => { :action => "cart_changed" })
75
+ end
76
+
77
+ def test_observe_form_using_function_for_callback
78
+ assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Observer('cart', 2, function(element, value) {alert('Form changed')})\n//]]>\n</script>),
79
+ observe_form("cart", :frequency => 2, :function => "alert('Form changed')")
80
+ end
81
+
82
+ def test_observe_field
83
+ assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/reorder_if_empty', {asynchronous:true, evalScripts:true, parameters:value})})\n//]]>\n</script>),
84
+ observe_field("glass", :frequency => 5.minutes, :url => { :action => "reorder_if_empty" })
85
+ end
86
+
87
+ def test_observe_field_using_with_option
88
+ expected = %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/check_value', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent(value)})})\n//]]>\n</script>)
89
+ assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => 'id')
90
+ assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "'id=' + encodeURIComponent(value)")
91
+ end
92
+
93
+ def test_observe_field_using_json_in_with_option
94
+ expected = %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/check_value', {asynchronous:true, evalScripts:true, parameters:{'id':value}})})\n//]]>\n</script>)
95
+ assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "{'id':value}")
96
+ end
97
+
98
+ def test_observe_field_using_function_for_callback
99
+ assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {alert('Element changed')})\n//]]>\n</script>),
100
+ observe_field("glass", :frequency => 5.minutes, :function => "alert('Element changed')")
101
+ end
102
+
103
+ def test_observe_field_without_frequency
104
+ assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.EventObserver('glass', function(element, value) {new Ajax.Request('http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:value})})\n//]]>\n</script>),
105
+ observe_field("glass")
106
+ end
107
+
108
+
109
+ def test_periodically_call_remote
110
+ assert_dom_equal %(<script type="text/javascript">\n//<![CDATA[\nnew PeriodicalExecuter(function() {new Ajax.Updater('schremser_bier', 'http://www.example.com/mehr_bier', {asynchronous:true, evalScripts:true})}, 10)\n//]]>\n</script>),
111
+ periodically_call_remote(:update => "schremser_bier", :url => { :action => "mehr_bier" })
112
+ end
113
+
114
+ def test_periodically_call_remote_with_frequency
115
+ assert_dom_equal(
116
+ "<script type=\"text/javascript\">\n//<![CDATA[\nnew PeriodicalExecuter(function() {new Ajax.Request('http://www.example.com/', {asynchronous:true, evalScripts:true})}, 2)\n//]]>\n</script>",
117
+ periodically_call_remote(:frequency => 2)
118
+ )
119
+ end
120
+
121
+
122
+ def test_form_remote_tag
123
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">),
124
+ form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast })
125
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">),
126
+ form_remote_tag(:update => { :success => "glass_of_beer" }, :url => { :action => :fast })
127
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">),
128
+ form_remote_tag(:update => { :failure => "glass_of_water" }, :url => { :action => :fast })
129
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer',failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">),
130
+ form_remote_tag(:update => { :success => 'glass_of_beer', :failure => "glass_of_water" }, :url => { :action => :fast })
131
+ end
132
+
133
+ def test_form_remote_tag_with_method
134
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\"><div style='margin:0;padding:0;display:inline'><input name='_method' type='hidden' value='put' /></div>),
135
+ form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, :html => { :method => :put })
136
+ end
137
+
138
+ def test_form_remote_tag_with_block_in_erb
139
+ __in_erb_template = ''
140
+ form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }) { concat "Hello world!" }
141
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">Hello world!</form>), output_buffer
142
+ end
143
+
144
+ def test_on_callbacks
145
+ callbacks = [:uninitialized, :loading, :loaded, :interactive, :complete, :success, :failure]
146
+ callbacks.each do |callback|
147
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
148
+ form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, callback=>"monkeys();")
149
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
150
+ form_remote_tag(:update => { :success => "glass_of_beer" }, :url => { :action => :fast }, callback=>"monkeys();")
151
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({failure:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
152
+ form_remote_tag(:update => { :failure => "glass_of_beer" }, :url => { :action => :fast }, callback=>"monkeys();")
153
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer',failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
154
+ form_remote_tag(:update => { :success => "glass_of_beer", :failure => "glass_of_water" }, :url => { :action => :fast }, callback=>"monkeys();")
155
+ end
156
+
157
+ #HTTP status codes 200 up to 599 have callbacks
158
+ #these should work
159
+ 100.upto(599) do |callback|
160
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
161
+ form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, callback=>"monkeys();")
162
+ end
163
+
164
+ #test 200 and 404
165
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on200:function(request){monkeys();}, on404:function(request){bananas();}, parameters:Form.serialize(this)}); return false;">),
166
+ form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, 200=>"monkeys();", 404=>"bananas();")
167
+
168
+ #these shouldn't
169
+ 1.upto(99) do |callback|
170
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">),
171
+ form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, callback=>"monkeys();")
172
+ end
173
+ 600.upto(999) do |callback|
174
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">),
175
+ form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, callback=>"monkeys();")
176
+ end
177
+
178
+ #test ultimate combo
179
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on200:function(request){monkeys();}, on404:function(request){bananas();}, onComplete:function(request){c();}, onFailure:function(request){f();}, onLoading:function(request){c1()}, onSuccess:function(request){s()}, parameters:Form.serialize(this)}); return false;\">),
180
+ form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, :loading => "c1()", :success => "s()", :failure => "f();", :complete => "c();", 200=>"monkeys();", 404=>"bananas();")
181
+ end
182
+
183
+ def test_remote_form_for_with_record_identification_with_new_record
184
+ remote_form_for(@record, {:html => { :id => 'create-author' }}) {}
185
+
186
+ expected = %(<form action='#{authors_path}' onsubmit="new Ajax.Request('#{authors_path}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='new_author' id='create-author' method='post'></form>)
187
+ assert_dom_equal expected, output_buffer
188
+ end
189
+
190
+ def test_remote_form_for_with_record_identification_without_html_options
191
+ remote_form_for(@record) {}
192
+
193
+ expected = %(<form action='#{authors_path}' onsubmit="new Ajax.Request('#{authors_path}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='new_author' method='post' id='new_author'></form>)
194
+ assert_dom_equal expected, output_buffer
195
+ end
196
+
197
+ def test_remote_form_for_with_record_identification_with_existing_record
198
+ @record.save
199
+ remote_form_for(@record) {}
200
+
201
+ expected = %(<form action='#{author_path(@record)}' id='edit_author_1' method='post' onsubmit="new Ajax.Request('#{author_path(@record)}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='edit_author'><div style='margin:0;padding:0;display:inline'><input name='_method' type='hidden' value='put' /></div></form>)
202
+ assert_dom_equal expected, output_buffer
203
+ end
204
+
205
+ def test_remote_form_for_with_new_object_in_list
206
+ remote_form_for([@author, @article]) {}
207
+
208
+ expected = %(<form action='#{author_articles_path(@author)}' onsubmit="new Ajax.Request('#{author_articles_path(@author)}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='new_article' method='post' id='new_article'></form>)
209
+ assert_dom_equal expected, output_buffer
210
+ end
211
+
212
+ def test_remote_form_for_with_existing_object_in_list
213
+ @author.save
214
+ @article.save
215
+ remote_form_for([@author, @article]) {}
216
+
217
+ expected = %(<form action='#{author_article_path(@author, @article)}' id='edit_article_1' method='post' onsubmit="new Ajax.Request('#{author_article_path(@author, @article)}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='edit_article'><div style='margin:0;padding:0;display:inline'><input name='_method' type='hidden' value='put' /></div></form>)
218
+ assert_dom_equal expected, output_buffer
219
+ end
220
+
221
+
222
+ def test_button_to_remote
223
+ assert_dom_equal %(<input class=\"fine\" type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true});\" />),
224
+ button_to_remote("Remote outpost", { :url => { :action => "whatnot" }}, { :class => "fine" })
225
+ assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onComplete:function(request){alert(request.reponseText)}});\" />),
226
+ button_to_remote("Remote outpost", :complete => "alert(request.reponseText)", :url => { :action => "whatnot" })
227
+ assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onSuccess:function(request){alert(request.reponseText)}});\" />),
228
+ button_to_remote("Remote outpost", :success => "alert(request.reponseText)", :url => { :action => "whatnot" })
229
+ assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.reponseText)}});\" />),
230
+ button_to_remote("Remote outpost", :failure => "alert(request.reponseText)", :url => { :action => "whatnot" })
231
+ assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot?a=10&amp;b=20', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.reponseText)}});\" />),
232
+ button_to_remote("Remote outpost", :failure => "alert(request.reponseText)", :url => { :action => "whatnot", :a => '10', :b => '20' })
233
+ end
234
+
235
+ def test_submit_to_remote
236
+ assert_dom_equal %(<input name=\"More beer!\" onclick=\"new Ajax.Updater('empty_bottle', 'http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});\" type=\"button\" value=\"1000000\" />),
237
+ submit_to_remote("More beer!", 1_000_000, :update => "empty_bottle")
238
+ end
239
+
240
+
241
+ def test_link_to_remote
242
+ assert_dom_equal %(<a class=\"fine\" href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true}); return false;\">Remote outauthor</a>),
243
+ link_to_remote("Remote outauthor", { :url => { :action => "whatnot" }}, { :class => "fine" })
244
+ assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onComplete:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
245
+ link_to_remote("Remote outauthor", :complete => "alert(request.responseText)", :url => { :action => "whatnot" })
246
+ assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onSuccess:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
247
+ link_to_remote("Remote outauthor", :success => "alert(request.responseText)", :url => { :action => "whatnot" })
248
+ assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
249
+ link_to_remote("Remote outauthor", :failure => "alert(request.responseText)", :url => { :action => "whatnot" })
250
+ assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot?a=10&amp;b=20', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
251
+ link_to_remote("Remote outauthor", :failure => "alert(request.responseText)", :url => { :action => "whatnot", :a => '10', :b => '20' })
252
+ assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:false, evalScripts:true}); return false;\">Remote outauthor</a>),
253
+ link_to_remote("Remote outauthor", :url => { :action => "whatnot" }, :type => :synchronous)
254
+ assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, insertion:'bottom'}); return false;\">Remote outauthor</a>),
255
+ link_to_remote("Remote outauthor", :url => { :action => "whatnot" }, :position => :bottom)
256
+ end
257
+
258
+ def test_link_to_remote_html_options
259
+ assert_dom_equal %(<a class=\"fine\" href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true}); return false;\">Remote outauthor</a>),
260
+ link_to_remote("Remote outauthor", { :url => { :action => "whatnot" }, :html => { :class => "fine" } })
261
+ end
262
+
263
+ def test_link_to_remote_url_quote_escaping
264
+ assert_dom_equal %(<a href="#" onclick="new Ajax.Request('http://www.example.com/whatnot\\\'s', {asynchronous:true, evalScripts:true}); return false;">Remote</a>),
265
+ link_to_remote("Remote", { :url => { :action => "whatnot's" } })
266
+ end
267
+
268
+ protected
269
+ def request_forgery_protection_token
270
+ nil
271
+ end
272
+
273
+ def protect_against_forgery?
274
+ false
275
+ end
276
+
277
+ def create_generator
278
+ block = Proc.new { |*args| yield *args if block_given? }
279
+ JavaScriptGenerator.new self, &block
280
+ end
281
+
282
+ def author_path(record)
283
+ "/authors/#{record.id}"
284
+ end
285
+
286
+ def authors_path
287
+ "/authors"
288
+ end
289
+
290
+ def author_articles_path(author)
291
+ "/authors/#{author.id}/articles"
292
+ end
293
+
294
+ def author_article_path(author, article)
295
+ "/authors/#{author.id}/articles/#{article.id}"
296
+ end
297
+ end
@@ -0,0 +1,5 @@
1
+ *SVN*
2
+
3
+ * Make Upload Progress work with edge Rails [4388] and higher, retain compatibility to earlier builds
4
+
5
+ * Make Upload Progress work with edge Rails [3526] and higher, retain compatibility to earlier builds
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2004 Sean Treadway, Thomas Fuchs
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,45 @@
1
+ =Overview
2
+
3
+ The upload progress plugin will alter your rails CGI handling to track the uploaded status of multipart/form encoded posts. The plugin will also add helper methods to create an AJAX updating progress bar.
4
+
5
+ ==Installing
6
+
7
+ Run "script/plugin upload_progress" or checkout the source into your plugins folder.
8
+
9
+ svn checkout http://dev.rubyonrails.com/svn/plugins/upload_progress
10
+
11
+ Expand this archive in your Rails.root/vendor/plugins directory. The resulting plugin directory should look like:
12
+
13
+ Rails.root/vendor/plugins/upload_progress/
14
+ Rails.root/vendor/plugins/upload_progress/README.txt
15
+ Rails.root/vendor/plugins/upload_progress/Rakefile
16
+ Rails.root/vendor/plugins/upload_progress/init.rb
17
+ Rails.root/vendor/plugins/upload_progress/public/
18
+ Rails.root/vendor/plugins/upload_progress/public/stylesheets/
19
+ Rails.root/vendor/plugins/upload_progress/public/stylesheets/upload_progress.css
20
+ Rails.root/vendor/plugins/upload_progress/lib/
21
+ Rails.root/vendor/plugins/upload_progress/doc/
22
+ Rails.root/vendor/plugins/upload_progress/test/
23
+
24
+ The stylesheets included in public/stylesheets are used as a guideline for styling your progress bar and status messages. You can copy them directly into your own public/stylesheets folder or copy and paste.
25
+
26
+ ==Documentation
27
+
28
+ You can create the documentation by running:
29
+
30
+ rake rdoc
31
+
32
+ ==Requirements
33
+
34
+ The requirments for getting periodic upload progress updates can be found here:
35
+
36
+ http://sean.treadway.info/articles/2005/07/18/upload-progress-checklist
37
+
38
+ ==Credits
39
+
40
+ Sean Treadway <seant@superchannel.org> http://sean.treadway.info
41
+ Thomas Fuchs <thomas@fesch.at> http://mir.aculo.us
42
+
43
+ ==License
44
+
45
+ This plugin is released under the MIT license. See MIT-LICENSE for details
@@ -5,18 +5,19 @@ require 'rake/rdoctask'
5
5
  desc 'Default: run unit tests.'
6
6
  task :default => :test
7
7
 
8
- desc 'Test acts_as_tree plugin.'
8
+ desc 'Test the upload progress plugin.'
9
9
  Rake::TestTask.new(:test) do |t|
10
10
  t.libs << 'lib'
11
11
  t.pattern = 'test/**/*_test.rb'
12
12
  t.verbose = true
13
13
  end
14
14
 
15
- desc 'Generate documentation for acts_as_tree plugin.'
15
+ desc 'Generate documentation for the upload progress plugin.'
16
16
  Rake::RDocTask.new(:rdoc) do |rdoc|
17
17
  rdoc.rdoc_dir = 'rdoc'
18
- rdoc.title = 'acts_as_tree'
19
- rdoc.options << '--line-numbers' << '--inline-source'
20
- rdoc.rdoc_files.include('README')
18
+ rdoc.title = 'Upload progress'
19
+ rdoc.options << '--line-numbers --inline-source'
20
+ rdoc.rdoc_files.include('README.txt')
21
21
  rdoc.rdoc_files.include('lib/**/*.rb')
22
22
  end
23
+
@@ -0,0 +1,7 @@
1
+ require 'multipart_progress'
2
+ require 'progress'
3
+ require 'upload_progress'
4
+ require 'upload_progress_helper'
5
+
6
+ ActionController::Base.send(:include, UploadProgress)
7
+ ActionView::Base.send(:include, UploadProgress::UploadProgressHelper)
@@ -0,0 +1,176 @@
1
+ # == Overview
2
+ #
3
+ # This module will extend the CGI module with methods to track the upload
4
+ # progress for multipart forms for use with progress meters. The progress is
5
+ # saved in the session to be used from any request from any server with the
6
+ # same session. In other words, this module will work across application
7
+ # instances.
8
+ #
9
+ # === Usage
10
+ #
11
+ # Just do your file-uploads as you normally would, but include an upload_id in
12
+ # the query string of your form action. Your form post action should look
13
+ # like:
14
+ #
15
+ # <form method="post" enctype="multipart/form-data" action="postaction?upload_id=SOMEIDYOUSET">
16
+ # <input type="file" name="client_file"/>
17
+ # </form>
18
+ #
19
+ # Query the upload state in a progress by reading the progress from the session
20
+ #
21
+ # class UploadController < ApplicationController
22
+ # def upload_status
23
+ # render :text => "Percent complete: " + @session[:uploads]['SOMEIDYOUSET'].completed_percent"
24
+ # end
25
+ # end
26
+ #
27
+ # === Session options
28
+ #
29
+ # Upload progress uses the session options defined in
30
+ # ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS. If you are passing
31
+ # custom session options to your dispatcher then please follow the
32
+ # "recommended way to change session options":http://wiki.rubyonrails.com/rails/show/HowtoChangeSessionOptions
33
+ #
34
+ # === Update frequency
35
+ #
36
+ # During an upload, the progress will be written to the session every 2
37
+ # seconds. This prevents excessive writes yet maintains a decent picture of
38
+ # the upload progress for larger files.
39
+ #
40
+ # User interfaces that update more often that every 2 seconds will display the same results.
41
+ # Consider this update frequency when designing your progress polling.
42
+ #
43
+
44
+ require 'cgi'
45
+
46
+ class CGI #:nodoc:
47
+ class ProgressIO < SimpleDelegator #:nodoc:
48
+ MIN_SAVE_INTERVAL = 1.0 # Number of seconds between session saves
49
+
50
+ attr_reader :progress, :session
51
+
52
+ def initialize(orig_io, progress, session)
53
+ @session = session
54
+ @progress = progress
55
+
56
+ @start_time = Time.now
57
+ @last_save_time = @start_time
58
+ save_progress
59
+
60
+ super(orig_io)
61
+ end
62
+
63
+ def read(*args)
64
+ data = __getobj__.read(*args)
65
+
66
+ if data and data.size > 0
67
+ now = Time.now
68
+ elapsed = now - @start_time
69
+ progress.update!(data.size, elapsed)
70
+
71
+ if now - @last_save_time > MIN_SAVE_INTERVAL
72
+ save_progress
73
+ @last_save_time = now
74
+ end
75
+ else
76
+ ActionController::Base.logger.debug("CGI::ProgressIO#read returns nothing when it should return nil if IO is finished: [#{args.inspect}], a cancelled upload or old FCGI bindings. Resetting the upload progress")
77
+
78
+ progress.reset!
79
+ save_progress
80
+ end
81
+
82
+ data
83
+ end
84
+
85
+ def save_progress
86
+ @session.update
87
+ end
88
+
89
+ def finish
90
+ @session.update
91
+ ActionController::Base.logger.debug("Finished processing multipart upload in #{@progress.elapsed_seconds.to_s}s")
92
+ end
93
+ end
94
+
95
+ module QueryExtension #:nodoc:
96
+ # Need to do lazy aliasing on the instance that we are extending because of the way QueryExtension
97
+ # gets included for each instance of the CGI object rather than on a module level. This method is a
98
+ # bit obtrusive because we are overriding CGI::QueryExtension::extended which could be used in the
99
+ # future. Need to research a better method
100
+ def self.extended(obj)
101
+ obj.instance_eval do
102
+ # unless defined? will prevent clobbering the progress IO on multiple extensions
103
+ alias :stdinput_without_progress :stdinput unless defined? stdinput_without_progress
104
+ alias :stdinput :stdinput_with_progress
105
+ end
106
+ end
107
+
108
+ def stdinput_with_progress
109
+ @stdin_with_progress or stdinput_without_progress
110
+ end
111
+
112
+ private
113
+ # Bootstrapped on UploadProgress::upload_status_for
114
+ def read_multipart_with_progress(boundary, content_length)
115
+ begin
116
+ begin
117
+ # Session disabled if the default session options have been set to 'false'
118
+ options = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS
119
+ raise RuntimeError.new("Multipart upload progress disabled, no session options") unless options
120
+
121
+ options = options.stringify_keys
122
+
123
+ # Pull in the application controller to satisfy any dependencies on class definitions
124
+ # of instances stored in the session.
125
+ # Be sure to stay compatible with Rails 1.0/const_load!
126
+ if Object.const_defined?(:Controllers) and Controllers.respond_to?(:const_load!)
127
+ Controllers.const_load!(:ApplicationController, "application") unless Controllers.const_defined?(:ApplicationController)
128
+ else
129
+ require_dependency('application.rb') unless Object.const_defined?(:ApplicationController)
130
+ end
131
+
132
+ # Assumes that @cookies has already been setup
133
+ # Raises nomethod if upload_id is not defined
134
+ @params = CGI::parse(read_params_from_query)
135
+ upload_id = @params[(options['upload_key'] || 'upload_id')].first
136
+ raise RuntimeError.new("Multipart upload progress disabled, no upload id in query string") unless upload_id
137
+
138
+ upload_progress = UploadProgress::Progress.new(content_length)
139
+
140
+ session = Session.new(self, options)
141
+ session[:uploads] = {} unless session[:uploads]
142
+ session[:uploads].delete(upload_id) # in case the same upload id is used twice
143
+ session[:uploads][upload_id] = upload_progress
144
+
145
+ @stdin_with_progress = CGI::ProgressIO.new(stdinput_without_progress, upload_progress, session)
146
+ ActionController::Base.logger.debug("Multipart upload with progress (id: #{upload_id}, size: #{content_length})")
147
+ rescue
148
+ ActionController::Base.logger.debug("Exception during setup of read_multipart_with_progress: #{$!}")
149
+ end
150
+ ensure
151
+ begin
152
+ params = read_multipart_without_progress(boundary, content_length)
153
+ @stdin_with_progress.finish if @stdin_with_progress.respond_to? :finish
154
+ ensure
155
+ @stdin_with_progress = nil
156
+ session.close if session
157
+ end
158
+ end
159
+ params
160
+ end
161
+
162
+ # Required because of changes in [4388]
163
+ unless private_instance_methods.include?("read_params_from_query")
164
+ def read_params_from_query
165
+ read_params(:get,nil)
166
+ end
167
+ end
168
+
169
+ # Prevent redefinition of aliases on multiple includes
170
+ unless private_instance_methods.include?("read_multipart_without_progress")
171
+ alias_method :read_multipart_without_progress, :read_multipart
172
+ alias_method :read_multipart, :read_multipart_with_progress
173
+ end
174
+
175
+ end
176
+ end