jquery.jplayer.inspector.js 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. * jPlayerInspector Plugin for jPlayer (2.0.0+) Plugin for jQuery JavaScript Library
  3. * http://www.happyworm.com/jquery/jplayer
  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: 1.0.3
  12. * Date: 7th August 2011
  13. *
  14. * For use with jPlayer Version: 2.0.29
  15. *
  16. * Note: Declare inspector instances after jPlayer instances. ie., Otherwise the jPlayer instance is nonsense.
  17. */
  18. (function($, undefined) {
  19. $.jPlayerInspector = {};
  20. $.jPlayerInspector.i = 0;
  21. $.jPlayerInspector.defaults = {
  22. jPlayer: undefined, // The jQuery selector of the jPlayer instance to inspect.
  23. idPrefix: "jplayer_inspector_",
  24. visible: false
  25. };
  26. var methods = {
  27. init: function(options) {
  28. var self = this;
  29. var $this = $(this);
  30. var config = $.extend({}, $.jPlayerInspector.defaults, options);
  31. $(this).data("jPlayerInspector", config);
  32. config.id = $(this).attr("id");
  33. config.jPlayerId = config.jPlayer.attr("id");
  34. config.windowId = config.idPrefix + "window_" + $.jPlayerInspector.i;
  35. config.statusId = config.idPrefix + "status_" + $.jPlayerInspector.i;
  36. config.configId = config.idPrefix + "config_" + $.jPlayerInspector.i;
  37. config.toggleId = config.idPrefix + "toggle_" + $.jPlayerInspector.i;
  38. config.eventResetId = config.idPrefix + "event_reset_" + $.jPlayerInspector.i;
  39. config.updateId = config.idPrefix + "update_" + $.jPlayerInspector.i;
  40. config.eventWindowId = config.idPrefix + "event_window_" + $.jPlayerInspector.i;
  41. config.eventId = {};
  42. config.eventJq = {};
  43. config.eventTimeout = {};
  44. config.eventOccurrence = {};
  45. $.each($.jPlayer.event, function(eventName,eventType) {
  46. config.eventId[eventType] = config.idPrefix + "event_" + eventName + "_" + $.jPlayerInspector.i;
  47. config.eventOccurrence[eventType] = 0;
  48. });
  49. var structure =
  50. '<p><a href="#" id="' + config.toggleId + '">' + (config.visible ? "Hide" : "Show") + '</a> jPlayer Inspector</p>'
  51. + '<div id="' + config.windowId + '">'
  52. + '<div id="' + config.statusId + '"></div>'
  53. + '<div id="' + config.eventWindowId + '" style="padding:5px 5px 0 5px;background-color:#eee;border:1px dotted #000;">'
  54. + '<p style="margin:0 0 10px 0;"><strong>jPlayer events that have occurred over the past 1 second:</strong>'
  55. + '<br />(Backgrounds: <span style="padding:0 5px;background-color:#eee;border:1px dotted #000;">Never occurred</span> <span style="padding:0 5px;background-color:#fff;border:1px dotted #000;">Occurred before</span> <span style="padding:0 5px;background-color:#9f9;border:1px dotted #000;">Occurred</span> <span style="padding:0 5px;background-color:#ff9;border:1px dotted #000;">Multiple occurrences</span> <a href="#" id="' + config.eventResetId + '">reset</a>)</p>';
  56. // MJP: Would use the next 3 lines for ease, but the events are just slapped on the page.
  57. // $.each($.jPlayer.event, function(eventName,eventType) {
  58. // structure += '<div id="' + config.eventId[eventType] + '" style="float:left;">' + eventName + '</div>';
  59. // });
  60. var eventStyle = "float:left;margin:0 5px 5px 0;padding:0 5px;border:1px dotted #000;";
  61. // MJP: Doing it longhand so order and layout easier to control.
  62. structure +=
  63. '<div id="' + config.eventId[$.jPlayer.event.ready] + '" style="' + eventStyle + '"></div>'
  64. + '<div id="' + config.eventId[$.jPlayer.event.flashreset] + '" style="' + eventStyle + '"></div>'
  65. + '<div id="' + config.eventId[$.jPlayer.event.resize] + '" style="' + eventStyle + '"></div>'
  66. + '<div id="' + config.eventId[$.jPlayer.event.repeat] + '" style="' + eventStyle + '"></div>'
  67. + '<div id="' + config.eventId[$.jPlayer.event.click] + '" style="' + eventStyle + '"></div>'
  68. + '<div id="' + config.eventId[$.jPlayer.event.error] + '" style="' + eventStyle + '"></div>'
  69. + '<div id="' + config.eventId[$.jPlayer.event.warning] + '" style="' + eventStyle + '"></div>'
  70. + '<div id="' + config.eventId[$.jPlayer.event.loadstart] + '" style="clear:left;' + eventStyle + '"></div>'
  71. + '<div id="' + config.eventId[$.jPlayer.event.progress] + '" style="' + eventStyle + '"></div>'
  72. + '<div id="' + config.eventId[$.jPlayer.event.timeupdate] + '" style="' + eventStyle + '"></div>'
  73. + '<div id="' + config.eventId[$.jPlayer.event.volumechange] + '" style="' + eventStyle + '"></div>'
  74. + '<div id="' + config.eventId[$.jPlayer.event.play] + '" style="clear:left;' + eventStyle + '"></div>'
  75. + '<div id="' + config.eventId[$.jPlayer.event.pause] + '" style="' + eventStyle + '"></div>'
  76. + '<div id="' + config.eventId[$.jPlayer.event.waiting] + '" style="' + eventStyle + '"></div>'
  77. + '<div id="' + config.eventId[$.jPlayer.event.playing] + '" style="' + eventStyle + '"></div>'
  78. + '<div id="' + config.eventId[$.jPlayer.event.seeking] + '" style="' + eventStyle + '"></div>'
  79. + '<div id="' + config.eventId[$.jPlayer.event.seeked] + '" style="' + eventStyle + '"></div>'
  80. + '<div id="' + config.eventId[$.jPlayer.event.ended] + '" style="' + eventStyle + '"></div>'
  81. + '<div id="' + config.eventId[$.jPlayer.event.loadeddata] + '" style="clear:left;' + eventStyle + '"></div>'
  82. + '<div id="' + config.eventId[$.jPlayer.event.loadedmetadata] + '" style="' + eventStyle + '"></div>'
  83. + '<div id="' + config.eventId[$.jPlayer.event.canplay] + '" style="' + eventStyle + '"></div>'
  84. + '<div id="' + config.eventId[$.jPlayer.event.canplaythrough] + '" style="' + eventStyle + '"></div>'
  85. + '<div id="' + config.eventId[$.jPlayer.event.suspend] + '" style="clear:left;' + eventStyle + '"></div>'
  86. + '<div id="' + config.eventId[$.jPlayer.event.abort] + '" style="' + eventStyle + '"></div>'
  87. + '<div id="' + config.eventId[$.jPlayer.event.emptied] + '" style="' + eventStyle + '"></div>'
  88. + '<div id="' + config.eventId[$.jPlayer.event.stalled] + '" style="' + eventStyle + '"></div>'
  89. + '<div id="' + config.eventId[$.jPlayer.event.ratechange] + '" style="' + eventStyle + '"></div>'
  90. + '<div id="' + config.eventId[$.jPlayer.event.durationchange] + '" style="' + eventStyle + '"></div>'
  91. + '<div style="clear:both"></div>';
  92. // MJP: Would like a check here in case we missed an event.
  93. // MJP: Check fails, since it is not on the page yet.
  94. /* $.each($.jPlayer.event, function(eventName,eventType) {
  95. if($("#" + config.eventId[eventType])[0] === undefined) {
  96. structure += '<div id="' + config.eventId[eventType] + '" style="clear:left;' + eventStyle + '">' + eventName + '</div>';
  97. }
  98. });
  99. */
  100. structure +=
  101. '</div>'
  102. + '<p><a href="#" id="' + config.updateId + '">Update</a> jPlayer Inspector</p>'
  103. + '<div id="' + config.configId + '"></div>'
  104. + '</div>';
  105. $(this).html(structure);
  106. config.windowJq = $("#" + config.windowId);
  107. config.statusJq = $("#" + config.statusId);
  108. config.configJq = $("#" + config.configId);
  109. config.toggleJq = $("#" + config.toggleId);
  110. config.eventResetJq = $("#" + config.eventResetId);
  111. config.updateJq = $("#" + config.updateId);
  112. $.each($.jPlayer.event, function(eventName,eventType) {
  113. config.eventJq[eventType] = $("#" + config.eventId[eventType]);
  114. config.eventJq[eventType].text(eventName + " (" + config.eventOccurrence[eventType] + ")"); // Sets the text to the event name and (0);
  115. config.jPlayer.bind(eventType + ".jPlayerInspector", function(e) {
  116. config.eventOccurrence[e.type]++;
  117. if(config.eventOccurrence[e.type] > 1) {
  118. config.eventJq[e.type].css("background-color","#ff9");
  119. } else {
  120. config.eventJq[e.type].css("background-color","#9f9");
  121. }
  122. config.eventJq[e.type].text(eventName + " (" + config.eventOccurrence[e.type] + ")");
  123. // The timer to handle the color
  124. clearTimeout(config.eventTimeout[e.type]);
  125. config.eventTimeout[e.type] = setTimeout(function() {
  126. config.eventJq[e.type].css("background-color","#fff");
  127. }, 1000);
  128. // The timer to handle the occurences.
  129. setTimeout(function() {
  130. config.eventOccurrence[e.type]--;
  131. config.eventJq[e.type].text(eventName + " (" + config.eventOccurrence[e.type] + ")");
  132. }, 1000);
  133. if(config.visible) { // Update the status, if inspector open.
  134. $this.jPlayerInspector("updateStatus");
  135. }
  136. });
  137. });
  138. config.jPlayer.bind($.jPlayer.event.ready + ".jPlayerInspector", function(e) {
  139. $this.jPlayerInspector("updateConfig");
  140. });
  141. config.toggleJq.click(function() {
  142. if(config.visible) {
  143. $(this).text("Show");
  144. config.windowJq.hide();
  145. config.statusJq.empty();
  146. config.configJq.empty();
  147. } else {
  148. $(this).text("Hide");
  149. config.windowJq.show();
  150. config.updateJq.click();
  151. }
  152. config.visible = !config.visible;
  153. $(this).blur();
  154. return false;
  155. });
  156. config.eventResetJq.click(function() {
  157. $.each($.jPlayer.event, function(eventName,eventType) {
  158. config.eventJq[eventType].css("background-color","#eee");
  159. });
  160. $(this).blur();
  161. return false;
  162. });
  163. config.updateJq.click(function() {
  164. $this.jPlayerInspector("updateStatus");
  165. $this.jPlayerInspector("updateConfig");
  166. return false;
  167. });
  168. if(!config.visible) {
  169. config.windowJq.hide();
  170. } else {
  171. // config.updateJq.click();
  172. }
  173. $.jPlayerInspector.i++;
  174. return this;
  175. },
  176. destroy: function() {
  177. $(this).data("jPlayerInspector") && $(this).data("jPlayerInspector").jPlayer.unbind(".jPlayerInspector");
  178. $(this).empty();
  179. },
  180. updateConfig: function() { // This displays information about jPlayer's configuration in inspector
  181. var jPlayerInfo = "<p>This jPlayer instance is running in your browser where:<br />"
  182. for(i = 0; i < $(this).data("jPlayerInspector").jPlayer.data("jPlayer").solutions.length; i++) {
  183. var solution = $(this).data("jPlayerInspector").jPlayer.data("jPlayer").solutions[i];
  184. jPlayerInfo += "&nbsp;jPlayer's <strong>" + solution + "</strong> solution is";
  185. if($(this).data("jPlayerInspector").jPlayer.data("jPlayer")[solution].used) {
  186. jPlayerInfo += " being <strong>used</strong> and will support:<strong>";
  187. for(format in $(this).data("jPlayerInspector").jPlayer.data("jPlayer")[solution].support) {
  188. if($(this).data("jPlayerInspector").jPlayer.data("jPlayer")[solution].support[format]) {
  189. jPlayerInfo += " " + format;
  190. }
  191. }
  192. jPlayerInfo += "</strong><br />";
  193. } else {
  194. jPlayerInfo += " <strong>not required</strong><br />";
  195. }
  196. }
  197. jPlayerInfo += "</p>";
  198. if($(this).data("jPlayerInspector").jPlayer.data("jPlayer").html.active) {
  199. if($(this).data("jPlayerInspector").jPlayer.data("jPlayer").flash.active) {
  200. jPlayerInfo += "<strong>Problem with jPlayer since both HTML5 and Flash are active.</strong>";
  201. } else {
  202. jPlayerInfo += "The <strong>HTML5 is active</strong>.";
  203. }
  204. } else {
  205. if($(this).data("jPlayerInspector").jPlayer.data("jPlayer").flash.active) {
  206. jPlayerInfo += "The <strong>Flash is active</strong>.";
  207. } else {
  208. jPlayerInfo += "No solution is currently active. jPlayer needs a setMedia().";
  209. }
  210. }
  211. jPlayerInfo += "</p>";
  212. var formatType = $(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.formatType;
  213. jPlayerInfo += "<p><code>status.formatType = '" + formatType + "'</code><br />";
  214. if(formatType) {
  215. jPlayerInfo += "<code>Browser canPlay('" + $.jPlayer.prototype.format[formatType].codec + "')</code>";
  216. } else {
  217. jPlayerInfo += "</p>";
  218. }
  219. jPlayerInfo += "<p><code>status.src = '" + $(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.src + "'</code></p>";
  220. jPlayerInfo += "<p><code>status.media = {<br />";
  221. for(prop in $(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.media) {
  222. jPlayerInfo += "&nbsp;" + prop + ": " + $(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.media[prop] + "<br />"; // Some are strings
  223. }
  224. jPlayerInfo += "};</code></p>"
  225. + "<p>Raw browser test for HTML5 support. Should equal a function if HTML5 is available.<br />";
  226. if($(this).data("jPlayerInspector").jPlayer.data("jPlayer").html.audio.available) {
  227. jPlayerInfo += "<code>htmlElement.audio.canPlayType = " + (typeof $(this).data("jPlayerInspector").jPlayer.data("jPlayer").htmlElement.audio.canPlayType) +"</code><br />"
  228. }
  229. if($(this).data("jPlayerInspector").jPlayer.data("jPlayer").html.video.available) {
  230. jPlayerInfo += "<code>htmlElement.video.canPlayType = " + (typeof $(this).data("jPlayerInspector").jPlayer.data("jPlayer").htmlElement.video.canPlayType) +"</code>";
  231. }
  232. jPlayerInfo += "</p>";
  233. jPlayerInfo += "<p>This instance is using the constructor options:<br />"
  234. + "<code>$('#" + $(this).data("jPlayerInspector").jPlayer.data("jPlayer").internal.self.id + "').jPlayer({<br />"
  235. + "&nbsp;swfPath: '" + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "swfPath") + "',<br />"
  236. + "&nbsp;solution: '" + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "solution") + "',<br />"
  237. + "&nbsp;supplied: '" + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "supplied") + "',<br />"
  238. + "&nbsp;preload: '" + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "preload") + "',<br />"
  239. + "&nbsp;volume: " + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "volume") + ",<br />"
  240. + "&nbsp;muted: " + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "muted") + ",<br />"
  241. + "&nbsp;backgroundColor: '" + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "backgroundColor") + "',<br />"
  242. + "&nbsp;cssSelectorAncestor: '" + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "cssSelectorAncestor") + "',<br />"
  243. + "&nbsp;cssSelector: {";
  244. var cssSelector = $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "cssSelector");
  245. for(prop in cssSelector) {
  246. // jPlayerInfo += "<br />&nbsp;&nbsp;" + prop + ": '" + cssSelector[prop] + "'," // This works too of course, but want to use option method for deep keys.
  247. jPlayerInfo += "<br />&nbsp;&nbsp;" + prop + ": '" + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "cssSelector." + prop) + "',"
  248. }
  249. jPlayerInfo = jPlayerInfo.slice(0, -1); // Because the sloppy comma was bugging me.
  250. jPlayerInfo += "<br />&nbsp;},<br />"
  251. + "&nbsp;errorAlerts: " + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "errorAlerts") + ",<br />"
  252. + "&nbsp;warningAlerts: " + $(this).data("jPlayerInspector").jPlayer.jPlayer("option", "warningAlerts") + "<br />"
  253. + "});</code></p>";
  254. $(this).data("jPlayerInspector").configJq.html(jPlayerInfo);
  255. return this;
  256. },
  257. updateStatus: function() { // This displays information about jPlayer's status in the inspector
  258. $(this).data("jPlayerInspector").statusJq.html(
  259. "<p>jPlayer is " +
  260. ($(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.paused ? "paused" : "playing") +
  261. " at time: " + Math.floor($(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.currentTime*10)/10 + "s." +
  262. " (d: " + Math.floor($(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.duration*10)/10 + "s" +
  263. ", sp: " + Math.floor($(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.seekPercent) + "%" +
  264. ", cpr: " + Math.floor($(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.currentPercentRelative) + "%" +
  265. ", cpa: " + Math.floor($(this).data("jPlayerInspector").jPlayer.data("jPlayer").status.currentPercentAbsolute) + "%)</p>"
  266. );
  267. return this;
  268. }
  269. };
  270. $.fn.jPlayerInspector = function( method ) {
  271. // Method calling logic
  272. if ( methods[method] ) {
  273. return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
  274. } else if ( typeof method === 'object' || ! method ) {
  275. return methods.init.apply( this, arguments );
  276. } else {
  277. $.error( 'Method ' + method + ' does not exist on jQuery.jPlayerInspector' );
  278. }
  279. };
  280. })(jQuery);