pageflow 12.6.0 → 13.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pageflow might be problematic. Click here for more details.

Files changed (215) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +78 -16
  3. data/README.md +8 -1
  4. data/Rakefile +0 -4
  5. data/admins/pageflow/accounts.rb +6 -9
  6. data/admins/pageflow/entry.rb +1 -1
  7. data/admins/pageflow/folder.rb +1 -1
  8. data/admins/pageflow/user.rb +4 -4
  9. data/app/assets/javascripts/pageflow/asset_urls.js.erb +1 -1
  10. data/app/assets/javascripts/pageflow/audio/multi_player.js +0 -4
  11. data/app/assets/javascripts/pageflow/audio_player.js +1 -1
  12. data/app/assets/javascripts/pageflow/base.js +0 -2
  13. data/app/assets/javascripts/pageflow/browser/agent.js +78 -92
  14. data/app/assets/javascripts/pageflow/browser/autoplay_support.js +2 -2
  15. data/app/assets/javascripts/pageflow/browser/video.js +1 -6
  16. data/app/assets/javascripts/pageflow/dist/react.js +1100 -2209
  17. data/app/assets/javascripts/pageflow/editor/models/configuration.js +5 -5
  18. data/app/assets/javascripts/pageflow/editor/templates/background_positioning_sliders.jst.ejs +0 -8
  19. data/app/assets/javascripts/pageflow/editor/views/background_positioning_sliders_view.js +23 -37
  20. data/app/assets/javascripts/pageflow/editor/views/background_positioning_view.js +2 -2
  21. data/app/assets/javascripts/pageflow/editor/views/configuration_editors/video.js +1 -1
  22. data/app/assets/javascripts/pageflow/editor/views/edit_widget_view.js +0 -9
  23. data/app/assets/javascripts/pageflow/jquery_utils.js +0 -10
  24. data/app/assets/javascripts/pageflow/media_player.js +3 -7
  25. data/app/assets/javascripts/pageflow/media_player/catch_play_promise.js +23 -0
  26. data/app/assets/javascripts/pageflow/media_player/volume_binding.js +1 -2
  27. data/app/assets/javascripts/pageflow/media_player/volume_fading/web_audio.js +24 -73
  28. data/app/assets/javascripts/pageflow/ready.js +1 -2
  29. data/app/assets/javascripts/pageflow/seed_entry_data.js +3 -3
  30. data/app/assets/javascripts/pageflow/slideshow.js +9 -17
  31. data/app/assets/javascripts/pageflow/slideshow/adjacent_pages.js +4 -9
  32. data/app/assets/javascripts/pageflow/slideshow/{successor_preparer.js → adjacent_preparer.js} +11 -14
  33. data/app/assets/javascripts/pageflow/slideshow/atmo.js +12 -23
  34. data/app/assets/javascripts/pageflow/slideshow/lazy_page_widget.js +2 -2
  35. data/app/assets/javascripts/pageflow/slideshow/progressive_preload.js +42 -0
  36. data/app/assets/javascripts/pageflow/ui/views/configuration_editor_view.js +2 -2
  37. data/app/assets/javascripts/pageflow/video_player/filter_sources.js +2 -16
  38. data/app/assets/javascripts/pageflow/video_player/lazy.js +1 -1
  39. data/app/assets/javascripts/pageflow/visited.js +0 -2
  40. data/app/assets/javascripts/pageflow/widgets.js +0 -1
  41. data/app/assets/javascripts/pageflow/widgets/multimedia_alert.js +1 -2
  42. data/app/assets/javascripts/pageflow/widgets/navigation.js +0 -1
  43. data/app/assets/javascripts/pageflow/widgets/navigation_mobile.js +0 -1
  44. data/app/assets/javascripts/pageflow/widgets/overview.js +1 -3
  45. data/app/assets/stylesheets/pageflow/admin.scss +2 -0
  46. data/app/assets/stylesheets/pageflow/admin/status_tags.scss +13 -0
  47. data/app/assets/stylesheets/pageflow/editor/background_positioning.scss +10 -34
  48. data/app/assets/stylesheets/pageflow/navigation_bar.scss +4 -0
  49. data/app/assets/stylesheets/pageflow/page_types/video.scss +4 -1
  50. data/app/assets/stylesheets/pageflow/themes/default/anchors.scss +0 -5
  51. data/app/assets/stylesheets/pageflow/themes/default/base.scss +0 -2
  52. data/app/assets/stylesheets/pageflow/themes/default/overview/icons/icon_font.scss +1 -4
  53. data/app/assets/stylesheets/pageflow/themes/default/page.scss +0 -19
  54. data/app/assets/stylesheets/pageflow/themes/default/page/anchors.scss +0 -4
  55. data/app/assets/stylesheets/pageflow/themes/default/slideshow.scss +0 -1
  56. data/app/controllers/concerns/pageflow/edit_locking.rb +2 -2
  57. data/app/controllers/concerns/pageflow/public_https_mode.rb +1 -5
  58. data/app/controllers/concerns/pageflow/quota_verification.rb +1 -1
  59. data/app/controllers/pageflow/application_controller.rb +2 -2
  60. data/app/controllers/pageflow/chapters_controller.rb +2 -2
  61. data/app/controllers/pageflow/edit_locks_controller.rb +1 -1
  62. data/app/controllers/pageflow/editor/encoding_confirmations_controller.rb +1 -1
  63. data/app/controllers/pageflow/editor/entries_controller.rb +1 -1
  64. data/app/controllers/pageflow/editor/entry_publications_controller.rb +1 -1
  65. data/app/controllers/pageflow/editor/files_controller.rb +1 -1
  66. data/app/controllers/pageflow/entries_controller.rb +5 -11
  67. data/app/controllers/pageflow/files_controller.rb +1 -1
  68. data/app/controllers/pageflow/pages_controller.rb +2 -2
  69. data/app/controllers/pageflow/revisions_controller.rb +1 -1
  70. data/app/controllers/pageflow/storylines_controller.rb +2 -3
  71. data/app/helpers/pageflow/common_entry_seed_helper.rb +0 -1
  72. data/app/helpers/pageflow/entries_helper.rb +6 -31
  73. data/app/helpers/pageflow/entry_json_seed_helper.rb +1 -1
  74. data/app/helpers/pageflow/public_i18n_helper.rb +1 -6
  75. data/app/jobs/pageflow/application_job.rb +6 -0
  76. data/app/jobs/pageflow/poll_meta_data_from_zencoder_job.rb +2 -4
  77. data/app/jobs/pageflow/poll_zencoder_job.rb +8 -8
  78. data/app/jobs/pageflow/process_file_job.rb +4 -4
  79. data/app/jobs/pageflow/prune_auto_snapshots_job.rb +3 -3
  80. data/app/jobs/pageflow/request_meta_data_from_zencoder_job.rb +4 -4
  81. data/app/jobs/pageflow/submit_file_to_zencoder_job.rb +4 -4
  82. data/app/jobs/pageflow/upload_file_to_s3_job.rb +5 -5
  83. data/app/mailers/pageflow/user_mailer.rb +1 -15
  84. data/app/models/concerns/pageflow/uploaded_file.rb +3 -3
  85. data/app/models/pageflow/audio_file.rb +1 -1
  86. data/app/models/pageflow/chapter.rb +1 -1
  87. data/app/models/pageflow/entry.rb +1 -1
  88. data/app/models/pageflow/invited_user.rb +1 -1
  89. data/app/models/pageflow/membership.rb +4 -2
  90. data/app/models/pageflow/page.rb +1 -1
  91. data/app/models/pageflow/published_entry.rb +3 -4
  92. data/app/models/pageflow/revision.rb +5 -3
  93. data/app/models/pageflow/storyline.rb +5 -1
  94. data/app/models/pageflow/theming.rb +1 -2
  95. data/app/models/pageflow/used_file.rb +12 -0
  96. data/app/models/pageflow/video_file.rb +1 -1
  97. data/app/views/admin/accounts/_form.html.erb +0 -8
  98. data/app/views/admin/accounts/_theming_details.html.arb +0 -3
  99. data/app/views/pageflow/entries/_mobile_navigation.html.erb +3 -2
  100. data/app/views/pageflow/entries/navigation/_page.html.erb +1 -3
  101. data/app/views/pageflow/entries/overview/_page.html.erb +1 -1
  102. data/app/views/pageflow/entry_json_seed/_entry.json.jbuilder +1 -1
  103. data/app/views/pageflow/user_mailer/invitation.html.erb +2 -2
  104. data/app/views/pageflow/user_mailer/invitation.text.erb +1 -1
  105. data/config/locales/de.yml +6 -16
  106. data/config/locales/en.yml +8 -18
  107. data/config/routes.rb +0 -6
  108. data/db/migrate/20140418225525_setup_schema.rb +295 -203
  109. data/db/migrate/20140418240000_add_attributes_to_users.rb +3 -6
  110. data/lib/generators/pageflow/resque/resque_generator.rb +6 -3
  111. data/lib/pageflow.rb +1 -1
  112. data/lib/pageflow/ability_mixin.rb +0 -1
  113. data/lib/pageflow/active_admin_patches/views/attributes_table.rb +1 -1
  114. data/lib/pageflow/active_admin_patches/views/table_for.rb +1 -1
  115. data/lib/pageflow/built_in_widget_type.rb +0 -8
  116. data/lib/pageflow/built_in_widget_types_plugin.rb +0 -2
  117. data/lib/pageflow/configuration.rb +0 -10
  118. data/lib/pageflow/engine.rb +5 -9
  119. data/lib/pageflow/user_mixin.rb +5 -0
  120. data/lib/pageflow/version.rb +1 -1
  121. data/lib/tasks/pageflow_tasks.rake +1 -11
  122. data/spec/factories/accounts.rb +1 -1
  123. data/spec/factories/audio_files.rb +1 -1
  124. data/spec/factories/chapters.rb +1 -3
  125. data/spec/factories/edit_locks.rb +2 -4
  126. data/spec/factories/entries.rb +1 -1
  127. data/spec/factories/feature_targets.rb +1 -1
  128. data/spec/factories/file_usages.rb +1 -1
  129. data/spec/factories/folders.rb +1 -1
  130. data/spec/factories/hosted_files.rb +6 -6
  131. data/spec/factories/image_files.rb +1 -1
  132. data/spec/factories/invited_user.rb +1 -1
  133. data/spec/factories/memberships.rb +1 -1
  134. data/spec/factories/pages.rb +1 -1
  135. data/spec/factories/revisions.rb +1 -1
  136. data/spec/factories/storylines.rb +1 -1
  137. data/spec/factories/text_track_files.rb +1 -1
  138. data/spec/factories/themings.rb +1 -1
  139. data/spec/factories/users.rb +1 -1
  140. data/spec/factories/video_files.rb +1 -1
  141. data/spec/factories/widgets.rb +1 -1
  142. data/vendor/assets/javascripts/audio5.min.js +129 -280
  143. metadata +103 -219
  144. data/app/assets/audios/pageflow/unmute.mp3 +0 -0
  145. data/app/assets/javascripts/pageflow/background_media.js +0 -22
  146. data/app/assets/javascripts/pageflow/cookie_notice.js +0 -7
  147. data/app/assets/javascripts/pageflow/editor/views/info_box_view.js +0 -8
  148. data/app/assets/javascripts/pageflow/editor/views/widget_types/cookie_notice_bar.js +0 -15
  149. data/app/assets/javascripts/pageflow/media_player/handle_failed_play.js +0 -34
  150. data/app/assets/javascripts/pageflow/slideshow/adjacent_preloader.js +0 -26
  151. data/app/assets/stylesheets/pageflow/page_types/video/mobile_poster.scss +0 -15
  152. data/app/assets/stylesheets/pageflow/themes/default/background_media_unmute_button.scss +0 -77
  153. data/app/assets/stylesheets/pageflow/themes/default/cookie_notice_bar.scss +0 -57
  154. data/app/assets/stylesheets/pageflow/themes/default/page/hyphenate.scss +0 -24
  155. data/app/controllers/pageflow/admin/initial_passwords_controller.rb +0 -8
  156. data/app/views/pageflow/admin/initial_passwords/edit.html.erb +0 -16
  157. data/app/views/pageflow/entries/mobile_navigation/_page.html.erb +0 -5
  158. data/db/migrate/20140624135420_create_themings.rb +0 -15
  159. data/db/migrate/20140624135421_create_themings_for_existing_accounts.rb +0 -26
  160. data/db/migrate/20140624135422_change_theme_references_to_theming_references.rb +0 -45
  161. data/db/migrate/20140624135423_remove_attributes_from_themes.rb +0 -10
  162. data/db/migrate/20140624135424_create_accounts_themes_join_table.rb +0 -8
  163. data/db/migrate/20140624135425_move_cname_from_account_to_theming.rb +0 -21
  164. data/db/migrate/20140625184800_drop_themes.rb +0 -14
  165. data/db/migrate/20140704110631_add_confirmed_by_to_encoded_files.rb +0 -6
  166. data/db/migrate/20140819081454_add_home_url_attributes_to_themings_and_revisions.rb +0 -9
  167. data/db/migrate/20141027102310_create_widgets.rb +0 -11
  168. data/db/migrate/20141028125408_add_emphasize_chapter_beginning_to_revisions.rb +0 -5
  169. data/db/migrate/20141119164526_add_emphasize_new_pages_to_revisions.rb +0 -5
  170. data/db/migrate/20141119174032_add_sharing_image_to_revisions.rb +0 -7
  171. data/db/migrate/20141128150305_add_locale_to_users.rb +0 -5
  172. data/db/migrate/20141208161030_add_locale_to_revisions.rb +0 -5
  173. data/db/migrate/20141211110226_add_configuration_to_chapters.rb +0 -5
  174. data/db/migrate/20150115175116_add_features_configuration_to_accounts.rb +0 -5
  175. data/db/migrate/20150115175207_add_features_configuration_to_entries.rb +0 -5
  176. data/db/migrate/20150603091823_add_password_attributes_to_revisions.rb +0 -6
  177. data/db/migrate/20150825133449_update_audio_loop_pages_to_use_atmo.rb +0 -24
  178. data/db/migrate/20150826125417_create_pageflow_storylines.rb +0 -12
  179. data/db/migrate/20150826125744_add_storyline_id_to_chapters.rb +0 -6
  180. data/db/migrate/20150826125745_insert_main_storylines.rb +0 -28
  181. data/db/migrate/20150830105831_remove_revision_id_from_chapters.rb +0 -5
  182. data/db/migrate/20150830110006_remove_entry_id_from_chapters.rb +0 -5
  183. data/db/migrate/20151022080518_add_first_published_at_to_entries.rb +0 -14
  184. data/db/migrate/20160131222203_add_cache_counters.rb +0 -23
  185. data/db/migrate/20160201130118_add_additional_cnames_to_themings.rb +0 -5
  186. data/db/migrate/20160216130336_add_meta_fields_to_revision.rb +0 -7
  187. data/db/migrate/20160225075853_add_overview_button_enabled_to_revisions.rb +0 -5
  188. data/db/migrate/20160304072911_rename_membership_entry_and_make_polymorphic.rb +0 -19
  189. data/db/migrate/20160304151327_add_role_to_membership.rb +0 -19
  190. data/db/migrate/20160310080213_add_edited_at_to_entries.rb +0 -9
  191. data/db/migrate/20160425192648_add_index_for_revision_publication_timestamps.rb +0 -5
  192. data/db/migrate/20160504093145_replace_role_and_account_on_user.rb +0 -42
  193. data/db/migrate/20160531152500_update_users_count.rb +0 -27
  194. data/db/migrate/20160617123557_add_meta_fields_to_theming.rb +0 -7
  195. data/db/migrate/20160707125400_add_output_presences_to_video_files.rb +0 -5
  196. data/db/migrate/20160715105408_add_share_url_to_revisions.rb +0 -5
  197. data/db/migrate/20160824115000_add_parent_file_to_video_files.rb +0 -8
  198. data/db/migrate/20160824115100_add_parent_file_to_audio_files.rb +0 -8
  199. data/db/migrate/20160824115200_add_parent_file_to_image_files.rb +0 -8
  200. data/db/migrate/20160929102700_add_configuration_to_files.rb +0 -7
  201. data/db/migrate/20161007144500_add_text_track_files.rb +0 -31
  202. data/db/migrate/20161216175734_move_configuration_from_file_to_file_usage.rb +0 -27
  203. data/db/migrate/20161230144429_add_processed_attachment_to_text_track_files.rb +0 -8
  204. data/db/migrate/20170201074328_add_configuration_to_widgets.rb +0 -5
  205. data/db/migrate/20170222124848_update_video_file_output_presences.rb +0 -12
  206. data/db/migrate/20170315130000_add_theme_name_to_revisions.rb +0 -12
  207. data/db/migrate/20170421112300_turn_background_video_pages_into_background_image_pages.rb +0 -22
  208. data/db/migrate/20170912165050_reset_copied_snapshot_type.rb +0 -24
  209. data/db/migrate/20170913105048_fix_hls_output_presences_for_legacy_video_files.rb +0 -12
  210. data/db/migrate/20180528144334_add_privacy_link_url_to_themings.rb +0 -5
  211. data/db/migrate/20190109085744_add_default_locale_to_themings.rb +0 -6
  212. data/lib/generators/pageflow/resque/templates/devise_async.rb +0 -6
  213. data/lib/generators/pageflow/resque/templates/resque_logger.rb +0 -16
  214. data/lib/generators/pageflow/resque/templates/resque_mailer.rb +0 -4
  215. data/lib/pageflow/primary_domain_entry_redirect.rb +0 -25
@@ -1,4 +1,4 @@
1
- class AddAttributesToUsers < ActiveRecord::Migration
1
+ class AddAttributesToUsers < ActiveRecord::Migration[4.2]
2
2
  def change
3
3
  add_column :users, :failed_attempts, :integer, default: 0
4
4
  add_column :users, :locked_at, :datetime
@@ -6,10 +6,7 @@ class AddAttributesToUsers < ActiveRecord::Migration
6
6
  add_column :users, :first_name, :string
7
7
  add_column :users, :last_name, :string
8
8
  add_column :users, :suspended_at, :datetime
9
- add_column :users, :account_id, :integer
10
- add_column :users, :role, :string, default: "editor", null: false
11
-
12
- add_index :users, [:account_id], name: "index_pageflow_users_on_account_id", using: :btree
13
- add_index :users, [:email], name: "index_pageflow_users_on_email", unique: true, using: :btree
9
+ add_column :users, :locale, :string
10
+ add_column :users, :admin, :boolean, null: false, default: false
14
11
  end
15
12
  end
@@ -9,11 +9,14 @@ module Pageflow
9
9
 
10
10
  def create_initializers
11
11
  template 'resque.rb', 'config/initializers/resque.rb'
12
- template 'resque_mailer.rb', 'config/initializers/resque_mailer.rb'
13
- template 'resque_logger.rb', 'config/initializers/resque_logger.rb'
14
12
  template 'resque_enqueue_after_commit_patch.rb', 'config/initializers/resque_enqueue_after_commit_patch.rb'
15
- template 'devise_async.rb', 'config/initializers/devise_async.rb'
16
13
  template 'resque.rake', 'lib/tasks/resque.rake'
14
+
15
+ inject_into_file 'config/application.rb', after: "config.load_defaults 5.2\n" do
16
+ <<-RUBY
17
+ config.active_job.queue_adapter = :resque
18
+ RUBY
19
+ end
17
20
  end
18
21
  end
19
22
  end
data/lib/pageflow.rb CHANGED
@@ -27,7 +27,7 @@ module Pageflow
27
27
  end
28
28
 
29
29
  def self.active_admin_settings(config)
30
- config.before_filter do
30
+ config.before_action do
31
31
  I18n.locale = current_user.try(:locale) || http_accept_language.compatible_language_from(I18n.available_locales) || I18n.default_locale
32
32
  end
33
33
  end
@@ -259,7 +259,6 @@ module Pageflow
259
259
  can :manage, [Entry, Revision]
260
260
  can :manage, Pageflow.config.file_types.map(&:model)
261
261
  can :manage, Folder
262
- can :manage, Resque
263
262
  can :manage, Theming
264
263
  can :manage, ::User
265
264
  end
@@ -19,7 +19,7 @@ module Pageflow
19
19
  type = value ? types.first : types.last
20
20
 
21
21
  if type
22
- status_tag(status, type, class: name.to_s.gsub(/\?$/, ''), label: text)
22
+ status_tag(status, class: [type, name.to_s.gsub(/\?$/, '')].join(' '), label: text)
23
23
  else
24
24
  text
25
25
  end
@@ -30,7 +30,7 @@ module Pageflow
30
30
  type = value ? types.first : types.last
31
31
 
32
32
  if type
33
- status_tag(status, type, class: name.to_s.gsub(/\?$/, ''), label: text)
33
+ status_tag(status, class: [type, name.to_s.gsub(/\?$/, '')].join(' '), label: text)
34
34
  else
35
35
  text
36
36
  end
@@ -31,13 +31,5 @@ module Pageflow
31
31
  def self.slim_player_controls
32
32
  new('slim_player_controls', ['player_controls'], 'pageflow/widgets/placeholder')
33
33
  end
34
-
35
- def self.cookie_notice_bar
36
- Pageflow::React.create_widget_type('cookie_notice_bar', 'cookie_notice')
37
- end
38
-
39
- def self.unmute_button
40
- Pageflow::React.create_widget_type('unmute_button', 'background_media_control')
41
- end
42
34
  end
43
35
  end
@@ -5,8 +5,6 @@ module Pageflow
5
5
  config.widget_types.register(Pageflow::BuiltInWidgetType.mobile_navigation, default: true)
6
6
  config.widget_types.register(Pageflow::BuiltInWidgetType.slim_player_controls)
7
7
  config.widget_types.register(Pageflow::BuiltInWidgetType.classic_player_controls, default: true)
8
- config.widget_types.register(Pageflow::BuiltInWidgetType.cookie_notice_bar)
9
- config.widget_types.register(Pageflow::BuiltInWidgetType.unmute_button, default: true)
10
8
  end
11
9
  end
12
10
  end
@@ -155,15 +155,6 @@ module Pageflow
155
155
  # end
156
156
  attr_accessor :public_entry_request_scope
157
157
 
158
- # Either a lambda or an object with a `call` method taking an
159
- # {Entry} record and an {ActionDispatch::Request} object and
160
- # returning `nil` or a path to redirect to. Can be used in
161
- # conjuction with {PrimaryDomainEntryRedirect} to make sure
162
- # entries are accessed via their account's configured cname.
163
- #
164
- # @since 12.4
165
- attr_accessor :public_entry_redirect
166
-
167
158
  # Either a lambda or an object with a `call` method taking a
168
159
  # {Theming} as paramater and returing a hash of options used to
169
160
  # construct the url of a published entry.
@@ -324,7 +315,6 @@ module Pageflow
324
315
 
325
316
  @theming_request_scope = CnameThemingRequestScope.new
326
317
  @public_entry_request_scope = lambda { |entries, request| entries }
327
- @public_entry_redirect = ->(_entry, _request) { nil }
328
318
  @public_entry_url_options = Pageflow::ThemingsHelper::DEFAULT_PUBLIC_ENTRY_OPTIONS
329
319
  @entry_embed_url_options = {protocol: 'https'}
330
320
 
@@ -11,12 +11,11 @@ require 'htmlentities'
11
11
  require 'kramdown'
12
12
  require 'react-rails'
13
13
 
14
- require 'resque_mailer'
15
- require 'resque_scheduler'
16
-
17
14
  require 'active_admin'
18
15
  require 'activeadmin-searchable_select'
19
16
 
17
+ require 'bourbon'
18
+ require 'jquery-ui-rails'
20
19
  require 'jquery-layout-rails'
21
20
  require 'backbone-rails'
22
21
  require 'marionette-rails'
@@ -54,9 +53,6 @@ module Pageflow
54
53
  I18n.default_locale = :en
55
54
  config.i18n.load_path += Dir[Engine.root.join('config', 'locales', '**', '*.yml').to_s]
56
55
  config.i18n.locale = :en
57
- # bypasses rails bug with i18n in production
58
- I18n.reload!
59
- config.i18n.reload!
60
56
  end
61
57
 
62
58
  # Make sure the configuration is recreated when classes are
@@ -66,9 +62,9 @@ module Pageflow
66
62
  Pageflow.configure!
67
63
  end
68
64
 
69
- initializer "pageflow.factories", :after => "factory_girl.set_factory_paths" do
70
- if Pageflow.configured? && defined?(FactoryGirl)
71
- FactoryGirl.definition_file_paths.unshift(Engine.root.join('spec', 'factories'))
65
+ initializer 'pageflow.factories', after: 'factory_bot.set_factory_paths' do
66
+ if Pageflow.configured? && defined?(FactoryBot)
67
+ FactoryBot.definition_file_paths.unshift(Engine.root.join('spec', 'factories'))
72
68
  end
73
69
  end
74
70
 
@@ -64,6 +64,11 @@ module Pageflow
64
64
  end
65
65
  end
66
66
 
67
+ # Configure devise to send emails using ActiveJob.
68
+ def send_devise_notification(notification, *args)
69
+ devise_mailer.send(notification, self, *args).deliver_later
70
+ end
71
+
67
72
  private
68
73
 
69
74
  def needs_password?(attributes)
@@ -1,3 +1,3 @@
1
1
  module Pageflow
2
- VERSION = '12.6.0'.freeze
2
+ VERSION = '13.0.0.beta1'.freeze
3
3
  end
@@ -8,17 +8,7 @@ namespace :pageflow do
8
8
  namespace :node_package do
9
9
  desc 'Build node package'
10
10
  task :build do
11
- system('bin/npm ci && bin/npm run build')
12
- end
13
- end
14
-
15
- namespace :release do
16
- task :pageflow_support do
17
- Dir.chdir('spec/support') do
18
- puts '=== Releasing pageflow-support ==='
19
- system('bundle exec rake release')
20
- puts '==='
21
- end
11
+ system('bin/npm run build')
22
12
  end
23
13
  end
24
14
 
@@ -1,4 +1,4 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :account, class: Pageflow::Account do
3
3
  name 'Account Name'
4
4
 
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
2
+ FactoryBot.define do
3
3
  factory :audio_file, :class => AudioFile do
4
4
  entry
5
5
  uploader { create(:user) }
@@ -1,7 +1,5 @@
1
- # Read about factories at https://github.com/thoughtbot/factory_girl
2
-
3
1
  module Pageflow
4
- FactoryGirl.define do
2
+ FactoryBot.define do
5
3
  factory :chapter, :class => Chapter do
6
4
  storyline
7
5
 
@@ -1,9 +1,7 @@
1
- # Read about factories at https://github.com/thoughtbot/factory_girl
2
-
3
1
  module Pageflow
4
- FactoryGirl.define do
2
+ FactoryBot.define do
5
3
  factory :edit_lock, :class => EditLock do
6
- user nil
4
+ user { build(:user) }
7
5
  entry { build(:entry) }
8
6
  updated_at { Time.now }
9
7
  end
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
2
+ FactoryBot.define do
3
3
  sequence :title do |n|
4
4
  "Entry #{n}"
5
5
  end
@@ -1,4 +1,4 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :feature_target, parent: :account do
3
3
  end
4
4
  end
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
2
+ FactoryBot.define do
3
3
  factory :file_usage, :class => FileUsage do
4
4
  revision nil
5
5
  file nil
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
2
+ FactoryBot.define do
3
3
  factory :folder, :class => Folder do
4
4
  name "some folder"
5
5
  account
@@ -1,11 +1,11 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
3
- hosted_file_model = Class.new(ActiveRecord::Base) do
4
- self.table_name = 'test_hosted_files'
5
- include HostedFile
6
- end
2
+ class TestHostedFile < ActiveRecord::Base
3
+ self.table_name = 'test_hosted_files'
4
+ include HostedFile
5
+ end
7
6
 
8
- factory :hosted_file, class: hosted_file_model do
7
+ FactoryBot.define do
8
+ factory :hosted_file, class: TestHostedFile do
9
9
  trait :on_filesystem do
10
10
  attachment_on_filesystem File.open(Engine.root.join('spec', 'fixtures', 'image.png'))
11
11
  attachment_on_s3 nil
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
2
+ FactoryBot.define do
3
3
  factory :image_file, :class => ImageFile do
4
4
  entry
5
5
  uploader { create(:user) }
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
2
+ FactoryBot.define do
3
3
  factory :invited_user, class: InvitedUser do
4
4
  email
5
5
  first_name 'Edison'
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
2
+ FactoryBot.define do
3
3
  factory :membership, class: Membership do
4
4
  user
5
5
  association :entity, factory: :entry
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
2
+ FactoryBot.define do
3
3
  factory :page, :class => Page do
4
4
  chapter
5
5
  template "background_image"
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
2
+ FactoryBot.define do
3
3
  factory :revision, :class => Revision do
4
4
  entry
5
5
 
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
2
+ FactoryBot.define do
3
3
  factory :storyline, class: Storyline do
4
4
  revision
5
5
  end
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
2
+ FactoryBot.define do
3
3
  factory :text_track_file, class: TextTrackFile do
4
4
  entry
5
5
  uploader { create(:user) }
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
2
+ FactoryBot.define do
3
3
  factory :theming, :class => Pageflow::Theming do
4
4
  account
5
5
  theme_name 'default'
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
2
+ FactoryBot.define do
3
3
  sequence :email do |n|
4
4
  "person#{n}@example.com"
5
5
  end
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- FactoryGirl.define do
2
+ FactoryBot.define do
3
3
  factory :video_file, :class => VideoFile do
4
4
  entry
5
5
  uploader { create(:user) }
@@ -1,4 +1,4 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :widget, :class => Pageflow::Widget do
3
3
  role 'navigation'
4
4
  type_name 'test_widget'
@@ -4,9 +4,9 @@
4
4
  * License MIT (c) Zohar Arad 2013
5
5
  */
6
6
  (function ($win, ns, factory) {
7
- "use strict";
8
7
  /*global define */
9
8
  /*global swfobject */
9
+ "use strict";
10
10
 
11
11
  if (typeof (module) !== 'undefined' && module.exports) { // CommonJS
12
12
  module.exports = factory(ns, $win);
@@ -134,35 +134,17 @@
134
134
  trigger: function (evt) {
135
135
  if (this.channels && this.channels.hasOwnProperty(evt)) {
136
136
  var args = Array.prototype.slice.call(arguments, 1);
137
-
138
- // temp array to store all subscribers for the channel evt that must be stored in state
139
- var evtSubscribers = [];
140
- // temp array to store all subscribers for the channel evt that is being triggered that must be executed.
141
- var evtSubscribersForExec = [];
142
-
137
+ var a = [];
143
138
  while(this.channels[evt].length > 0) {
144
139
  var sub = this.channels[evt].shift();
145
-
146
- if ( !sub.once ){
147
- // for any channel event triggers that are not marked as once only, we need to keep.
148
- evtSubscribers.push(sub);
149
- }
150
-
151
- // if we have a function with the channel subscription, store in temp array ready to call after all proceeded
152
140
  if (typeof (sub.fn) === 'function') {
153
- // every subscriber we've processed will be executed
154
- evtSubscribersForExec.push(sub);
141
+ sub.fn.apply(sub.ctx, args);
142
+ }
143
+ if ( !sub.once ){
144
+ a.push(sub);
155
145
  }
156
146
  }
157
-
158
- // before we execute any of the subscribers to the trigger, we must make sure keep this.channels[evt] up to date in case any sub fns call off
159
- this.channels[evt] = evtSubscribers;
160
-
161
- // run all the event subscribers that need executing
162
- while(evtSubscribersForExec.length > 0) {
163
- var eventSub = evtSubscribersForExec.shift();
164
- eventSub.fn.apply(eventSub.ctx, args);
165
- }
147
+ this.channels[evt] = a;
166
148
  }
167
149
  }
168
150
  };
@@ -171,21 +153,19 @@
171
153
  /**
172
154
  * Flash embed code string with cross-browser support.
173
155
  */
174
- flash_embed_code: function (id, swf_location, ts) {
156
+ flash_embed_code: (function () {
175
157
  var prefix;
176
- var elemId = ns + id;
177
- var s = '<param name="movie" value="' + swf_location + '?playerInstanceNumber=' + id + '&datetime=' + ts + '"/>' +
158
+ var s = '<param name="movie" value="$2?playerInstance=window.' + ns + '_flash.instances[\'$1\']&datetime=$3"/>' +
178
159
  '<param name="wmode" value="transparent"/>' +
179
160
  '<param name="allowscriptaccess" value="always" />' +
180
161
  '</object>';
181
162
  if (ActiveXObject) {
182
- prefix = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="1" height="1" id="' + elemId + '">';
163
+ prefix = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="1" height="1" id="$1">';
183
164
  } else {
184
- prefix = '<object type="application/x-shockwave-flash" data="' + swf_location + '?playerInstanceNumber=' + id + '&datetime=' + ts + '" width="1" height="1" id="' + elemId + '" >';
165
+ prefix = '<object type="application/x-shockwave-flash" data="$2?playerInstance=window.' + ns + '_flash.instances[\'$1\']&datetime=$3" width="1" height="1" id="$1" >';
185
166
  }
186
-
187
167
  return prefix + s;
188
- },
168
+ }()),
189
169
  /**
190
170
  * Check if browser supports audio mime type.
191
171
  * @param {String} mime_type audio mime type to check
@@ -195,36 +175,30 @@
195
175
  var a = document.createElement('audio');
196
176
  var mime_str;
197
177
  switch (mime_type) {
198
- case 'mp3':
199
- mime_str = 'audio/mpeg;';
200
- break;
201
- case 'vorbis':
202
- mime_str = 'audio/ogg; codecs="vorbis"';
203
- break;
204
- case 'opus':
205
- mime_str = 'audio/ogg; codecs="opus"';
206
- break;
207
- case 'webm':
208
- mime_str = 'audio/webm; codecs="vorbis"';
209
- break;
210
- case 'mp4':
211
- mime_str = 'audio/mp4; codecs="mp4a.40.5"';
212
- break;
213
- case 'wav':
214
- mime_str = 'audio/wav; codecs="1"';
215
- break;
216
- }
217
- if (mime_str !== undefined) {
218
- if (mime_type === 'mp3' && navigator.userAgent.match(/Android/i) && navigator.userAgent.match(/Firefox/i)) {
219
- return true;
220
- }
221
- try {
222
- return !!a.canPlayType && a.canPlayType(mime_str) !== '';
223
- } catch (e) {
224
- return false;
225
- }
178
+ case 'mp3':
179
+ mime_str = 'audio/mpeg; codecs="mp3"';
180
+ break;
181
+ case 'vorbis':
182
+ mime_str = 'audio/ogg; codecs="vorbis"';
183
+ break;
184
+ case 'opus':
185
+ mime_str = 'audio/ogg; codecs="opus"';
186
+ break;
187
+ case 'webm':
188
+ mime_str = 'audio/webm; codecs="vorbis"';
189
+ break;
190
+ case 'mp4':
191
+ mime_str = 'audio/mp4; codecs="mp4a.40.5"';
192
+ break;
193
+ case 'wav':
194
+ mime_str = 'audio/wav; codecs="1"';
195
+ break;
196
+ }
197
+ if (mime_str === undefined) {
198
+ throw new Error('Unspecified Audio Mime Type');
199
+ } else {
200
+ return !!a.canPlayType && a.canPlayType(mime_str) !== '';
226
201
  }
227
- return false;
228
202
  },
229
203
  /**
230
204
  * Boolean flag indicating whether the browser has Flash installed or not
@@ -258,17 +232,19 @@
258
232
  document.body.appendChild(d);
259
233
  if(typeof($win.swfobject) === 'object'){
260
234
  var fv = {
261
- playerInstance: 'window.'+ ns + '_flash.instances[\''+id+'\']'
235
+ playerInstance: 'window.'+ ns + '_flash.instances["'+id+'"]'
262
236
  };
263
237
  var params = {
264
238
  allowscriptaccess: 'always',
265
239
  wmode: 'transparent'
266
240
  };
267
- d.innerHTML = '<div id="'+ ns + id +'"></div>';
268
- swfobject.embedSWF(swf_location + '?ts='+(new Date().getTime() + Math.random()), ns + id, "1", "1", "9.0.0", null, fv, params);
241
+ d.innerHTML = '<div id="'+id+'"></div>';
242
+ swfobject.embedSWF(swf_location + '?ts='+(new Date().getTime() + Math.random()), id, "1", "1", "9.0.0", null, fv, params);
269
243
  } else {
270
- var ts = new Date().getTime() + Math.random(); // Ensure swf is not pulled from cache
271
- d.innerHTML = this.flash_embed_code(id, swf_location, ts);
244
+ var flashSource = this.flash_embed_code.replace(/\$1/g, id);
245
+ flashSource = flashSource.replace(/\$2/g, swf_location);
246
+ flashSource = flashSource.replace(/\$3/g, (new Date().getTime() + Math.random())); // Ensure swf is not pulled from cache
247
+ d.innerHTML = flashSource;
272
248
  }
273
249
  return document.getElementById(id);
274
250
  },
@@ -305,7 +281,7 @@
305
281
  duration: 0, /** {Float} audio duration (sec) */
306
282
  position: 0, /** {Float} audio position (sec) */
307
283
  load_percent: 0, /** {Float} audio file load percent (%) */
308
- seekable: false, /** {Boolean} is loaded audio seekable */
284
+ seekable: null, /** {Boolean} is loaded audio seekable */
309
285
  ready: null /** {Boolean} is loaded audio seekable */
310
286
  };
311
287
 
@@ -315,7 +291,8 @@
315
291
  * @type {Object}
316
292
  */
317
293
  var globalAudio5Flash = $win[ns + '_flash'] = $win[ns + '_flash'] || {
318
- instances: [] /** FlashAudioPlayer instance hash */
294
+ instances: { }, /** FlashAudioPlayer instance hash */
295
+ count: 0 /** FlashAudioPlayer instance count */
319
296
  };
320
297
 
321
298
  /**
@@ -334,8 +311,9 @@
334
311
  * @param {String} swf_src path to audio player SWF file
335
312
  */
336
313
  init: function (swf_src) {
337
- globalAudio5Flash.instances.push(this);
338
- this.id = globalAudio5Flash.instances.length - 1;
314
+ globalAudio5Flash.count += 1;
315
+ this.id = ns + globalAudio5Flash.count;
316
+ globalAudio5Flash.instances[this.id] = this;
339
317
  this.embed(swf_src);
340
318
  },
341
319
  /**
@@ -349,7 +327,7 @@
349
327
  * ExternalInterface callback indicating SWF is ready
350
328
  */
351
329
  eiReady: function () {
352
- this.audio = document.getElementById(ns + this.id);
330
+ this.audio = document.getElementById(this.id);
353
331
  this.trigger('ready');
354
332
  },
355
333
  /**
@@ -385,13 +363,9 @@
385
363
  /**
386
364
  * ExternalInterface download progress callback. Fires as long as audio file is downloaded by browser.
387
365
  * @param {Float} percent audio download percent
388
- * @param {Float} duration audio total duration (sec)
389
- * * @param {Boolean} seekable is audio seekable or not (download or streaming)
390
366
  */
391
- eiProgress: function (percent, duration, seekable) {
367
+ eiProgress: function (percent) {
392
368
  this.load_percent = percent;
393
- this.duration = duration;
394
- this.seekable = seekable;
395
369
  this.trigger('progress', percent);
396
370
  },
397
371
  /**
@@ -407,7 +381,6 @@
407
381
  eiPlay: function () {
408
382
  this.playing = true;
409
383
  this.trigger('play');
410
- this.trigger('playing');
411
384
  },
412
385
  /**
413
386
  * ExternalInterface audio pause callback. Fires when audio is paused.
@@ -420,7 +393,7 @@
420
393
  * ExternalInterface audio ended callback. Fires when audio playback ended.
421
394
  */
422
395
  eiEnded: function () {
423
- this.pause();
396
+ this.playing = false;
424
397
  this.trigger('ended');
425
398
  },
426
399
  /**
@@ -486,24 +459,6 @@
486
459
  this.audio.seekTo(position);
487
460
  this.position = position;
488
461
  } catch (e) {}
489
- },
490
- /**
491
- * This feature was not implemented for Flash
492
- */
493
- rate: function () {
494
- // Not implemented
495
- },
496
- /**
497
- * Destroy audio object and remove from DOM
498
- */
499
- destroyAudio: function() {
500
- if(this.audio){
501
- this.pause();
502
- this.audio.parentNode.removeChild(this.audio);
503
- delete globalAudio5Flash.instances[this.id];
504
- globalAudio5Flash.instances.splice(this.id, 1);
505
- delete this.audio;
506
- }
507
462
  }
508
463
  };
509
464
 
@@ -520,91 +475,52 @@
520
475
  /**
521
476
  * Initialize the player instance
522
477
  */
523
- init: function () {
524
- this._rate = 1;
478
+ init: function (reusedTag) {
479
+ this.reusedTag = reusedTag;
525
480
  this.trigger('ready');
526
481
  },
527
- /**
528
- * Create new audio instance
529
- */
530
482
  createAudio: function(){
531
- this.audio = new Audio();
483
+ this.audio = this.reusedTag || new Audio();
532
484
  this.audio.autoplay = false;
533
485
  this.audio.preload = 'auto';
534
486
  this.audio.autobuffer = true;
535
- this.audio.playbackRate = this._rate;
536
487
 
537
488
  this.audio.setAttribute('crossorigin', 'anonymous');
538
489
 
539
490
  this.bindEvents();
540
491
  },
541
- /**
542
- * Destroy current audio instance
543
- */
544
492
  destroyAudio: function(){
545
493
  if(this.audio){
546
- this.pause();
547
494
  this.unbindEvents();
548
- try {
549
- this.audio.setAttribute('src', '');
550
- } finally {
551
- delete this.audio;
552
- }
495
+ delete this.audio;
553
496
  }
554
497
  },
555
- /**
556
- * Sets up audio event listeners once so adding / removing event listeners is always done
557
- * on the same callbacks.
558
- */
559
- setupEventListeners: function(){
560
- this.listeners = {
561
- loadstart: this.onLoadStart.bind(this),
562
- canplay: this.onLoad.bind(this),
563
- loadedmetadata: this.onLoadedMetadata.bind(this),
564
- play: this.onPlay.bind(this),
565
- playing: this.onPlaying.bind(this),
566
- pause: this.onPause.bind(this),
567
- ended: this.onEnded.bind(this),
568
- error: this.onError.bind(this),
569
- timeupdate: this.onTimeUpdate.bind(this),
570
- seeking: this.onSeeking.bind(this),
571
- seeked: this.onSeeked.bind(this)
572
- };
573
- },
574
498
  /**
575
499
  * Bind DOM events to Audio object
576
500
  */
577
- bindEvents: function() {
578
- if(this.listeners === undefined){
579
- this.setupEventListeners();
580
- }
581
- this.audio.addEventListener('loadstart', this.listeners.loadstart, false);
582
- this.audio.addEventListener('canplay', this.listeners.canplay, false);
583
- this.audio.addEventListener('loadedmetadata', this.listeners.loadedmetadata, false);
584
- this.audio.addEventListener('play', this.listeners.play, false);
585
- this.audio.addEventListener('playing', this.listeners.playing, false);
586
- this.audio.addEventListener('pause', this.listeners.pause, false);
587
- this.audio.addEventListener('ended', this.listeners.ended, false);
588
- this.audio.addEventListener('error', this.listeners.error, false);
589
- this.audio.addEventListener('timeupdate', this.listeners.timeupdate, false);
590
- this.audio.addEventListener('seeking', this.listeners.seeking, false);
591
- this.audio.addEventListener('seeked', this.listeners.seeked, false);
592
- },
593
- /**
594
- * Unbind DOM events from Audio object
595
- */
596
- unbindEvents: function() {
597
- this.audio.removeEventListener('loadstart', this.listeners.loadstart);
598
- this.audio.removeEventListener('canplay', this.listeners.canplay);
599
- this.audio.removeEventListener('loadedmetadata', this.listeners.loadedmetadata);
600
- this.audio.removeEventListener('play', this.listeners.play);
601
- this.audio.removeEventListener('playing', this.listeners.playing);
602
- this.audio.removeEventListener('pause', this.listeners.pause);
603
- this.audio.removeEventListener('ended', this.listeners.ended);
604
- this.audio.removeEventListener('error', this.listeners.error);
605
- this.audio.removeEventListener('timeupdate', this.listeners.timeupdate);
606
- this.audio.removeEventListener('seeking', this.listeners.seeking);
607
- this.audio.removeEventListener('seeked', this.listeners.seeked);
501
+ bindEvents: function () {
502
+ this.audio.addEventListener('loadstart', this.onLoadStart.bind(this));
503
+ this.audio.addEventListener('canplay', this.onLoad.bind(this));
504
+ this.audio.addEventListener('loadedmetadata', this.onLoadedMetadata.bind(this));
505
+ this.audio.addEventListener('playing', this.onPlay.bind(this));
506
+ this.audio.addEventListener('pause', this.onPause.bind(this));
507
+ this.audio.addEventListener('ended', this.onEnded.bind(this));
508
+ this.audio.addEventListener('error', this.onError.bind(this));
509
+ this.audio.addEventListener('timeupdate', this.onTimeUpdate.bind(this));
510
+ this.audio.addEventListener('seeking', this.onSeeking.bind(this));
511
+ this.audio.addEventListener('seeked', this.onSeeked.bind(this));
512
+ },
513
+ unbindEvents: function(){
514
+ this.audio.removeEventListener('loadstart', this.onLoadStart.bind(this));
515
+ this.audio.removeEventListener('canplay', this.onLoad.bind(this));
516
+ this.audio.removeEventListener('loadedmetadata', this.onLoadedMetadata.bind(this));
517
+ this.audio.removeEventListener('playing', this.onPlay.bind(this));
518
+ this.audio.removeEventListener('pause', this.onPause.bind(this));
519
+ this.audio.removeEventListener('ended', this.onEnded.bind(this));
520
+ this.audio.removeEventListener('error', this.onError.bind(this));
521
+ this.audio.removeEventListener('timeupdate', this.onTimeUpdate.bind(this));
522
+ this.audio.removeEventListener('seeking', this.onSeeking.bind(this));
523
+ this.audio.removeEventListener('seeked', this.onSeeked.bind(this));
608
524
  },
609
525
  /**
610
526
  * Audio load start event handler. Triggered when audio starts loading
@@ -617,9 +533,6 @@
617
533
  * Resets player parameters and starts audio download progress timer.
618
534
  */
619
535
  onLoad: function () {
620
- if(!this.audio){
621
- return setTimeout(this.onLoad.bind(this), 100);
622
- }
623
536
  this.seekable = this.audio.seekable && this.audio.seekable.length > 0;
624
537
  if (this.seekable) {
625
538
  this.timer = setInterval(this.onProgress.bind(this), 250);
@@ -636,21 +549,12 @@
636
549
  * Audio play event handler. Triggered when audio starts playing.
637
550
  */
638
551
  onPlay: function () {
639
- this.playing = true;
640
552
  this.trigger('play');
641
553
  },
642
- /**
643
- * Audio play event handler. Triggered when audio starts playing.
644
- */
645
- onPlaying: function () {
646
- this.playing = true;
647
- this.trigger('playing');
648
- },
649
554
  /**
650
555
  * Audio pause event handler. Triggered when audio is paused.
651
556
  */
652
557
  onPause: function () {
653
- this.playing = false;
654
558
  this.trigger('pause');
655
559
  },
656
560
  /**
@@ -664,11 +568,9 @@
664
568
  * Audio timeupdate event handler. Triggered as long as playhead position is updated (audio is being played).
665
569
  */
666
570
  onTimeUpdate: function () {
667
- if (this.audio && this.playing) {
668
- try{
669
- this.position = this.audio.currentTime;
670
- this.duration = this.audio.duration === Infinity ? null : this.audio.duration;
671
- } catch (e){}
571
+ if (this.audio.buffered !== null && this.playing) {
572
+ this.position = this.audio.currentTime;
573
+ this.duration = this.audio.duration === Infinity ? null : this.audio.duration;
672
574
  this.trigger('timeupdate', this.position, this.duration);
673
575
  }
674
576
  },
@@ -678,9 +580,8 @@
678
580
  * Cancelled when audio has fully download or when a new audio file has been loaded to the player.
679
581
  */
680
582
  onProgress: function () {
681
- if (this.audio && this.audio.buffered !== null && this.audio.buffered.length) {
682
- this.duration = this.audio.duration === Infinity ? null : this.audio.duration;
683
- this.load_percent = parseInt(((this.audio.buffered.end(this.audio.buffered.length - 1) / this.duration) * 100), 10);
583
+ if (this.audio.buffered !== null) {
584
+ this.load_percent = parseInt(((this.audio.buffered.end(this.audio.buffered.length - 1) / this.audio.duration) * 100), 10);
684
585
  this.trigger('progress', this.load_percent);
685
586
  if (this.load_percent >= 100) {
686
587
  this.clearLoadProgress();
@@ -731,11 +632,8 @@
731
632
  */
732
633
  load: function (url) {
733
634
  this.reset();
734
- this.trigger('pause');
735
- //this.destroyAudio();
736
- if(this.audio === undefined){
737
- this.createAudio();
738
- }
635
+ this.destroyAudio();
636
+ this.createAudio();
739
637
  this.audio.setAttribute('src', url);
740
638
  this.audio.load();
741
639
  },
@@ -743,19 +641,15 @@
743
641
  * Play audio
744
642
  */
745
643
  play: function () {
746
- if(this.audio) {
747
- var playPromise = this.audio.play();
748
- this.audio.playbackRate = this._rate;
749
- return playPromise;
750
- }
644
+ this.playing = true;
645
+ this.audio.play();
751
646
  },
752
647
  /**
753
648
  * Pause audio
754
649
  */
755
650
  pause: function () {
756
- if(this.audio) {
757
- this.audio.pause();
758
- }
651
+ this.playing = false;
652
+ this.audio.pause();
759
653
  },
760
654
  /**
761
655
  * Get / Set audio volume
@@ -782,23 +676,10 @@
782
676
  if (playing) {
783
677
  this.play();
784
678
  } else {
785
- if (this.audio.buffered !== null && this.audio.buffered.length) {
679
+ if (this.audio.buffered !== null) {
786
680
  this.trigger('timeupdate', this.position, this.duration);
787
681
  }
788
682
  }
789
- },
790
- /**
791
- * Define the playback rate
792
- * @param {Float} v playback rate value to be set
793
- */
794
- rate: function (v) {
795
- if (v === undefined || isNaN(parseFloat(v))) {
796
- return this._rate;
797
- }
798
- this._rate = v;
799
- if (this.audio) {
800
- this.audio.playbackRate = v;
801
- }
802
683
  }
803
684
  };
804
685
 
@@ -867,7 +748,7 @@
867
748
  if (this.settings.use_flash) {
868
749
  this.audio.init(s.swf_path);
869
750
  } else {
870
- this.audio.init();
751
+ this.audio.init(s.reusedTag);
871
752
  }
872
753
  },
873
754
  /**
@@ -876,36 +757,28 @@
876
757
  * @return {FlashAudioPlayer,HTML5AudioPlayer} audio player instance
877
758
  */
878
759
  getPlayer: function () {
879
- var i, l, player, codec;
880
- if(this.settings.use_flash){
881
- player = new FlashAudioPlayer();
882
- this.settings.player = {
883
- engine: 'flash',
884
- codec: 'mp3'
885
- };
886
- } else {
887
- for (i = 0, l = this.settings.codecs.length; i < l; i++) {
888
- codec = this.settings.codecs[i];
889
- if (Audio5js.can_play(codec)) {
890
- player = new HTML5AudioPlayer();
891
- this.settings.use_flash = false;
892
- this.settings.player = {
893
- engine: 'html',
894
- codec: codec
895
- };
896
- break;
897
- }
898
- }
899
- if (player === undefined) {
900
- // here we double check for mp3 support instead of defaulting to Flash in case user overrode the settings.codecs array with an empty array.
901
- this.settings.use_flash = !Audio5js.can_play('mp3');
902
- player = this.settings.use_flash ? new FlashAudioPlayer() : new HTML5AudioPlayer();
760
+ var i, l, player;
761
+ for (i = 0, l = this.settings.codecs.length; i < l; i++) {
762
+ var codec = this.settings.codecs[i];
763
+ if (Audio5js.can_play(codec)) {
764
+ player = new HTML5AudioPlayer();
765
+ this.settings.use_flash = false;
903
766
  this.settings.player = {
904
- engine: (this.settings.use_flash ? 'flash' : 'html'),
905
- codec: 'mp3'
767
+ engine: 'html',
768
+ codec: codec
906
769
  };
770
+ break;
907
771
  }
908
772
  }
773
+ if (player === undefined) {
774
+ // here we double check for mp3 support instead of defaulting to Flash in case user overrode the settings.codecs array with an empty array.
775
+ this.settings.use_flash = !Audio5js.can_play('mp3');
776
+ player = this.settings.use_flash ? new FlashAudioPlayer() : new HTML5AudioPlayer();
777
+ this.settings.player = {
778
+ engine: (this.settings.use_flash ? 'flash' : 'html'),
779
+ codec: 'mp3'
780
+ };
781
+ }
909
782
  return player;
910
783
  },
911
784
  /**
@@ -925,36 +798,18 @@
925
798
  this.audio.on('seeking', this.onSeeking, this);
926
799
  this.audio.on('seeked', this.onSeeked, this);
927
800
  },
928
- /**
929
- * Bind events from audio object to internal callbacks
930
- */
931
- unbindAudioEvents: function () {
932
- this.audio.off('ready', this.onReady);
933
- this.audio.off('loadstart', this.onLoadStart);
934
- this.audio.off('loadedmetadata', this.onLoadedMetadata);
935
- this.audio.off('play', this.onPlay);
936
- this.audio.off('pause', this.onPause);
937
- this.audio.off('ended', this.onEnded);
938
- this.audio.off('canplay', this.onCanPlay);
939
- this.audio.off('timeupdate', this.onTimeUpdate);
940
- this.audio.off('progress', this.onProgress);
941
- this.audio.off('error', this.onError);
942
- this.audio.off('seeking', this.onSeeking);
943
- this.audio.off('seeked', this.onSeeked);
944
- },
945
801
  /**
946
802
  * Load audio from URL
947
803
  * @param {String} url URL of audio to load
948
804
  */
949
805
  load: function (url) {
950
- var that = this;
951
806
  var f = function(u){
952
- that.audio.load(u);
953
- that.trigger('load');
954
- };
807
+ this.audio.load(u);
808
+ this.trigger('load');
809
+ }.bind(this, url);
955
810
 
956
811
  if(this.ready){
957
- f(url);
812
+ f();
958
813
  } else {
959
814
  this.on('ready', f);
960
815
  }
@@ -964,7 +819,8 @@
964
819
  */
965
820
  play: function () {
966
821
  if(!this.playing){
967
- return this.audio.play();
822
+ this.playing = true;
823
+ this.audio.play();
968
824
  }
969
825
  },
970
826
  /**
@@ -972,6 +828,7 @@
972
828
  */
973
829
  pause: function () {
974
830
  if(this.playing){
831
+ this.playing = false;
975
832
  this.audio.pause();
976
833
  }
977
834
  },
@@ -1002,20 +859,6 @@
1002
859
  this.audio.seek(position);
1003
860
  this.position = position;
1004
861
  },
1005
- /**
1006
- * Define the playback rate
1007
- * @param {Float} value playback rate value to be set
1008
- */
1009
- rate: function (value) {
1010
- return this.audio.rate(value);
1011
- },
1012
- /**
1013
- * Destroy audio object and remove from DOM
1014
- */
1015
- destroy: function() {
1016
- this.unbindAudioEvents();
1017
- this.audio.destroyAudio();
1018
- },
1019
862
  /**
1020
863
  * Callback for audio ready event. Indicates audio is ready for playback.
1021
864
  * Looks for ready callback in settings object and invokes it in the context of player instance
@@ -1043,22 +886,27 @@
1043
886
  * Audio play event handler
1044
887
  */
1045
888
  onPlay: function () {
1046
- this.playing = true;
1047
889
  this.trigger('play');
1048
890
  },
1049
891
  /**
1050
892
  * Audio pause event handler
1051
893
  */
1052
894
  onPause: function () {
1053
- this.playing = false;
1054
895
  this.trigger('pause');
1055
896
  },
1056
897
  /**
1057
898
  * Playback end event handler
1058
899
  */
1059
900
  onEnded: function () {
1060
- this.playing = false;
1061
- this.trigger('ended');
901
+ var wasPlaying = this.playing;
902
+
903
+ if (this.settings.loop && wasPlaying) {
904
+ this.audio.play();
905
+ }
906
+ else {
907
+ this.playing = false;
908
+ this.trigger('ended');
909
+ }
1062
910
  },
1063
911
  /**
1064
912
  * Audio error event handler
@@ -1096,7 +944,9 @@
1096
944
  */
1097
945
  onTimeUpdate: function (position, duration) {
1098
946
  this.position = this.settings.format_time ? util.formatTime(position) : position;
1099
- this.duration = this.settings.format_time && duration !== null ? util.formatTime(duration) : duration;
947
+ if (this.duration !== duration) {
948
+ this.duration = this.settings.format_time && duration !== null ? util.formatTime(duration) : duration;
949
+ }
1100
950
  this.trigger('timeupdate', this.position, this.duration);
1101
951
  },
1102
952
  /**
@@ -1104,7 +954,6 @@
1104
954
  * @param {Float} loaded audio download percent
1105
955
  */
1106
956
  onProgress: function (loaded) {
1107
- this.duration = this.audio.duration;
1108
957
  this.load_percent = loaded;
1109
958
  this.trigger('progress', loaded);
1110
959
  }
@@ -1115,4 +964,4 @@
1115
964
 
1116
965
  return Audio5js;
1117
966
 
1118
- }));
967
+ }));