pageflow 13.0.0.beta6 → 13.0.0.beta7
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +74 -0
- data/README.md +1 -0
- data/app/assets/audios/pageflow/unmute.mp3 +0 -0
- data/app/assets/images/pageflow/editor/help/phone_horizontal_slideshow_mode.gif +0 -0
- data/app/assets/javascripts/pageflow/asset_urls.js.erb +1 -1
- data/app/assets/javascripts/pageflow/audio/multi_player.js +4 -0
- data/app/assets/javascripts/pageflow/audio_player.js +1 -1
- data/app/assets/javascripts/pageflow/background_media.js +22 -0
- data/app/assets/javascripts/pageflow/base.js +1 -0
- data/app/assets/javascripts/pageflow/browser/agent.js +92 -78
- data/app/assets/javascripts/pageflow/browser/autoplay_support.js +2 -2
- data/app/assets/javascripts/pageflow/dist/react.js +711 -252
- data/app/assets/javascripts/pageflow/editor/api/page_type.js +4 -0
- data/app/assets/javascripts/pageflow/editor/base.js +1 -0
- data/app/assets/javascripts/pageflow/editor/collections/files_collection.js +8 -0
- data/app/assets/javascripts/pageflow/editor/initializers/boot.js +6 -4
- data/app/assets/javascripts/pageflow/editor/initializers/setup_asset_urls.js +3 -0
- data/app/assets/javascripts/pageflow/editor/models/entry.js +2 -2
- data/app/assets/javascripts/pageflow/editor/models/file_stage.js +6 -1
- data/app/assets/javascripts/pageflow/editor/models/mixins/stage_provider.js +9 -0
- data/app/assets/javascripts/pageflow/editor/models/mixins/transient_references.js +12 -2
- data/app/assets/javascripts/pageflow/editor/models/preview_entry_data.js +5 -0
- data/app/assets/javascripts/pageflow/editor/models/uploaded_file.js +6 -1
- data/app/assets/javascripts/pageflow/editor/templates/emulation_mode_button.jst.ejs +26 -0
- data/app/assets/javascripts/pageflow/editor/templates/entry_preview.jst.ejs +8 -3
- data/app/assets/javascripts/pageflow/editor/views/configuration_editors/groups/options.js +1 -1
- data/app/assets/javascripts/pageflow/editor/views/configuration_editors/groups/page_link.js +3 -6
- data/app/assets/javascripts/pageflow/editor/views/configuration_editors/groups/page_transitions.js +14 -4
- data/app/assets/javascripts/pageflow/editor/views/edit_storyline_view.js +3 -6
- data/app/assets/javascripts/pageflow/editor/views/embedded/background_image_embedded_view.js +47 -12
- data/app/assets/javascripts/pageflow/editor/views/emulation_mode_button_view.js +45 -0
- data/app/assets/javascripts/pageflow/editor/views/entry_preview_view.js +62 -8
- data/app/assets/javascripts/pageflow/editor/views/file_stage_item_view.js +7 -0
- data/app/assets/javascripts/pageflow/editor/views/help_image_view.js +9 -0
- data/app/assets/javascripts/pageflow/editor/views/info_box_view.js +1 -1
- data/app/assets/javascripts/pageflow/editor/views/inputs/file_processing_state_display_view.js +60 -0
- data/app/assets/javascripts/pageflow/editor/views/sidebar_footer_view.js +12 -0
- data/app/assets/javascripts/pageflow/editor/views/widget_types/phone_horizontal_slideshow_mode.js +14 -0
- data/app/assets/javascripts/pageflow/entry_data.js +4 -0
- data/app/assets/javascripts/pageflow/media_player.js +7 -3
- data/app/assets/javascripts/pageflow/media_player/handle_failed_play.js +34 -0
- data/app/assets/javascripts/pageflow/media_player/volume_fading/web_audio.js +29 -3
- data/app/assets/javascripts/pageflow/page_transitions.js +59 -15
- data/app/assets/javascripts/pageflow/page_type.js +5 -1
- data/app/assets/javascripts/pageflow/seed_entry_data.js +13 -0
- data/app/assets/javascripts/pageflow/slideshow.js +31 -11
- data/app/assets/javascripts/pageflow/slideshow/atmo.js +23 -12
- data/app/assets/javascripts/pageflow/slideshow/lazy_page_widget.js +9 -3
- data/app/assets/javascripts/pageflow/slideshow/navigation_direction.js +37 -0
- data/app/assets/javascripts/pageflow/slideshow/page_widget.js +12 -6
- data/app/assets/javascripts/pageflow/slideshow/scroll_indicator_widget.js +13 -16
- data/app/assets/javascripts/pageflow/slideshow/scroller_widget.js +49 -14
- data/app/assets/javascripts/pageflow/ui/views/mixins/input_view.js +10 -3
- data/app/assets/javascripts/pageflow/video_player/lazy.js +1 -1
- data/app/assets/stylesheets/pageflow/animations/bounce.scss +13 -1
- data/app/assets/stylesheets/pageflow/editor/base.scss +5 -0
- data/app/assets/stylesheets/pageflow/editor/emulation_mode_button.scss +78 -0
- data/app/assets/stylesheets/pageflow/editor/entry_preview.scss +41 -0
- data/app/assets/stylesheets/pageflow/editor/file_stages.scss +11 -3
- data/app/assets/stylesheets/pageflow/editor/help.scss +4 -14
- data/app/assets/stylesheets/pageflow/editor/help_image.scss +5 -0
- data/app/assets/stylesheets/pageflow/editor/info_box.scss +5 -0
- data/app/assets/stylesheets/pageflow/editor/inputs.scss +1 -0
- data/app/assets/stylesheets/pageflow/editor/inputs/file_processing_state_display.scss +18 -0
- data/app/assets/stylesheets/pageflow/editor/sidebar_footer.scss +12 -0
- data/app/assets/stylesheets/pageflow/entries.scss +29 -6
- data/app/assets/stylesheets/pageflow/mixins/breakpoints.scss +5 -3
- data/app/assets/stylesheets/pageflow/mixins/icons/fontawesome.scss +1 -1
- data/app/assets/stylesheets/pageflow/navigation_mobile.scss +5 -1
- data/app/assets/stylesheets/pageflow/page_transitions.scss +0 -6
- data/app/assets/stylesheets/pageflow/page_transitions/crossfade.scss +5 -1
- data/app/assets/stylesheets/pageflow/page_transitions/fade.scss +44 -36
- data/app/assets/stylesheets/pageflow/page_transitions/scroll.scss +96 -11
- data/app/assets/stylesheets/pageflow/slideshow.scss +0 -4
- data/app/assets/stylesheets/pageflow/themes/default/background_media_unmute_button.scss +68 -0
- data/app/assets/stylesheets/pageflow/themes/default/base.scss +1 -0
- data/app/assets/stylesheets/pageflow/themes/default/indicators/icons/icon_font.scss +7 -0
- data/app/assets/stylesheets/pageflow/ui/forms.scss +4 -0
- data/app/controllers/pageflow/editor/files_controller.rb +9 -1
- data/app/helpers/pageflow/asset_urls_helper.rb +9 -0
- data/app/helpers/pageflow/background_image_helper.rb +6 -10
- data/app/helpers/pageflow/file_background_images_helper.rb +78 -0
- data/app/helpers/pageflow/pages_helper.rb +2 -2
- data/app/helpers/pageflow/render_json_helper.rb +3 -2
- data/app/models/concerns/pageflow/hosted_file.rb +2 -9
- data/app/models/concerns/pageflow/uploaded_file.rb +9 -0
- data/app/models/pageflow/draft_entry.rb +2 -2
- data/app/models/pageflow/image_file.rb +5 -20
- data/app/models/pageflow/image_file_css_background_image_urls.rb +17 -0
- data/app/models/pageflow/video_file_css_background_image_urls.rb +13 -0
- data/app/views/pageflow/editor/asset_urls/_asset_urls.json.jbuilder +4 -0
- data/app/views/pageflow/editor/entries/seed.json.erb +3 -1
- data/app/views/pageflow/editor/image_files/_image_file.json.jbuilder +1 -1
- data/app/views/pageflow/entries/_indicators.html.erb +8 -3
- data/app/views/pageflow/entries/edit.html.erb +1 -1
- data/app/views/pageflow/entries/show.css.erb +6 -20
- data/app/views/pageflow/file_background_images/_rule.css.erb +3 -0
- data/config/initializers/features.rb +1 -0
- data/config/locales/de.yml +20 -8
- data/config/locales/en.yml +23 -11
- data/config/routes.rb +1 -0
- data/lib/pageflow/built_in_file_type.rb +4 -0
- data/lib/pageflow/built_in_widget_type.rb +12 -0
- data/lib/pageflow/built_in_widget_types_plugin.rb +5 -0
- data/lib/pageflow/file_type.rb +39 -0
- data/lib/pageflow/file_types.rb +6 -0
- data/lib/pageflow/version.rb +1 -1
- data/spec/factories/hosted_files.rb +12 -8
- data/vendor/assets/javascripts/audio5.min.js +280 -129
- data/vendor/assets/javascripts/iscroll.js +16 -11
- metadata +47 -16
- data/app/assets/javascripts/pageflow/media_player/catch_play_promise.js +0 -23
- data/app/assets/stylesheets/pageflow/page_transitions/scroll_in.scss +0 -66
- data/app/assets/stylesheets/pageflow/page_transitions/scroll_in_right.scss +0 -68
- data/app/assets/stylesheets/pageflow/page_transitions/scroll_left.scss +0 -20
- data/app/assets/stylesheets/pageflow/page_transitions/scroll_over_from_left.scss +0 -12
- data/app/assets/stylesheets/pageflow/page_transitions/scroll_over_from_right.scss +0 -12
- data/app/assets/stylesheets/pageflow/page_transitions/scroll_right.scss +0 -20
- data/lib/pageflow/images/palette.png +0 -0
@@ -8,6 +8,8 @@ module Pageflow
|
|
8
8
|
editor_partial: 'pageflow/editor/image_files/image_file',
|
9
9
|
collection_name: 'image_files',
|
10
10
|
url_templates: ImageFileUrlTemplates.new,
|
11
|
+
css_background_image_urls: ImageFileCssBackgroundImageUrls.new,
|
12
|
+
css_background_image_class_prefix: 'image',
|
11
13
|
top_level_type: true)
|
12
14
|
end
|
13
15
|
|
@@ -17,6 +19,8 @@ module Pageflow
|
|
17
19
|
editor_partial: 'pageflow/editor/video_files/video_file',
|
18
20
|
collection_name: 'video_files',
|
19
21
|
url_templates: VideoFileUrlTemplates.new,
|
22
|
+
css_background_image_urls: VideoFileCssBackgroundImageUrls.new,
|
23
|
+
css_background_image_class_prefix: 'video_poster',
|
20
24
|
top_level_type: true,
|
21
25
|
nested_file_types: [BuiltInFileType.text_track])
|
22
26
|
end
|
@@ -32,8 +32,20 @@ module Pageflow
|
|
32
32
|
new('slim_player_controls', ['player_controls'], 'pageflow/widgets/placeholder')
|
33
33
|
end
|
34
34
|
|
35
|
+
def self.default_slideshow_mode
|
36
|
+
new('default_slideshow_mode', ['slideshow_mode'], 'pageflow/widgets/placeholder')
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.phone_horizontal_slideshow_mode
|
40
|
+
new('phone_horizontal_slideshow_mode', ['slideshow_mode'], 'pageflow/widgets/placeholder')
|
41
|
+
end
|
42
|
+
|
35
43
|
def self.cookie_notice_bar
|
36
44
|
Pageflow::React.create_widget_type('cookie_notice_bar', 'cookie_notice')
|
37
45
|
end
|
46
|
+
|
47
|
+
def self.unmute_button
|
48
|
+
Pageflow::React.create_widget_type('unmute_button', 'background_media_control')
|
49
|
+
end
|
38
50
|
end
|
39
51
|
end
|
@@ -1,11 +1,16 @@
|
|
1
1
|
module Pageflow
|
2
2
|
class BuiltInWidgetTypesPlugin < Plugin
|
3
3
|
def configure(config)
|
4
|
+
config.widget_types.register(Pageflow::BuiltInWidgetType.default_slideshow_mode,
|
5
|
+
default: true)
|
6
|
+
config.widget_types.register(Pageflow::BuiltInWidgetType.phone_horizontal_slideshow_mode)
|
7
|
+
|
4
8
|
config.widget_types.register(Pageflow::BuiltInWidgetType.navigation, default: true)
|
5
9
|
config.widget_types.register(Pageflow::BuiltInWidgetType.mobile_navigation, default: true)
|
6
10
|
config.widget_types.register(Pageflow::BuiltInWidgetType.slim_player_controls)
|
7
11
|
config.widget_types.register(Pageflow::BuiltInWidgetType.classic_player_controls, default: true)
|
8
12
|
config.widget_types.register(Pageflow::BuiltInWidgetType.cookie_notice_bar)
|
13
|
+
config.widget_types.register(Pageflow::BuiltInWidgetType.unmute_button, default: true)
|
9
14
|
end
|
10
15
|
end
|
11
16
|
end
|
data/lib/pageflow/file_type.rb
CHANGED
@@ -24,11 +24,37 @@ module Pageflow
|
|
24
24
|
# @return {Boolean}
|
25
25
|
attr_reader :top_level_type
|
26
26
|
|
27
|
+
# Callable that receives a file record and returns a hash of one
|
28
|
+
# of the following forms:
|
29
|
+
#
|
30
|
+
# {
|
31
|
+
# poster: "url/of/image"
|
32
|
+
# }
|
33
|
+
#
|
34
|
+
# where `poster` is an arbitrary css class infix. Use `default` to
|
35
|
+
# skip the infix in the generated css class name. Or
|
36
|
+
#
|
37
|
+
# {
|
38
|
+
# poster: {
|
39
|
+
# desktop: "desktop/url/of/image",
|
40
|
+
# mobile: "mobile/url/of/image"
|
41
|
+
# }
|
42
|
+
# }
|
43
|
+
#
|
44
|
+
# to provide different urls for the two media breakpoints.
|
45
|
+
#
|
46
|
+
# @return [#call]
|
47
|
+
attr_reader :css_background_image_urls
|
48
|
+
|
27
49
|
# Callable that returns a hash of url template strings indexed by
|
28
50
|
# their names.
|
29
51
|
# @return [#call]
|
30
52
|
attr_reader :url_templates
|
31
53
|
|
54
|
+
# Attributes that are custom to this file type.
|
55
|
+
# @return {Array<Symbol>}
|
56
|
+
attr_reader :custom_attributes
|
57
|
+
|
32
58
|
# Create file type to be returned in {PageType#file_types}.
|
33
59
|
#
|
34
60
|
# @example
|
@@ -50,9 +76,14 @@ module Pageflow
|
|
50
76
|
# model `Pageflow::Rainbow::File`.
|
51
77
|
# @option options [Array<FileType>] :nested_file_types
|
52
78
|
# Optional. Array of FileTypes allowed for nested files. Defaults to [].
|
79
|
+
# @option options [#call] :css_background_image_urls
|
80
|
+
# Optional. See {#css_background_image_urls}
|
53
81
|
# @option options [#call] :url_templates
|
54
82
|
# Optional. Callable returning a hash of url template strings
|
55
83
|
# indexed by their names.
|
84
|
+
# @option options [Array<Symbol>] :custom_attributes
|
85
|
+
# Optional. Array of strings containing attribute names that are
|
86
|
+
# custom to this file type
|
56
87
|
def initialize(options)
|
57
88
|
@model_string_or_reference = options.fetch(:model)
|
58
89
|
@partial = options[:partial]
|
@@ -60,7 +91,10 @@ module Pageflow
|
|
60
91
|
@collection_name_or_blank = options[:collection_name]
|
61
92
|
@nested_file_types = options.fetch(:nested_file_types, [])
|
62
93
|
@top_level_type = options.fetch(:top_level_type, false)
|
94
|
+
@css_background_image_urls = options[:css_background_image_urls]
|
95
|
+
@css_background_image_class_prefix = options[:css_background_image_class_prefix]
|
63
96
|
@url_templates = options.fetch(:url_templates, ->() { {} })
|
97
|
+
@custom_attributes = options.fetch(:custom_attributes, [])
|
64
98
|
end
|
65
99
|
|
66
100
|
# ActiveRecord model that represents the files of this type.
|
@@ -84,6 +118,11 @@ module Pageflow
|
|
84
118
|
end
|
85
119
|
end
|
86
120
|
|
121
|
+
# @api private
|
122
|
+
def css_background_image_class_prefix
|
123
|
+
@css_background_image_class_prefix || model.model_name.singular
|
124
|
+
end
|
125
|
+
|
87
126
|
# @api private
|
88
127
|
def param_key
|
89
128
|
model.model_name.param_key.to_sym
|
data/lib/pageflow/file_types.rb
CHANGED
data/lib/pageflow/version.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
module Pageflow
|
2
|
-
class TestHostedFile < ActiveRecord::Base
|
3
|
-
self.table_name = 'test_hosted_files'
|
4
|
-
include HostedFile
|
5
|
-
end
|
6
|
-
|
7
2
|
FactoryBot.define do
|
8
|
-
factory :hosted_file, class: TestHostedFile do
|
3
|
+
factory :hosted_file, class: 'Pageflow::TestHostedFile' do
|
4
|
+
attachment_on_s3 { File.open(Engine.root.join('spec', 'fixtures', 'image.png')) }
|
5
|
+
state { 'uploaded_to_s3' }
|
6
|
+
|
7
|
+
transient do
|
8
|
+
used_in { nil }
|
9
|
+
end
|
10
|
+
|
11
|
+
after(:create) do |file, evaluator|
|
12
|
+
create(:file_usage, file: file, revision: evaluator.used_in) if evaluator.used_in
|
13
|
+
end
|
14
|
+
|
9
15
|
trait :on_filesystem do
|
10
16
|
attachment_on_filesystem { File.open(Engine.root.join('spec', 'fixtures', 'image.png')) }
|
11
17
|
attachment_on_s3 { nil }
|
@@ -19,8 +25,6 @@ module Pageflow
|
|
19
25
|
end
|
20
26
|
|
21
27
|
trait :uploaded_to_s3 do
|
22
|
-
attachment_on_s3 { File.open(Engine.root.join('spec', 'fixtures', 'image.png')) }
|
23
|
-
state { 'uploaded_to_s3' }
|
24
28
|
end
|
25
29
|
|
26
30
|
trait :with_overridden_keep_on_filesystem do
|
@@ -4,9 +4,9 @@
|
|
4
4
|
* License MIT (c) Zohar Arad 2013
|
5
5
|
*/
|
6
6
|
(function ($win, ns, factory) {
|
7
|
+
"use strict";
|
7
8
|
/*global define */
|
8
9
|
/*global swfobject */
|
9
|
-
"use strict";
|
10
10
|
|
11
11
|
if (typeof (module) !== 'undefined' && module.exports) { // CommonJS
|
12
12
|
module.exports = factory(ns, $win);
|
@@ -134,17 +134,35 @@
|
|
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
|
-
|
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
|
+
|
138
143
|
while(this.channels[evt].length > 0) {
|
139
144
|
var sub = this.channels[evt].shift();
|
140
|
-
|
141
|
-
sub.fn.apply(sub.ctx, args);
|
142
|
-
}
|
145
|
+
|
143
146
|
if ( !sub.once ){
|
144
|
-
|
147
|
+
// for any channel event triggers that are not marked as once only, we need to keep.
|
148
|
+
evtSubscribers.push(sub);
|
145
149
|
}
|
150
|
+
|
151
|
+
// if we have a function with the channel subscription, store in temp array ready to call after all proceeded
|
152
|
+
if (typeof (sub.fn) === 'function') {
|
153
|
+
// every subscriber we've processed will be executed
|
154
|
+
evtSubscribersForExec.push(sub);
|
155
|
+
}
|
156
|
+
}
|
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);
|
146
165
|
}
|
147
|
-
this.channels[evt] = a;
|
148
166
|
}
|
149
167
|
}
|
150
168
|
};
|
@@ -153,19 +171,21 @@
|
|
153
171
|
/**
|
154
172
|
* Flash embed code string with cross-browser support.
|
155
173
|
*/
|
156
|
-
|
174
|
+
flash_embed_code: function (id, swf_location, ts) {
|
157
175
|
var prefix;
|
158
|
-
var
|
176
|
+
var elemId = ns + id;
|
177
|
+
var s = '<param name="movie" value="' + swf_location + '?playerInstanceNumber=' + id + '&datetime=' + ts + '"/>' +
|
159
178
|
'<param name="wmode" value="transparent"/>' +
|
160
179
|
'<param name="allowscriptaccess" value="always" />' +
|
161
180
|
'</object>';
|
162
181
|
if (ActiveXObject) {
|
163
|
-
prefix = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="1" height="1" id="
|
182
|
+
prefix = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="1" height="1" id="' + elemId + '">';
|
164
183
|
} else {
|
165
|
-
prefix = '<object type="application/x-shockwave-flash" data="
|
184
|
+
prefix = '<object type="application/x-shockwave-flash" data="' + swf_location + '?playerInstanceNumber=' + id + '&datetime=' + ts + '" width="1" height="1" id="' + elemId + '" >';
|
166
185
|
}
|
186
|
+
|
167
187
|
return prefix + s;
|
168
|
-
}
|
188
|
+
},
|
169
189
|
/**
|
170
190
|
* Check if browser supports audio mime type.
|
171
191
|
* @param {String} mime_type audio mime type to check
|
@@ -175,30 +195,36 @@
|
|
175
195
|
var a = document.createElement('audio');
|
176
196
|
var mime_str;
|
177
197
|
switch (mime_type) {
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
}
|
197
|
-
if (mime_str === undefined) {
|
198
|
-
throw new Error('Unspecified Audio Mime Type');
|
199
|
-
} else {
|
200
|
-
return !!a.canPlayType && a.canPlayType(mime_str) !== '';
|
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;
|
201
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
|
+
}
|
226
|
+
}
|
227
|
+
return false;
|
202
228
|
},
|
203
229
|
/**
|
204
230
|
* Boolean flag indicating whether the browser has Flash installed or not
|
@@ -232,19 +258,17 @@
|
|
232
258
|
document.body.appendChild(d);
|
233
259
|
if(typeof($win.swfobject) === 'object'){
|
234
260
|
var fv = {
|
235
|
-
playerInstance: 'window.'+ ns + '_flash.instances[
|
261
|
+
playerInstance: 'window.'+ ns + '_flash.instances[\''+id+'\']'
|
236
262
|
};
|
237
263
|
var params = {
|
238
264
|
allowscriptaccess: 'always',
|
239
265
|
wmode: 'transparent'
|
240
266
|
};
|
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);
|
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);
|
243
269
|
} else {
|
244
|
-
var
|
245
|
-
|
246
|
-
flashSource = flashSource.replace(/\$3/g, (new Date().getTime() + Math.random())); // Ensure swf is not pulled from cache
|
247
|
-
d.innerHTML = flashSource;
|
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);
|
248
272
|
}
|
249
273
|
return document.getElementById(id);
|
250
274
|
},
|
@@ -281,7 +305,7 @@
|
|
281
305
|
duration: 0, /** {Float} audio duration (sec) */
|
282
306
|
position: 0, /** {Float} audio position (sec) */
|
283
307
|
load_percent: 0, /** {Float} audio file load percent (%) */
|
284
|
-
seekable:
|
308
|
+
seekable: false, /** {Boolean} is loaded audio seekable */
|
285
309
|
ready: null /** {Boolean} is loaded audio seekable */
|
286
310
|
};
|
287
311
|
|
@@ -291,8 +315,7 @@
|
|
291
315
|
* @type {Object}
|
292
316
|
*/
|
293
317
|
var globalAudio5Flash = $win[ns + '_flash'] = $win[ns + '_flash'] || {
|
294
|
-
instances:
|
295
|
-
count: 0 /** FlashAudioPlayer instance count */
|
318
|
+
instances: [] /** FlashAudioPlayer instance hash */
|
296
319
|
};
|
297
320
|
|
298
321
|
/**
|
@@ -311,9 +334,8 @@
|
|
311
334
|
* @param {String} swf_src path to audio player SWF file
|
312
335
|
*/
|
313
336
|
init: function (swf_src) {
|
314
|
-
globalAudio5Flash.
|
315
|
-
this.id =
|
316
|
-
globalAudio5Flash.instances[this.id] = this;
|
337
|
+
globalAudio5Flash.instances.push(this);
|
338
|
+
this.id = globalAudio5Flash.instances.length - 1;
|
317
339
|
this.embed(swf_src);
|
318
340
|
},
|
319
341
|
/**
|
@@ -327,7 +349,7 @@
|
|
327
349
|
* ExternalInterface callback indicating SWF is ready
|
328
350
|
*/
|
329
351
|
eiReady: function () {
|
330
|
-
this.audio = document.getElementById(this.id);
|
352
|
+
this.audio = document.getElementById(ns + this.id);
|
331
353
|
this.trigger('ready');
|
332
354
|
},
|
333
355
|
/**
|
@@ -363,9 +385,13 @@
|
|
363
385
|
/**
|
364
386
|
* ExternalInterface download progress callback. Fires as long as audio file is downloaded by browser.
|
365
387
|
* @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)
|
366
390
|
*/
|
367
|
-
eiProgress: function (percent) {
|
391
|
+
eiProgress: function (percent, duration, seekable) {
|
368
392
|
this.load_percent = percent;
|
393
|
+
this.duration = duration;
|
394
|
+
this.seekable = seekable;
|
369
395
|
this.trigger('progress', percent);
|
370
396
|
},
|
371
397
|
/**
|
@@ -381,6 +407,7 @@
|
|
381
407
|
eiPlay: function () {
|
382
408
|
this.playing = true;
|
383
409
|
this.trigger('play');
|
410
|
+
this.trigger('playing');
|
384
411
|
},
|
385
412
|
/**
|
386
413
|
* ExternalInterface audio pause callback. Fires when audio is paused.
|
@@ -393,7 +420,7 @@
|
|
393
420
|
* ExternalInterface audio ended callback. Fires when audio playback ended.
|
394
421
|
*/
|
395
422
|
eiEnded: function () {
|
396
|
-
this.
|
423
|
+
this.pause();
|
397
424
|
this.trigger('ended');
|
398
425
|
},
|
399
426
|
/**
|
@@ -459,6 +486,24 @@
|
|
459
486
|
this.audio.seekTo(position);
|
460
487
|
this.position = position;
|
461
488
|
} 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
|
+
}
|
462
507
|
}
|
463
508
|
};
|
464
509
|
|
@@ -475,52 +520,91 @@
|
|
475
520
|
/**
|
476
521
|
* Initialize the player instance
|
477
522
|
*/
|
478
|
-
init: function (
|
479
|
-
this.
|
523
|
+
init: function () {
|
524
|
+
this._rate = 1;
|
480
525
|
this.trigger('ready');
|
481
526
|
},
|
527
|
+
/**
|
528
|
+
* Create new audio instance
|
529
|
+
*/
|
482
530
|
createAudio: function(){
|
483
|
-
this.audio =
|
531
|
+
this.audio = new Audio();
|
484
532
|
this.audio.autoplay = false;
|
485
533
|
this.audio.preload = 'auto';
|
486
534
|
this.audio.autobuffer = true;
|
535
|
+
this.audio.playbackRate = this._rate;
|
487
536
|
|
488
537
|
this.audio.setAttribute('crossorigin', 'anonymous');
|
489
538
|
|
490
539
|
this.bindEvents();
|
491
540
|
},
|
541
|
+
/**
|
542
|
+
* Destroy current audio instance
|
543
|
+
*/
|
492
544
|
destroyAudio: function(){
|
493
545
|
if(this.audio){
|
546
|
+
this.pause();
|
494
547
|
this.unbindEvents();
|
495
|
-
|
548
|
+
try {
|
549
|
+
this.audio.setAttribute('src', '');
|
550
|
+
} finally {
|
551
|
+
delete this.audio;
|
552
|
+
}
|
496
553
|
}
|
497
554
|
},
|
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
|
+
},
|
498
574
|
/**
|
499
575
|
* Bind DOM events to Audio object
|
500
576
|
*/
|
501
|
-
bindEvents: function
|
502
|
-
this.
|
503
|
-
|
504
|
-
|
505
|
-
this.audio.addEventListener('
|
506
|
-
this.audio.addEventListener('
|
507
|
-
this.audio.addEventListener('
|
508
|
-
this.audio.addEventListener('
|
509
|
-
this.audio.addEventListener('
|
510
|
-
this.audio.addEventListener('
|
511
|
-
this.audio.addEventListener('
|
512
|
-
|
513
|
-
|
514
|
-
this.audio.
|
515
|
-
this.audio.
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
this.audio.removeEventListener('
|
522
|
-
this.audio.removeEventListener('
|
523
|
-
this.audio.removeEventListener('
|
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);
|
524
608
|
},
|
525
609
|
/**
|
526
610
|
* Audio load start event handler. Triggered when audio starts loading
|
@@ -533,6 +617,9 @@
|
|
533
617
|
* Resets player parameters and starts audio download progress timer.
|
534
618
|
*/
|
535
619
|
onLoad: function () {
|
620
|
+
if(!this.audio){
|
621
|
+
return setTimeout(this.onLoad.bind(this), 100);
|
622
|
+
}
|
536
623
|
this.seekable = this.audio.seekable && this.audio.seekable.length > 0;
|
537
624
|
if (this.seekable) {
|
538
625
|
this.timer = setInterval(this.onProgress.bind(this), 250);
|
@@ -549,12 +636,21 @@
|
|
549
636
|
* Audio play event handler. Triggered when audio starts playing.
|
550
637
|
*/
|
551
638
|
onPlay: function () {
|
639
|
+
this.playing = true;
|
552
640
|
this.trigger('play');
|
553
641
|
},
|
642
|
+
/**
|
643
|
+
* Audio play event handler. Triggered when audio starts playing.
|
644
|
+
*/
|
645
|
+
onPlaying: function () {
|
646
|
+
this.playing = true;
|
647
|
+
this.trigger('playing');
|
648
|
+
},
|
554
649
|
/**
|
555
650
|
* Audio pause event handler. Triggered when audio is paused.
|
556
651
|
*/
|
557
652
|
onPause: function () {
|
653
|
+
this.playing = false;
|
558
654
|
this.trigger('pause');
|
559
655
|
},
|
560
656
|
/**
|
@@ -568,9 +664,11 @@
|
|
568
664
|
* Audio timeupdate event handler. Triggered as long as playhead position is updated (audio is being played).
|
569
665
|
*/
|
570
666
|
onTimeUpdate: function () {
|
571
|
-
if (this.audio
|
572
|
-
|
573
|
-
|
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){}
|
574
672
|
this.trigger('timeupdate', this.position, this.duration);
|
575
673
|
}
|
576
674
|
},
|
@@ -580,8 +678,9 @@
|
|
580
678
|
* Cancelled when audio has fully download or when a new audio file has been loaded to the player.
|
581
679
|
*/
|
582
680
|
onProgress: function () {
|
583
|
-
if (this.audio.buffered !== null) {
|
584
|
-
this.
|
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);
|
585
684
|
this.trigger('progress', this.load_percent);
|
586
685
|
if (this.load_percent >= 100) {
|
587
686
|
this.clearLoadProgress();
|
@@ -632,8 +731,11 @@
|
|
632
731
|
*/
|
633
732
|
load: function (url) {
|
634
733
|
this.reset();
|
635
|
-
this.
|
636
|
-
this.
|
734
|
+
this.trigger('pause');
|
735
|
+
//this.destroyAudio();
|
736
|
+
if(this.audio === undefined){
|
737
|
+
this.createAudio();
|
738
|
+
}
|
637
739
|
this.audio.setAttribute('src', url);
|
638
740
|
this.audio.load();
|
639
741
|
},
|
@@ -641,15 +743,19 @@
|
|
641
743
|
* Play audio
|
642
744
|
*/
|
643
745
|
play: function () {
|
644
|
-
this.
|
645
|
-
|
746
|
+
if(this.audio) {
|
747
|
+
var playPromise = this.audio.play();
|
748
|
+
this.audio.playbackRate = this._rate;
|
749
|
+
return playPromise;
|
750
|
+
}
|
646
751
|
},
|
647
752
|
/**
|
648
753
|
* Pause audio
|
649
754
|
*/
|
650
755
|
pause: function () {
|
651
|
-
this.
|
652
|
-
|
756
|
+
if(this.audio) {
|
757
|
+
this.audio.pause();
|
758
|
+
}
|
653
759
|
},
|
654
760
|
/**
|
655
761
|
* Get / Set audio volume
|
@@ -676,10 +782,23 @@
|
|
676
782
|
if (playing) {
|
677
783
|
this.play();
|
678
784
|
} else {
|
679
|
-
if (this.audio.buffered !== null) {
|
785
|
+
if (this.audio.buffered !== null && this.audio.buffered.length) {
|
680
786
|
this.trigger('timeupdate', this.position, this.duration);
|
681
787
|
}
|
682
788
|
}
|
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
|
+
}
|
683
802
|
}
|
684
803
|
};
|
685
804
|
|
@@ -748,7 +867,7 @@
|
|
748
867
|
if (this.settings.use_flash) {
|
749
868
|
this.audio.init(s.swf_path);
|
750
869
|
} else {
|
751
|
-
this.audio.init(
|
870
|
+
this.audio.init();
|
752
871
|
}
|
753
872
|
},
|
754
873
|
/**
|
@@ -757,27 +876,35 @@
|
|
757
876
|
* @return {FlashAudioPlayer,HTML5AudioPlayer} audio player instance
|
758
877
|
*/
|
759
878
|
getPlayer: function () {
|
760
|
-
var i, l, player;
|
761
|
-
|
762
|
-
|
763
|
-
if (Audio5js.can_play(codec)) {
|
764
|
-
player = new HTML5AudioPlayer();
|
765
|
-
this.settings.use_flash = false;
|
766
|
-
this.settings.player = {
|
767
|
-
engine: 'html',
|
768
|
-
codec: codec
|
769
|
-
};
|
770
|
-
break;
|
771
|
-
}
|
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();
|
879
|
+
var i, l, player, codec;
|
880
|
+
if(this.settings.use_flash){
|
881
|
+
player = new FlashAudioPlayer();
|
777
882
|
this.settings.player = {
|
778
|
-
engine:
|
883
|
+
engine: 'flash',
|
779
884
|
codec: 'mp3'
|
780
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();
|
903
|
+
this.settings.player = {
|
904
|
+
engine: (this.settings.use_flash ? 'flash' : 'html'),
|
905
|
+
codec: 'mp3'
|
906
|
+
};
|
907
|
+
}
|
781
908
|
}
|
782
909
|
return player;
|
783
910
|
},
|
@@ -798,18 +925,36 @@
|
|
798
925
|
this.audio.on('seeking', this.onSeeking, this);
|
799
926
|
this.audio.on('seeked', this.onSeeked, this);
|
800
927
|
},
|
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
|
+
},
|
801
945
|
/**
|
802
946
|
* Load audio from URL
|
803
947
|
* @param {String} url URL of audio to load
|
804
948
|
*/
|
805
949
|
load: function (url) {
|
950
|
+
var that = this;
|
806
951
|
var f = function(u){
|
807
|
-
|
808
|
-
|
809
|
-
}
|
952
|
+
that.audio.load(u);
|
953
|
+
that.trigger('load');
|
954
|
+
};
|
810
955
|
|
811
956
|
if(this.ready){
|
812
|
-
f();
|
957
|
+
f(url);
|
813
958
|
} else {
|
814
959
|
this.on('ready', f);
|
815
960
|
}
|
@@ -819,8 +964,7 @@
|
|
819
964
|
*/
|
820
965
|
play: function () {
|
821
966
|
if(!this.playing){
|
822
|
-
this.
|
823
|
-
this.audio.play();
|
967
|
+
return this.audio.play();
|
824
968
|
}
|
825
969
|
},
|
826
970
|
/**
|
@@ -828,7 +972,6 @@
|
|
828
972
|
*/
|
829
973
|
pause: function () {
|
830
974
|
if(this.playing){
|
831
|
-
this.playing = false;
|
832
975
|
this.audio.pause();
|
833
976
|
}
|
834
977
|
},
|
@@ -859,6 +1002,20 @@
|
|
859
1002
|
this.audio.seek(position);
|
860
1003
|
this.position = position;
|
861
1004
|
},
|
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
|
+
},
|
862
1019
|
/**
|
863
1020
|
* Callback for audio ready event. Indicates audio is ready for playback.
|
864
1021
|
* Looks for ready callback in settings object and invokes it in the context of player instance
|
@@ -886,27 +1043,22 @@
|
|
886
1043
|
* Audio play event handler
|
887
1044
|
*/
|
888
1045
|
onPlay: function () {
|
1046
|
+
this.playing = true;
|
889
1047
|
this.trigger('play');
|
890
1048
|
},
|
891
1049
|
/**
|
892
1050
|
* Audio pause event handler
|
893
1051
|
*/
|
894
1052
|
onPause: function () {
|
1053
|
+
this.playing = false;
|
895
1054
|
this.trigger('pause');
|
896
1055
|
},
|
897
1056
|
/**
|
898
1057
|
* Playback end event handler
|
899
1058
|
*/
|
900
1059
|
onEnded: function () {
|
901
|
-
|
902
|
-
|
903
|
-
if (this.settings.loop && wasPlaying) {
|
904
|
-
this.audio.play();
|
905
|
-
}
|
906
|
-
else {
|
907
|
-
this.playing = false;
|
908
|
-
this.trigger('ended');
|
909
|
-
}
|
1060
|
+
this.playing = false;
|
1061
|
+
this.trigger('ended');
|
910
1062
|
},
|
911
1063
|
/**
|
912
1064
|
* Audio error event handler
|
@@ -944,9 +1096,7 @@
|
|
944
1096
|
*/
|
945
1097
|
onTimeUpdate: function (position, duration) {
|
946
1098
|
this.position = this.settings.format_time ? util.formatTime(position) : position;
|
947
|
-
|
948
|
-
this.duration = this.settings.format_time && duration !== null ? util.formatTime(duration) : duration;
|
949
|
-
}
|
1099
|
+
this.duration = this.settings.format_time && duration !== null ? util.formatTime(duration) : duration;
|
950
1100
|
this.trigger('timeupdate', this.position, this.duration);
|
951
1101
|
},
|
952
1102
|
/**
|
@@ -954,6 +1104,7 @@
|
|
954
1104
|
* @param {Float} loaded audio download percent
|
955
1105
|
*/
|
956
1106
|
onProgress: function (loaded) {
|
1107
|
+
this.duration = this.audio.duration;
|
957
1108
|
this.load_percent = loaded;
|
958
1109
|
this.trigger('progress', loaded);
|
959
1110
|
}
|
@@ -964,4 +1115,4 @@
|
|
964
1115
|
|
965
1116
|
return Audio5js;
|
966
1117
|
|
967
|
-
}));
|
1118
|
+
}));
|