imagine_cms 3.0.0.beta6 → 3.0.0.beta7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +1 -1
- data/app/assets/images/codepress/line-numbers.png +0 -0
- data/app/assets/images/cropper/marqueeHoriz.gif +0 -0
- data/app/assets/images/cropper/marqueeVert.gif +0 -0
- data/app/assets/images/management/btn_add.gif +0 -0
- data/app/assets/images/management/btn_archive.gif +0 -0
- data/app/assets/images/management/btn_delete.gif +0 -0
- data/app/assets/images/management/btn_duplicate.gif +0 -0
- data/app/assets/images/management/btn_edit.gif +0 -0
- data/app/assets/images/management/btn_help.gif +0 -0
- data/app/assets/images/management/btn_new_page.gif +0 -0
- data/app/assets/images/management/btn_preview.gif +0 -0
- data/app/assets/images/management/btn_properties.gif +0 -0
- data/app/assets/images/management/btn_restore.gif +0 -0
- data/app/assets/images/management/btn_top_delete.gif +0 -0
- data/app/assets/images/management/btn_top_duplicate.gif +0 -0
- data/app/assets/images/management/btn_top_edit.gif +0 -0
- data/app/assets/images/management/btn_top_new.gif +0 -0
- data/app/assets/images/management/btn_top_preview.gif +0 -0
- data/app/assets/images/management/btn_top_properties.gif +0 -0
- data/app/assets/{manage → images/management}/bullet.gif +0 -0
- data/app/assets/images/management/cvv2_graphic.gif +0 -0
- data/app/assets/images/management/error.gif +0 -0
- data/app/assets/images/management/gallery_index.gif +0 -0
- data/app/assets/images/management/gallery_preview_overlay.png +0 -0
- data/app/assets/images/management/gallery_small_drag_overlay.png +0 -0
- data/app/assets/images/management/gallery_small_overlay.png +0 -0
- data/app/assets/images/management/gallery_sort.gif +0 -0
- data/app/assets/images/management/icon_download.gif +0 -0
- data/app/assets/images/management/icon_locked.png +0 -0
- data/app/assets/images/management/icon_page.gif +0 -0
- data/app/assets/images/management/icon_time.gif +0 -0
- data/app/assets/images/management/icon_unlocked.png +0 -0
- data/app/assets/images/management/page_loading.gif +0 -0
- data/app/assets/{manage → images/management}/start.gif +0 -0
- data/app/assets/images/management/vcard.gif +0 -0
- data/app/assets/javascripts/builder.js +101 -0
- data/app/assets/javascripts/codepress/codepress.html +36 -0
- data/app/assets/javascripts/codepress/codepress.js +130 -0
- data/app/assets/javascripts/codepress/engines/gecko.js +240 -0
- data/{vendor/gems/acts_as_tree/test/abstract_unit.rb → app/assets/javascripts/codepress/engines/khtml.js} +0 -0
- data/app/assets/javascripts/codepress/engines/msie.js +263 -0
- data/{vendor/gems/acts_as_tree/test/database.yml → app/assets/javascripts/codepress/engines/older.js} +0 -0
- data/app/assets/javascripts/codepress/engines/opera.js +259 -0
- data/app/assets/javascripts/codepress/languages/css.js +23 -0
- data/app/assets/javascripts/codepress/languages/generic.js +25 -0
- data/app/assets/javascripts/codepress/languages/html.js +63 -0
- data/app/assets/javascripts/codepress/languages/java.js +24 -0
- data/app/assets/javascripts/codepress/languages/javascript.js +30 -0
- data/app/assets/javascripts/codepress/languages/perl.js +27 -0
- data/app/assets/javascripts/codepress/languages/php.js +60 -0
- data/app/assets/javascripts/codepress/languages/ruby.js +26 -0
- data/app/assets/javascripts/codepress/languages/sql.js +30 -0
- data/app/assets/javascripts/codepress/languages/text.js +9 -0
- data/app/assets/javascripts/cropper.js +568 -0
- data/app/assets/javascripts/dojo/dojo.js +14155 -0
- data/app/assets/javascripts/dojo/src/html/images/shadowB.png +0 -0
- data/app/assets/javascripts/dojo/src/html/images/shadowBL.png +0 -0
- data/app/assets/javascripts/dojo/src/html/images/shadowBR.png +0 -0
- data/app/assets/javascripts/dojo/src/html/images/shadowL.png +0 -0
- data/app/assets/javascripts/dojo/src/html/images/shadowR.png +0 -0
- data/app/assets/javascripts/dojo/src/html/images/shadowT.png +0 -0
- data/app/assets/javascripts/dojo/src/html/images/shadowTL.png +0 -0
- data/app/assets/javascripts/dojo/src/html/images/shadowTR.png +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/Editor2/showtableborder_gecko.css +19 -0
- data/app/assets/javascripts/dojo/src/widget/templates/HslColorPicker.svg +30 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/aggregate.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/aggregate.psd +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/backcolor.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/bg-fade.png +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/bold.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/cancel.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/copy.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/createlink.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/cut.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/delete.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/forecolor.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/hilitecolor.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/indent.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/inserthorizontalrule.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/insertimage.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/insertorderedlist.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/inserttable.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/insertunorderedlist.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/italic.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifycenter.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifyfull.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifyleft.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifyright.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/left_to_right.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_bullet_indent.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_bullet_outdent.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_num_indent.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_num_outdent.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/outdent.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/paste.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/redo.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/removeformat.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/right_to_left.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/save.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/sep.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/space.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/strikethrough.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/subscript.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/superscript.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/underline.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/undo.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/buttons/wikiword.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/check.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/decrementMonth.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/decrementWeek.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/grabCorner.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/floatingPaneClose.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaAccordionOff.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaAccordionSelected.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaActive-c.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaActive-l.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaActive-r.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaBarBg.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaButton-c.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaButton-l.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaButton-r.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaDisabled-c.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaDisabled-l.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaDisabled-r.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaMenuBg.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaPressed-c.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaPressed-l.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/soriaPressed-r.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/tab_close.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/images/toolbar-bg.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/incrementMonth.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/incrementWeek.gif +0 -0
- data/app/assets/javascripts/dojo/src/widget/templates/richtextframe.html +24 -0
- data/app/assets/javascripts/imagine.js +1385 -0
- data/app/assets/javascripts/jquery_no_conflict.js +9405 -0
- data/app/assets/stylesheets/codepress/codepress.css +7 -0
- data/app/assets/stylesheets/codepress/languages/css.css +10 -0
- data/app/assets/stylesheets/codepress/languages/generic.css +9 -0
- data/app/assets/stylesheets/codepress/languages/html.css +18 -0
- data/app/assets/stylesheets/codepress/languages/java.css +7 -0
- data/app/assets/stylesheets/codepress/languages/javascript.css +8 -0
- data/app/assets/stylesheets/codepress/languages/perl.css +11 -0
- data/app/assets/stylesheets/codepress/languages/php.css +12 -0
- data/app/assets/stylesheets/codepress/languages/ruby.css +10 -0
- data/app/assets/stylesheets/codepress/languages/sql.css +10 -0
- data/app/assets/stylesheets/codepress/languages/text.css +5 -0
- data/app/assets/stylesheets/cropper.css +182 -0
- data/app/assets/stylesheets/management.css +96 -0
- data/app/assets/stylesheets/reset.css +58 -0
- data/app/controllers/cms/content_controller.rb +318 -2
- data/app/controllers/management/cms_controller.rb +1669 -0
- data/app/controllers/management/user_controller.rb +4 -4
- data/app/controllers/management/users_controller.rb +18 -4
- data/app/controllers/util_controller.rb +45 -0
- data/app/helpers/cms_application_helper.rb +662 -15
- data/app/models/cms_content_sweeper.rb +21 -0
- data/app/models/cms_page.rb +126 -0
- data/app/models/cms_page_object.rb +23 -0
- data/app/models/cms_page_tag.rb +5 -0
- data/app/models/cms_page_version.rb +3 -0
- data/app/models/cms_snippet.rb +16 -0
- data/app/models/cms_template.rb +29 -0
- data/app/models/user.rb +6 -3
- data/app/views/management/cms/_complete_gallery.html.erb +5 -0
- data/app/views/management/cms/_create_file_link.html.erb +21 -0
- data/app/views/management/cms/_crop_feature_image.html.erb +188 -0
- data/app/views/management/cms/_crop_image.html.erb +188 -0
- data/app/views/management/cms/_crop_results.html.erb +1 -0
- data/app/views/management/cms/_crop_results_feature_image.html.erb +1 -0
- data/app/views/management/cms/_crop_results_thumb.html.erb +1 -0
- data/app/views/management/cms/_crop_thumb.html.erb +188 -0
- data/app/views/management/cms/_dialogs.html.erb +39 -0
- data/app/views/management/cms/_edit_page.html.erb +176 -0
- data/app/views/management/cms/_gallery_index.html.erb +10 -0
- data/app/views/management/cms/_gallery_setup.html.erb +22 -0
- data/app/views/management/cms/_image.html.erb +3 -0
- data/app/views/management/cms/_image_details.html.erb +26 -0
- data/app/views/management/cms/_image_draggable.html.erb +4 -0
- data/app/views/management/cms/_list_page.html.erb +8 -0
- data/app/views/management/cms/_list_page_select.html.erb +8 -0
- data/app/views/management/cms/_list_pages.html.erb +1 -0
- data/app/views/management/cms/_list_pages_select.html.erb +1 -0
- data/app/views/management/cms/_page_attribute.html.erb +6 -0
- data/app/views/management/cms/_page_list.html.erb +171 -0
- data/app/views/management/cms/_page_list_source_folder.html.erb +20 -0
- data/app/views/management/cms/_page_list_source_tag.html.erb +18 -0
- data/app/views/management/cms/_select_gallery.html.erb +117 -0
- data/app/views/management/cms/_snippet.html.erb +3 -0
- data/app/views/management/cms/_sort_images.html.erb +15 -0
- data/app/views/management/cms/_temp.html.erb +3 -0
- data/app/views/management/cms/_template_options.html.erb +21 -0
- data/app/views/management/cms/_template_reference.html.erb +42 -0
- data/app/views/management/cms/_upload_feature_image.html.erb +35 -0
- data/app/views/management/cms/_upload_file.html.erb +31 -0
- data/app/views/management/cms/_upload_image.html.erb +74 -0
- data/app/views/management/cms/_upload_thumb.html.erb +35 -0
- data/app/views/management/cms/edit_master.html.erb +48 -0
- data/app/views/management/cms/edit_page_content.html.erb +4 -0
- data/app/views/management/cms/edit_snippet.html.erb +47 -0
- data/app/views/management/cms/edit_template.html.erb +48 -0
- data/app/views/management/cms/gallery_management.html.erb +108 -0
- data/app/views/management/cms/index.html.erb +20 -0
- data/app/views/management/cms/page_tags_for_lookup.html.erb +5 -0
- data/app/views/management/cms/pages.html.erb +99 -0
- data/app/views/management/cms/permission_denied.html.erb +1 -0
- data/app/views/management/cms/select_page.html.erb +57 -0
- data/app/views/management/cms/snippets.html.erb +14 -0
- data/app/views/management/cms/templates.html.erb +14 -0
- data/app/views/management/cms/toolbar_edit.html.erb +269 -0
- data/app/views/management/cms/toolbar_preview.html.erb +109 -0
- data/app/views/util/_calendar_days.html.erb +72 -0
- data/app/views/util/_calendar_month_year.html.erb +1 -0
- data/app/views/util/_date_picker.html.erb +56 -0
- data/app/views/util/_message.html.erb +1 -0
- data/app/views/util/_show_message.js.erb +6 -0
- data/app/views/util/_tab.html.erb +4 -0
- data/config/routes.rb +4 -1
- data/imagine_cms.gemspec +4 -0
- data/{vendor/gems → lib}/acts_as_versioned/.document +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/.gitignore +2 -0
- data/{vendor/gems → lib}/acts_as_versioned/CHANGELOG +0 -0
- data/lib/acts_as_versioned/Gemfile +7 -0
- data/{vendor/gems → lib}/acts_as_versioned/MIT-LICENSE +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/README +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/RUNNING_UNIT_TESTS +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/Rakefile +1 -1
- data/{vendor/gems → lib}/acts_as_versioned/acts_as_versioned.gemspec +4 -4
- data/{vendor/gems → lib}/acts_as_versioned/init.rb +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/lib/acts_as_versioned.rb +109 -107
- data/{vendor/gems → lib}/acts_as_versioned/test/abstract_unit.rb +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/test/database.yml +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/authors.yml +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/landmark.rb +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/landmark_versions.yml +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/landmarks.yml +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/locked_pages.yml +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/locked_pages_revisions.yml +0 -0
- 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
- data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/page.rb +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/page_versions.yml +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/pages.yml +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/widget.rb +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/test/migration_test.rb +0 -1
- data/{vendor/gems → lib}/acts_as_versioned/test/schema.rb +0 -0
- data/{vendor/gems → lib}/acts_as_versioned/test/versioned_test.rb +0 -0
- data/lib/extensions/action_controller.rb +154 -143
- data/lib/imagine_cms/engine.rb +33 -12
- data/lib/imagine_cms/version.rb +1 -1
- data/lib/imagine_cms.rb +30 -6
- data/lib/prototype_legacy_helper/README.markdown +13 -0
- data/lib/prototype_legacy_helper/init.rb +1 -0
- data/lib/prototype_legacy_helper/lib/prototype_legacy_helper.rb +430 -0
- data/lib/prototype_legacy_helper/test/test_prototype_helper.rb +297 -0
- data/lib/upload_progress/CHANGELOG +5 -0
- data/lib/upload_progress/MIT-LICENSE +20 -0
- data/lib/upload_progress/README +45 -0
- data/{vendor/gems/acts_as_tree → lib/upload_progress}/Rakefile +6 -5
- data/lib/upload_progress/init.rb +7 -0
- data/lib/upload_progress/lib/multipart_progress.rb +176 -0
- data/lib/upload_progress/lib/progress.rb +145 -0
- data/lib/upload_progress/lib/upload_progress.rb +303 -0
- data/lib/upload_progress/lib/upload_progress_helper.rb +425 -0
- data/lib/upload_progress/public/stylesheets/upload_progress.css +21 -0
- data/lib/upload_progress/test/multipart_progress_testx.rb +364 -0
- data/lib/upload_progress/test/upload_progress_helper_testx.rb +134 -0
- data/lib/upload_progress/test/upload_progress_testx.rb +88 -0
- metadata +305 -43
- data/app/assets/manage/btn_delete.gif +0 -0
- data/vendor/gems/.DS_Store +0 -0
- data/vendor/gems/acts_as_tree/README +0 -26
- data/vendor/gems/acts_as_tree/init.rb +0 -1
- data/vendor/gems/acts_as_tree/lib/active_record/acts/tree.rb +0 -96
- data/vendor/gems/acts_as_tree/test/acts_as_tree_test.rb +0 -219
- data/vendor/gems/acts_as_tree/test/fixtures/mixin.rb +0 -0
- data/vendor/gems/acts_as_tree/test/fixtures/mixins.yml +0 -0
- data/vendor/gems/acts_as_tree/test/schema.rb +0 -0
- 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&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&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,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
|
|
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
|
|
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 = '
|
|
19
|
-
rdoc.options << '--line-numbers
|
|
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,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
|