transit 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (186) hide show
  1. data/Gemfile +19 -11
  2. data/app/assets/images/transit/icon24x24.png +0 -0
  3. data/app/assets/images/transit/icon24x24_files.png +0 -0
  4. data/app/assets/images/transit/jplayer.swf +0 -0
  5. data/app/assets/images/transit/uploadify.swf +0 -0
  6. data/app/assets/images/transit/video_player.swf +0 -0
  7. data/app/assets/javascripts/jqtools/expose.js +224 -0
  8. data/app/assets/javascripts/jqtools/flashembed.js +300 -0
  9. data/app/assets/javascripts/jqtools/overlay.js +294 -0
  10. data/app/assets/javascripts/jqtools/scrollable.js +3 -0
  11. data/app/assets/javascripts/jqtools/scrollable/autoscroll.js +81 -0
  12. data/app/assets/javascripts/jqtools/scrollable/base.js +335 -0
  13. data/app/assets/javascripts/jqtools/scrollable/navigator.js +139 -0
  14. data/app/assets/javascripts/jqtools/validator.js +590 -0
  15. data/app/assets/javascripts/jqueryui/accordion.js +611 -0
  16. data/app/assets/javascripts/jqueryui/autocomplete.js +612 -0
  17. data/app/assets/javascripts/jqueryui/button.js +388 -0
  18. data/app/assets/javascripts/jqueryui/core.js +312 -0
  19. data/app/assets/javascripts/jqueryui/datepicker.js +1791 -0
  20. data/app/assets/javascripts/jqueryui/dialog.js +878 -0
  21. data/app/assets/javascripts/jqueryui/draggable.js +815 -0
  22. data/app/assets/javascripts/jqueryui/droppable.js +285 -0
  23. data/app/assets/javascripts/jqueryui/effects/blind.js +49 -0
  24. data/app/assets/javascripts/jqueryui/effects/bounce.js +78 -0
  25. data/app/assets/javascripts/jqueryui/effects/clip.js +54 -0
  26. data/app/assets/javascripts/jqueryui/effects/core.js +746 -0
  27. data/app/assets/javascripts/jqueryui/effects/drop.js +50 -0
  28. data/app/assets/javascripts/jqueryui/effects/explode.js +79 -0
  29. data/app/assets/javascripts/jqueryui/effects/fade.js +32 -0
  30. data/app/assets/javascripts/jqueryui/effects/fold.js +56 -0
  31. data/app/assets/javascripts/jqueryui/effects/highlight.js +50 -0
  32. data/app/assets/javascripts/jqueryui/effects/pulsate.js +51 -0
  33. data/app/assets/javascripts/jqueryui/effects/scale.js +178 -0
  34. data/app/assets/javascripts/jqueryui/effects/shake.js +57 -0
  35. data/app/assets/javascripts/jqueryui/effects/slide.js +50 -0
  36. data/app/assets/javascripts/jqueryui/effects/transfer.js +45 -0
  37. data/app/assets/javascripts/jqueryui/mouse.js +160 -0
  38. data/app/assets/javascripts/jqueryui/position.js +252 -0
  39. data/app/assets/javascripts/jqueryui/progressbar.js +109 -0
  40. data/app/assets/javascripts/jqueryui/resizable.js +814 -0
  41. data/app/assets/javascripts/jqueryui/selectable.js +266 -0
  42. data/app/assets/javascripts/jqueryui/slider.js +666 -0
  43. data/app/assets/javascripts/jqueryui/sortable.js +1077 -0
  44. data/app/assets/javascripts/jqueryui/tabs.js +758 -0
  45. data/app/assets/javascripts/jqueryui/widget.js +262 -0
  46. data/app/assets/javascripts/libs/backbone.js +1152 -0
  47. data/app/assets/javascripts/libs/cookie.js +89 -0
  48. data/app/assets/javascripts/libs/fileinput.js +130 -0
  49. data/app/assets/javascripts/libs/jplayer.js +1768 -0
  50. data/app/assets/javascripts/libs/proper.js +541 -0
  51. data/app/assets/javascripts/libs/sanitize.js +282 -0
  52. data/app/assets/javascripts/libs/selecttolist.js +75 -0
  53. data/app/assets/javascripts/libs/underscore.js +807 -0
  54. data/app/assets/javascripts/libs/uploadify.js +677 -0
  55. data/app/assets/javascripts/libs/wymeditor.js +9538 -0
  56. data/app/assets/javascripts/transit.js +4 -0
  57. data/app/assets/javascripts/transit/admin.js +22 -0
  58. data/app/assets/javascripts/transit/admin/contexts.js +52 -0
  59. data/app/assets/javascripts/transit/admin/fields.js +36 -0
  60. data/app/assets/javascripts/transit/admin/upload.js +109 -0
  61. data/app/assets/javascripts/transit/config.js.erb +101 -0
  62. data/app/assets/javascripts/transit/contexts/audio.js +39 -0
  63. data/app/assets/javascripts/transit/contexts/video.js +79 -0
  64. data/app/assets/javascripts/transit/core.js +171 -0
  65. data/app/assets/javascripts/transit/frontend.js +3 -0
  66. data/app/assets/javascripts/transit/lib/base64.js +120 -0
  67. data/app/assets/javascripts/transit/lib/editor.js +177 -0
  68. data/app/assets/javascripts/transit/views/audio_player.jst +22 -0
  69. data/app/assets/javascripts/transit/views/editor_toolbar.jst +12 -0
  70. data/app/assets/javascripts/transit/views/file_upload.jst +5 -0
  71. data/app/assets/javascripts/transit/views/video_player.jst +20 -0
  72. data/app/assets/javascripts/transit/views/wym_box.jst +4 -0
  73. data/app/assets/javascripts/transit/views/wym_iframe.jst +3 -0
  74. data/app/assets/stylesheets/transit.css.scss.erb +42 -0
  75. data/app/assets/stylesheets/transit/forms.css.scss +66 -0
  76. data/app/assets/stylesheets/transit/media/audio.css.scss +65 -0
  77. data/app/assets/stylesheets/transit/media/video.css.scss +30 -0
  78. data/app/assets/stylesheets/transit/panel.css.scss +100 -0
  79. data/app/assets/stylesheets/transit/ui.css.scss +507 -0
  80. data/app/controllers/pages_controller.rb +3 -0
  81. data/app/controllers/posts_controller.rb +3 -0
  82. data/app/controllers/transit/assets_controller.rb +38 -0
  83. data/app/controllers/transit/contexts_controller.rb +12 -9
  84. data/app/controllers/transit/pages_controller.rb +26 -0
  85. data/app/controllers/transit/posts_controller.rb +31 -0
  86. data/app/controllers/transit/topics_controller.rb +5 -0
  87. data/app/controllers/transit_controller.rb +16 -0
  88. data/app/helpers/transit/admin_helper.rb +43 -0
  89. data/app/helpers/transit/form_helper.rb +17 -0
  90. data/app/helpers/transit/package_helper.rb +41 -0
  91. data/app/helpers/transit/pagination_helper.rb +58 -0
  92. data/app/helpers/transit_helper.rb +42 -0
  93. data/app/models/comment.rb +37 -0
  94. data/app/models/contexts/audio.rb +12 -0
  95. data/app/models/{text.rb → contexts/text.rb} +0 -0
  96. data/app/models/contexts/video.rb +24 -0
  97. data/app/models/topic.rb +19 -0
  98. data/app/models/transit/asset.rb +68 -0
  99. data/{lib → app/models}/transit/context.rb +29 -0
  100. data/app/views/contexts/_text.html.erb +1 -1
  101. data/app/views/posts/index.rss.builder +18 -0
  102. data/app/views/transit/assets/_file.html.erb +4 -0
  103. data/app/views/transit/assets/_image.html.erb +13 -0
  104. data/app/views/transit/assets/create.js.erb +8 -0
  105. data/app/views/transit/assets/destroy.js.erb +3 -0
  106. data/app/views/transit/assets/manage.html.erb +20 -0
  107. data/app/views/transit/contexts/_audio.html.erb +18 -0
  108. data/app/views/transit/contexts/_text.html.erb +6 -0
  109. data/app/views/transit/contexts/_video.html.erb +13 -0
  110. data/app/views/transit/contexts/destroy.js.erb +1 -0
  111. data/app/views/transit/contexts/index.html.erb +5 -0
  112. data/app/views/transit/contexts/new.js.erb +7 -0
  113. data/app/views/transit/contexts/show.html.erb +8 -0
  114. data/app/views/transit/index.html.erb +26 -0
  115. data/app/views/transit/index.js.erb +1 -0
  116. data/app/views/transit/interface/post_panel.html.erb +96 -0
  117. data/app/views/transit/pages/_table.html.erb +7 -0
  118. data/app/views/transit/pages/edit.html.erb +17 -0
  119. data/app/views/transit/pages/index.html.erb +17 -0
  120. data/app/views/transit/pages/update.js.erb +1 -0
  121. data/app/views/transit/posts/_form.html.erb +49 -0
  122. data/app/views/transit/posts/edit.html.erb +14 -0
  123. data/app/views/transit/posts/new.html.erb +21 -0
  124. data/app/views/transit/table.html.erb +13 -0
  125. data/app/views/transit/table.js.erb +8 -0
  126. data/app/views/transit/topics/manage.html.erb +28 -0
  127. data/config/locales/en.yml +22 -0
  128. data/config/routes.rb +3 -3
  129. data/lib/transit.rb +51 -17
  130. data/lib/transit/admin.rb +85 -0
  131. data/lib/transit/builders/form_builder.rb +319 -0
  132. data/lib/transit/builders/jst_builder.rb +38 -0
  133. data/lib/transit/builders/package_builder.rb +45 -0
  134. data/lib/transit/config.rb +20 -0
  135. data/lib/transit/controller/generator.rb +42 -0
  136. data/lib/transit/controller/responder.rb +34 -0
  137. data/lib/transit/core_ext.rb +18 -0
  138. data/lib/transit/errors/resource_not_found.rb +6 -0
  139. data/lib/transit/model/assets.rb +14 -0
  140. data/lib/transit/model/attachments.rb +55 -0
  141. data/lib/transit/model/auto_increment.rb +22 -0
  142. data/lib/transit/model/base.rb +56 -0
  143. data/lib/transit/model/comments.rb +19 -0
  144. data/lib/transit/model/hooks.rb +38 -0
  145. data/lib/transit/model/owners.rb +14 -0
  146. data/lib/transit/model/paginator.rb +92 -0
  147. data/lib/transit/model/topics.rb +14 -0
  148. data/lib/transit/package/page.rb +20 -12
  149. data/lib/transit/package/post.rb +87 -33
  150. data/lib/transit/package/post/validations.rb +14 -0
  151. data/lib/transit/rails/engine.rb +29 -13
  152. data/lib/transit/rails/railtie.rb +31 -0
  153. data/lib/transit/rails/routing.rb +11 -6
  154. data/lib/transit/services.rb +13 -0
  155. data/lib/transit/services/base.rb +14 -0
  156. data/lib/transit/services/facebook.rb +13 -0
  157. data/lib/transit/services/ted.rb +10 -0
  158. data/lib/transit/services/twitter.rb +13 -0
  159. data/lib/transit/services/vimeo.rb +10 -0
  160. data/lib/transit/services/you_tube.rb +12 -0
  161. data/lib/transit/version.rb +1 -1
  162. metadata +178 -31
  163. data/app/assets/stylesheets/includes/_compat.scss +0 -24
  164. data/app/assets/stylesheets/includes/_defaults.scss +0 -99
  165. data/app/assets/stylesheets/includes/_global.scss +0 -16
  166. data/app/assets/stylesheets/includes/_imports.scss +0 -27
  167. data/app/assets/stylesheets/includes/_mixins.scss +0 -38
  168. data/app/assets/stylesheets/includes/_setup.scss +0 -85
  169. data/app/assets/stylesheets/layout.css.scss +0 -29
  170. data/app/assets/stylesheets/transit.css +0 -3
  171. data/app/controllers/application_controller.rb +0 -5
  172. data/app/controllers/transit/index_controller.rb +0 -7
  173. data/app/controllers/transit/packages_controller.rb +0 -64
  174. data/app/controllers/transit/transit_controller.rb +0 -4
  175. data/app/helpers/routing_helpers.rb +0 -7
  176. data/app/models/audio.rb +0 -4
  177. data/app/models/package_asset.rb +0 -11
  178. data/app/models/video.rb +0 -8
  179. data/app/views/contexts/_audio.html.erb +0 -1
  180. data/app/views/contexts/_video.html.erb +0 -1
  181. data/app/views/layouts/transit.html.erb +0 -31
  182. data/app/views/transit/index/index.html.erb +0 -0
  183. data/lib/transit/helpers/controller_helpers.rb +0 -40
  184. data/lib/transit/helpers/model_helpers.rb +0 -26
  185. data/lib/transit/package.rb +0 -25
  186. data/lib/transit/package/base.rb +0 -49
@@ -0,0 +1,89 @@
1
+ /*jslint browser: true */ /*global jQuery: true */
2
+
3
+ /**
4
+ * jQuery Cookie plugin
5
+ *
6
+ * Copyright (c) 2010 Klaus Hartl (stilbuero.de)
7
+ * Dual licensed under the MIT and GPL licenses:
8
+ * http://www.opensource.org/licenses/mit-license.php
9
+ * http://www.gnu.org/licenses/gpl.html
10
+ *
11
+ */
12
+
13
+ // TODO JsDoc
14
+
15
+ /**
16
+ * Create a cookie with the given key and value and other optional parameters.
17
+ *
18
+ * @example $.cookie('the_cookie', 'the_value');
19
+ * @desc Set the value of a cookie.
20
+ * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
21
+ * @desc Create a cookie with all available options.
22
+ * @example $.cookie('the_cookie', 'the_value');
23
+ * @desc Create a session cookie.
24
+ * @example $.cookie('the_cookie', null);
25
+ * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
26
+ * used when the cookie was set.
27
+ *
28
+ * @param String key The key of the cookie.
29
+ * @param String value The value of the cookie.
30
+ * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
31
+ * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
32
+ * If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
33
+ * If set to null or omitted, the cookie will be a session cookie and will not be retained
34
+ * when the the browser exits.
35
+ * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
36
+ * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
37
+ * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
38
+ * require a secure protocol (like HTTPS).
39
+ * @type undefined
40
+ *
41
+ * @name $.cookie
42
+ * @cat Plugins/Cookie
43
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
44
+ */
45
+
46
+ /**
47
+ * Get the value of a cookie with the given key.
48
+ *
49
+ * @example $.cookie('the_cookie');
50
+ * @desc Get the value of a cookie.
51
+ *
52
+ * @param String key The key of the cookie.
53
+ * @return The value of the cookie.
54
+ * @type String
55
+ *
56
+ * @name $.cookie
57
+ * @cat Plugins/Cookie
58
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
59
+ */
60
+ jQuery.cookie = function (key, value, options) {
61
+
62
+ // key and value given, set cookie...
63
+ if (arguments.length > 1 && (value === null || typeof value !== "object")) {
64
+ options = jQuery.extend({}, options);
65
+
66
+ if (value === null) {
67
+ options.expires = -1;
68
+ }
69
+
70
+ if (typeof options.expires === 'number') {
71
+ var days = options.expires, t = options.expires = new Date();
72
+ t.setDate(t.getDate() + days);
73
+ }
74
+
75
+ return (document.cookie = [
76
+ encodeURIComponent(key), '=',
77
+ options.raw ? String(value) : encodeURIComponent(String(value)),
78
+ options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
79
+ options.path ? '; path=' + options.path : '',
80
+ options.domain ? '; domain=' + options.domain : '',
81
+ options.secure ? '; secure' : ''
82
+ ].join(''));
83
+ }
84
+
85
+ // key and possibly options given, get cookie...
86
+ options = value || {};
87
+ var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent;
88
+ return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
89
+ };
@@ -0,0 +1,130 @@
1
+ /*
2
+ * This file is part of fileinput.
3
+ *
4
+ * fileinput is free software: you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License as published by
6
+ * the Free Software Foundation, either version 3 of the License, or
7
+ * (at your option) any later version.
8
+ *
9
+ * fileinput is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
16
+ */
17
+
18
+ (function($){
19
+
20
+ var wrapperClasses = 'fileinput-wrapper ui-widget',
21
+ inputClasses = 'fileinput-input ui-state-default ui-widget-content ui-corner-left',
22
+ buttonClasses = 'fileinput-button ui-state-default ui-widget-header ui-corner-right',
23
+ buttonTextClasses = 'fileinput-button-text',
24
+ fileClasses = 'fileinput-file',
25
+ hoverClasses = 'ui-state-hover',
26
+ activeClasses = 'ui-state-active',
27
+ stateClasses = hoverClasses + ' ' + activeClasses,
28
+ fakePath = 'C:\\fakepath\\';
29
+
30
+ $.widget("shimmy.fileinput", {
31
+ options: {
32
+ buttonText: "Browse",
33
+ inputText: ""
34
+ },
35
+
36
+ _create: function(){
37
+ var self = this,
38
+ options = self.options;
39
+
40
+ self.fileFile = self.element,
41
+ self.fileWrapper = $('<div></div>')
42
+ .addClass(wrapperClasses)
43
+ .hover(function(){
44
+ self.fileButton.addClass(hoverClasses);
45
+ },function(){
46
+ self.fileButton.removeClass(stateClasses);
47
+ }).bind('mousemove.fileinput',function(e){
48
+ var x = (e.pageX - $(this).offset().left) - (self.fileFile.width() / 1.2);
49
+ var y = (e.pageY - $(this).offset().top) - (self.fileFile.height() / 2);
50
+ self.fileFile.css('top', y).css('left', x);
51
+ }).bind('mousedown.fileinput',function(e){
52
+ self.fileButton.addClass(activeClasses);
53
+ }).bind('mouseup.fileinput',function(e){
54
+ self.fileButton.removeClass(activeClasses);
55
+ }),
56
+ self.fileFile
57
+ .addClass(fileClasses)
58
+ .wrap(self.fileWrapper),
59
+ self.fileInput = $('<span></span>')
60
+ .addClass(inputClasses)
61
+ .text(self._getText())
62
+ .insertBefore(self.fileFile),
63
+ self.fileButtonText = $('<span></span>')
64
+ .addClass(buttonTextClasses)
65
+ .text(options.buttonText)
66
+ self.fileButton = $('<span></span>')
67
+ .addClass(buttonClasses)
68
+ .insertAfter(self.fileInput)
69
+ .html(self.fileButtonText);
70
+
71
+ self.fileFile.bind('change.fileinput mouseout.fileinput',function(){
72
+ self.fileInput.text(self._getText());
73
+ }).bind('focusin.fileinput',function(){
74
+ self.fileButton.addClass(hoverClasses);
75
+ }).bind('focusout.fileinput',function(){
76
+ self.fileButton.removeClass(hoverClasses);
77
+ });
78
+
79
+ },
80
+
81
+ _getText: function(){
82
+ var self = this;
83
+ fileValue = self.getValue();
84
+ inputTextValue = self.options.inputText;
85
+
86
+ if(fileValue == ''){
87
+ return inputTextValue;
88
+ }else{
89
+ return fileValue;
90
+ }
91
+ },
92
+
93
+ getValue: function(){
94
+ var self = this;
95
+ return fileValue = self.fileFile.val().replace(fakePath,'');
96
+ },
97
+
98
+ reset: function() {
99
+ var self = this;
100
+ self.fileInput.text(self.options.inputText);
101
+ },
102
+
103
+ destroy: function(){
104
+ var self = this;
105
+
106
+ self.fileInput.remove();
107
+ self.fileButton.remove();
108
+ self.fileButtonText.remove();
109
+ self.fileFile.removeClass(fileClasses).unwrap(self.fileWrapper);
110
+ self.fileWrapper.remove();
111
+
112
+ $.Widget.prototype.destroy.call( self );
113
+ },
114
+
115
+ _setOption: function(option, value){
116
+ var self = this;
117
+ $.Widget.prototype._setOption.apply( self, arguments );
118
+ switch(option){
119
+ case "buttonText":
120
+ self.fileButtonText.text(value);
121
+ break;
122
+ case "inputText":
123
+ self.fileInput.text(self._getText());
124
+ break;
125
+ }
126
+ }
127
+
128
+ });
129
+
130
+ })(jQuery);
@@ -0,0 +1,1768 @@
1
+ /*
2
+ * jPlayer Plugin for jQuery JavaScript Library
3
+ * http://www.happyworm.com/jquery/jplayer
4
+ *
5
+ * Copyright (c) 2009 - 2010 Happyworm Ltd
6
+ * Dual licensed under the MIT and GPL licenses.
7
+ * - http://www.opensource.org/licenses/mit-license.php
8
+ * - http://www.gnu.org/copyleft/gpl.html
9
+ *
10
+ * Author: Mark J Panaghiston
11
+ * Version: 2.0.0
12
+ * Date: 20th December 2010
13
+ */
14
+
15
+ (function($, undefined) {
16
+
17
+ // Adapted from jquery.ui.widget.js (1.8.7): $.widget.bridge
18
+ $.fn.jPlayer = function( options ) {
19
+ var name = "jPlayer";
20
+ var isMethodCall = typeof options === "string",
21
+ args = Array.prototype.slice.call( arguments, 1 ),
22
+ returnValue = this;
23
+
24
+ // allow multiple hashes to be passed on init
25
+ options = !isMethodCall && args.length ?
26
+ $.extend.apply( null, [ true, options ].concat(args) ) :
27
+ options;
28
+
29
+ // prevent calls to internal methods
30
+ if ( isMethodCall && options.charAt( 0 ) === "_" ) {
31
+ return returnValue;
32
+ }
33
+
34
+ if ( isMethodCall ) {
35
+ this.each(function() {
36
+ var instance = $.data( this, name ),
37
+ methodValue = instance && $.isFunction( instance[options] ) ?
38
+ instance[ options ].apply( instance, args ) :
39
+ instance;
40
+ if ( methodValue !== instance && methodValue !== undefined ) {
41
+ returnValue = methodValue;
42
+ return false;
43
+ }
44
+ });
45
+ } else {
46
+ this.each(function() {
47
+ var instance = $.data( this, name );
48
+ if ( instance ) {
49
+ instance.option( options || {} )._init(); // Orig jquery.ui.widget.js code: Not recommend for jPlayer. ie., Applying new options to an existing instance (via the jPlayer constructor) and performing the _init(). The _init() is what concerns me. It would leave a lot of event handlers acting on jPlayer instance and the interface.
50
+ instance.option( options || {} ); // The new constructor only changes the options. Changing options only has basic support atm.
51
+ } else {
52
+ $.data( this, name, new $.jPlayer( options, this ) );
53
+ }
54
+ });
55
+ }
56
+
57
+ return returnValue;
58
+ };
59
+
60
+ $.jPlayer = function( options, element ) {
61
+ // allow instantiation without initializing for simple inheritance
62
+ if ( arguments.length ) {
63
+ this.element = $(element);
64
+ this.options = $.extend(true, {},
65
+ this.options,
66
+ options
67
+ );
68
+ var self = this;
69
+ this.element.bind( "remove.jPlayer", function() {
70
+ self.destroy();
71
+ });
72
+ this._init();
73
+ }
74
+ };
75
+ // End of: (Adapted from jquery.ui.widget.js (1.8.7))
76
+
77
+ $.jPlayer.event = {
78
+ ready: "jPlayer_ready",
79
+ resize: "jPlayer_resize", // Not implemented.
80
+ error: "jPlayer_error", // Event error code in event.jPlayer.error.type. See $.jPlayer.error
81
+ warning: "jPlayer_warning", // Event warning code in event.jPlayer.warning.type. See $.jPlayer.warning
82
+
83
+ // Other events match HTML5 spec.
84
+ loadstart: "jPlayer_loadstart",
85
+ progress: "jPlayer_progress",
86
+ suspend: "jPlayer_suspend",
87
+ abort: "jPlayer_abort",
88
+ emptied: "jPlayer_emptied",
89
+ stalled: "jPlayer_stalled",
90
+ play: "jPlayer_play",
91
+ pause: "jPlayer_pause",
92
+ loadedmetadata: "jPlayer_loadedmetadata",
93
+ loadeddata: "jPlayer_loadeddata",
94
+ waiting: "jPlayer_waiting",
95
+ playing: "jPlayer_playing",
96
+ canplay: "jPlayer_canplay",
97
+ canplaythrough: "jPlayer_canplaythrough",
98
+ seeking: "jPlayer_seeking",
99
+ seeked: "jPlayer_seeked",
100
+ timeupdate: "jPlayer_timeupdate",
101
+ ended: "jPlayer_ended",
102
+ ratechange: "jPlayer_ratechange",
103
+ durationchange: "jPlayer_durationchange",
104
+ volumechange: "jPlayer_volumechange"
105
+ };
106
+
107
+ $.jPlayer.htmlEvent = [ // These HTML events are bubbled through to the jPlayer event, without any internal action.
108
+ "loadstart",
109
+ // "progress", // jPlayer uses internally before bubbling.
110
+ // "suspend", // jPlayer uses internally before bubbling.
111
+ "abort",
112
+ // "error", // jPlayer uses internally before bubbling.
113
+ "emptied",
114
+ "stalled",
115
+ // "play", // jPlayer uses internally before bubbling.
116
+ // "pause", // jPlayer uses internally before bubbling.
117
+ "loadedmetadata",
118
+ "loadeddata",
119
+ // "waiting", // jPlayer uses internally before bubbling.
120
+ // "playing", // jPlayer uses internally before bubbling.
121
+ // "canplay", // jPlayer fixes the volume (for Chrome) before bubbling.
122
+ "canplaythrough",
123
+ // "seeking", // jPlayer uses internally before bubbling.
124
+ // "seeked", // jPlayer uses internally before bubbling.
125
+ // "timeupdate", // jPlayer uses internally before bubbling.
126
+ // "ended", // jPlayer uses internally before bubbling.
127
+ "ratechange"
128
+ // "durationchange" // jPlayer uses internally before bubbling.
129
+ // "volumechange" // Handled by jPlayer in volume() method, primarily due to the volume fix (for Chrome) in the canplay event. [*] Need to review whether the latest Chrome still needs the fix sometime.
130
+ ];
131
+
132
+ $.jPlayer.pause = function() {
133
+ // $.each($.jPlayer.instances, function(i, element) {
134
+ $.each($.jPlayer.prototype.instances, function(i, element) {
135
+ if(element.data("jPlayer").status.srcSet) { // Check that media is set otherwise would cause error event.
136
+ element.jPlayer("pause");
137
+ }
138
+ });
139
+ };
140
+
141
+ $.jPlayer.timeFormat = {
142
+ showHour: false,
143
+ showMin: true,
144
+ showSec: true,
145
+ padHour: false,
146
+ padMin: true,
147
+ padSec: true,
148
+ sepHour: ":",
149
+ sepMin: ":",
150
+ sepSec: ""
151
+ };
152
+
153
+ $.jPlayer.convertTime = function(sec) {
154
+ var myTime = new Date(sec * 1000);
155
+ var hour = myTime.getUTCHours();
156
+ var min = myTime.getUTCMinutes();
157
+ var sec = myTime.getUTCSeconds();
158
+ var strHour = ($.jPlayer.timeFormat.padHour && hour < 10) ? "0" + hour : hour;
159
+ var strMin = ($.jPlayer.timeFormat.padMin && min < 10) ? "0" + min : min;
160
+ var strSec = ($.jPlayer.timeFormat.padSec && sec < 10) ? "0" + sec : sec;
161
+ return (($.jPlayer.timeFormat.showHour) ? strHour + $.jPlayer.timeFormat.sepHour : "") + (($.jPlayer.timeFormat.showMin) ? strMin + $.jPlayer.timeFormat.sepMin : "") + (($.jPlayer.timeFormat.showSec) ? strSec + $.jPlayer.timeFormat.sepSec : "");
162
+ };
163
+
164
+ // Adapting jQuery 1.4.4 code for jQuery.browser. Required since jQuery 1.3.2 does not detect Chrome as webkit.
165
+ $.jPlayer.uaMatch = function( ua ) {
166
+ var ua = ua.toLowerCase();
167
+
168
+ // Useragent RegExp
169
+ var rwebkit = /(webkit)[ \/]([\w.]+)/;
170
+ var ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/;
171
+ var rmsie = /(msie) ([\w.]+)/;
172
+ var rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/;
173
+
174
+ var match = rwebkit.exec( ua ) ||
175
+ ropera.exec( ua ) ||
176
+ rmsie.exec( ua ) ||
177
+ ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
178
+ [];
179
+
180
+ return { browser: match[1] || "", version: match[2] || "0" };
181
+ };
182
+
183
+ $.jPlayer.browser = {
184
+ };
185
+
186
+ var browserMatch = $.jPlayer.uaMatch(navigator.userAgent);
187
+ if ( browserMatch.browser ) {
188
+ $.jPlayer.browser[ browserMatch.browser ] = true;
189
+ $.jPlayer.browser.version = browserMatch.version;
190
+ }
191
+
192
+ $.jPlayer.prototype = {
193
+ count: 0, // Static Variable: Change it via prototype.
194
+ version: { // Static Object
195
+ script: "2.0.0",
196
+ needFlash: "2.0.0",
197
+ flash: "unknown"
198
+ },
199
+ options: { // Instanced in $.jPlayer() constructor
200
+ swfPath: "js", // Path to Jplayer.swf. Can be relative, absolute or server root relative.
201
+ solution: "html, flash", // Valid solutions: html, flash. Order defines priority. 1st is highest,
202
+ supplied: "mp3", // Defines which formats jPlayer will try and support and the priority by the order. 1st is highest,
203
+ preload: 'metadata', // HTML5 Spec values: none, metadata, auto.
204
+ volume: 0.8, // The volume. Number 0 to 1.
205
+ muted: false,
206
+ backgroundColor: "#000000", // To define the jPlayer div and Flash background color.
207
+ cssSelectorAncestor: "#jp_interface_1",
208
+ cssSelector: {
209
+ videoPlay: ".jp-video-play",
210
+ play: ".jp-play",
211
+ pause: ".jp-pause",
212
+ stop: ".jp-stop",
213
+ seekBar: ".jp-seek-bar",
214
+ playBar: ".jp-play-bar",
215
+ mute: ".jp-mute",
216
+ unmute: ".jp-unmute",
217
+ volumeBar: ".jp-volume-bar",
218
+ volumeBarValue: ".jp-volume-bar-value",
219
+ currentTime: ".jp-current-time",
220
+ duration: ".jp-duration"
221
+ },
222
+ // globalVolume: false, // Not implemented: Set to make volume changes affect all jPlayer instances
223
+ // globalMute: false, // Not implemented: Set to make mute changes affect all jPlayer instances
224
+ idPrefix: "jp", // Prefix for the ids of html elements created by jPlayer. For flash, this must not include characters: . - + * / \
225
+ errorAlerts: false,
226
+ warningAlerts: false
227
+ },
228
+ instances: {}, // Static Object
229
+ status: { // Instanced in _init()
230
+ src: "",
231
+ media: {},
232
+ paused: true,
233
+ format: {},
234
+ formatType: "",
235
+ waitForPlay: true, // Same as waitForLoad except in case where preloading.
236
+ waitForLoad: true,
237
+ srcSet: false,
238
+ video: false, // True if playing a video
239
+ seekPercent: 0,
240
+ currentPercentRelative: 0,
241
+ currentPercentAbsolute: 0,
242
+ currentTime: 0,
243
+ duration: 0
244
+ },
245
+ _status: { // Instanced in _init(): These status values are persistent. ie., Are not affected by a status reset.
246
+ volume: undefined, // Set by constructor option/default.
247
+ muted: false, // Set by constructor option/default.
248
+ width: 0, // Read from CSS
249
+ height: 0 // Read from CSS
250
+ },
251
+ internal: { // Instanced in _init()
252
+ ready: false,
253
+ instance: undefined,
254
+ htmlDlyCmdId: undefined
255
+ },
256
+ solution: { // Static Object: Defines the solutions built in jPlayer.
257
+ html: true,
258
+ flash: true
259
+ },
260
+ // 'MPEG-4 support' : canPlayType('video/mp4; codecs="mp4v.20.8"')
261
+ format: { // Static Object
262
+ mp3: {
263
+ codec: 'audio/mpeg; codecs="mp3"',
264
+ flashCanPlay: true,
265
+ media: 'audio'
266
+ },
267
+ m4a: { // AAC / MP4
268
+ codec: 'audio/mp4; codecs="mp4a.40.2"',
269
+ flashCanPlay: true,
270
+ media: 'audio'
271
+ },
272
+ oga: { // OGG
273
+ codec: 'audio/ogg; codecs="vorbis"',
274
+ flashCanPlay: false,
275
+ media: 'audio'
276
+ },
277
+ wav: { // PCM
278
+ codec: 'audio/wav; codecs="1"',
279
+ flashCanPlay: false,
280
+ media: 'audio'
281
+ },
282
+ webma: { // WEBM
283
+ codec: 'audio/webm; codecs="vorbis"',
284
+ flashCanPlay: false,
285
+ media: 'audio'
286
+ },
287
+ m4v: { // H.264 / MP4
288
+ codec: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',
289
+ flashCanPlay: true,
290
+ media: 'video'
291
+ },
292
+ ogv: { // OGG
293
+ codec: 'video/ogg; codecs="theora, vorbis"',
294
+ flashCanPlay: false,
295
+ media: 'video'
296
+ },
297
+ webmv: { // WEBM
298
+ codec: 'video/webm; codecs="vorbis, vp8"',
299
+ flashCanPlay: false,
300
+ media: 'video'
301
+ }
302
+ },
303
+ _init: function() {
304
+ var self = this;
305
+
306
+ this.element.empty();
307
+
308
+ this.status = $.extend({}, this.status, this._status); // Copy static to unique instance. Adds the status propeties that persist through a reset. NB: Might want to use $.jPlayer.prototype.status instead once options completely implmented and _init() returned to $.fn.jPlayer plugin.
309
+ this.internal = $.extend({}, this.internal); // Copy static to unique instance.
310
+
311
+ this.formats = []; // Array based on supplied string option. Order defines priority.
312
+ this.solutions = []; // Array based on solution string option. Order defines priority.
313
+ this.require = {}; // Which media types are required: video, audio.
314
+
315
+ this.htmlElement = {}; // DOM elements created by jPlayer
316
+ this.html = {}; // In _init()'s this.desired code and setmedia(): Accessed via this[solution], where solution from this.solutions array.
317
+ this.html.audio = {};
318
+ this.html.video = {};
319
+ this.flash = {}; // In _init()'s this.desired code and setmedia(): Accessed via this[solution], where solution from this.solutions array.
320
+
321
+ this.css = {};
322
+ this.css.cs = {}; // Holds the css selector strings
323
+ this.css.jq = {}; // Holds jQuery selectors. ie., $(css.cs.method)
324
+
325
+ this.status.volume = this._limitValue(this.options.volume, 0, 1); // Set volume status from constructor option.
326
+ this.status.muted = this.options.muted; // Set muted status from constructor option.
327
+ this.status.width = this.element.css('width'); // Sets from CSS.
328
+ this.status.height = this.element.css('height'); // Sets from CSS.
329
+
330
+ this.element.css({'background-color': this.options.backgroundColor});
331
+
332
+ // Create the formats array, with prority based on the order of the supplied formats string
333
+ $.each(this.options.supplied.toLowerCase().split(","), function(index1, value1) {
334
+ var format = value1.replace(/^\s+|\s+$/g, ""); //trim
335
+ if(self.format[format]) { // Check format is valid.
336
+ var dupFound = false;
337
+ $.each(self.formats, function(index2, value2) { // Check for duplicates
338
+ if(format === value2) {
339
+ dupFound = true;
340
+ return false;
341
+ }
342
+ });
343
+ if(!dupFound) {
344
+ self.formats.push(format);
345
+ }
346
+ }
347
+ });
348
+
349
+ // Create the solutions array, with prority based on the order of the solution string
350
+ $.each(this.options.solution.toLowerCase().split(","), function(index1, value1) {
351
+ var solution = value1.replace(/^\s+|\s+$/g, ""); //trim
352
+ if(self.solution[solution]) { // Check solution is valid.
353
+ var dupFound = false;
354
+ $.each(self.solutions, function(index2, value2) { // Check for duplicates
355
+ if(solution === value2) {
356
+ dupFound = true;
357
+ return false;
358
+ }
359
+ });
360
+ if(!dupFound) {
361
+ self.solutions.push(solution);
362
+ }
363
+ }
364
+ });
365
+
366
+ this.internal.instance = "jp_" + this.count;
367
+ this.instances[this.internal.instance] = this.element;
368
+
369
+ // Check the jPlayer div has an id and create one if required. Important for Flash to know the unique id for comms.
370
+ if(this.element.attr("id") === "") {
371
+ this.element.attr("id", this.options.idPrefix + "_jplayer_" + this.count);
372
+ }
373
+
374
+ this.internal.self = $.extend({}, {
375
+ id: this.element.attr("id"),
376
+ jq: this.element
377
+ });
378
+ this.internal.audio = $.extend({}, {
379
+ id: this.options.idPrefix + "_audio_" + this.count,
380
+ jq: undefined
381
+ });
382
+ this.internal.video = $.extend({}, {
383
+ id: this.options.idPrefix + "_video_" + this.count,
384
+ jq: undefined
385
+ });
386
+ this.internal.flash = $.extend({}, {
387
+ id: this.options.idPrefix + "_flash_" + this.count,
388
+ jq: undefined,
389
+ swf: this.options.swfPath// + ((this.options.swfPath !== "" && this.options.swfPath.slice(-1) !== "/") ? "/" : "")
390
+ });
391
+ this.internal.poster = $.extend({}, {
392
+ id: this.options.idPrefix + "_poster_" + this.count,
393
+ jq: undefined
394
+ });
395
+
396
+ // Register listeners defined in the constructor
397
+ $.each($.jPlayer.event, function(eventName,eventType) {
398
+ if(self.options[eventName] !== undefined) {
399
+ self.element.bind(eventType + ".jPlayer", self.options[eventName]); // With .jPlayer namespace.
400
+ self.options[eventName] = undefined; // Destroy the handler pointer copy on the options. Reason, events can be added/removed in other ways so this could be obsolete and misleading.
401
+ }
402
+ });
403
+
404
+ // Create the poster image.
405
+ this.htmlElement.poster = document.createElement('img');
406
+ this.htmlElement.poster.id = this.internal.poster.id;
407
+ this.htmlElement.poster.onload = function() { // Note that this did not work on Firefox 3.6: poster.addEventListener("onload", function() {}, false); Did not investigate x-browser.
408
+ if(!self.status.video || self.status.waitForPlay) {
409
+ self.internal.poster.jq.show();
410
+ }
411
+ };
412
+ this.element.append(this.htmlElement.poster);
413
+ this.internal.poster.jq = $("#" + this.internal.poster.id);
414
+ this.internal.poster.jq.css({'width': this.status.width, 'height': this.status.height});
415
+ this.internal.poster.jq.hide();
416
+
417
+ // Determine if we require solutions for audio, video or both media types.
418
+ this.require.audio = false;
419
+ this.require.video = false;
420
+ $.each(this.formats, function(priority, format) {
421
+ self.require[self.format[format].media] = true;
422
+ });
423
+
424
+ this.html.audio.available = false;
425
+ if(this.require.audio) { // If a supplied format is audio
426
+ this.htmlElement.audio = document.createElement('audio');
427
+ this.htmlElement.audio.id = this.internal.audio.id;
428
+ this.html.audio.available = !!this.htmlElement.audio.canPlayType;
429
+ }
430
+ this.html.video.available = false;
431
+ if(this.require.video) { // If a supplied format is video
432
+ this.htmlElement.video = document.createElement('video');
433
+ this.htmlElement.video.id = this.internal.video.id;
434
+ this.html.video.available = !!this.htmlElement.video.canPlayType;
435
+ }
436
+
437
+ this.flash.available = this._checkForFlash(10); // IE9 forced to false due to ExternalInterface problem.
438
+
439
+ this.html.canPlay = {};
440
+ this.flash.canPlay = {};
441
+ $.each(this.formats, function(priority, format) {
442
+ self.html.canPlay[format] = self.html[self.format[format].media].available && "" !== self.htmlElement[self.format[format].media].canPlayType(self.format[format].codec);
443
+ self.flash.canPlay[format] = self.format[format].flashCanPlay && self.flash.available;
444
+ });
445
+ this.html.desired = false;
446
+ this.flash.desired = false;
447
+ $.each(this.solutions, function(solutionPriority, solution) {
448
+ if(solutionPriority === 0) {
449
+ self[solution].desired = true;
450
+ } else {
451
+ var audioCanPlay = false;
452
+ var videoCanPlay = false;
453
+ $.each(self.formats, function(formatPriority, format) {
454
+ if(self[self.solutions[0]].canPlay[format]) { // The other solution can play
455
+ if(self.format[format].media === 'video') {
456
+ videoCanPlay = true;
457
+ } else {
458
+ audioCanPlay = true;
459
+ }
460
+ }
461
+ });
462
+ self[solution].desired = (self.require.audio && !audioCanPlay) || (self.require.video && !videoCanPlay);
463
+ }
464
+ });
465
+ // This is what jPlayer will support, based on solution and supplied.
466
+ this.html.support = {};
467
+ this.flash.support = {};
468
+ $.each(this.formats, function(priority, format) {
469
+ self.html.support[format] = self.html.canPlay[format] && self.html.desired;
470
+ self.flash.support[format] = self.flash.canPlay[format] && self.flash.desired;
471
+ });
472
+ // If jPlayer is supporting any format in a solution, then the solution is used.
473
+ this.html.used = false;
474
+ this.flash.used = false;
475
+ $.each(this.solutions, function(solutionPriority, solution) {
476
+ $.each(self.formats, function(formatPriority, format) {
477
+ if(self[solution].support[format]) {
478
+ self[solution].used = true;
479
+ return false;
480
+ }
481
+ });
482
+ });
483
+
484
+ // If neither html nor flash are being used by this browser, then media playback is not possible. Trigger an error event.
485
+ if(!(this.html.used || this.flash.used)) {
486
+ this._error( {
487
+ type: $.jPlayer.error.NO_SOLUTION,
488
+ context: "{solution:'" + this.options.solution + "', supplied:'" + this.options.supplied + "'}",
489
+ message: $.jPlayer.errorMsg.NO_SOLUTION,
490
+ hint: $.jPlayer.errorHint.NO_SOLUTION
491
+ });
492
+ }
493
+
494
+ // Init solution active state and the event gates to false.
495
+ this.html.active = false;
496
+ this.html.audio.gate = false;
497
+ this.html.video.gate = false;
498
+ this.flash.active = false;
499
+ this.flash.gate = false;
500
+
501
+ // Add the flash solution if it is being used.
502
+ if(this.flash.used) {
503
+ var flashVars = 'id=' + escape(this.internal.self.id) + '&vol=' + this.status.volume + '&muted=' + this.status.muted;
504
+
505
+ if($.browser.msie && Number($.browser.version) <= 8) {
506
+ var html_obj = '<object id="' + this.internal.flash.id + '"';
507
+ html_obj += ' classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"';
508
+ html_obj += ' codebase="' + document.URL.substring(0,document.URL.indexOf(':')) + '://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab"'; // Fixed IE non secured element warning.
509
+ html_obj += ' type="application/x-shockwave-flash"';
510
+ html_obj += ' width="0" height="0">';
511
+ html_obj += '</object>';
512
+
513
+ var obj_param = [];
514
+ obj_param[0] = '<param name="movie" value="' + this.internal.flash.swf + '" />';
515
+ obj_param[1] = '<param name="quality" value="high" />';
516
+ obj_param[2] = '<param name="FlashVars" value="' + flashVars + '" />';
517
+ obj_param[3] = '<param name="allowScriptAccess" value="always" />';
518
+ obj_param[4] = '<param name="bgcolor" value="' + this.options.backgroundColor + '" />';
519
+
520
+ var ie_dom = document.createElement(html_obj);
521
+ for(var i=0; i < obj_param.length; i++) {
522
+ ie_dom.appendChild(document.createElement(obj_param[i]));
523
+ }
524
+ this.element.append(ie_dom);
525
+ } else {
526
+ var html_embed = '<embed name="' + this.internal.flash.id + '" id="' + this.internal.flash.id + '" src="' + this.internal.flash.swf + '"';
527
+ html_embed += ' width="0" height="0" bgcolor="' + this.options.backgroundColor + '"';
528
+ html_embed += ' quality="high" FlashVars="' + flashVars + '"';
529
+ html_embed += ' allowScriptAccess="always"';
530
+ html_embed += ' type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />';
531
+ this.element.append(html_embed);
532
+ }
533
+ this.internal.flash.jq = $("#" + this.internal.flash.id);
534
+ this.internal.flash.jq.css({'width':'0px', 'height':'0px'}); // Must do via CSS as setting attr() to zero causes a jQuery error in IE.
535
+ }
536
+
537
+ // Add the HTML solution if being used.
538
+ if(this.html.used) {
539
+
540
+ // The HTML Audio handlers
541
+ if(this.html.audio.available) {
542
+ this._addHtmlEventListeners(this.htmlElement.audio, this.html.audio);
543
+ this.element.append(this.htmlElement.audio);
544
+ this.internal.audio.jq = $("#" + this.internal.audio.id);
545
+ }
546
+
547
+ // The HTML Video handlers
548
+ if(this.html.video.available) {
549
+ this._addHtmlEventListeners(this.htmlElement.video, this.html.video);
550
+ this.element.append(this.htmlElement.video);
551
+ this.internal.video.jq = $("#" + this.internal.video.id);
552
+ this.internal.video.jq.css({'width':'0px', 'height':'0px'}); // Using size 0x0 since a .hide() causes issues in iOS
553
+ }
554
+ }
555
+
556
+ if(this.html.used && !this.flash.used) { // If only HTML, then emulate flash ready() call after 100ms.
557
+ window.setTimeout( function() {
558
+ self.internal.ready = true;
559
+ self.version.flash = "n/a";
560
+ self._trigger($.jPlayer.event.ready);
561
+ }, 100);
562
+ }
563
+
564
+ // Set up the css selectors for the control and feedback entities.
565
+ $.each(this.options.cssSelector, function(fn, cssSel) {
566
+ self._cssSelector(fn, cssSel);
567
+ });
568
+
569
+ this._updateInterface();
570
+ this._updateButtons(false);
571
+ this._updateVolume(this.status.volume);
572
+ this._updateMute(this.status.muted);
573
+ if(this.css.jq.videoPlay.length) {
574
+ this.css.jq.videoPlay.hide();
575
+ }
576
+ $.jPlayer.prototype.count++; // Change static variable via prototype.
577
+ },
578
+ destroy: function() {
579
+ // MJP: The background change remains. Review later.
580
+
581
+ // Reset the interface, remove seeking effect and times.
582
+ this._resetStatus();
583
+ this._updateInterface();
584
+ this._seeked();
585
+ if(this.css.jq.currentTime.length) {
586
+ this.css.jq.currentTime.text("");
587
+ }
588
+ if(this.css.jq.duration.length) {
589
+ this.css.jq.duration.text("");
590
+ }
591
+
592
+ if(this.status.srcSet) { // Or you get a bogus error event
593
+ this.pause(); // Pauses the media and clears any delayed commands used in the HTML solution.
594
+ }
595
+ $.each(this.css.jq, function(fn, jq) { // Remove any bindings from the interface controls.
596
+ jq.unbind(".jPlayer");
597
+ });
598
+ this.element.removeData("jPlayer"); // Remove jPlayer data
599
+ this.element.unbind(".jPlayer"); // Remove all event handlers created by the jPlayer constructor
600
+ this.element.empty(); // Remove the inserted child elements
601
+
602
+ this.instances[this.internal.instance] = undefined; // Clear the instance on the static instance object
603
+ },
604
+ enable: function() { // Plan to implement
605
+ // options.disabled = false
606
+ },
607
+ disable: function () { // Plan to implement
608
+ // options.disabled = true
609
+ },
610
+ _addHtmlEventListeners: function(mediaElement, entity) {
611
+ var self = this;
612
+ mediaElement.preload = this.options.preload;
613
+ mediaElement.muted = this.options.muted;
614
+
615
+ // Create the event listeners
616
+ // Only want the active entity to affect jPlayer and bubble events.
617
+ // Using entity.gate so that object is referenced and gate property always current
618
+
619
+ mediaElement.addEventListener("progress", function() {
620
+ if(entity.gate && !self.status.waitForLoad) {
621
+ self._getHtmlStatus(mediaElement);
622
+ self._updateInterface();
623
+ self._trigger($.jPlayer.event.progress);
624
+ }
625
+ }, false);
626
+ mediaElement.addEventListener("timeupdate", function() {
627
+ if(entity.gate && !self.status.waitForLoad) {
628
+ self._getHtmlStatus(mediaElement);
629
+ self._updateInterface();
630
+ self._trigger($.jPlayer.event.timeupdate);
631
+ }
632
+ }, false);
633
+ mediaElement.addEventListener("durationchange", function() {
634
+ if(entity.gate && !self.status.waitForLoad) {
635
+ self.status.duration = this.duration;
636
+ self._getHtmlStatus(mediaElement);
637
+ self._updateInterface();
638
+ self._trigger($.jPlayer.event.durationchange);
639
+ }
640
+ }, false);
641
+ mediaElement.addEventListener("play", function() {
642
+ if(entity.gate && !self.status.waitForLoad) {
643
+ self._updateButtons(true);
644
+ self._trigger($.jPlayer.event.play);
645
+ }
646
+ }, false);
647
+ mediaElement.addEventListener("playing", function() {
648
+ if(entity.gate && !self.status.waitForLoad) {
649
+ self._updateButtons(true);
650
+ self._seeked();
651
+ self._trigger($.jPlayer.event.playing);
652
+ }
653
+ }, false);
654
+ mediaElement.addEventListener("pause", function() {
655
+ if(entity.gate && !self.status.waitForLoad) {
656
+ self._updateButtons(false);
657
+ self._trigger($.jPlayer.event.pause);
658
+ }
659
+ }, false);
660
+ mediaElement.addEventListener("waiting", function() {
661
+ if(entity.gate && !self.status.waitForLoad) {
662
+ self._seeking();
663
+ self._trigger($.jPlayer.event.waiting);
664
+ }
665
+ }, false);
666
+ mediaElement.addEventListener("canplay", function() {
667
+ if(entity.gate && !self.status.waitForLoad) {
668
+ mediaElement.volume = self._volumeFix(self.status.volume);
669
+ self._trigger($.jPlayer.event.canplay);
670
+ }
671
+ }, false);
672
+ mediaElement.addEventListener("seeking", function() {
673
+ if(entity.gate && !self.status.waitForLoad) {
674
+ self._seeking();
675
+ self._trigger($.jPlayer.event.seeking);
676
+ }
677
+ }, false);
678
+ mediaElement.addEventListener("seeked", function() {
679
+ if(entity.gate && !self.status.waitForLoad) {
680
+ self._seeked();
681
+ self._trigger($.jPlayer.event.seeked);
682
+ }
683
+ }, false);
684
+ mediaElement.addEventListener("suspend", function() { // Seems to be the only way of capturing that the iOS4 browser did not actually play the media from the page code. ie., It needs a user gesture.
685
+ if(entity.gate && !self.status.waitForLoad) {
686
+ self._seeked();
687
+ self._trigger($.jPlayer.event.suspend);
688
+ }
689
+ }, false);
690
+ mediaElement.addEventListener("ended", function() {
691
+ if(entity.gate && !self.status.waitForLoad) {
692
+ // Order of the next few commands are important. Change the time and then pause.
693
+ // Solves a bug in Firefox, where issuing pause 1st causes the media to play from the start. ie., The pause is ignored.
694
+ if(!$.jPlayer.browser.webkit) { // Chrome crashes if you do this in conjunction with a setMedia command in an ended event handler. ie., The playlist demo.
695
+ self.htmlElement.media.currentTime = 0; // Safari does not care about this command. ie., It works with or without this line. (Both Safari and Chrome are Webkit.)
696
+ }
697
+ self.htmlElement.media.pause(); // Pause otherwise a click on the progress bar will play from that point, when it shouldn't, since it stopped playback.
698
+ self._updateButtons(false);
699
+ self._getHtmlStatus(mediaElement, true); // With override true. Otherwise Chrome leaves progress at full.
700
+ self._updateInterface();
701
+ self._trigger($.jPlayer.event.ended);
702
+ }
703
+ }, false);
704
+ mediaElement.addEventListener("error", function() {
705
+ if(entity.gate && !self.status.waitForLoad) {
706
+ self._updateButtons(false);
707
+ self._seeked();
708
+ if(self.status.srcSet) { // Deals with case of clearMedia() causing an error event.
709
+ self.status.waitForLoad = true; // Allows the load operation to try again.
710
+ self.status.waitForPlay = true; // Reset since a play was captured.
711
+ if(self.status.video) {
712
+ self.internal.video.jq.css({'width':'0px', 'height':'0px'});
713
+ }
714
+ if(self._validString(self.status.media.poster)) {
715
+ self.internal.poster.jq.show();
716
+ }
717
+ if(self.css.jq.videoPlay.length) {
718
+ self.css.jq.videoPlay.show();
719
+ }
720
+ self._error( {
721
+ type: $.jPlayer.error.URL,
722
+ context: self.status.src, // this.src shows absolute urls. Want context to show the url given.
723
+ message: $.jPlayer.errorMsg.URL,
724
+ hint: $.jPlayer.errorHint.URL
725
+ });
726
+ }
727
+ }
728
+ }, false);
729
+ // Create all the other event listeners that bubble up to a jPlayer event from html, without being used by jPlayer.
730
+ $.each($.jPlayer.htmlEvent, function(i, eventType) {
731
+ mediaElement.addEventListener(this, function() {
732
+ if(entity.gate && !self.status.waitForLoad) {
733
+ self._trigger($.jPlayer.event[eventType]);
734
+ }
735
+ }, false);
736
+ });
737
+ },
738
+ _getHtmlStatus: function(media, override) {
739
+ var ct = 0, d = 0, cpa = 0, sp = 0, cpr = 0;
740
+
741
+ ct = media.currentTime;
742
+ cpa = (this.status.duration > 0) ? 100 * ct / this.status.duration : 0;
743
+ if((typeof media.seekable === "object") && (media.seekable.length > 0)) {
744
+ sp = (this.status.duration > 0) ? 100 * media.seekable.end(media.seekable.length-1) / this.status.duration : 100;
745
+ cpr = 100 * media.currentTime / media.seekable.end(media.seekable.length-1);
746
+ } else {
747
+ sp = 100;
748
+ cpr = cpa;
749
+ }
750
+
751
+ if(override) {
752
+ ct = 0;
753
+ cpr = 0;
754
+ cpa = 0;
755
+ }
756
+
757
+ this.status.seekPercent = sp;
758
+ this.status.currentPercentRelative = cpr;
759
+ this.status.currentPercentAbsolute = cpa;
760
+ this.status.currentTime = ct;
761
+ },
762
+ _resetStatus: function() {
763
+ var self = this;
764
+ this.status = $.extend({}, this.status, $.jPlayer.prototype.status); // Maintains the status properties that persist through a reset. ie., The properties of this._status, contained in the current this.status.
765
+
766
+ },
767
+ _trigger: function(eventType, error, warning) { // eventType always valid as called using $.jPlayer.event.eventType
768
+ var event = $.Event(eventType);
769
+ event.jPlayer = {};
770
+ event.jPlayer.version = $.extend({}, this.version);
771
+ event.jPlayer.status = $.extend(true, {}, this.status); // Deep copy
772
+ event.jPlayer.html = $.extend(true, {}, this.html); // Deep copy
773
+ event.jPlayer.flash = $.extend(true, {}, this.flash); // Deep copy
774
+ if(error) event.jPlayer.error = $.extend({}, error);
775
+ if(warning) event.jPlayer.warning = $.extend({}, warning);
776
+ this.element.trigger(event);
777
+ },
778
+ jPlayerFlashEvent: function(eventType, status) { // Called from Flash
779
+ if(eventType === $.jPlayer.event.ready && !this.internal.ready) {
780
+ this.internal.ready = true;
781
+ this.version.flash = status.version;
782
+ if(this.version.needFlash !== this.version.flash) {
783
+ this._error( {
784
+ type: $.jPlayer.error.VERSION,
785
+ context: this.version.flash,
786
+ message: $.jPlayer.errorMsg.VERSION + this.version.flash,
787
+ hint: $.jPlayer.errorHint.VERSION
788
+ });
789
+ }
790
+ this._trigger(eventType);
791
+ }
792
+ if(this.flash.gate) {
793
+ switch(eventType) {
794
+ case $.jPlayer.event.progress:
795
+ this._getFlashStatus(status);
796
+ this._updateInterface();
797
+ this._trigger(eventType);
798
+ break;
799
+ case $.jPlayer.event.timeupdate:
800
+ this._getFlashStatus(status);
801
+ this._updateInterface();
802
+ this._trigger(eventType);
803
+ break;
804
+ case $.jPlayer.event.play:
805
+ this._seeked();
806
+ this._updateButtons(true);
807
+ this._trigger(eventType);
808
+ break;
809
+ case $.jPlayer.event.pause:
810
+ this._updateButtons(false);
811
+ this._trigger(eventType);
812
+ break;
813
+ case $.jPlayer.event.ended:
814
+ this._updateButtons(false);
815
+ this._trigger(eventType);
816
+ break;
817
+ case $.jPlayer.event.error:
818
+ this.status.waitForLoad = true; // Allows the load operation to try again.
819
+ this.status.waitForPlay = true; // Reset since a play was captured.
820
+ if(this.status.video) {
821
+ this.internal.flash.jq.css({'width':'0px', 'height':'0px'});
822
+ }
823
+ if(this._validString(this.status.media.poster)) {
824
+ this.internal.poster.jq.show();
825
+ }
826
+ if(this.css.jq.videoPlay.length) {
827
+ this.css.jq.videoPlay.show();
828
+ }
829
+ if(this.status.video) { // Set up for another try. Execute before error event.
830
+ this._flash_setVideo(this.status.media);
831
+ } else {
832
+ this._flash_setAudio(this.status.media);
833
+ }
834
+ this._error( {
835
+ type: $.jPlayer.error.URL,
836
+ context:status.src,
837
+ message: $.jPlayer.errorMsg.URL,
838
+ hint: $.jPlayer.errorHint.URL
839
+ });
840
+ break;
841
+ case $.jPlayer.event.seeking:
842
+ this._seeking();
843
+ this._trigger(eventType);
844
+ break;
845
+ case $.jPlayer.event.seeked:
846
+ this._seeked();
847
+ this._trigger(eventType);
848
+ break;
849
+ default:
850
+ this._trigger(eventType);
851
+ }
852
+ }
853
+ return false;
854
+ },
855
+ _getFlashStatus: function(status) {
856
+ this.status.seekPercent = status.seekPercent;
857
+ this.status.currentPercentRelative = status.currentPercentRelative;
858
+ this.status.currentPercentAbsolute = status.currentPercentAbsolute;
859
+ this.status.currentTime = status.currentTime;
860
+ this.status.duration = status.duration;
861
+ },
862
+ _updateButtons: function(playing) {
863
+ this.status.paused = !playing;
864
+ if(this.css.jq.play.length && this.css.jq.pause.length) {
865
+ if(playing) {
866
+ this.css.jq.play.hide();
867
+ this.css.jq.pause.show();
868
+ } else {
869
+ this.css.jq.play.show();
870
+ this.css.jq.pause.hide();
871
+ }
872
+ }
873
+ },
874
+ _updateInterface: function() {
875
+ if(this.css.jq.seekBar.length) {
876
+ this.css.jq.seekBar.width(this.status.seekPercent+"%");
877
+ }
878
+ if(this.css.jq.playBar.length) {
879
+ this.css.jq.playBar.width(this.status.currentPercentRelative+"%");
880
+ }
881
+ if(this.css.jq.currentTime.length) {
882
+ this.css.jq.currentTime.text($.jPlayer.convertTime(this.status.currentTime));
883
+ }
884
+ if(this.css.jq.duration.length) {
885
+ this.css.jq.duration.text($.jPlayer.convertTime(this.status.duration));
886
+ }
887
+ },
888
+ _seeking: function() {
889
+ if(this.css.jq.seekBar.length) {
890
+ this.css.jq.seekBar.addClass("jp-seeking-bg");
891
+ }
892
+ },
893
+ _seeked: function() {
894
+ if(this.css.jq.seekBar.length) {
895
+ this.css.jq.seekBar.removeClass("jp-seeking-bg");
896
+ }
897
+ },
898
+ setMedia: function(media) {
899
+
900
+ /* media[format] = String: URL of format. Must contain all of the supplied option's video or audio formats.
901
+ * media.poster = String: Video poster URL.
902
+ * media.subtitles = String: * NOT IMPLEMENTED * URL of subtitles SRT file
903
+ * media.chapters = String: * NOT IMPLEMENTED * URL of chapters SRT file
904
+ * media.stream = Boolean: * NOT IMPLEMENTED * Designating actual media streams. ie., "false/undefined" for files. Plan to refresh the flash every so often.
905
+ */
906
+
907
+ var self = this;
908
+
909
+ this._seeked();
910
+ clearTimeout(this.internal.htmlDlyCmdId); // Clears any delayed commands used in the HTML solution.
911
+
912
+ // Store the current html gates, since we need for clearMedia() conditions.
913
+ var audioGate = this.html.audio.gate;
914
+ var videoGate = this.html.video.gate;
915
+
916
+ var supported = false;
917
+ $.each(this.formats, function(formatPriority, format) {
918
+ var isVideo = self.format[format].media === 'video';
919
+ $.each(self.solutions, function(solutionPriority, solution) {
920
+ if(self[solution].support[format] && self._validString(media[format])) { // Format supported in solution and url given for format.
921
+ var isHtml = solution === 'html';
922
+
923
+ if(isVideo) {
924
+ if(isHtml) {
925
+ self.html.audio.gate = false;
926
+ self.html.video.gate = true;
927
+ self.flash.gate = false;
928
+ } else {
929
+ self.html.audio.gate = false;
930
+ self.html.video.gate = false;
931
+ self.flash.gate = true;
932
+ }
933
+ } else {
934
+ if(isHtml) {
935
+ self.html.audio.gate = true;
936
+ self.html.video.gate = false;
937
+ self.flash.gate = false;
938
+ } else {
939
+ self.html.audio.gate = false;
940
+ self.html.video.gate = false;
941
+ self.flash.gate = true;
942
+ }
943
+ }
944
+
945
+ // Clear media of the previous solution if:
946
+ // - it was Flash
947
+ // - changing from HTML to Flash
948
+ // - the HTML solution media type (audio or video) remained the same.
949
+ // Note that, we must be careful with clearMedia() on iPhone, otherwise clearing the video when changing to audio corrupts the built in video player.
950
+ if(self.flash.active || (self.html.active && self.flash.gate) || (audioGate === self.html.audio.gate && videoGate === self.html.video.gate)) {
951
+ self.clearMedia();
952
+ } else if(audioGate !== self.html.audio.gate && videoGate !== self.html.video.gate) { // If switching between html elements
953
+ self._html_pause();
954
+ // Hide the video if it was being used.
955
+ if(self.status.video) {
956
+ self.internal.video.jq.css({'width':'0px', 'height':'0px'});
957
+ }
958
+ self._resetStatus(); // Since clearMedia usually does this. Execute after status.video useage.
959
+ }
960
+
961
+ if(isVideo) {
962
+ if(isHtml) {
963
+ self._html_setVideo(media);
964
+ self.html.active = true;
965
+ self.flash.active = false;
966
+ } else {
967
+ self._flash_setVideo(media);
968
+ self.html.active = false;
969
+ self.flash.active = true;
970
+ }
971
+ if(self.css.jq.videoPlay.length) {
972
+ self.css.jq.videoPlay.show();
973
+ }
974
+ self.status.video = true;
975
+ } else {
976
+ if(isHtml) {
977
+ self._html_setAudio(media);
978
+ self.html.active = true;
979
+ self.flash.active = false;
980
+ } else {
981
+ self._flash_setAudio(media);
982
+ self.html.active = false;
983
+ self.flash.active = true;
984
+ }
985
+ if(self.css.jq.videoPlay.length) {
986
+ self.css.jq.videoPlay.hide();
987
+ }
988
+ self.status.video = false;
989
+ }
990
+
991
+ supported = true;
992
+ return false; // Exit $.each
993
+ }
994
+ });
995
+ if(supported) {
996
+ return false; // Exit $.each
997
+ }
998
+ });
999
+
1000
+ if(supported) {
1001
+ // Set poster after the possible clearMedia() command above. IE had issues since the IMG onload event occurred immediately when cached. ie., The clearMedia() hide the poster.
1002
+ if(this._validString(media.poster)) {
1003
+ if(this.htmlElement.poster.src !== media.poster) { // Since some browsers do not generate img onload event.
1004
+ this.htmlElement.poster.src = media.poster;
1005
+ } else {
1006
+ this.internal.poster.jq.show();
1007
+ }
1008
+ } else {
1009
+ this.internal.poster.jq.hide(); // Hide if not used, since clearMedia() does not always occur above. ie., HTML audio <-> video switching.
1010
+ }
1011
+ this.status.srcSet = true;
1012
+ this.status.media = $.extend({}, media);
1013
+ this._updateButtons(false);
1014
+ this._updateInterface();
1015
+ } else { // jPlayer cannot support any formats provided in this browser
1016
+ // Pause here if old media could be playing. Otherwise, playing media being changed to bad media would leave the old media playing.
1017
+ if(this.status.srcSet && !this.status.waitForPlay) {
1018
+ this.pause();
1019
+ }
1020
+ // Reset all the control flags
1021
+ this.html.audio.gate = false;
1022
+ this.html.video.gate = false;
1023
+ this.flash.gate = false;
1024
+ this.html.active = false;
1025
+ this.flash.active = false;
1026
+ // Reset status and interface.
1027
+ this._resetStatus();
1028
+ this._updateInterface();
1029
+ this._updateButtons(false);
1030
+ // Hide the any old media
1031
+ this.internal.poster.jq.hide();
1032
+ if(this.html.used && this.require.video) {
1033
+ this.internal.video.jq.css({'width':'0px', 'height':'0px'});
1034
+ }
1035
+ if(this.flash.used) {
1036
+ this.internal.flash.jq.css({'width':'0px', 'height':'0px'});
1037
+ }
1038
+ // Send an error event
1039
+ this._error( {
1040
+ type: $.jPlayer.error.NO_SUPPORT,
1041
+ context: "{supplied:'" + this.options.supplied + "'}",
1042
+ message: $.jPlayer.errorMsg.NO_SUPPORT,
1043
+ hint: $.jPlayer.errorHint.NO_SUPPORT
1044
+ });
1045
+ }
1046
+ },
1047
+ clearMedia: function() {
1048
+ this._resetStatus();
1049
+ this._updateButtons(false);
1050
+
1051
+ this.internal.poster.jq.hide();
1052
+
1053
+ clearTimeout(this.internal.htmlDlyCmdId);
1054
+
1055
+ if(this.html.active) {
1056
+ this._html_clearMedia();
1057
+ } else if(this.flash.active) {
1058
+ this._flash_clearMedia();
1059
+ }
1060
+ },
1061
+ load: function() {
1062
+ if(this.status.srcSet) {
1063
+ if(this.html.active) {
1064
+ this._html_load();
1065
+ } else if(this.flash.active) {
1066
+ this._flash_load();
1067
+ }
1068
+ } else {
1069
+ this._urlNotSetError("load");
1070
+ }
1071
+ },
1072
+ play: function(time) {
1073
+ time = (typeof time === "number") ? time : NaN; // Remove jQuery event from click handler
1074
+ if(this.status.srcSet) {
1075
+ if(this.html.active) {
1076
+ this._html_play(time);
1077
+ } else if(this.flash.active) {
1078
+ this._flash_play(time);
1079
+ }
1080
+ } else {
1081
+ this._urlNotSetError("play");
1082
+ }
1083
+ },
1084
+ videoPlay: function(e) { // Handles clicks on the play button over the video poster
1085
+ this.play();
1086
+ },
1087
+ pause: function(time) {
1088
+ time = (typeof time === "number") ? time : NaN; // Remove jQuery event from click handler
1089
+ if(this.status.srcSet) {
1090
+ if(this.html.active) {
1091
+ this._html_pause(time);
1092
+ } else if(this.flash.active) {
1093
+ this._flash_pause(time);
1094
+ }
1095
+ } else {
1096
+ this._urlNotSetError("pause");
1097
+ }
1098
+ },
1099
+ pauseOthers: function() {
1100
+ var self = this;
1101
+ $.each(this.instances, function(i, element) {
1102
+ if(self.element !== element) { // Do not this instance.
1103
+ if(element.data("jPlayer").status.srcSet) { // Check that media is set otherwise would cause error event.
1104
+ element.jPlayer("pause");
1105
+ }
1106
+ }
1107
+ });
1108
+ },
1109
+ stop: function() {
1110
+ if(this.status.srcSet) {
1111
+ if(this.html.active) {
1112
+ this._html_pause(0);
1113
+ } else if(this.flash.active) {
1114
+ this._flash_pause(0);
1115
+ }
1116
+ } else {
1117
+ this._urlNotSetError("stop");
1118
+ }
1119
+ },
1120
+ playHead: function(p) {
1121
+ p = this._limitValue(p, 0, 100);
1122
+ if(this.status.srcSet) {
1123
+ if(this.html.active) {
1124
+ this._html_playHead(p);
1125
+ } else if(this.flash.active) {
1126
+ this._flash_playHead(p);
1127
+ }
1128
+ } else {
1129
+ this._urlNotSetError("playHead");
1130
+ }
1131
+ },
1132
+ mute: function() {
1133
+ this.status.muted = true;
1134
+ if(this.html.used) {
1135
+ this._html_mute(true);
1136
+ }
1137
+ if(this.flash.used) {
1138
+ this._flash_mute(true);
1139
+ }
1140
+ this._updateMute(true);
1141
+ this._updateVolume(0);
1142
+ this._trigger($.jPlayer.event.volumechange);
1143
+ },
1144
+ unmute: function() {
1145
+ this.status.muted = false;
1146
+ if(this.html.used) {
1147
+ this._html_mute(false);
1148
+ }
1149
+ if(this.flash.used) {
1150
+ this._flash_mute(false);
1151
+ }
1152
+ this._updateMute(false);
1153
+ this._updateVolume(this.status.volume);
1154
+ this._trigger($.jPlayer.event.volumechange);
1155
+ },
1156
+ _updateMute: function(mute) {
1157
+ if(this.css.jq.mute.length && this.css.jq.unmute.length) {
1158
+ if(mute) {
1159
+ this.css.jq.mute.hide();
1160
+ this.css.jq.unmute.show();
1161
+ } else {
1162
+ this.css.jq.mute.show();
1163
+ this.css.jq.unmute.hide();
1164
+ }
1165
+ }
1166
+ },
1167
+ volume: function(v) {
1168
+ v = this._limitValue(v, 0, 1);
1169
+ this.status.volume = v;
1170
+
1171
+ if(this.html.used) {
1172
+ this._html_volume(v);
1173
+ }
1174
+ if(this.flash.used) {
1175
+ this._flash_volume(v);
1176
+ }
1177
+ if(!this.status.muted) {
1178
+ this._updateVolume(v);
1179
+ }
1180
+ this._trigger($.jPlayer.event.volumechange);
1181
+ },
1182
+ volumeBar: function(e) { // Handles clicks on the volumeBar
1183
+ if(!this.status.muted && this.css.jq.volumeBar) { // Ignore clicks when muted
1184
+ var offset = this.css.jq.volumeBar.offset();
1185
+ var x = e.pageX - offset.left;
1186
+ var w = this.css.jq.volumeBar.width();
1187
+ var v = x/w;
1188
+ this.volume(v);
1189
+ }
1190
+ },
1191
+ volumeBarValue: function(e) { // Handles clicks on the volumeBarValue
1192
+ this.volumeBar(e);
1193
+ },
1194
+ _updateVolume: function(v) {
1195
+ if(this.css.jq.volumeBarValue.length) {
1196
+ this.css.jq.volumeBarValue.width((v*100)+"%");
1197
+ }
1198
+ },
1199
+ _volumeFix: function(v) { // Need to review if this is still necessary on latest Chrome
1200
+ var rnd = 0.001 * Math.random(); // Fix for Chrome 4: Fix volume being set multiple times before playing bug.
1201
+ var fix = (v < 0.5) ? rnd : -rnd; // Fix for Chrome 4: Solves volume change before play bug. (When new vol == old vol Chrome 4 does nothing!)
1202
+ return (v + fix); // Fix for Chrome 4: Event solves initial volume not being set correctly.
1203
+ },
1204
+ _cssSelectorAncestor: function(ancestor, refresh) {
1205
+ this.options.cssSelectorAncestor = ancestor;
1206
+ if(refresh) {
1207
+ $.each(this.options.cssSelector, function(fn, cssSel) {
1208
+ self._cssSelector(fn, cssSel);
1209
+ });
1210
+ }
1211
+ },
1212
+ _cssSelector: function(fn, cssSel) {
1213
+ var self = this;
1214
+ if(typeof cssSel === 'string') {
1215
+ if($.jPlayer.prototype.options.cssSelector[fn]) {
1216
+ if(this.css.jq[fn] && this.css.jq[fn].length) {
1217
+ this.css.jq[fn].unbind(".jPlayer");
1218
+ }
1219
+ this.options.cssSelector[fn] = cssSel;
1220
+ this.css.cs[fn] = this.options.cssSelectorAncestor + " " + cssSel;
1221
+
1222
+ if(cssSel) { // Checks for empty string
1223
+ this.css.jq[fn] = $(this.css.cs[fn]);
1224
+ } else {
1225
+ this.css.jq[fn] = []; // To comply with the css.jq[fn].length check before its use. As of jQuery 1.4 could have used $() for an empty set.
1226
+ }
1227
+
1228
+ if(this.css.jq[fn].length) {
1229
+ var handler = function(e) {
1230
+ self[fn](e);
1231
+ $(this).blur();
1232
+ return false;
1233
+ }
1234
+ this.css.jq[fn].bind("click.jPlayer", handler); // Using jPlayer namespace
1235
+ }
1236
+
1237
+ if(cssSel && this.css.jq[fn].length !== 1) { // So empty strings do not generate the warning. ie., they just remove the old one.
1238
+ this._warning( {
1239
+ type: $.jPlayer.warning.CSS_SELECTOR_COUNT,
1240
+ context: this.css.cs[fn],
1241
+ message: $.jPlayer.warningMsg.CSS_SELECTOR_COUNT + this.css.jq[fn].length + " found for " + fn + " method.",
1242
+ hint: $.jPlayer.warningHint.CSS_SELECTOR_COUNT
1243
+ });
1244
+ }
1245
+ } else {
1246
+ this._warning( {
1247
+ type: $.jPlayer.warning.CSS_SELECTOR_METHOD,
1248
+ context: fn,
1249
+ message: $.jPlayer.warningMsg.CSS_SELECTOR_METHOD,
1250
+ hint: $.jPlayer.warningHint.CSS_SELECTOR_METHOD
1251
+ });
1252
+ }
1253
+ } else {
1254
+ this._warning( {
1255
+ type: $.jPlayer.warning.CSS_SELECTOR_STRING,
1256
+ context: cssSel,
1257
+ message: $.jPlayer.warningMsg.CSS_SELECTOR_STRING,
1258
+ hint: $.jPlayer.warningHint.CSS_SELECTOR_STRING
1259
+ });
1260
+ }
1261
+ },
1262
+ seekBar: function(e) { // Handles clicks on the seekBar
1263
+ if(this.css.jq.seekBar) {
1264
+ var offset = this.css.jq.seekBar.offset();
1265
+ var x = e.pageX - offset.left;
1266
+ var w = this.css.jq.seekBar.width();
1267
+ var p = 100*x/w;
1268
+ this.playHead(p);
1269
+ }
1270
+ },
1271
+ playBar: function(e) { // Handles clicks on the playBar
1272
+ this.seekBar(e);
1273
+ },
1274
+ currentTime: function(e) { // Handles clicks on the text
1275
+ // Added to avoid errors using cssSelector system for the text
1276
+ },
1277
+ duration: function(e) { // Handles clicks on the text
1278
+ // Added to avoid errors using cssSelector system for the text
1279
+ },
1280
+ // Options code adapted from ui.widget.js (1.8.7). Made changes so the key can use dot notation. To match previous getData solution in jPlayer 1.
1281
+ option: function(key, value) {
1282
+ var options = key;
1283
+
1284
+ // Enables use: options(). Returns a copy of options object
1285
+ if ( arguments.length === 0 ) {
1286
+ return $.extend( true, {}, this.options );
1287
+ }
1288
+
1289
+ if(typeof key === "string") {
1290
+ var keys = key.split(".");
1291
+
1292
+ // Enables use: options("someOption") Returns a copy of the option. Supports dot notation.
1293
+ if(value === undefined) {
1294
+
1295
+ var opt = $.extend(true, {}, this.options);
1296
+ for(var i = 0; i < keys.length; i++) {
1297
+ if(opt[keys[i]] !== undefined) {
1298
+ opt = opt[keys[i]];
1299
+ } else {
1300
+ this._warning( {
1301
+ type: $.jPlayer.warning.OPTION_KEY,
1302
+ context: key,
1303
+ message: $.jPlayer.warningMsg.OPTION_KEY,
1304
+ hint: $.jPlayer.warningHint.OPTION_KEY
1305
+ });
1306
+ return undefined;
1307
+ }
1308
+ }
1309
+ return opt;
1310
+ }
1311
+
1312
+ // Enables use: options("someOptionObject", someObject}). Creates: {someOptionObject:someObject}
1313
+ // Enables use: options("someOption", someValue). Creates: {someOption:someValue}
1314
+ // Enables use: options("someOptionObject.someOption", someValue). Creates: {someOptionObject:{someOption:someValue}}
1315
+
1316
+ options = {};
1317
+ var opt = options;
1318
+
1319
+ for(var i = 0; i < keys.length; i++) {
1320
+ if(i < keys.length - 1) {
1321
+ opt[keys[i]] = {};
1322
+ opt = opt[keys[i]];
1323
+ } else {
1324
+ opt[keys[i]] = value;
1325
+ }
1326
+ }
1327
+ }
1328
+
1329
+ // Otherwise enables use: options(optionObject). Uses original object (the key)
1330
+
1331
+ this._setOptions(options);
1332
+
1333
+ return this;
1334
+ },
1335
+ _setOptions: function(options) {
1336
+ var self = this;
1337
+ $.each(options, function(key, value) { // This supports the 2 level depth that the options of jPlayer has. Would review if we ever need more depth.
1338
+ self._setOption(key, value);
1339
+ });
1340
+
1341
+ return this;
1342
+ },
1343
+ _setOption: function(key, value) {
1344
+ var self = this;
1345
+
1346
+ // The ability to set options is limited at this time.
1347
+
1348
+ switch(key) {
1349
+ case "cssSelectorAncestor" :
1350
+ this.options[key] = value;
1351
+ $.each(self.options.cssSelector, function(fn, cssSel) { // Refresh all associations for new ancestor.
1352
+ self._cssSelector(fn, cssSel);
1353
+ });
1354
+ break;
1355
+ case "cssSelector" :
1356
+ $.each(value, function(fn, cssSel) {
1357
+ self._cssSelector(fn, cssSel);
1358
+ });
1359
+ break;
1360
+ }
1361
+
1362
+ return this;
1363
+ },
1364
+ // End of: (Options code adapted from ui.widget.js)
1365
+
1366
+ // The resize() set of functions are not implemented yet.
1367
+ // Basically are currently used to allow Flash debugging without too much hassle.
1368
+ resize: function(css) {
1369
+ // MJP: Want to run some checks on dim {} first.
1370
+ if(this.html.active) {
1371
+ this._resizeHtml(css);
1372
+ }
1373
+ if(this.flash.active) {
1374
+ this._resizeFlash(css);
1375
+ }
1376
+ this._trigger($.jPlayer.event.resize);
1377
+ },
1378
+ _resizePoster: function(css) {
1379
+ // Not implemented yet
1380
+ },
1381
+ _resizeHtml: function(css) {
1382
+ // Not implemented yet
1383
+ },
1384
+ _resizeFlash: function(css) {
1385
+ this.internal.flash.jq.css({'width':css.width, 'height':css.height});
1386
+ },
1387
+
1388
+ _html_initMedia: function() {
1389
+ if(this.status.srcSet && !this.status.waitForPlay) {
1390
+ this.htmlElement.media.pause();
1391
+ }
1392
+ if(this.options.preload !== 'none') {
1393
+ this._html_load();
1394
+ }
1395
+ this._trigger($.jPlayer.event.timeupdate); // The flash generates this event for its solution.
1396
+ },
1397
+ _html_setAudio: function(media) {
1398
+ var self = this;
1399
+ // Always finds a format due to checks in setMedia()
1400
+ $.each(this.formats, function(priority, format) {
1401
+ if(self.html.support[format] && media[format]) {
1402
+ self.status.src = media[format];
1403
+ self.status.format[format] = true;
1404
+ self.status.formatType = format;
1405
+ return false;
1406
+ }
1407
+ });
1408
+ this.htmlElement.media = this.htmlElement.audio;
1409
+ this._html_initMedia();
1410
+ },
1411
+ _html_setVideo: function(media) {
1412
+ var self = this;
1413
+ // Always finds a format due to checks in setMedia()
1414
+ $.each(this.formats, function(priority, format) {
1415
+ if(self.html.support[format] && media[format]) {
1416
+ self.status.src = media[format];
1417
+ self.status.format[format] = true;
1418
+ self.status.formatType = format;
1419
+ return false;
1420
+ }
1421
+ });
1422
+ this.htmlElement.media = this.htmlElement.video;
1423
+ this._html_initMedia();
1424
+ },
1425
+ _html_clearMedia: function() {
1426
+ if(this.htmlElement.media) {
1427
+ if(this.htmlElement.media.id === this.internal.video.id) {
1428
+ this.internal.video.jq.css({'width':'0px', 'height':'0px'});
1429
+ }
1430
+ this.htmlElement.media.pause();
1431
+ this.htmlElement.media.src = "";
1432
+
1433
+ if(!($.browser.msie && Number($.browser.version) >= 9)) { // IE9 Bug: media.load() on broken src causes an exception. In try/catch IE9 generates the error event too, but it is delayed and corrupts jPlayer's event masking.
1434
+ this.htmlElement.media.load(); // Stops an old, "in progress" download from continuing the download. Triggers the loadstart, error and emptied events, due to the empty src. Also an abort event if a download was in progress.
1435
+ }
1436
+ }
1437
+ },
1438
+ _html_load: function() {
1439
+ if(this.status.waitForLoad) {
1440
+ this.status.waitForLoad = false;
1441
+ this.htmlElement.media.src = this.status.src;
1442
+ try {
1443
+ this.htmlElement.media.load(); // IE9 Beta throws an exception here on broken links. Review again later as IE9 Beta matures
1444
+ } catch(err) {}
1445
+ }
1446
+ clearTimeout(this.internal.htmlDlyCmdId);
1447
+ },
1448
+ _html_play: function(time) {
1449
+ var self = this;
1450
+ this._html_load(); // Loads if required and clears any delayed commands.
1451
+
1452
+ this.htmlElement.media.play(); // Before currentTime attempt otherwise Firefox 4 Beta never loads.
1453
+
1454
+ if(!isNaN(time)) {
1455
+ try {
1456
+ this.htmlElement.media.currentTime = time;
1457
+ } catch(err) {
1458
+ this.internal.htmlDlyCmdId = setTimeout(function() {
1459
+ self.play(time);
1460
+ }, 100);
1461
+ return; // Cancel execution and wait for the delayed command.
1462
+ }
1463
+ }
1464
+ this._html_checkWaitForPlay();
1465
+ },
1466
+ _html_pause: function(time) {
1467
+ var self = this;
1468
+
1469
+ if(time > 0) { // We do not want the stop() command, which does pause(0), causing a load operation.
1470
+ this._html_load(); // Loads if required and clears any delayed commands.
1471
+ } else {
1472
+ clearTimeout(this.internal.htmlDlyCmdId);
1473
+ }
1474
+
1475
+ // Order of these commands is important for Safari (Win) and IE9. Pause then change currentTime.
1476
+ this.htmlElement.media.pause();
1477
+
1478
+ if(!isNaN(time)) {
1479
+ try {
1480
+ this.htmlElement.media.currentTime = time;
1481
+ } catch(err) {
1482
+ this.internal.htmlDlyCmdId = setTimeout(function() {
1483
+ self.pause(time);
1484
+ }, 100);
1485
+ return; // Cancel execution and wait for the delayed command.
1486
+ }
1487
+ }
1488
+ if(time > 0) { // Avoids a setMedia() followed by stop() or pause(0) hiding the video play button.
1489
+ this._html_checkWaitForPlay();
1490
+ }
1491
+ },
1492
+ _html_playHead: function(percent) {
1493
+ var self = this;
1494
+ this._html_load(); // Loads if required and clears any delayed commands.
1495
+ try {
1496
+ if((typeof this.htmlElement.media.seekable === "object") && (this.htmlElement.media.seekable.length > 0)) {
1497
+ this.htmlElement.media.currentTime = percent * this.htmlElement.media.seekable.end(this.htmlElement.media.seekable.length-1) / 100;
1498
+ } else if(this.htmlElement.media.duration > 0 && !isNaN(this.htmlElement.media.duration)) {
1499
+ this.htmlElement.media.currentTime = percent * this.htmlElement.media.duration / 100;
1500
+ } else {
1501
+ throw "e";
1502
+ }
1503
+ } catch(err) {
1504
+ this.internal.htmlDlyCmdId = setTimeout(function() {
1505
+ self.playHead(percent);
1506
+ }, 100);
1507
+ return; // Cancel execution and wait for the delayed command.
1508
+ }
1509
+ if(!this.status.waitForLoad) {
1510
+ this._html_checkWaitForPlay();
1511
+ }
1512
+ },
1513
+ _html_checkWaitForPlay: function() {
1514
+ if(this.status.waitForPlay) {
1515
+ this.status.waitForPlay = false;
1516
+ if(this.css.jq.videoPlay.length) {
1517
+ this.css.jq.videoPlay.hide();
1518
+ }
1519
+ if(this.status.video) {
1520
+ this.internal.poster.jq.hide();
1521
+ this.internal.video.jq.css({'width': this.status.width, 'height': this.status.height});
1522
+ }
1523
+ }
1524
+ },
1525
+ _html_volume: function(v) {
1526
+ if(this.html.audio.available) {
1527
+ this.htmlElement.audio.volume = v;
1528
+ }
1529
+ if(this.html.video.available) {
1530
+ this.htmlElement.video.volume = v;
1531
+ }
1532
+ },
1533
+ _html_mute: function(m) {
1534
+ if(this.html.audio.available) {
1535
+ this.htmlElement.audio.muted = m;
1536
+ }
1537
+ if(this.html.video.available) {
1538
+ this.htmlElement.video.muted = m;
1539
+ }
1540
+ },
1541
+ _flash_setAudio: function(media) {
1542
+ var self = this;
1543
+ try {
1544
+ // Always finds a format due to checks in setMedia()
1545
+ $.each(this.formats, function(priority, format) {
1546
+ if(self.flash.support[format] && media[format]) {
1547
+ switch (format) {
1548
+ case "m4a" :
1549
+ self._getMovie().fl_setAudio_m4a(media[format]);
1550
+ break;
1551
+ case "mp3" :
1552
+ self._getMovie().fl_setAudio_mp3(media[format]);
1553
+ break;
1554
+ }
1555
+ self.status.src = media[format];
1556
+ self.status.format[format] = true;
1557
+ self.status.formatType = format;
1558
+ return false;
1559
+ }
1560
+ });
1561
+
1562
+ if(this.options.preload === 'auto') {
1563
+ this._flash_load();
1564
+ this.status.waitForLoad = false;
1565
+ }
1566
+ } catch(err) { this._flashError(err); }
1567
+ },
1568
+ _flash_setVideo: function(media) {
1569
+ var self = this;
1570
+ try {
1571
+ // Always finds a format due to checks in setMedia()
1572
+ $.each(this.formats, function(priority, format) {
1573
+ if(self.flash.support[format] && media[format]) {
1574
+ switch (format) {
1575
+ case "m4v" :
1576
+ self._getMovie().fl_setVideo_m4v(media[format]);
1577
+ break;
1578
+ }
1579
+ self.status.src = media[format];
1580
+ self.status.format[format] = true;
1581
+ self.status.formatType = format;
1582
+ return false;
1583
+ }
1584
+ });
1585
+
1586
+ if(this.options.preload === 'auto') {
1587
+ this._flash_load();
1588
+ this.status.waitForLoad = false;
1589
+ }
1590
+ } catch(err) { this._flashError(err); }
1591
+ },
1592
+ _flash_clearMedia: function() {
1593
+ this.internal.flash.jq.css({'width':'0px', 'height':'0px'}); // Must do via CSS as setting attr() to zero causes a jQuery error in IE.
1594
+ try {
1595
+ this._getMovie().fl_clearMedia();
1596
+ } catch(err) { this._flashError(err); }
1597
+ },
1598
+ _flash_load: function() {
1599
+ try {
1600
+ this._getMovie().fl_load();
1601
+ } catch(err) { this._flashError(err); }
1602
+ this.status.waitForLoad = false;
1603
+ },
1604
+ _flash_play: function(time) {
1605
+ try {
1606
+ this._getMovie().fl_play(time);
1607
+ } catch(err) { this._flashError(err); }
1608
+ this.status.waitForLoad = false;
1609
+ this._flash_checkWaitForPlay();
1610
+ },
1611
+ _flash_pause: function(time) {
1612
+ try {
1613
+ this._getMovie().fl_pause(time);
1614
+ } catch(err) { this._flashError(err); }
1615
+ if(time > 0) { // Avoids a setMedia() followed by stop() or pause(0) hiding the video play button.
1616
+ this.status.waitForLoad = false;
1617
+ this._flash_checkWaitForPlay();
1618
+ }
1619
+ },
1620
+ _flash_playHead: function(p) {
1621
+ try {
1622
+ this._getMovie().fl_play_head(p)
1623
+ } catch(err) { this._flashError(err); }
1624
+ if(!this.status.waitForLoad) {
1625
+ this._flash_checkWaitForPlay();
1626
+ }
1627
+ },
1628
+ _flash_checkWaitForPlay: function() {
1629
+ if(this.status.waitForPlay) {
1630
+ this.status.waitForPlay = false;
1631
+ if(this.css.jq.videoPlay.length) {
1632
+ this.css.jq.videoPlay.hide();
1633
+ }
1634
+ if(this.status.video) {
1635
+ this.internal.poster.jq.hide();
1636
+ this.internal.flash.jq.css({'width': this.status.width, 'height': this.status.height});
1637
+ }
1638
+ }
1639
+ },
1640
+ _flash_volume: function(v) {
1641
+ try {
1642
+ this._getMovie().fl_volume(v);
1643
+ } catch(err) { this._flashError(err); }
1644
+ },
1645
+ _flash_mute: function(m) {
1646
+ try {
1647
+ this._getMovie().fl_mute(m);
1648
+ } catch(err) { this._flashError(err); }
1649
+ },
1650
+ _getMovie: function() {
1651
+ return document[this.internal.flash.id];
1652
+ },
1653
+ _checkForFlash: function (version) {
1654
+ // Function checkForFlash adapted from FlashReplace by Robert Nyman
1655
+ // http://code.google.com/p/flashreplace/
1656
+ var flashIsInstalled = false;
1657
+ var flash;
1658
+ if(window.ActiveXObject){
1659
+ try{
1660
+ flash = new ActiveXObject(("ShockwaveFlash.ShockwaveFlash." + version));
1661
+ flashIsInstalled = true;
1662
+ }
1663
+ catch(e){
1664
+ // Throws an error if the version isn't available
1665
+ }
1666
+ }
1667
+ else if(navigator.plugins && navigator.mimeTypes.length > 0){
1668
+ flash = navigator.plugins["Shockwave Flash"];
1669
+ if(flash){
1670
+ var flashVersion = navigator.plugins["Shockwave Flash"].description.replace(/.*\s(\d+\.\d+).*/, "$1");
1671
+ if(flashVersion >= version){
1672
+ flashIsInstalled = true;
1673
+ }
1674
+ }
1675
+ }
1676
+ if($.browser.msie && Number($.browser.version) >= 9) { // IE9 does not work with external interface. With dynamic Flash insertion like jPlayer uses.
1677
+ return false;
1678
+ } else {
1679
+ return flashIsInstalled;
1680
+ }
1681
+ },
1682
+ _validString: function(url) {
1683
+ return (url && typeof url === "string"); // Empty strings return false
1684
+ },
1685
+ _limitValue: function(value, min, max) {
1686
+ return (value < min) ? min : ((value > max) ? max : value);
1687
+ },
1688
+ _urlNotSetError: function(context) {
1689
+ this._error( {
1690
+ type: $.jPlayer.error.URL_NOT_SET,
1691
+ context: context,
1692
+ message: $.jPlayer.errorMsg.URL_NOT_SET,
1693
+ hint: $.jPlayer.errorHint.URL_NOT_SET
1694
+ });
1695
+ },
1696
+ _flashError: function(error) {
1697
+ this._error( {
1698
+ type: $.jPlayer.error.FLASH,
1699
+ context: this.internal.flash.swf,
1700
+ message: $.jPlayer.errorMsg.FLASH + error.message,
1701
+ hint: $.jPlayer.errorHint.FLASH
1702
+ });
1703
+ },
1704
+ _error: function(error) {
1705
+ this._trigger($.jPlayer.event.error, error);
1706
+ if(this.options.errorAlerts) {
1707
+ this._alert("Error!" + (error.message ? "\n\n" + error.message : "") + (error.hint ? "\n\n" + error.hint : "") + "\n\nContext: " + error.context);
1708
+ }
1709
+ },
1710
+ _warning: function(warning) {
1711
+ this._trigger($.jPlayer.event.warning, undefined, warning);
1712
+ if(this.options.errorAlerts) {
1713
+ this._alert("Warning!" + (warning.message ? "\n\n" + warning.message : "") + (warning.hint ? "\n\n" + warning.hint : "") + "\n\nContext: " + warning.context);
1714
+ }
1715
+ },
1716
+ _alert: function(message) {
1717
+ alert("jPlayer " + this.version.script + " : id='" + this.internal.self.id +"' : " + message);
1718
+ }
1719
+ };
1720
+
1721
+ $.jPlayer.error = {
1722
+ FLASH: "e_flash",
1723
+ NO_SOLUTION: "e_no_solution",
1724
+ NO_SUPPORT: "e_no_support",
1725
+ URL: "e_url",
1726
+ URL_NOT_SET: "e_url_not_set",
1727
+ VERSION: "e_version"
1728
+ };
1729
+
1730
+ $.jPlayer.errorMsg = {
1731
+ FLASH: "jPlayer's Flash fallback is not configured correctly, or a command was issued before the jPlayer Ready event. Details: ", // Used in: _flashError()
1732
+ NO_SOLUTION: "No solution can be found by jPlayer in this browser. Neither HTML nor Flash can be used.", // Used in: _init()
1733
+ NO_SUPPORT: "It is not possible to play any media format provided in setMedia() on this browser using your current options.", // Used in: setMedia()
1734
+ URL: "Media URL could not be loaded.", // Used in: jPlayerFlashEvent() and _addHtmlEventListeners()
1735
+ URL_NOT_SET: "Attempt to issue media playback commands, while no media url is set.", // Used in: load(), play(), pause(), stop() and playHead()
1736
+ VERSION: "jPlayer " + $.jPlayer.prototype.version.script + " needs Jplayer.swf version " + $.jPlayer.prototype.version.needFlash + " but found " // Used in: jPlayerReady()
1737
+ };
1738
+
1739
+ $.jPlayer.errorHint = {
1740
+ FLASH: "Check your swfPath option and that Jplayer.swf is there.",
1741
+ NO_SOLUTION: "Review the jPlayer options: support and supplied.",
1742
+ NO_SUPPORT: "Video or audio formats defined in the supplied option are missing.",
1743
+ URL: "Check media URL is valid.",
1744
+ URL_NOT_SET: "Use setMedia() to set the media URL.",
1745
+ VERSION: "Update jPlayer files."
1746
+ };
1747
+
1748
+ $.jPlayer.warning = {
1749
+ CSS_SELECTOR_COUNT: "e_css_selector_count",
1750
+ CSS_SELECTOR_METHOD: "e_css_selector_method",
1751
+ CSS_SELECTOR_STRING: "e_css_selector_string",
1752
+ OPTION_KEY: "e_option_key"
1753
+ };
1754
+
1755
+ $.jPlayer.warningMsg = {
1756
+ CSS_SELECTOR_COUNT: "The number of methodCssSelectors found did not equal one: ",
1757
+ CSS_SELECTOR_METHOD: "The methodName given in jPlayer('cssSelector') is not a valid jPlayer method.",
1758
+ CSS_SELECTOR_STRING: "The methodCssSelector given in jPlayer('cssSelector') is not a String or is empty.",
1759
+ OPTION_KEY: "The option requested in jPlayer('option') is undefined."
1760
+ };
1761
+
1762
+ $.jPlayer.warningHint = {
1763
+ CSS_SELECTOR_COUNT: "Check your css selector and the ancestor.",
1764
+ CSS_SELECTOR_METHOD: "Check your method name.",
1765
+ CSS_SELECTOR_STRING: "Check your css selector is a string.",
1766
+ OPTION_KEY: "Check your option name."
1767
+ };
1768
+ })(jQuery);