/* * jPlayerInspector Plugin for jPlayer Plugin for jQuery JavaScript Library * http://www.jplayer.org * * Copyright (c) 2009 - 2014 Happyworm Ltd * Licensed under the MIT license. * http://www.opensource.org/licenses/MIT * * Author: Mark J Panaghiston * Version: 1.0.5 * Date: 1st April 2014 * * For use with jPlayer Version: 2.6.0+ * * Note: Declare inspector instances after jPlayer instances. ie., Otherwise the jPlayer instance is nonsense. */ (function($, undefined) { $.jPlayerInspector = {}; $.jPlayerInspector.i = 0; $.jPlayerInspector.defaults = { jPlayer: undefined, // The jQuery selector of the jPlayer instance to inspect. idPrefix: "jplayer_inspector_", visible: false }; var methods = { init: function(options) { var self = this; var $this = $(this); var config = $.extend({}, $.jPlayerInspector.defaults, options); $(this).data("jPlayerInspector", config); config.id = $(this).attr("id"); config.jPlayerId = config.jPlayer.attr("id"); config.windowId = config.idPrefix + "window_" + $.jPlayerInspector.i; config.statusId = config.idPrefix + "status_" + $.jPlayerInspector.i; config.configId = config.idPrefix + "config_" + $.jPlayerInspector.i; config.toggleId = config.idPrefix + "toggle_" + $.jPlayerInspector.i; config.eventResetId = config.idPrefix + "event_reset_" + $.jPlayerInspector.i; config.updateId = config.idPrefix + "update_" + $.jPlayerInspector.i; config.eventWindowId = config.idPrefix + "event_window_" + $.jPlayerInspector.i; config.eventId = {}; config.eventJq = {}; config.eventTimeout = {}; config.eventOccurrence = {}; $.each($.jPlayer.event, function(eventName,eventType) { config.eventId[eventType] = config.idPrefix + "event_" + eventName + "_" + $.jPlayerInspector.i; config.eventOccurrence[eventType] = 0; }); var structure = '

' + (config.visible ? "Hide" : "Show") + ' jPlayer Inspector

' + '
' + '
' + '
' + '

jPlayer events that have occurred over the past 1 second:' + '
(Backgrounds: Never occurred Occurred before Occurred Multiple occurrences reset)

'; // MJP: Would use the next 3 lines for ease, but the events are just slapped on the page. // $.each($.jPlayer.event, function(eventName,eventType) { // structure += '
' + eventName + '
'; // }); var eventStyle = "float:left;margin:0 5px 5px 0;padding:0 5px;border:1px dotted #000;"; // MJP: Doing it longhand so order and layout easier to control. structure += '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
'; // MJP: Would like a check here in case we missed an event. // MJP: Check fails, since it is not on the page yet. /* $.each($.jPlayer.event, function(eventName,eventType) { if($("#" + config.eventId[eventType])[0] === undefined) { structure += '
' + eventName + '
'; } }); */ structure += '
' + '

Update jPlayer Inspector

' + '
' + '
'; $(this).html(structure); config.windowJq = $("#" + config.windowId); config.statusJq = $("#" + config.statusId); config.configJq = $("#" + config.configId); config.toggleJq = $("#" + config.toggleId); config.eventResetJq = $("#" + config.eventResetId); config.updateJq = $("#" + config.updateId); $.each($.jPlayer.event, function(eventName,eventType) { config.eventJq[eventType] = $("#" + config.eventId[eventType]); config.eventJq[eventType].text(eventName + " (" + config.eventOccurrence[eventType] + ")"); // Sets the text to the event name and (0); config.jPlayer.bind(eventType + ".jPlayerInspector", function(e) { config.eventOccurrence[e.type]++; if(config.eventOccurrence[e.type] > 1) { config.eventJq[e.type].css("background-color","#ff9"); } else { config.eventJq[e.type].css("background-color","#9f9"); } config.eventJq[e.type].text(eventName + " (" + config.eventOccurrence[e.type] + ")"); // The timer to handle the color clearTimeout(config.eventTimeout[e.type]); config.eventTimeout[e.type] = setTimeout(function() { config.eventJq[e.type].css("background-color","#fff"); }, 1000); // The timer to handle the occurences. setTimeout(function() { config.eventOccurrence[e.type]--; config.eventJq[e.type].text(eventName + " (" + config.eventOccurrence[e.type] + ")"); }, 1000); if(config.visible) { // Update the status, if inspector open. $this.jPlayerInspector("updateStatus"); } }); }); config.jPlayer.bind($.jPlayer.event.ready + ".jPlayerInspector", function(e) { $this.jPlayerInspector("updateConfig"); }); config.toggleJq.click(function() { if(config.visible) { $(this).text("Show"); config.windowJq.hide(); config.statusJq.empty(); config.configJq.empty(); } else { $(this).text("Hide"); config.windowJq.show(); config.updateJq.click(); } config.visible = !config.visible; $(this).blur(); return false; }); config.eventResetJq.click(function() { $.each($.jPlayer.event, function(eventName,eventType) { config.eventJq[eventType].css("background-color","#eee"); }); $(this).blur(); return false; }); config.updateJq.click(function() { $this.jPlayerInspector("updateStatus"); $this.jPlayerInspector("updateConfig"); return false; }); if(!config.visible) { config.windowJq.hide(); } else { // config.updateJq.click(); } $.jPlayerInspector.i++; return this; }, destroy: function() { $(this).data("jPlayerInspector") && $(this).data("jPlayerInspector").jPlayer.unbind(".jPlayerInspector"); $(this).empty(); }, updateConfig: function() { // This displays information about jPlayer's configuration in inspector var jPlayerInfo = "

This jPlayer instance is running in your browser where:
" for(i = 0; i < $(this).data("jPlayerInspector").jPlayer.data("jPlayer").solutions.length; i++) { var solution = $(this).data("jPlayerInspector").jPlayer.data("jPlayer").solutions[i]; jPlayerInfo += " jPlayer's " + solution + " solution is"; if($(this).data("jPlayerInspector").jPlayer.data("jPlayer")[solution].used) { jPlayerInfo += " being used and will support:"; for(format in $(this).data("jPlayerInspector").jPlayer.data("jPlayer")[solution].support) { if($(this).data("jPlayerInspector").jPlayer.data("jPlayer")[solution].support[format]) { jPlayerInfo += " " + format; } } jPlayerInfo += "
"; } else { jPlayerInfo += " not required
"; } } jPlayerInfo += "

"; if($(this).data("jPlayerInspector").jPlayer.data("jPlayer").html.active) { if($(this).data("jPlayerInspector").jPlayer.data("jPlayer").flash.active) { jPlayerInfo += "Problem with jPlayer since both HTML5 and Flash are active."; } else { jPlayerInfo += "The HTML5 is active."; } } else { if($(this).data("jPlayerInspector").jPlayer.data("jPlayer").flash.active) { jPlayerInfo += "The Flash is active."; } else { jPlayerInfo += "No solution is currently active. jPlayer needs a setMedia()."; } } jPlayerInfo += "

"; var formatType = $(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.formatType; jPlayerInfo += "

status.formatType = '" + formatType + "'
"; if(formatType) { jPlayerInfo += "Browser canPlay('" + $.jPlayer.prototype.format[formatType].codec + "')"; } else { jPlayerInfo += "

"; } jPlayerInfo += "

status.src = '" + $(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.src + "'

"; jPlayerInfo += "

status.media = {
"; for(prop in $(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.media) { jPlayerInfo += " " + prop + ": " + $(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.media[prop] + "
"; // Some are strings } jPlayerInfo += "};

" jPlayerInfo += "

"; jPlayerInfo += "status.videoWidth = '" + $(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.videoWidth + "'"; jPlayerInfo += " | status.videoHeight = '" + $(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.videoHeight + "'"; jPlayerInfo += "
status.width = '" + $(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.width + "'"; jPlayerInfo += " | status.height = '" + $(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.height + "'"; jPlayerInfo += "

"; + "

Raw browser test for HTML5 support. Should equal a function if HTML5 is available.
"; if($(this).data("jPlayerInspector").jPlayer.data("jPlayer").html.audio.available) { jPlayerInfo += "htmlElement.audio.canPlayType = " + (typeof $(this).data("jPlayerInspector").jPlayer.data("jPlayer").htmlElement.audio.canPlayType) +"
" } if($(this).data("jPlayerInspector").jPlayer.data("jPlayer").html.video.available) { jPlayerInfo += "htmlElement.video.canPlayType = " + (typeof $(this).data("jPlayerInspector").jPlayer.data("jPlayer").htmlElement.video.canPlayType) +""; } jPlayerInfo += "

"; jPlayerInfo += "

This instance is using the constructor options:
" + "$('#" + $(this).data("jPlayerInspector").jPlayer.data("jPlayer").internal.self.id + "').jPlayer({
" + " swfPath: '" + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "swfPath") + "',
" + " solution: '" + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "solution") + "',
" + " supplied: '" + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "supplied") + "',
" + " preload: '" + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "preload") + "',
" + " volume: " + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "volume") + ",
" + " muted: " + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "muted") + ",
" + " backgroundColor: '" + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "backgroundColor") + "',
" + " cssSelectorAncestor: '" + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "cssSelectorAncestor") + "',
" + " cssSelector: {"; var cssSelector = $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "cssSelector"); for(prop in cssSelector) { // jPlayerInfo += "
  " + prop + ": '" + cssSelector[prop] + "'," // This works too of course, but want to use option method for deep keys. jPlayerInfo += "
  " + prop + ": '" + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "cssSelector." + prop) + "'," } jPlayerInfo = jPlayerInfo.slice(0, -1); // Because the sloppy comma was bugging me. jPlayerInfo += "
 },
" + " errorAlerts: " + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "errorAlerts") + ",
" + " warningAlerts: " + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "warningAlerts") + "
" + "});

"; $(this).data("jPlayerInspector").configJq.html(jPlayerInfo); return this; }, updateStatus: function() { // This displays information about jPlayer's status in the inspector $(this).data("jPlayerInspector").statusJq.html( "

jPlayer is " + ($(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.paused ? "paused" : "playing") + " at time: " + Math.floor($(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.currentTime*10)/10 + "s." + " (d: " + Math.floor($(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.duration*10)/10 + "s" + ", sp: " + Math.floor($(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.seekPercent) + "%" + ", cpr: " + Math.floor($(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.currentPercentRelative) + "%" + ", cpa: " + Math.floor($(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.currentPercentAbsolute) + "%)

" ); return this; } }; $.fn.jPlayerInspector = function( method ) { // Method calling logic if ( methods[method] ) { return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 )); } else if ( typeof method === 'object' || ! method ) { return methods.init.apply( this, arguments ); } else { $.error( 'Method ' + method + ' does not exist on jQuery.jPlayerInspector' ); } }; })(jQuery);