vendor: 26,969 bytes, lines 1-736
1/* 2 * jPlayer Plugin for jQuery JavaScript Library 3 * http://www.jplayer.org 4 * 5 * Copyright (c) 2009 - 2011 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.22 12 * Date: 13th July 2011 13 */ 14 15/* Code verified using http://www.jshint.com/ */ 16/*jshint asi:false, bitwise:false, boss:false, browser:true, curly:true, debug:false, eqeqeq:true, eqnull:false, evil:false, forin:false, immed:false, jquery:true, laxbreak:false, newcap:true, noarg:true, noempty:true, nonew:true, nomem:false, onevar:false, passfail:false, plusplus:false, regexp:false, undef:true, sub:false, strict:false, white:false */ 17/*global jQuery:false, ActiveXObject:false, alert:false */ 18 19(function($, undefined) { 20 21 // Adapted from jquery.ui.widget.js (1.8.7): $.widget.bridge 22 $.fn.jPlayer = function( options ) { 23 var name = "jPlayer"; 24 var isMethodCall = typeof options === "string", 25 args = Array.prototype.slice.call( arguments, 1 ), 26 returnValue = this; 27 28 // allow multiple hashes to be passed on init 29 options = !isMethodCall && args.length ? 30 $.extend.apply( null, [ true, options ].concat(args) ) : 31 options; 32 33 // prevent calls to internal methods 34 if ( isMethodCall && options.charAt( 0 ) === "_" ) { 35 return returnValue; 36 } 37 38 if ( isMethodCall ) { 39 this.each(function() { 40 var instance = $.data( this, name ), 41 methodValue = instance && $.isFunction( instance[options] ) ? 42 instance[ options ].apply( instance, args ) : 43 instance; 44 if ( methodValue !== instance && methodValue !== undefined ) { 45 returnValue = methodValue; 46 return false; 47 } 48 }); 49 } else { 50 this.each(function() { 51 var instance = $.data( this, name ); 52 if ( instance ) { 53 // 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. 54 instance.option( options || {} ); // The new constructor only changes the options. Changing options only has basic support atm. 55 } else { 56 $.data( this, name, new $.jPlayer( options, this ) ); 57 } 58 }); 59 } 60 61 return returnValue; 62 }; 63 64 $.jPlayer = function( options, element ) { 65 // allow instantiation without initializing for simple inheritance 66 if ( arguments.length ) { 67 this.element = $(element); 68 this.options = $.extend(true, {}, 69 this.options, 70 options 71 ); 72 var self = this; 73 this.element.bind( "remove.jPlayer", function() { 74 self.destroy(); 75 }); 76 this._init(); 77 } 78 }; 79 // End of: (Adapted from jquery.ui.widget.js (1.8.7)) 80 81 // Emulated HTML5 methods and properties 82 $.jPlayer.emulateMethods = "load play pause"; 83 $.jPlayer.emulateStatus = "src readyState networkState currentTime duration paused ended playbackRate"; 84 $.jPlayer.emulateOptions = "muted volume"; 85 86 // Reserved event names generated by jPlayer that are not part of the HTML5 Media element spec 87 $.jPlayer.reservedEvent = "ready flashreset resize repeat error warning"; 88 89 // Events generated by jPlayer 90 $.jPlayer.event = { 91 ready: "jPlayer_ready", 92 flashreset: "jPlayer_flashreset", // Similar to the ready event if the Flash solution is set to display:none and then shown again or if it's reloaded for another reason by the browser. For example, using CSS position:fixed on Firefox for the full screen feature. 93 resize: "jPlayer_resize", // Occurs when the size changes through a full/restore screen operation or if the size/sizeFull options are changed. 94 repeat: "jPlayer_repeat", // Occurs when the repeat status changes. Usually through clicks on the repeat button of the interface. 95 error: "jPlayer_error", // Event error code in event.jPlayer.error.type. See $.jPlayer.error 96 warning: "jPlayer_warning", // Event warning code in event.jPlayer.warning.type. See $.jPlayer.warning 97 98 // Other events match HTML5 spec. 99 loadstart: "jPlayer_loadstart", 100 progress: "jPlayer_progress", 101 suspend: "jPlayer_suspend", 102 abort: "jPlayer_abort", 103 emptied: "jPlayer_emptied", 104 stalled: "jPlayer_stalled", 105 play: "jPlayer_play", 106 pause: "jPlayer_pause", 107 loadedmetadata: "jPlayer_loadedmetadata", 108 loadeddata: "jPlayer_loadeddata", 109 waiting: "jPlayer_waiting", 110 playing: "jPlayer_playing", 111 canplay: "jPlayer_canplay", 112 canplaythrough: "jPlayer_canplaythrough", 113 seeking: "jPlayer_seeking", 114 seeked: "jPlayer_seeked", 115 timeupdate: "jPlayer_timeupdate", 116 ended: "jPlayer_ended", 117 ratechange: "jPlayer_ratechange", 118 durationchange: "jPlayer_durationchange", 119 volumechange: "jPlayer_volumechange" 120 }; 121 122 $.jPlayer.htmlEvent = [ // These HTML events are bubbled through to the jPlayer event, without any internal action. 123 "loadstart", 124 // "progress", // jPlayer uses internally before bubbling. 125 // "suspend", // jPlayer uses internally before bubbling. 126 "abort", 127 // "error", // jPlayer uses internally before bubbling. 128 "emptied", 129 "stalled", 130 // "play", // jPlayer uses internally before bubbling. 131 // "pause", // jPlayer uses internally before bubbling. 132 "loadedmetadata", 133 "loadeddata", 134 // "waiting", // jPlayer uses internally before bubbling. 135 // "playing", // jPlayer uses internally before bubbling. 136 "canplay", 137 "canplaythrough", 138 // "seeking", // jPlayer uses internally before bubbling. 139 // "seeked", // jPlayer uses internally before bubbling. 140 // "timeupdate", // jPlayer uses internally before bubbling. 141 // "ended", // jPlayer uses internally before bubbling. 142 "ratechange" 143 // "durationchange" // jPlayer uses internally before bubbling. 144 // "volumechange" // jPlayer uses internally before bubbling. 145 ]; 146 147 $.jPlayer.pause = function() { 148 // $.each($.jPlayer.instances, function(i, element) { 149 $.each($.jPlayer.prototype.instances, function(i, element) { 150 if(element.data("jPlayer").status.srcSet) { // Check that media is set otherwise would cause error event. 151 element.jPlayer("pause"); 152 } 153 }); 154 }; 155 156 $.jPlayer.timeFormat = { 157 showHour: false, 158 showMin: true, 159 showSec: true, 160 padHour: false, 161 padMin: true, 162 padSec: true, 163 sepHour: ":", 164 sepMin: ":", 165 sepSec: "" 166 }; 167 168 $.jPlayer.convertTime = function(s) { 169 var myTime = new Date(s * 1000); 170 var hour = myTime.getUTCHours(); 171 var min = myTime.getUTCMinutes(); 172 var sec = myTime.getUTCSeconds(); 173 var strHour = ($.jPlayer.timeFormat.padHour && hour < 10) ? "0" + hour : hour; 174 var strMin = ($.jPlayer.timeFormat.padMin && min < 10) ? "0" + min : min; 175 var strSec = ($.jPlayer.timeFormat.padSec && sec < 10) ? "0" + sec : sec; 176 return (($.jPlayer.timeFormat.showHour) ? strHour + $.jPlayer.timeFormat.sepHour : "") + (($.jPlayer.timeFormat.showMin) ? strMin + $.jPlayer.timeFormat.sepMin : "") + (($.jPlayer.timeFormat.showSec) ? strSec + $.jPlayer.timeFormat.sepSec : ""); 177 }; 178 179 // Adapting jQuery 1.4.4 code for jQuery.browser. Required since jQuery 1.3.2 does not detect Chrome as webkit. 180 $.jPlayer.uaBrowser = function( userAgent ) { 181 var ua = userAgent.toLowerCase(); 182 183 // Useragent RegExp 184 var rwebkit = /(webkit)[ \/]([\w.]+)/; 185 var ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/; 186 var rmsie = /(msie) ([\w.]+)/; 187 var rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/; 188 189 var match = rwebkit.exec( ua ) || 190 ropera.exec( ua ) || 191 rmsie.exec( ua ) || 192 ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || 193 []; 194 195 return { browser: match[1] || "", version: match[2] || "0" }; 196 }; 197 198 // Platform sniffer for detecting mobile devices 199 $.jPlayer.uaPlatform = function( userAgent ) { 200 var ua = userAgent.toLowerCase(); 201 202 // Useragent RegExp 203 var rplatform = /(ipad|iphone|ipod|android|blackberry|playbook|windows ce|webos)/; 204 var rtablet = /(ipad|playbook)/; 205 var randroid = /(android)/; 206 var rmobile = /(mobile)/; 207 208 var platform = rplatform.exec( ua ) || []; 209 var tablet = rtablet.exec( ua ) || 210 !rmobile.exec( ua ) && randroid.exec( ua ) || 211 []; 212 213 return { platform: platform[1] || "", tablet: tablet[1] || "" }; 214 }; 215 216 $.jPlayer.browser = { 217 }; 218 $.jPlayer.platform = { 219 }; 220 221 var browserMatch = $.jPlayer.uaBrowser(navigator.userAgent); 222 if ( browserMatch.browser ) { 223 $.jPlayer.browser[ browserMatch.browser ] = true; 224 $.jPlayer.browser.version = browserMatch.version; 225 } 226 var platformMatch = $.jPlayer.uaPlatform(navigator.userAgent); 227 if ( platformMatch.platform ) { 228 $.jPlayer.platform[ platformMatch.platform ] = true; 229 $.jPlayer.platform.mobile = !platformMatch.tablet; 230 $.jPlayer.platform.tablet = !!platformMatch.tablet; 231 } 232 233 $.jPlayer.prototype = { 234 count: 0, // Static Variable: Change it via prototype. 235 version: { // Static Object 236 script: "2.0.22", 237 needFlash: "2.0.9", 238 flash: "unknown" 239 }, 240 options: { // Instanced in $.jPlayer() constructor 241 swfPath: "js", // Path to Jplayer.swf. Can be relative, absolute or server root relative. 242 solution: "html, flash", // Valid solutions: html, flash. Order defines priority. 1st is highest, 243 supplied: "mp3", // Defines which formats jPlayer will try and support and the priority by the order. 1st is highest, 244 preload: 'metadata', // HTML5 Spec values: none, metadata, auto. 245 volume: 0.8, // The volume. Number 0 to 1. 246 muted: false, 247 wmode: "opaque", // Valid wmode: window, transparent, opaque, direct, gpu. 248 backgroundColor: "#000000", // To define the jPlayer div and Flash background color. 249 cssSelectorAncestor: "#jp_container_1", 250 cssSelector: { // * denotes properties that should only be required when video media type required. _cssSelector() would require changes to enable splitting these into Audio and Video defaults. 251 videoPlay: ".jp-video-play", // * 252 play: ".jp-play", 253 pause: ".jp-pause", 254 stop: ".jp-stop", 255 seekBar: ".jp-seek-bar", 256 playBar: ".jp-play-bar", 257 mute: ".jp-mute", 258 unmute: ".jp-unmute", 259 volumeBar: ".jp-volume-bar", 260 volumeBarValue: ".jp-volume-bar-value", 261 volumeMax: ".jp-volume-max", 262 currentTime: ".jp-current-time", 263 duration: ".jp-duration", 264 fullScreen: ".jp-full-screen", // * 265 restoreScreen: ".jp-restore-screen", // * 266 repeat: ".jp-repeat", 267 repeatOff: ".jp-repeat-off", 268 gui: ".jp-gui" // The interface used with autohide feature. 269 }, 270 fullScreen: false, 271 autohide: { 272 restored: false, // Controls the interface autohide feature. 273 full: true, // Controls the interface autohide feature. 274 fadeIn: 200, // Milliseconds. The period of the fadeIn anim. 275 fadeOut: 600, // Milliseconds. The period of the fadeOut anim. 276 hold: 1000 // Milliseconds. The period of the pause before autohide beings. 277 }, 278 loop: false, 279 repeat: function(event) { // The default jPlayer repeat event handler 280 if(event.jPlayer.options.loop) { 281 $(this).unbind(".jPlayerRepeat").bind($.jPlayer.event.ended + ".jPlayer.jPlayerRepeat", function() { 282 $(this).jPlayer("play"); 283 }); 284 } else { 285 $(this).unbind(".jPlayerRepeat"); 286 } 287 }, 288 // globalVolume: false, // Not implemented: Set to make volume changes affect all jPlayer instances 289 // globalMute: false, // Not implemented: Set to make mute changes affect all jPlayer instances 290 idPrefix: "jp", // Prefix for the ids of html elements created by jPlayer. For flash, this must not include characters: . - + * / \ 291 noConflict: "jQuery", 292 emulateHtml: false, // Emulates the HTML5 Media element on the jPlayer element. 293 errorAlerts: false, 294 warningAlerts: false 295 }, 296 optionsAudio: { 297 size: { 298 width: "0px", 299 height: "0px", 300 cssClass: "" 301 }, 302 sizeFull: { 303 width: "0px", 304 height: "0px", 305 cssClass: "" 306 } 307 }, 308 optionsVideo: { 309 size: { 310 width: "480px", 311 height: "270px", 312 cssClass: "jp-video-270p" 313 }, 314 sizeFull: { 315 width: "100%", 316 height: "100%", 317 cssClass: "jp-video-full" 318 } 319 }, 320 instances: {}, // Static Object 321 status: { // Instanced in _init() 322 src: "", 323 media: {}, 324 paused: true, 325 format: {}, 326 formatType: "", 327 waitForPlay: true, // Same as waitForLoad except in case where preloading. 328 waitForLoad: true, 329 srcSet: false, 330 video: false, // True if playing a video 331 seekPercent: 0, 332 currentPercentRelative: 0, 333 currentPercentAbsolute: 0, 334 currentTime: 0, 335 duration: 0, 336 readyState: 0, 337 networkState: 0, 338 playbackRate: 1, 339 ended: 0 340 341/* Persistant status properties created dynamically at _init(): 342 width 343 height 344 cssClass 345*/ 346 }, 347 348 internal: { // Instanced in _init() 349 ready: false 350 // instance: undefined, 351 // domNode: undefined, 352 // htmlDlyCmdId: undefined 353 // autohideId: undefined 354 }, 355 solution: { // Static Object: Defines the solutions built in jPlayer. 356 html: true, 357 flash: true 358 }, 359 // 'MPEG-4 support' : canPlayType('video/mp4; codecs="mp4v.20.8"') 360 format: { // Static Object 361 mp3: { 362 codec: 'audio/mpeg; codecs="mp3"', 363 flashCanPlay: true, 364 media: 'audio' 365 }, 366 m4a: { // AAC / MP4 367 codec: 'audio/mp4; codecs="mp4a.40.2"', 368 flashCanPlay: true, 369 media: 'audio' 370 }, 371 oga: { // OGG 372 codec: 'audio/ogg; codecs="vorbis"', 373 flashCanPlay: false, 374 media: 'audio' 375 }, 376 wav: { // PCM 377 codec: 'audio/wav; codecs="1"', 378 flashCanPlay: false, 379 media: 'audio' 380 }, 381 webma: { // WEBM 382 codec: 'audio/webm; codecs="vorbis"', 383 flashCanPlay: false, 384 media: 'audio' 385 }, 386 fla: { // FLV / F4A 387 codec: 'audio/x-flv', 388 flashCanPlay: true, 389 media: 'audio' 390 }, 391 m4v: { // H.264 / MP4 392 codec: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"', 393 flashCanPlay: true, 394 media: 'video' 395 }, 396 ogv: { // OGG 397 codec: 'video/ogg; codecs="theora, vorbis"', 398 flashCanPlay: false, 399 media: 'video' 400 }, 401 webmv: { // WEBM 402 codec: 'video/webm; codecs="vorbis, vp8"', 403 flashCanPlay: false, 404 media: 'video' 405 }, 406 flv: { // FLV / F4V 407 codec: 'video/x-flv', 408 flashCanPlay: true, 409 media: 'video' 410 } 411 }, 412 _init: function() { 413 var self = this; 414 415 this.element.empty(); 416 417 this.status = $.extend({}, this.status); // Copy static to unique instance. 418 this.internal = $.extend({}, this.internal); // Copy static to unique instance. 419 420 this.internal.domNode = this.element.get(0); 421 422 this.formats = []; // Array based on supplied string option. Order defines priority. 423 this.solutions = []; // Array based on solution string option. Order defines priority. 424 this.require = {}; // Which media types are required: video, audio. 425 426 this.htmlElement = {}; // DOM elements created by jPlayer 427 this.html = {}; // In _init()'s this.desired code and setmedia(): Accessed via this[solution], where solution from this.solutions array. 428 this.html.audio = {}; 429 this.html.video = {}; 430 this.flash = {}; // In _init()'s this.desired code and setmedia(): Accessed via this[solution], where solution from this.solutions array. 431 432 this.css = {}; 433 this.css.cs = {}; // Holds the css selector strings 434 this.css.jq = {}; // Holds jQuery selectors. ie., $(css.cs.method) 435 436 this.ancestorJq = []; // Holds jQuery selector of cssSelectorAncestor. Init would use $() instead of [], but it is only 1.4+ 437 438 this.options.volume = this._limitValue(this.options.volume, 0, 1); // Limit volume value's bounds. 439 440 // Create the formats array, with prority based on the order of the supplied formats string 441 $.each(this.options.supplied.toLowerCase().split(","), function(index1, value1) { 442 var format = value1.replace(/^\s+|\s+$/g, ""); //trim 443 if(self.format[format]) { // Check format is valid. 444 var dupFound = false; 445 $.each(self.formats, function(index2, value2) { // Check for duplicates 446 if(format === value2) { 447 dupFound = true; 448 return false; 449 } 450 }); 451 if(!dupFound) { 452 self.formats.push(format); 453 } 454 } 455 }); 456 457 // Create the solutions array, with prority based on the order of the solution string 458 $.each(this.options.solution.toLowerCase().split(","), function(index1, value1) { 459 var solution = value1.replace(/^\s+|\s+$/g, ""); //trim 460 if(self.solution[solution]) { // Check solution is valid. 461 var dupFound = false; 462 $.each(self.solutions, function(index2, value2) { // Check for duplicates 463 if(solution === value2) { 464 dupFound = true; 465 return false; 466 } 467 }); 468 if(!dupFound) { 469 self.solutions.push(solution); 470 } 471 } 472 }); 473 474 this.internal.instance = "jp_" + this.count; 475 this.instances[this.internal.instance] = this.element; 476 477 // Check the jPlayer div has an id and create one if required. Important for Flash to know the unique id for comms. 478 if(!this.element.attr("id")) { 479 this.element.attr("id", this.options.idPrefix + "_jplayer_" + this.count); 480 } 481 482 this.internal.self = $.extend({}, { 483 id: this.element.attr("id"), 484 jq: this.element 485 }); 486 this.internal.audio = $.extend({}, { 487 id: this.options.idPrefix + "_audio_" + this.count, 488 jq: undefined 489 }); 490 this.internal.video = $.extend({}, { 491 id: this.options.idPrefix + "_video_" + this.count, 492 jq: undefined 493 }); 494 this.internal.flash = $.extend({}, { 495 id: this.options.idPrefix + "_flash_" + this.count, 496 jq: undefined, 497 swf: this.options.swfPath + ((this.options.swfPath !== "" && this.options.swfPath.slice(-1) !== "/") ? "/" : "") + "Jplayer.swf" 498 }); 499 this.internal.poster = $.extend({}, { 500 id: this.options.idPrefix + "_poster_" + this.count, 501 jq: undefined 502 }); 503 504 // Register listeners defined in the constructor 505 $.each($.jPlayer.event, function(eventName,eventType) { 506 if(self.options[eventName] !== undefined) { 507 self.element.bind(eventType + ".jPlayer", self.options[eventName]); // With .jPlayer namespace. 508 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. 509 } 510 }); 511 512 // Determine if we require solutions for audio, video or both media types. 513 this.require.audio = false; 514 this.require.video = false; 515 $.each(this.formats, function(priority, format) { 516 self.require[self.format[format].media] = true; 517 }); 518 519 // Now required types are known, finish the options default settings. 520 if(this.require.video) { 521 this.options = $.extend(true, {}, 522 this.optionsVideo, 523 this.options 524 ); 525 } else { 526 this.options = $.extend(true, {}, 527 this.optionsAudio, 528 this.options 529 ); 530 } 531 this._setSize(); // update status and jPlayer element size 532 533 // Create the poster image. 534 this.htmlElement.poster = document.createElement('img'); 535 this.htmlElement.poster.id = this.internal.poster.id; 536 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. 537 if(!self.status.video || self.status.waitForPlay) { 538 self.internal.poster.jq.show(); 539 } 540 }; 541 this.element.append(this.htmlElement.poster); 542 this.internal.poster.jq = $("#" + this.internal.poster.id); 543 this.internal.poster.jq.css({'width': this.status.width, 'height': this.status.height}); 544 this.internal.poster.jq.hide(); 545 546 // Generate the required media elements 547 this.html.audio.available = false; 548 if(this.require.audio) { // If a supplied format is audio 549 this.htmlElement.audio = document.createElement('audio'); 550 this.htmlElement.audio.id = this.internal.audio.id; 551 this.html.audio.available = !!this.htmlElement.audio.canPlayType; 552 } 553 this.html.video.available = false; 554 if(this.require.video) { // If a supplied format is video 555 this.htmlElement.video = document.createElement('video'); 556 this.htmlElement.video.id = this.internal.video.id; 557 this.html.video.available = !!this.htmlElement.video.canPlayType; 558 } 559 560 this.flash.available = this._checkForFlash(10); 561 562 this.html.canPlay = {}; 563 this.flash.canPlay = {}; 564 $.each(this.formats, function(priority, format) { 565 self.html.canPlay[format] = self.html[self.format[format].media].available && "" !== self.htmlElement[self.format[format].media].canPlayType(self.format[format].codec); 566 self.flash.canPlay[format] = self.format[format].flashCanPlay && self.flash.available; 567 }); 568 this.html.desired = false; 569 this.flash.desired = false; 570 $.each(this.solutions, function(solutionPriority, solution) { 571 if(solutionPriority === 0) { 572 self[solution].desired = true; 573 } else { 574 var audioCanPlay = false; 575 var videoCanPlay = false; 576 $.each(self.formats, function(formatPriority, format) { 577 if(self[self.solutions[0]].canPlay[format]) { // The other solution can play 578 if(self.format[format].media === 'video') { 579 videoCanPlay = true; 580 } else { 581 audioCanPlay = true; 582 } 583 } 584 }); 585 self[solution].desired = (self.require.audio && !audioCanPlay) || (self.require.video && !videoCanPlay); 586 } 587 }); 588 // This is what jPlayer will support, based on solution and supplied. 589 this.html.support = {}; 590 this.flash.support = {}; 591 $.each(this.formats, function(priority, format) { 592 self.html.support[format] = self.html.canPlay[format] && self.html.desired; 593 self.flash.support[format] = self.flash.canPlay[format] && self.flash.desired; 594 }); 595 // If jPlayer is supporting any format in a solution, then the solution is used. 596 this.html.used = false; 597 this.flash.used = false; 598 $.each(this.solutions, function(solutionPriority, solution) { 599 $.each(self.formats, function(formatPriority, format) { 600 if(self[solution].support[format]) { 601 self[solution].used = true; 602 return false; 603 } 604 }); 605 }); 606 607 // Init solution active state and the event gates to false. 608 this.html.active = false; 609 this.html.audio.gate = false; 610 this.html.video.gate = false; 611 this.flash.active = false; 612 this.flash.gate = false; 613 614 // Set up the css selectors for the control and feedback entities. 615 this._cssSelectorAncestor(this.options.cssSelectorAncestor); 616 617 // If neither html nor flash are being used by this browser, then media playback is not possible. Trigger an error event. 618 if(!(this.html.used || this.flash.used)) { 619 this._error( { 620 type: $.jPlayer.error.NO_SOLUTION, 621 context: "{solution:'" + this.options.solution + "', supplied:'" + this.options.supplied + "'}", 622 message: $.jPlayer.errorMsg.NO_SOLUTION, 623 hint: $.jPlayer.errorHint.NO_SOLUTION 624 }); 625 } 626 627 // Add the flash solution if it is being used. 628 if(this.flash.used) { 629 var htmlObj, 630 flashVars = 'jQuery=' + encodeURI(this.options.noConflict) + '&id=' + encodeURI(this.internal.self.id) + '&vol=' + this.options.volume + '&muted=' + this.options.muted; 631 632 // Code influenced by SWFObject 2.2: http://code.google.com/p/swfobject/ 633 // Non IE browsers have an initial Flash size of 1 by 1 otherwise the wmode affected the Flash ready event. 634 635 if($.browser.msie && Number($.browser.version) <= 8) { 636 var objStr = '<object id="' + this.internal.flash.id + '" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="0" height="0"></object>'; 637 638 var paramStr = [ 639 '<param name="movie" value="' + this.internal.flash.swf + '" />', 640 '<param name="FlashVars" value="' + flashVars + '" />', 641 '<param name="allowScriptAccess" value="always" />', 642 '<param name="bgcolor" value="' + this.options.backgroundColor + '" />', 643 '<param name="wmode" value="' + this.options.wmode + '" />' 644 ]; 645 646 htmlObj = document.createElement(objStr); 647 for(var i=0; i < paramStr.length; i++) { 648 htmlObj.appendChild(document.createElement(paramStr[i])); 649 } 650 } else { 651 var createParam = function(el, n, v) { 652 var p = document.createElement("param"); 653 p.setAttribute("name", n); 654 p.setAttribute("value", v); 655 el.appendChild(p); 656 }; 657 658 htmlObj = document.createElement("object"); 659 htmlObj.setAttribute("id", this.internal.flash.id); 660 htmlObj.setAttribute("data", this.internal.flash.swf); 661 htmlObj.setAttribute("type", "application/x-shockwave-flash"); 662 htmlObj.setAttribute("width", "1"); // Non-zero 663 htmlObj.setAttribute("height", "1"); // Non-zero 664 createParam(htmlObj, "flashvars", flashVars); 665 createParam(htmlObj, "allowscriptaccess", "always"); 666 createParam(htmlObj, "bgcolor", this.options.backgroundColor); 667 createParam(htmlObj, "wmode", this.options.wmode); 668 } 669 670 this.element.append(htmlObj); 671 this.internal.flash.jq = $(htmlObj); 672 } 673 674 // Add the HTML solution if being used. 675 if(this.html.used) { 676 677 // The HTML Audio handlers 678 if(this.html.audio.available) { 679 this._addHtmlEventListeners(this.htmlElement.audio, this.html.audio); 680 this.element.append(this.htmlElement.audio); 681 this.internal.audio.jq = $("#" + this.internal.audio.id); 682 } 683 684 // The HTML Video handlers 685 if(this.html.video.available) { 686 this._addHtmlEventListeners(this.htmlElement.video, this.html.video); 687 this.element.append(this.htmlElement.video); 688 this.internal.video.jq = $("#" + this.internal.video.id); 689 this.internal.video.jq.css({'width':'0px', 'height':'0px'}); // Using size 0x0 since a .hide() causes issues in iOS 690 } 691 } 692 693 // Create the bridge that emulates the HTML Media element on the jPlayer DIV 694 if( this.options.emulateHtml ) { 695 this._emulateHtmlBridge(); 696 } 697 698 if(this.html.used && !this.flash.used) { // If only HTML, then emulate flash ready() call after 100ms. 699 setTimeout( function() { 700 self.internal.ready = true; 701 self.version.flash = "n/a"; 702 self._trigger($.jPlayer.event.repeat); // Trigger the repeat event so its handler can initialize itself with the loop option. 703 self._trigger($.jPlayer.event.ready); 704 }, 100); 705 } 706 707 // Initialize the interface components with the options. 708 this._updateInterface(); 709 this._updateButtons(false); 710 this._updateAutohide(); 711 this._updateVolume(this.options.volume); 712 this._updateMute(this.options.muted); 713 if(this.css.jq.videoPlay.length) { 714 this.css.jq.videoPlay.hide(); 715 } 716 717 $.jPlayer.prototype.count++; // Change static variable via prototype. 718 }, 719 destroy: function() { 720 // MJP: The background change remains. Would need to store the original to restore it correctly. 721 722 // Reset the interface, remove seeking effect and times. 723 this._resetStatus(); 724 this._updateInterface(); 725 this._seeked(); 726 if(this.css.jq.currentTime.length) { 727 this.css.jq.currentTime.text(""); 728 } 729 if(this.css.jq.duration.length) { 730 this.css.jq.duration.text(""); 731 } 732 733 if(this.status.srcSet) { // Or you get a bogus error event 734 this.pause(); // Pauses the media and clears any delayed commands used in the HTML solution. 735 } 736 $.each(this.css.jq, function(fn, jq) { // Remove any bindings from the interface controls.
737 // Check selector is valid before trying to execute method. 738 if(jq.length) { 739 jq.unbind(".jPlayer"); 740 } 741 }); 742 if( this.options.emulateHtml ) { 743 this._destroyHtmlBridge(); 744 } 745 this.element.removeData("jPlayer"); // Remove jPlayer data 746 this.element.unbind(".jPlayer"); // Remove all event handlers created by the jPlayer constructor 747 this.element.empty(); // Remove the inserted child elements 748 749 this.instances[this.internal.instance] = undefined; // Clear the instance on the static instance object 750 }, 751 enable: function() { // Plan to implement 752 // options.disabled = false 753 }, 754 disable: function () { // Plan to implement 755 // options.disabled = true 756 }, 757 _addHtmlEventListeners: function(mediaElement, entity) { 758 var self = this; 759 mediaElement.preload = this.options.preload; 760 mediaElement.muted = this.options.muted; 761 mediaElement.volume = this.options.volume; 762 763 // Create the event listeners 764 // Only want the active entity to affect jPlayer and bubble events. 765 // Using entity.gate so that object is referenced and gate property always current 766 767 mediaElement.addEventListener("progress", function() { 768 if(entity.gate && !self.status.waitForLoad) { 769 self._getHtmlStatus(mediaElement); 770 self._updateInterface(); 771 self._trigger($.jPlayer.event.progress); 772 } 773 }, false); 774 mediaElement.addEventListener("timeupdate", function() { 775 if(entity.gate && !self.status.waitForLoad) { 776 self._getHtmlStatus(mediaElement); 777 self._updateInterface(); 778 self._trigger($.jPlayer.event.timeupdate); 779 } 780 }, false); 781 mediaElement.addEventListener("durationchange", function() { 782 if(entity.gate && !self.status.waitForLoad) { 783 self.status.duration = this.duration; 784 self._getHtmlStatus(mediaElement); 785 self._updateInterface(); 786 self._trigger($.jPlayer.event.durationchange); 787 } 788 }, false); 789 mediaElement.addEventListener("play", function() { 790 if(entity.gate && !self.status.waitForLoad) { 791 self._updateButtons(true); 792 self._trigger($.jPlayer.event.play); 793 } 794 }, false); 795 mediaElement.addEventListener("playing", function() { 796 if(entity.gate && !self.status.waitForLoad) { 797 self._updateButtons(true); 798 self._seeked(); 799 self._trigger($.jPlayer.event.playing); 800 } 801 }, false); 802 mediaElement.addEventListener("pause", function() { 803 if(entity.gate && !self.status.waitForLoad) { 804 self._updateButtons(false); 805 self._trigger($.jPlayer.event.pause); 806 } 807 }, false); 808 mediaElement.addEventListener("waiting", function() { 809 if(entity.gate && !self.status.waitForLoad) { 810 self._seeking(); 811 self._trigger($.jPlayer.event.waiting); 812 } 813 }, false); 814 mediaElement.addEventListener("seeking", function() { 815 if(entity.gate && !self.status.waitForLoad) { 816 self._seeking(); 817 self._trigger($.jPlayer.event.seeking); 818 } 819 }, false); 820 mediaElement.addEventListener("seeked", function() { 821 if(entity.gate && !self.status.waitForLoad) { 822 self._seeked(); 823 self._trigger($.jPlayer.event.seeked); 824 } 825 }, false); 826 mediaElement.addEventListener("volumechange", function() { 827 if(entity.gate && !self.status.waitForLoad) { 828 // Read the values back from the element as the Blackberry PlayBook shares the volume with the physical buttons master volume control. 829 // However, when tested 6th July 2011, those buttons do not generate an event. The physical play/pause button does though. 830 self.options.volume = mediaElement.volume; 831 self.options.muted = mediaElement.muted; 832 self._updateMute(); 833 self._updateVolume(); 834 self._trigger($.jPlayer.event.volumechange); 835 } 836 }, false); 837 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. 838 if(entity.gate && !self.status.waitForLoad) { 839 self._seeked(); 840 self._trigger($.jPlayer.event.suspend); 841 } 842 }, false); 843 mediaElement.addEventListener("ended", function() { 844 if(entity.gate && !self.status.waitForLoad) { 845 // Order of the next few commands are important. Change the time and then pause.
vendor: 10,510 bytes, lines 846-1126
846 // Solves a bug in Firefox, where issuing pause 1st causes the media to play from the start. ie., The pause is ignored. 847 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. 848 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.) 849 } 850 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. 851 self._updateButtons(false); 852 self._getHtmlStatus(mediaElement, true); // With override true. Otherwise Chrome leaves progress at full. 853 self._updateInterface(); 854 self._trigger($.jPlayer.event.ended); 855 } 856 }, false); 857 mediaElement.addEventListener("error", function() { 858 if(entity.gate && !self.status.waitForLoad) { 859 self._updateButtons(false); 860 self._seeked(); 861 if(self.status.srcSet) { // Deals with case of clearMedia() causing an error event. 862 clearTimeout(self.internal.htmlDlyCmdId); // Clears any delayed commands used in the HTML solution. 863 self.status.waitForLoad = true; // Allows the load operation to try again. 864 self.status.waitForPlay = true; // Reset since a play was captured. 865 if(self.status.video) { 866 self.internal.video.jq.css({'width':'0px', 'height':'0px'}); 867 } 868 if(self._validString(self.status.media.poster)) { 869 self.internal.poster.jq.show(); 870 } 871 if(self.css.jq.videoPlay.length) { 872 self.css.jq.videoPlay.show(); 873 } 874 self._error( { 875 type: $.jPlayer.error.URL, 876 context: self.status.src, // this.src shows absolute urls. Want context to show the url given. 877 message: $.jPlayer.errorMsg.URL, 878 hint: $.jPlayer.errorHint.URL 879 }); 880 } 881 } 882 }, false); 883 // Create all the other event listeners that bubble up to a jPlayer event from html, without being used by jPlayer. 884 $.each($.jPlayer.htmlEvent, function(i, eventType) { 885 mediaElement.addEventListener(this, function() { 886 if(entity.gate && !self.status.waitForLoad) { 887 self._trigger($.jPlayer.event[eventType]); 888 } 889 }, false); 890 }); 891 }, 892 _getHtmlStatus: function(media, override) { 893 var ct = 0, d = 0, cpa = 0, sp = 0, cpr = 0; 894 895 if(media.duration) { // Fixes the duration bug in iOS, where the durationchange event occurs when media.duration is not always correct. 896 this.status.duration = media.duration; 897 } 898 ct = media.currentTime; 899 cpa = (this.status.duration > 0) ? 100 * ct / this.status.duration : 0; 900 if((typeof media.seekable === "object") && (media.seekable.length > 0)) { 901 sp = (this.status.duration > 0) ? 100 * media.seekable.end(media.seekable.length-1) / this.status.duration : 100; 902 cpr = 100 * media.currentTime / media.seekable.end(media.seekable.length-1); 903 } else { 904 sp = 100; 905 cpr = cpa; 906 } 907 908 if(override) { 909 ct = 0; 910 cpr = 0; 911 cpa = 0; 912 } 913 914 this.status.seekPercent = sp; 915 this.status.currentPercentRelative = cpr; 916 this.status.currentPercentAbsolute = cpa; 917 this.status.currentTime = ct; 918 919 this.status.readyState = media.readyState; 920 this.status.networkState = media.networkState; 921 this.status.playbackRate = media.playbackRate; 922 this.status.ended = media.ended; 923 }, 924 _resetStatus: function() { 925 this.status = $.extend({}, this.status, $.jPlayer.prototype.status); // Maintains the status properties that persist through a reset. 926 }, 927 _trigger: function(eventType, error, warning) { // eventType always valid as called using $.jPlayer.event.eventType 928 var event = $.Event(eventType); 929 event.jPlayer = {}; 930 event.jPlayer.version = $.extend({}, this.version); 931 event.jPlayer.options = $.extend(true, {}, this.options); // Deep copy 932 event.jPlayer.status = $.extend(true, {}, this.status); // Deep copy 933 event.jPlayer.html = $.extend(true, {}, this.html); // Deep copy 934 event.jPlayer.flash = $.extend(true, {}, this.flash); // Deep copy 935 if(error) { 936 event.jPlayer.error = $.extend({}, error); 937 } 938 if(warning) { 939 event.jPlayer.warning = $.extend({}, warning); 940 } 941 this.element.trigger(event); 942 }, 943 jPlayerFlashEvent: function(eventType, status) { // Called from Flash 944 if(eventType === $.jPlayer.event.ready) { 945 if(!this.internal.ready) { 946 this.internal.ready = true; 947 this.internal.flash.jq.css({'width':'0px', 'height':'0px'}); // Once Flash generates the ready event, minimise to zero as it is not affected by wmode anymore. 948 949 this.version.flash = status.version; 950 if(this.version.needFlash !== this.version.flash) { 951 this._error( { 952 type: $.jPlayer.error.VERSION, 953 context: this.version.flash, 954 message: $.jPlayer.errorMsg.VERSION + this.version.flash, 955 hint: $.jPlayer.errorHint.VERSION 956 }); 957 } 958 this._trigger($.jPlayer.event.repeat); // Trigger the repeat event so its handler can initialize itself with the loop option. 959 this._trigger(eventType); 960 } else { 961 // This condition occurs if the Flash is hidden and then shown again. 962 // Firefox also reloads the Flash if the CSS position changes. position:fixed is used for full screen. 963 964 // Only do this if the Flash is the solution being used at the moment. Affects Media players where both solution may be being used. 965 if(this.flash.gate) { 966 967 // Send the current status to the Flash now that it is ready (available) again. 968 if(this.status.srcSet) { 969 970 // Need to read original status before issuing the setMedia command. 971 var currentTime = this.status.currentTime, 972 paused = this.status.paused; 973 974 this.setMedia(this.status.media); 975 if(currentTime > 0) { 976 if(paused) { 977 this.pause(currentTime); 978 } else { 979 this.play(currentTime); 980 } 981 } 982 } 983 this._trigger($.jPlayer.event.flashreset); 984 } 985 } 986 } 987 if(this.flash.gate) { 988 switch(eventType) { 989 case $.jPlayer.event.progress: 990 this._getFlashStatus(status); 991 this._updateInterface(); 992 this._trigger(eventType); 993 break; 994 case $.jPlayer.event.timeupdate: 995 this._getFlashStatus(status); 996 this._updateInterface(); 997 this._trigger(eventType); 998 break; 999 case $.jPlayer.event.play: 1000 this._seeked(); 1001 this._updateButtons(true); 1002 this._trigger(eventType); 1003 break; 1004 case $.jPlayer.event.pause: 1005 this._updateButtons(false); 1006 this._trigger(eventType); 1007 break; 1008 case $.jPlayer.event.ended: 1009 this._updateButtons(false); 1010 this._trigger(eventType); 1011 break; 1012 case $.jPlayer.event.error: 1013 this.status.waitForLoad = true; // Allows the load operation to try again. 1014 this.status.waitForPlay = true; // Reset since a play was captured. 1015 if(this.status.video) { 1016 this.internal.flash.jq.css({'width':'0px', 'height':'0px'}); 1017 } 1018 if(this._validString(this.status.media.poster)) { 1019 this.internal.poster.jq.show(); 1020 } 1021 if(this.css.jq.videoPlay.length) { 1022 this.css.jq.videoPlay.show(); 1023 } 1024 if(this.status.video) { // Set up for another try. Execute before error event. 1025 this._flash_setVideo(this.status.media); 1026 } else { 1027 this._flash_setAudio(this.status.media); 1028 } 1029 this._error( { 1030 type: $.jPlayer.error.URL, 1031 context:status.src, 1032 message: $.jPlayer.errorMsg.URL, 1033 hint: $.jPlayer.errorHint.URL 1034 }); 1035 break; 1036 case $.jPlayer.event.seeking: 1037 this._seeking(); 1038 this._trigger(eventType); 1039 break; 1040 case $.jPlayer.event.seeked: 1041 this._seeked(); 1042 this._trigger(eventType); 1043 break; 1044 case $.jPlayer.event.ready: 1045 // The ready event is handled outside the switch statement. 1046 // Captured here otherwise 2 ready events would be generated if the ready event handler used setMedia. 1047 break; 1048 default: 1049 this._trigger(eventType); 1050 } 1051 } 1052 return false; 1053 }, 1054 _getFlashStatus: function(status) { 1055 this.status.seekPercent = status.seekPercent; 1056 this.status.currentPercentRelative = status.currentPercentRelative; 1057 this.status.currentPercentAbsolute = status.currentPercentAbsolute; 1058 this.status.currentTime = status.currentTime; 1059 this.status.duration = status.duration; 1060 1061 // The Flash does not generate this information in this release 1062 this.status.readyState = 4; // status.readyState; 1063 this.status.networkState = 0; // status.networkState; 1064 this.status.playbackRate = 1; // status.playbackRate; 1065 this.status.ended = false; // status.ended; 1066 }, 1067 _updateButtons: function(playing) { 1068 if(playing !== undefined) { 1069 this.status.paused = !playing; 1070 if(this.css.jq.play.length && this.css.jq.pause.length) { 1071 if(playing) { 1072 this.css.jq.play.hide(); 1073 this.css.jq.pause.show(); 1074 } else { 1075 this.css.jq.play.show(); 1076 this.css.jq.pause.hide(); 1077 } 1078 } 1079 } 1080 if(this.css.jq.restoreScreen.length && this.css.jq.fullScreen.length) { 1081 if(this.options.fullScreen) { 1082 this.css.jq.fullScreen.hide(); 1083 this.css.jq.restoreScreen.show(); 1084 } else { 1085 this.css.jq.fullScreen.show(); 1086 this.css.jq.restoreScreen.hide(); 1087 } 1088 } 1089 if(this.css.jq.repeat.length && this.css.jq.repeatOff.length) { 1090 if(this.options.loop) { 1091 this.css.jq.repeat.hide(); 1092 this.css.jq.repeatOff.show(); 1093 } else { 1094 this.css.jq.repeat.show(); 1095 this.css.jq.repeatOff.hide(); 1096 } 1097 } 1098 }, 1099 _updateInterface: function() { 1100 if(this.css.jq.seekBar.length) { 1101 this.css.jq.seekBar.width(this.status.seekPercent+"%"); 1102 } 1103 if(this.css.jq.playBar.length) { 1104 this.css.jq.playBar.width(this.status.currentPercentRelative+"%"); 1105 } 1106 if(this.css.jq.currentTime.length) { 1107 this.css.jq.currentTime.text($.jPlayer.convertTime(this.status.currentTime)); 1108 } 1109 if(this.css.jq.duration.length) { 1110 this.css.jq.duration.text($.jPlayer.convertTime(this.status.duration)); 1111 } 1112 }, 1113 _seeking: function() { 1114 if(this.css.jq.seekBar.length) { 1115 this.css.jq.seekBar.addClass("jp-seeking-bg"); 1116 } 1117 }, 1118 _seeked: function() { 1119 if(this.css.jq.seekBar.length) { 1120 this.css.jq.seekBar.removeClass("jp-seeking-bg"); 1121 } 1122 }, 1123 setMedia: function(media) { 1124 1125 /* media[format] = String: URL of format. Must contain all of the supplied option's video or audio formats. 1126 * media.poster = String: Video poster URL.
1127 * media.subtitles = String: * NOT IMPLEMENTED * URL of subtitles SRT file 1128 * media.chapters = String: * NOT IMPLEMENTED * URL of chapters SRT file 1129 * media.stream = Boolean: * NOT IMPLEMENTED * Designating actual media streams. ie., "false/undefined" for files. Plan to refresh the flash every so often. 1130 */ 1131 1132 var self = this; 1133 1134 this._seeked(); 1135 clearTimeout(this.internal.htmlDlyCmdId); // Clears any delayed commands used in the HTML solution. 1136 1137 // Store the current html gates, since we need for clearMedia() conditions. 1138 var audioGate = this.html.audio.gate; 1139 var videoGate = this.html.video.gate; 1140 1141 var supported = false; 1142 $.each(this.formats, function(formatPriority, format) { 1143 var isVideo = self.format[format].media === 'video'; 1144 $.each(self.solutions, function(solutionPriority, solution) { 1145 if(self[solution].support[format] && self._validString(media[format])) { // Format supported in solution and url given for format. 1146 var isHtml = solution === 'html'; 1147 1148 if(isVideo) { 1149 if(isHtml) { 1150 self.html.audio.gate = false; 1151 self.html.video.gate = true; 1152 self.flash.gate = false; 1153 } else { 1154 self.html.audio.gate = false; 1155 self.html.video.gate = false; 1156 self.flash.gate = true; 1157 } 1158 } else { 1159 if(isHtml) { 1160 self.html.audio.gate = true; 1161 self.html.video.gate = false; 1162 self.flash.gate = false; 1163 } else { 1164 self.html.audio.gate = false; 1165 self.html.video.gate = false; 1166 self.flash.gate = true; 1167 } 1168 } 1169 1170 // Clear media of the previous solution if: 1171 // - it was Flash 1172 // - changing from HTML to Flash 1173 // - the HTML solution media type (audio or video) remained the same. 1174 // Note that, we must be careful with clearMedia() on iPhone, otherwise clearing the video when changing to audio corrupts the built in video player. 1175 if(self.flash.active || (self.html.active && self.flash.gate) || (audioGate === self.html.audio.gate && videoGate === self.html.video.gate)) { 1176 self.clearMedia(); 1177 } else if(audioGate !== self.html.audio.gate && videoGate !== self.html.video.gate) { // If switching between html elements 1178 self._html_pause(); 1179 // Hide the video if it was being used. 1180 if(self.status.video) { 1181 self.internal.video.jq.css({'width':'0px', 'height':'0px'}); 1182 } 1183 self._resetStatus(); // Since clearMedia usually does this. Execute after status.video useage. 1184 } 1185 1186 if(isVideo) { 1187 if(isHtml) { 1188 self._html_setVideo(media); 1189 self.html.active = true; 1190 self.flash.active = false; 1191 } else { 1192 self._flash_setVideo(media); 1193 self.html.active = false; 1194 self.flash.active = true; 1195 } 1196 if(self.css.jq.videoPlay.length) { 1197 self.css.jq.videoPlay.show(); 1198 } 1199 self.status.video = true; 1200 } else { 1201 if(isHtml) { 1202 self._html_setAudio(media); 1203 self.html.active = true; 1204 self.flash.active = false; 1205 } else { 1206 self._flash_setAudio(media); 1207 self.html.active = false; 1208 self.flash.active = true; 1209 } 1210 if(self.css.jq.videoPlay.length) { 1211 self.css.jq.videoPlay.hide(); 1212 } 1213 self.status.video = false; 1214 } 1215 1216 supported = true; 1217 return false; // Exit $.each 1218 } 1219 }); 1220 if(supported) { 1221 return false; // Exit $.each 1222 } 1223 }); 1224 1225 if(supported) { 1226 // 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. 1227 if(this._validString(media.poster)) { 1228 if(this.htmlElement.poster.src !== media.poster) { // Since some browsers do not generate img onload event. 1229 this.htmlElement.poster.src = media.poster; 1230 } else { 1231 this.internal.poster.jq.show(); 1232 } 1233 } else { 1234 this.internal.poster.jq.hide(); // Hide if not used, since clearMedia() does not always occur above. ie., HTML audio <-> video switching. 1235 } 1236 this.status.srcSet = true; 1237 this.status.media = $.extend({}, media); 1238 this._updateButtons(false); 1239 this._updateInterface(); 1240 } else { // jPlayer cannot support any formats provided in this browser 1241 // Pause here if old media could be playing. Otherwise, playing media being changed to bad media would leave the old media playing. 1242 if(this.status.srcSet && !this.status.waitForPlay) { 1243 this.pause(); 1244 } 1245 // Reset all the control flags 1246 this.html.audio.gate = false;
vendor: 16,364 bytes, lines 1247-1773
1247 this.html.video.gate = false; 1248 this.flash.gate = false; 1249 this.html.active = false; 1250 this.flash.active = false; 1251 // Reset status and interface. 1252 this._resetStatus(); 1253 this._updateInterface(); 1254 this._updateButtons(false); 1255 // Hide the any old media 1256 this.internal.poster.jq.hide(); 1257 if(this.html.used && this.require.video) { 1258 this.internal.video.jq.css({'width':'0px', 'height':'0px'}); 1259 } 1260 if(this.flash.used) { 1261 this.internal.flash.jq.css({'width':'0px', 'height':'0px'}); 1262 } 1263 // Send an error event 1264 this._error( { 1265 type: $.jPlayer.error.NO_SUPPORT, 1266 context: "{supplied:'" + this.options.supplied + "'}", 1267 message: $.jPlayer.errorMsg.NO_SUPPORT, 1268 hint: $.jPlayer.errorHint.NO_SUPPORT 1269 }); 1270 } 1271 }, 1272 clearMedia: function() { 1273 this._resetStatus(); 1274 this._updateButtons(false); 1275 1276 this.internal.poster.jq.hide(); 1277 1278 clearTimeout(this.internal.htmlDlyCmdId); 1279 1280 if(this.html.active) { 1281 this._html_clearMedia(); 1282 } else if(this.flash.active) { 1283 this._flash_clearMedia(); 1284 } 1285 }, 1286 load: function() { 1287 if(this.status.srcSet) { 1288 if(this.html.active) { 1289 this._html_load(); 1290 } else if(this.flash.active) { 1291 this._flash_load(); 1292 } 1293 } else { 1294 this._urlNotSetError("load"); 1295 } 1296 }, 1297 play: function(time) { 1298 time = (typeof time === "number") ? time : NaN; // Remove jQuery event from click handler 1299 if(this.status.srcSet) { 1300 if(this.html.active) { 1301 this._html_play(time); 1302 } else if(this.flash.active) { 1303 this._flash_play(time); 1304 } 1305 } else { 1306 this._urlNotSetError("play"); 1307 } 1308 }, 1309 videoPlay: function(e) { // Handles clicks on the play button over the video poster 1310 this.play(); 1311 }, 1312 pause: function(time) { 1313 time = (typeof time === "number") ? time : NaN; // Remove jQuery event from click handler 1314 if(this.status.srcSet) { 1315 if(this.html.active) { 1316 this._html_pause(time); 1317 } else if(this.flash.active) { 1318 this._flash_pause(time); 1319 } 1320 } else { 1321 this._urlNotSetError("pause"); 1322 } 1323 }, 1324 pauseOthers: function() { 1325 var self = this; 1326 $.each(this.instances, function(i, element) { 1327 if(self.element !== element) { // Do not this instance. 1328 if(element.data("jPlayer").status.srcSet) { // Check that media is set otherwise would cause error event. 1329 element.jPlayer("pause"); 1330 } 1331 } 1332 }); 1333 }, 1334 stop: function() { 1335 if(this.status.srcSet) { 1336 if(this.html.active) { 1337 this._html_pause(0); 1338 } else if(this.flash.active) { 1339 this._flash_pause(0); 1340 } 1341 } else { 1342 this._urlNotSetError("stop"); 1343 } 1344 }, 1345 playHead: function(p) { 1346 p = this._limitValue(p, 0, 100); 1347 if(this.status.srcSet) { 1348 if(this.html.active) { 1349 this._html_playHead(p); 1350 } else if(this.flash.active) { 1351 this._flash_playHead(p); 1352 } 1353 } else { 1354 this._urlNotSetError("playHead"); 1355 } 1356 }, 1357 _muted: function(muted) { 1358 this.options.muted = muted; 1359 if(this.html.used) { 1360 this._html_mute(muted); 1361 } 1362 if(this.flash.used) { 1363 this._flash_mute(muted); 1364 } 1365 1366 // The HTML solution generates this event from the media element itself. 1367 if(this.flash.gate) { 1368 this._updateMute(muted); 1369 this._updateVolume(this.options.volume); 1370 this._trigger($.jPlayer.event.volumechange); 1371 } 1372 }, 1373 mute: function(mute) { // mute is either: undefined (true), an event object (true) or a boolean (muted). 1374 mute = mute === undefined ? true : !!mute; 1375 this._muted(mute); 1376 }, 1377 unmute: function(unmute) { // unmute is either: undefined (true), an event object (true) or a boolean (!muted). 1378 unmute = unmute === undefined ? true : !!unmute; 1379 this._muted(!unmute); 1380 }, 1381 _updateMute: function(mute) { 1382 if(mute === undefined) { 1383 mute = this.options.muted; 1384 } 1385 if(this.css.jq.mute.length && this.css.jq.unmute.length) { 1386 if(mute) { 1387 this.css.jq.mute.hide(); 1388 this.css.jq.unmute.show(); 1389 } else { 1390 this.css.jq.mute.show(); 1391 this.css.jq.unmute.hide(); 1392 } 1393 } 1394 }, 1395 volume: function(v) { 1396 v = this._limitValue(v, 0, 1); 1397 this.options.volume = v; 1398 1399 if(this.html.used) { 1400 this._html_volume(v); 1401 } 1402 if(this.flash.used) { 1403 this._flash_volume(v); 1404 } 1405 1406 // The HTML solution generates this event from the media element itself. 1407 if(this.flash.gate) { 1408 this._updateVolume(v); 1409 this._trigger($.jPlayer.event.volumechange); 1410 } 1411 }, 1412 volumeBar: function(e) { // Handles clicks on the volumeBar 1413 if(this.css.jq.volumeBar.length) { 1414 var offset = this.css.jq.volumeBar.offset(); 1415 var x = e.pageX - offset.left; 1416 var w = this.css.jq.volumeBar.width(); 1417 var v = x/w; 1418 this.volume(v); 1419 } 1420 if(this.options.muted) { 1421 this._muted(false); 1422 } 1423 }, 1424 volumeBarValue: function(e) { // Handles clicks on the volumeBarValue 1425 this.volumeBar(e); 1426 }, 1427 _updateVolume: function(v) { 1428 if(v === undefined) { 1429 v = this.options.volume; 1430 } 1431 v = this.options.muted ? 0 : v; 1432 1433 if(this.css.jq.volumeBarValue.length) { 1434 this.css.jq.volumeBarValue.width((v*100)+"%"); 1435 } 1436 }, 1437 volumeMax: function() { // Handles clicks on the volume max 1438 this.volume(1); 1439 if(this.options.muted) { 1440 this._muted(false); 1441 } 1442 }, 1443 _cssSelectorAncestor: function(ancestor) { 1444 var self = this; 1445 this.options.cssSelectorAncestor = ancestor; 1446 this._removeUiClass(); 1447 this.ancestorJq = ancestor ? $(ancestor) : []; // Would use $() instead of [], but it is only 1.4+ 1448 if(ancestor && this.ancestorJq.length !== 1) { // So empty strings do not generate the warning. 1449 this._warning( { 1450 type: $.jPlayer.warning.CSS_SELECTOR_COUNT, 1451 context: ancestor, 1452 message: $.jPlayer.warningMsg.CSS_SELECTOR_COUNT + this.ancestorJq.length + " found for cssSelectorAncestor.", 1453 hint: $.jPlayer.warningHint.CSS_SELECTOR_COUNT 1454 }); 1455 } 1456 this._addUiClass(); 1457 $.each(this.options.cssSelector, function(fn, cssSel) { 1458 self._cssSelector(fn, cssSel); 1459 }); 1460 }, 1461 _cssSelector: function(fn, cssSel) { 1462 var self = this; 1463 if(typeof cssSel === 'string') { 1464 if($.jPlayer.prototype.options.cssSelector[fn]) { 1465 if(this.css.jq[fn] && this.css.jq[fn].length) { 1466 this.css.jq[fn].unbind(".jPlayer"); 1467 } 1468 this.options.cssSelector[fn] = cssSel; 1469 this.css.cs[fn] = this.options.cssSelectorAncestor + " " + cssSel; 1470 1471 if(cssSel) { // Checks for empty string 1472 this.css.jq[fn] = $(this.css.cs[fn]); 1473 } else { 1474 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. 1475 } 1476 1477 if(this.css.jq[fn].length) { 1478 var handler = function(e) { 1479 self[fn](e); 1480 $(this).blur(); 1481 return false; 1482 }; 1483 this.css.jq[fn].bind("click.jPlayer", handler); // Using jPlayer namespace 1484 } 1485 1486 if(cssSel && this.css.jq[fn].length !== 1) { // So empty strings do not generate the warning. ie., they just remove the old one. 1487 this._warning( { 1488 type: $.jPlayer.warning.CSS_SELECTOR_COUNT, 1489 context: this.css.cs[fn], 1490 message: $.jPlayer.warningMsg.CSS_SELECTOR_COUNT + this.css.jq[fn].length + " found for " + fn + " method.", 1491 hint: $.jPlayer.warningHint.CSS_SELECTOR_COUNT 1492 }); 1493 } 1494 } else { 1495 this._warning( { 1496 type: $.jPlayer.warning.CSS_SELECTOR_METHOD, 1497 context: fn, 1498 message: $.jPlayer.warningMsg.CSS_SELECTOR_METHOD, 1499 hint: $.jPlayer.warningHint.CSS_SELECTOR_METHOD 1500 }); 1501 } 1502 } else { 1503 this._warning( { 1504 type: $.jPlayer.warning.CSS_SELECTOR_STRING, 1505 context: cssSel, 1506 message: $.jPlayer.warningMsg.CSS_SELECTOR_STRING, 1507 hint: $.jPlayer.warningHint.CSS_SELECTOR_STRING 1508 }); 1509 } 1510 }, 1511 seekBar: function(e) { // Handles clicks on the seekBar 1512 if(this.css.jq.seekBar) { 1513 var offset = this.css.jq.seekBar.offset(); 1514 var x = e.pageX - offset.left; 1515 var w = this.css.jq.seekBar.width(); 1516 var p = 100*x/w; 1517 this.playHead(p); 1518 } 1519 }, 1520 playBar: function(e) { // Handles clicks on the playBar 1521 this.seekBar(e); 1522 }, 1523 repeat: function() { // Handle clicks on the repeat button 1524 this._loop(true); 1525 }, 1526 repeatOff: function() { // Handle clicks on the repeatOff button 1527 this._loop(false); 1528 }, 1529 _loop: function(loop) { 1530 if(this.options.loop !== loop) { 1531 this.options.loop = loop; 1532 this._updateButtons(); 1533 this._trigger($.jPlayer.event.repeat); 1534 } 1535 }, 1536 1537 // Plan to review the cssSelector method to cope with missing associated functions accordingly. 1538 1539 currentTime: function(e) { // Handles clicks on the text 1540 // Added to avoid errors using cssSelector system for the text 1541 }, 1542 duration: function(e) { // Handles clicks on the text 1543 // Added to avoid errors using cssSelector system for the text 1544 }, 1545 gui: function(e) { // Handles clicks on the gui 1546 // Added to avoid errors using cssSelector system for the gui 1547 }, 1548 1549 // 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. 1550 option: function(key, value) { 1551 var options = key; 1552 1553 // Enables use: options(). Returns a copy of options object 1554 if ( arguments.length === 0 ) { 1555 return $.extend( true, {}, this.options ); 1556 } 1557 1558 if(typeof key === "string") { 1559 var keys = key.split("."); 1560 1561 // Enables use: options("someOption") Returns a copy of the option. Supports dot notation. 1562 if(value === undefined) { 1563 1564 var opt = $.extend(true, {}, this.options); 1565 for(var i = 0; i < keys.length; i++) { 1566 if(opt[keys[i]] !== undefined) { 1567 opt = opt[keys[i]]; 1568 } else { 1569 this._warning( { 1570 type: $.jPlayer.warning.OPTION_KEY, 1571 context: key, 1572 message: $.jPlayer.warningMsg.OPTION_KEY, 1573 hint: $.jPlayer.warningHint.OPTION_KEY 1574 }); 1575 return undefined; 1576 } 1577 } 1578 return opt; 1579 } 1580 1581 // Enables use: options("someOptionObject", someObject}). Creates: {someOptionObject:someObject} 1582 // Enables use: options("someOption", someValue). Creates: {someOption:someValue} 1583 // Enables use: options("someOptionObject.someOption", someValue). Creates: {someOptionObject:{someOption:someValue}} 1584 1585 options = {}; 1586 var opts = options; 1587 1588 for(var j = 0; j < keys.length; j++) { 1589 if(j < keys.length - 1) { 1590 opts[keys[j]] = {}; 1591 opts = opts[keys[j]]; 1592 } else { 1593 opts[keys[j]] = value; 1594 } 1595 } 1596 } 1597 1598 // Otherwise enables use: options(optionObject). Uses original object (the key) 1599 1600 this._setOptions(options); 1601 1602 return this; 1603 }, 1604 _setOptions: function(options) { 1605 var self = this; 1606 $.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. 1607 self._setOption(key, value); 1608 }); 1609 1610 return this; 1611 }, 1612 _setOption: function(key, value) { 1613 var self = this; 1614 1615 // The ability to set options is limited at this time. 1616 1617 switch(key) { 1618 case "volume" : 1619 this.volume(value); 1620 break; 1621 case "muted" : 1622 this._muted(value); 1623 break; 1624 case "cssSelectorAncestor" : 1625 this._cssSelectorAncestor(value); // Set and refresh all associations for the new ancestor. 1626 break; 1627 case "cssSelector" : 1628 $.each(value, function(fn, cssSel) { 1629 self._cssSelector(fn, cssSel); // NB: The option is set inside this function, after further validity checks. 1630 }); 1631 break; 1632 case "fullScreen" : 1633 if(this.options[key] !== value) { // if changed 1634 this._removeUiClass(); 1635 this.options[key] = value; 1636 this._refreshSize(); 1637 } 1638 break; 1639 case "size" : 1640 if(!this.options.fullScreen && this.options[key].cssClass !== value.cssClass) { 1641 this._removeUiClass(); 1642 } 1643 this.options[key] = $.extend({}, this.options[key], value); // store a merged copy of it, incase not all properties changed. 1644 this._refreshSize(); 1645 break; 1646 case "sizeFull" : 1647 if(this.options.fullScreen && this.options[key].cssClass !== value.cssClass) { 1648 this._removeUiClass(); 1649 } 1650 this.options[key] = $.extend({}, this.options[key], value); // store a merged copy of it, incase not all properties changed. 1651 this._refreshSize(); 1652 break; 1653 case "autohide" : 1654 this.options[key] = $.extend({}, this.options[key], value); // store a merged copy of it, incase not all properties changed. 1655 this._updateAutohide(); 1656 break; 1657 case "loop" : 1658 this._loop(value); 1659 break; 1660 case "emulateHtml" : 1661 if(this.options[key] !== value) { // To avoid multiple event handlers being created, if true already. 1662 this.options[key] = value; 1663 if(value) { 1664 this._emulateHtmlBridge(); 1665 } else { 1666 this._destroyHtmlBridge(); 1667 } 1668 } 1669 break; 1670 } 1671 1672 return this; 1673 }, 1674 // End of: (Options code adapted from ui.widget.js) 1675 1676 _refreshSize: function() { 1677 this._setSize(); // update status and jPlayer element size 1678 this._addUiClass(); // update the ui class 1679 this._updateSize(); // update internal sizes 1680 this._updateButtons(); 1681 this._updateAutohide(); 1682 this._trigger($.jPlayer.event.resize); 1683 }, 1684 _setSize: function() { 1685 // Determine the current size from the options 1686 if(this.options.fullScreen) { 1687 this.status.width = this.options.sizeFull.width; 1688 this.status.height = this.options.sizeFull.height; 1689 this.status.cssClass = this.options.sizeFull.cssClass; 1690 } else { 1691 this.status.width = this.options.size.width; 1692 this.status.height = this.options.size.height; 1693 this.status.cssClass = this.options.size.cssClass; 1694 } 1695 1696 // Set the size of the jPlayer area. 1697 this.element.css({'width': this.status.width, 'height': this.status.height}); 1698 }, 1699 _addUiClass: function() { 1700 if(this.ancestorJq.length) { 1701 this.ancestorJq.addClass(this.status.cssClass); 1702 } 1703 }, 1704 _removeUiClass: function() { 1705 if(this.ancestorJq.length) { 1706 this.ancestorJq.removeClass(this.status.cssClass); 1707 } 1708 }, 1709 _updateSize: function() { 1710 // The poster uses show/hide so can simply resize it. 1711 this.internal.poster.jq.css({'width': this.status.width, 'height': this.status.height}); 1712 1713 // Video html or flash resized if necessary at this time. 1714 if(!this.status.waitForPlay) { 1715 if(this.html.active && this.status.video) { // Only if video media 1716 this.internal.video.jq.css({'width': this.status.width, 'height': this.status.height}); 1717 } 1718 else if(this.flash.active) { 1719 this.internal.flash.jq.css({'width': this.status.width, 'height': this.status.height}); 1720 } 1721 } 1722 }, 1723 _updateAutohide: function() { 1724 var self = this, 1725 event = "mousemove.jPlayer", 1726 namespace = ".jPlayerAutohide", 1727 eventType = event + namespace, 1728 handler = function() { 1729 self.css.jq.gui.fadeIn(self.options.autohide.fadeIn, function() { 1730 clearTimeout(self.internal.autohideId); 1731 self.internal.autohideId = setTimeout( function() { 1732 self.css.jq.gui.fadeOut(self.options.autohide.fadeOut); 1733 }, self.options.autohide.hold); 1734 }); 1735 }; 1736 1737 clearTimeout(this.internal.autohideId); 1738 this.element.unbind(namespace); 1739 if(this.css.jq.gui.length) { 1740 this.css.jq.gui.unbind(namespace); 1741 if(this.options.fullScreen && this.options.autohide.full || !this.options.fullScreen && this.options.autohide.restored) { 1742 this.element.bind(eventType, handler); 1743 this.css.jq.gui.bind(eventType, handler); 1744 this.css.jq.gui.hide(); 1745 } else { 1746 this.css.jq.gui.stop(true, true).show(); // Need the stop() otherwise a change screen mode during the GUI fade out hides the GUI in the other mode. 1747 } 1748 } 1749 }, 1750 fullScreen: function() { 1751 this._setOption("fullScreen", true); 1752 }, 1753 restoreScreen: function() { 1754 this._setOption("fullScreen", false); 1755 }, 1756 _html_initMedia: function() { 1757 if(this.status.srcSet && !this.status.waitForPlay) { 1758 this.htmlElement.media.pause(); 1759 } 1760 if(this.options.preload !== 'none') { 1761 this._html_load(); 1762 } 1763 this._trigger($.jPlayer.event.timeupdate); // The flash generates this event for its solution. 1764 }, 1765 _html_setAudio: function(media) { 1766 var self = this; 1767 // Always finds a format due to checks in setMedia() 1768 $.each(this.formats, function(priority, format) { 1769 if(self.html.support[format] && media[format]) { 1770 self.status.src = media[format]; 1771 self.status.format[format] = true; 1772 self.status.formatType = format; 1773 return false;
1774 } 1775 }); 1776 this.htmlElement.media = this.htmlElement.audio; 1777 this._html_initMedia(); 1778 }, 1779 _html_setVideo: function(media) { 1780 var self = this; 1781 // Always finds a format due to checks in setMedia() 1782 $.each(this.formats, function(priority, format) { 1783 if(self.html.support[format] && media[format]) { 1784 self.status.src = media[format]; 1785 self.status.format[format] = true; 1786 self.status.formatType = format; 1787 return false; 1788 } 1789 }); 1790 this.htmlElement.media = this.htmlElement.video; 1791 this._html_initMedia(); 1792 }, 1793 _html_clearMedia: function() { 1794 if(this.htmlElement.media) { 1795 if(this.htmlElement.media.id === this.internal.video.id) { 1796 this.internal.video.jq.css({'width':'0px', 'height':'0px'}); 1797 } 1798 this.htmlElement.media.pause(); 1799 this.htmlElement.media.src = ""; 1800 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. 1801 } 1802 }, 1803 _html_load: function() { 1804 if(this.status.waitForLoad) { 1805 this.status.waitForLoad = false; 1806 this.htmlElement.media.src = this.status.src; 1807 this.htmlElement.media.load(); 1808 } 1809 clearTimeout(this.internal.htmlDlyCmdId); 1810 }, 1811 _html_play: function(time) { 1812 var self = this; 1813 this._html_load(); // Loads if required and clears any delayed commands. 1814 1815 this.htmlElement.media.play(); // Before currentTime attempt otherwise Firefox 4 Beta never loads. 1816 1817 if(!isNaN(time)) { 1818 try { 1819 this.htmlElement.media.currentTime = time; 1820 } catch(err) { 1821 this.internal.htmlDlyCmdId = setTimeout(function() { 1822 self.play(time); 1823 }, 100); 1824 return; // Cancel execution and wait for the delayed command. 1825 } 1826 } 1827 this._html_checkWaitForPlay(); 1828 }, 1829 _html_pause: function(time) { 1830 var self = this; 1831 1832 if(time > 0) { // We do not want the stop() command, which does pause(0), causing a load operation. 1833 this._html_load(); // Loads if required and clears any delayed commands. 1834 } else { 1835 clearTimeout(this.internal.htmlDlyCmdId); 1836 } 1837 1838 // Order of these commands is important for Safari (Win) and IE9. Pause then change currentTime. 1839 this.htmlElement.media.pause(); 1840 1841 if(!isNaN(time)) { 1842 try { 1843 this.htmlElement.media.currentTime = time; 1844 } catch(err) { 1845 this.internal.htmlDlyCmdId = setTimeout(function() { 1846 self.pause(time); 1847 }, 100); 1848 return; // Cancel execution and wait for the delayed command. 1849 } 1850 } 1851 if(time > 0) { // Avoids a setMedia() followed by stop() or pause(0) hiding the video play button. 1852 this._html_checkWaitForPlay(); 1853 } 1854 }, 1855 _html_playHead: function(percent) { 1856 var self = this; 1857 this._html_load(); // Loads if required and clears any delayed commands. 1858 try { 1859 if((typeof this.htmlElement.media.seekable === "object") && (this.htmlElement.media.seekable.length > 0)) { 1860 this.htmlElement.media.currentTime = percent * this.htmlElement.media.seekable.end(this.htmlElement.media.seekable.length-1) / 100; 1861 } else if(this.htmlElement.media.duration > 0 && !isNaN(this.htmlElement.media.duration)) { 1862 this.htmlElement.media.currentTime = percent * this.htmlElement.media.duration / 100; 1863 } else { 1864 throw "e"; 1865 } 1866 } catch(err) { 1867 this.internal.htmlDlyCmdId = setTimeout(function() { 1868 self.playHead(percent); 1869 }, 100); 1870 return; // Cancel execution and wait for the delayed command. 1871 } 1872 if(!this.status.waitForLoad) { 1873 this._html_checkWaitForPlay(); 1874 } 1875 }, 1876 _html_checkWaitForPlay: function() { 1877 if(this.status.waitForPlay) { 1878 this.status.waitForPlay = false; 1879 if(this.css.jq.videoPlay.length) { 1880 this.css.jq.videoPlay.hide(); 1881 } 1882 if(this.status.video) { 1883 this.internal.poster.jq.hide(); 1884 this.internal.video.jq.css({'width': this.status.width, 'height': this.status.height}); 1885 } 1886 } 1887 }, 1888 _html_volume: function(v) { 1889 if(this.html.audio.available) { 1890 this.htmlElement.audio.volume = v; 1891 } 1892 if(this.html.video.available) { 1893 this.htmlElement.video.volume = v; 1894 } 1895 }, 1896 _html_mute: function(m) { 1897 if(this.html.audio.available) { 1898 this.htmlElement.audio.muted = m; 1899 } 1900 if(this.html.video.available) { 1901 this.htmlElement.video.muted = m; 1902 } 1903 }, 1904 _flash_setAudio: function(media) { 1905 var self = this; 1906 try { 1907 // Always finds a format due to checks in setMedia() 1908 $.each(this.formats, function(priority, format) { 1909 if(self.flash.support[format] && media[format]) { 1910 switch (format) { 1911 case "m4a" : 1912 case "fla" : 1913 self._getMovie().fl_setAudio_m4a(media[format]); 1914 break; 1915 case "mp3" : 1916 self._getMovie().fl_setAudio_mp3(media[format]); 1917 break; 1918 } 1919 self.status.src = media[format]; 1920 self.status.format[format] = true; 1921 self.status.formatType = format; 1922 return false;
vendor: 9,623 bytes, lines 1923-2195
1923 } 1924 }); 1925 1926 if(this.options.preload === 'auto') { 1927 this._flash_load(); 1928 this.status.waitForLoad = false; 1929 } 1930 } catch(err) { this._flashError(err); } 1931 }, 1932 _flash_setVideo: function(media) { 1933 var self = this; 1934 try { 1935 // Always finds a format due to checks in setMedia() 1936 $.each(this.formats, function(priority, format) { 1937 if(self.flash.support[format] && media[format]) { 1938 switch (format) { 1939 case "m4v" : 1940 case "flv" : 1941 self._getMovie().fl_setVideo_m4v(media[format]); 1942 break; 1943 } 1944 self.status.src = media[format]; 1945 self.status.format[format] = true; 1946 self.status.formatType = format; 1947 return false; 1948 } 1949 }); 1950 1951 if(this.options.preload === 'auto') { 1952 this._flash_load(); 1953 this.status.waitForLoad = false; 1954 } 1955 } catch(err) { this._flashError(err); } 1956 }, 1957 _flash_clearMedia: function() { 1958 this.internal.flash.jq.css({'width':'0px', 'height':'0px'}); // Must do via CSS as setting attr() to zero causes a jQuery error in IE. 1959 try { 1960 this._getMovie().fl_clearMedia(); 1961 } catch(err) { this._flashError(err); } 1962 }, 1963 _flash_load: function() { 1964 try { 1965 this._getMovie().fl_load(); 1966 } catch(err) { this._flashError(err); } 1967 this.status.waitForLoad = false; 1968 }, 1969 _flash_play: function(time) { 1970 try { 1971 this._getMovie().fl_play(time); 1972 } catch(err) { this._flashError(err); } 1973 this.status.waitForLoad = false; 1974 this._flash_checkWaitForPlay(); 1975 }, 1976 _flash_pause: function(time) { 1977 try { 1978 this._getMovie().fl_pause(time); 1979 } catch(err) { this._flashError(err); } 1980 if(time > 0) { // Avoids a setMedia() followed by stop() or pause(0) hiding the video play button. 1981 this.status.waitForLoad = false; 1982 this._flash_checkWaitForPlay(); 1983 } 1984 }, 1985 _flash_playHead: function(p) { 1986 try { 1987 this._getMovie().fl_play_head(p); 1988 } catch(err) { this._flashError(err); } 1989 if(!this.status.waitForLoad) { 1990 this._flash_checkWaitForPlay(); 1991 } 1992 }, 1993 _flash_checkWaitForPlay: function() { 1994 if(this.status.waitForPlay) { 1995 this.status.waitForPlay = false; 1996 if(this.css.jq.videoPlay.length) { 1997 this.css.jq.videoPlay.hide(); 1998 } 1999 if(this.status.video) { 2000 this.internal.poster.jq.hide(); 2001 this.internal.flash.jq.css({'width': this.status.width, 'height': this.status.height}); 2002 } 2003 } 2004 }, 2005 _flash_volume: function(v) { 2006 try { 2007 this._getMovie().fl_volume(v); 2008 } catch(err) { this._flashError(err); } 2009 }, 2010 _flash_mute: function(m) { 2011 try { 2012 this._getMovie().fl_mute(m); 2013 } catch(err) { this._flashError(err); } 2014 }, 2015 _getMovie: function() { 2016 return document[this.internal.flash.id]; 2017 }, 2018 _checkForFlash: function (version) { 2019 // Function checkForFlash adapted from FlashReplace by Robert Nyman 2020 // http://code.google.com/p/flashreplace/ 2021 var flashIsInstalled = false; 2022 var flash; 2023 if(window.ActiveXObject){ 2024 try{ 2025 flash = new ActiveXObject(("ShockwaveFlash.ShockwaveFlash." + version)); 2026 flashIsInstalled = true; 2027 } 2028 catch(e){ 2029 // Throws an error if the version isn't available 2030 } 2031 } 2032 else if(navigator.plugins && navigator.mimeTypes.length > 0){ 2033 flash = navigator.plugins["Shockwave Flash"]; 2034 if(flash){ 2035 var flashVersion = navigator.plugins["Shockwave Flash"].description.replace(/.*\s(\d+\.\d+).*/, "$1"); 2036 if(flashVersion >= version){ 2037 flashIsInstalled = true; 2038 } 2039 } 2040 } 2041 return flashIsInstalled; 2042 }, 2043 _validString: function(url) { 2044 return (url && typeof url === "string"); // Empty strings return false 2045 }, 2046 _limitValue: function(value, min, max) { 2047 return (value < min) ? min : ((value > max) ? max : value); 2048 }, 2049 _urlNotSetError: function(context) { 2050 this._error( { 2051 type: $.jPlayer.error.URL_NOT_SET, 2052 context: context, 2053 message: $.jPlayer.errorMsg.URL_NOT_SET, 2054 hint: $.jPlayer.errorHint.URL_NOT_SET 2055 }); 2056 }, 2057 _flashError: function(error) { 2058 var errorType; 2059 if(!this.internal.ready) { 2060 errorType = "FLASH"; 2061 } else { 2062 errorType = "FLASH_DISABLED"; 2063 } 2064 this._error( { 2065 type: $.jPlayer.error[errorType], 2066 context: this.internal.flash.swf, 2067 message: $.jPlayer.errorMsg[errorType] + error.message, 2068 hint: $.jPlayer.errorHint[errorType] 2069 }); 2070 2071 }, 2072 _error: function(error) { 2073 this._trigger($.jPlayer.event.error, error); 2074 if(this.options.errorAlerts) { 2075 this._alert("Error!" + (error.message ? "\n\n" + error.message : "") + (error.hint ? "\n\n" + error.hint : "") + "\n\nContext: " + error.context); 2076 } 2077 }, 2078 _warning: function(warning) { 2079 this._trigger($.jPlayer.event.warning, undefined, warning); 2080 if(this.options.warningAlerts) { 2081 this._alert("Warning!" + (warning.message ? "\n\n" + warning.message : "") + (warning.hint ? "\n\n" + warning.hint : "") + "\n\nContext: " + warning.context); 2082 } 2083 }, 2084 _alert: function(message) { 2085 alert("jPlayer " + this.version.script + " : id='" + this.internal.self.id +"' : " + message); 2086 }, 2087 _emulateHtmlBridge: function() { 2088 var self = this, 2089 methods = $.jPlayer.emulateMethods; 2090 2091 // Emulate methods on jPlayer's DOM element. 2092 $.each( $.jPlayer.emulateMethods.split(/\s+/g), function(i, name) { 2093 self.internal.domNode[name] = function(arg) { 2094 self[name](arg); 2095 }; 2096 2097 }); 2098 2099 // Bubble jPlayer events to its DOM element. 2100 $.each($.jPlayer.event, function(eventName,eventType) { 2101 var nativeEvent = true; 2102 $.each( $.jPlayer.reservedEvent.split(/\s+/g), function(i, name) { 2103 if(name === eventName) { 2104 nativeEvent = false; 2105 return false; 2106 } 2107 }); 2108 if(nativeEvent) { 2109 self.element.bind(eventType + ".jPlayer.jPlayerHtml", function() { // With .jPlayer & .jPlayerHtml namespaces. 2110 self._emulateHtmlUpdate(); 2111 var domEvent = document.createEvent("Event"); 2112 domEvent.initEvent(eventName, false, true); 2113 self.internal.domNode.dispatchEvent(domEvent); 2114 }); 2115 } 2116 // The error event would require a special case 2117 }); 2118 2119 // IE9 has a readyState property on all elements. The document should have it, but all (except media) elements inherit it in IE9. This conflicts with Popcorn, which polls the readyState. 2120 }, 2121 _emulateHtmlUpdate: function() { 2122 var self = this; 2123 2124 $.each( $.jPlayer.emulateStatus.split(/\s+/g), function(i, name) { 2125 self.internal.domNode[name] = self.status[name]; 2126 }); 2127 $.each( $.jPlayer.emulateOptions.split(/\s+/g), function(i, name) { 2128 self.internal.domNode[name] = self.options[name]; 2129 }); 2130 }, 2131 _destroyHtmlBridge: function() { 2132 var self = this; 2133 2134 // Bridge event handlers are also removed by destroy() through .jPlayer namespace. 2135 this.element.unbind(".jPlayerHtml"); // Remove all event handlers created by the jPlayer bridge. So you can change the emulateHtml option. 2136 2137 // Remove the methods and properties 2138 var emulated = $.jPlayer.emulateMethods + " " + $.jPlayer.emulateStatus + " " + $.jPlayer.emulateOptions; 2139 $.each( emulated.split(/\s+/g), function(i, name) { 2140 delete self.internal.domNode[name]; 2141 }); 2142 } 2143 }; 2144 2145 $.jPlayer.error = { 2146 FLASH: "e_flash", 2147 FLASH_DISABLED: "e_flash_disabled", 2148 NO_SOLUTION: "e_no_solution", 2149 NO_SUPPORT: "e_no_support", 2150 URL: "e_url", 2151 URL_NOT_SET: "e_url_not_set", 2152 VERSION: "e_version" 2153 }; 2154 2155 $.jPlayer.errorMsg = { 2156 FLASH: "jPlayer's Flash fallback is not configured correctly, or a command was issued before the jPlayer Ready event. Details: ", // Used in: _flashError() 2157 FLASH_DISABLED: "jPlayer's Flash fallback has been disabled by the browser due to the CSS rules you have used. Details: ", // Used in: _flashError() 2158 NO_SOLUTION: "No solution can be found by jPlayer in this browser. Neither HTML nor Flash can be used.", // Used in: _init() 2159 NO_SUPPORT: "It is not possible to play any media format provided in setMedia() on this browser using your current options.", // Used in: setMedia() 2160 URL: "Media URL could not be loaded.", // Used in: jPlayerFlashEvent() and _addHtmlEventListeners() 2161 URL_NOT_SET: "Attempt to issue media playback commands, while no media url is set.", // Used in: load(), play(), pause(), stop() and playHead() 2162 VERSION: "jPlayer " + $.jPlayer.prototype.version.script + " needs Jplayer.swf version " + $.jPlayer.prototype.version.needFlash + " but found " // Used in: jPlayerReady() 2163 }; 2164 2165 $.jPlayer.errorHint = { 2166 FLASH: "Check your swfPath option and that Jplayer.swf is there.", 2167 FLASH_DISABLED: "Check that you have not display:none; the jPlayer entity or any ancestor.", 2168 NO_SOLUTION: "Review the jPlayer options: support and supplied.", 2169 NO_SUPPORT: "Video or audio formats defined in the supplied option are missing.", 2170 URL: "Check media URL is valid.", 2171 URL_NOT_SET: "Use setMedia() to set the media URL.", 2172 VERSION: "Update jPlayer files." 2173 }; 2174 2175 $.jPlayer.warning = { 2176 CSS_SELECTOR_COUNT: "e_css_selector_count", 2177 CSS_SELECTOR_METHOD: "e_css_selector_method", 2178 CSS_SELECTOR_STRING: "e_css_selector_string", 2179 OPTION_KEY: "e_option_key" 2180 }; 2181 2182 $.jPlayer.warningMsg = { 2183 CSS_SELECTOR_COUNT: "The number of css selectors found did not equal one: ", 2184 CSS_SELECTOR_METHOD: "The methodName given in jPlayer('cssSelector') is not a valid jPlayer method.", 2185 CSS_SELECTOR_STRING: "The methodCssSelector given in jPlayer('cssSelector') is not a String or is empty.", 2186 OPTION_KEY: "The option requested in jPlayer('option') is undefined." 2187 }; 2188 2189 $.jPlayer.warningHint = { 2190 CSS_SELECTOR_COUNT: "Check your css selector and the ancestor.", 2191 CSS_SELECTOR_METHOD: "Check your method name.", 2192 CSS_SELECTOR_STRING: "Check your css selector is a string.", 2193 OPTION_KEY: "Check your option name." 2194 }; 2195})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.