You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

459 lines
13 KiB

  1. /* ******************************
  2. Module - Video Component
  3. Author: Jack Lukic
  4. Notes: First Commit June 30, 2012
  5. This is a video playlist and video embed plugin which helps
  6. provide helpers for adding embed code for vimeo and youtube and
  7. abstracting event handlers for each library
  8. ****************************** */
  9. ;(function ($, window, document, undefined) {
  10. $.fn.video = function(parameters) {
  11. var
  12. $allModules = $(this),
  13. settings = ( $.isPlainObject(parameters) )
  14. ? $.extend(true, {}, $.fn.video.settings, parameters)
  15. : $.fn.video.settings,
  16. moduleSelector = $allModules.selector || '',
  17. time = new Date().getTime(),
  18. performance = [],
  19. query = arguments[0],
  20. methodInvoked = (typeof query == 'string'),
  21. queryArguments = [].slice.call(arguments, 1),
  22. selector = settings.selector,
  23. className = settings.className,
  24. error = settings.error,
  25. metadata = settings.metadata,
  26. namespace = settings.namespace,
  27. eventNamespace = '.' + namespace,
  28. moduleNamespace = namespace + '-module',
  29. invokedResponse
  30. ;
  31. $allModules
  32. .each(function() {
  33. var
  34. $module = $(this),
  35. $placeholder = $module.find(selector.placeholder),
  36. $playButton = $module.find(selector.playButton),
  37. $embed = $module.find(selector.embed),
  38. element = this,
  39. instance = $module.data(moduleNamespace),
  40. module
  41. ;
  42. module = {
  43. initialize: function() {
  44. module.debug('Initializing video');
  45. $placeholder
  46. .on('click' + eventNamespace, module.play)
  47. ;
  48. $playButton
  49. .on('click' + eventNamespace, module.play)
  50. ;
  51. module.instantiate();
  52. },
  53. instantiate: function() {
  54. module.verbose('Storing instance of module', module);
  55. instance = module;
  56. $module
  57. .data(moduleNamespace, module)
  58. ;
  59. },
  60. destroy: function() {
  61. module.verbose('Destroying previous instance of video');
  62. $module
  63. .removeData(moduleNamespace)
  64. .off(eventNamespace)
  65. ;
  66. },
  67. // sets new video
  68. change: function(source, id, url) {
  69. module.debug('Changing video to ', source, id, url);
  70. $module
  71. .data(metadata.source, source)
  72. .data(metadata.id, id)
  73. .data(metadata.url, url)
  74. ;
  75. settings.onChange();
  76. },
  77. // clears video embed
  78. reset: function() {
  79. module.debug('Clearing video embed and showing placeholder');
  80. $module
  81. .removeClass(className.active)
  82. ;
  83. $embed
  84. .html(' ')
  85. ;
  86. $placeholder
  87. .show()
  88. ;
  89. settings.onReset();
  90. },
  91. // plays current video
  92. play: function() {
  93. module.debug('Playing video');
  94. var
  95. source = $module.data(metadata.source) || false,
  96. url = $module.data(metadata.url) || false,
  97. id = $module.data(metadata.id) || false
  98. ;
  99. $embed
  100. .html( module.generate.html(source, id, url) )
  101. ;
  102. $module
  103. .addClass(className.active)
  104. ;
  105. settings.onPlay();
  106. },
  107. generate: {
  108. // generates iframe html
  109. html: function(source, id, url) {
  110. module.debug('Generating embed html');
  111. var
  112. width = (settings.width == 'auto')
  113. ? $module.width()
  114. : settings.width,
  115. height = (settings.height == 'auto')
  116. ? $module.height()
  117. : settings.height,
  118. html
  119. ;
  120. if(source && id) {
  121. if(source == 'vimeo') {
  122. html = ''
  123. + '<iframe src="http://player.vimeo.com/video/' + id + '?=' + module.generate.url(source) + '"'
  124. + ' width="' + width + '" height="' + height + '"'
  125. + ' frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'
  126. ;
  127. }
  128. else if(source == 'youtube') {
  129. html = ''
  130. + '<iframe src="http://www.youtube.com/embed/' + id + '?=' + module.generate.url(source) + '"'
  131. + ' width="' + width + '" height="' + height + '"'
  132. + ' frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'
  133. ;
  134. }
  135. }
  136. else if(url) {
  137. html = ''
  138. + '<iframe src="' + url + '"'
  139. + ' width="' + width + '" height="' + height + '"'
  140. + ' frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'
  141. ;
  142. }
  143. else {
  144. module.error(error.noVideo);
  145. }
  146. return html;
  147. },
  148. // generate url parameters
  149. url: function(source) {
  150. var
  151. api = (settings.api)
  152. ? 1
  153. : 0,
  154. autoplay = (settings.autoplay)
  155. ? 1
  156. : 0,
  157. hd = (settings.hd)
  158. ? 1
  159. : 0,
  160. showUI = (settings.showUI)
  161. ? 1
  162. : 0,
  163. // opposite used for some params
  164. hideUI = !(settings.showUI)
  165. ? 1
  166. : 0,
  167. url = ''
  168. ;
  169. if(source == 'vimeo') {
  170. url = ''
  171. + 'api=' + api
  172. + '&amp;title=' + showUI
  173. + '&amp;byline=' + showUI
  174. + '&amp;portrait=' + showUI
  175. + '&amp;autoplay=' + autoplay
  176. ;
  177. if(settings.color) {
  178. url += '&amp;color=' + settings.color;
  179. }
  180. }
  181. if(source == 'ustream') {
  182. url = ''
  183. + 'autoplay=' + autoplay
  184. ;
  185. if(settings.color) {
  186. url += '&amp;color=' + settings.color;
  187. }
  188. }
  189. else if(source == 'youtube') {
  190. url = ''
  191. + 'enablejsapi=' + api
  192. + '&amp;autoplay=' + autoplay
  193. + '&amp;autohide=' + hideUI
  194. + '&amp;hq=' + hd
  195. + '&amp;modestbranding=1'
  196. ;
  197. if(settings.color) {
  198. url += '&amp;color=' + settings.color;
  199. }
  200. }
  201. return url;
  202. }
  203. },
  204. setting: function(name, value) {
  205. if(value !== undefined) {
  206. if( $.isPlainObject(name) ) {
  207. $.extend(true, settings, name);
  208. }
  209. else {
  210. settings[name] = value;
  211. }
  212. }
  213. else {
  214. return settings[name];
  215. }
  216. },
  217. internal: function(name, value) {
  218. if(value !== undefined) {
  219. if( $.isPlainObject(name) ) {
  220. $.extend(true, module, name);
  221. }
  222. else {
  223. module[name] = value;
  224. }
  225. }
  226. else {
  227. return module[name];
  228. }
  229. },
  230. debug: function() {
  231. if(settings.debug) {
  232. if(settings.performance) {
  233. module.performance.log(arguments);
  234. }
  235. else {
  236. module.debug = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
  237. module.debug.apply(console, arguments);
  238. }
  239. }
  240. },
  241. verbose: function() {
  242. if(settings.verbose && settings.debug) {
  243. if(settings.performance) {
  244. module.performance.log(arguments);
  245. }
  246. else {
  247. module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
  248. module.verbose.apply(console, arguments);
  249. }
  250. }
  251. },
  252. error: function() {
  253. module.error = Function.prototype.bind.call(console.error, console, settings.moduleName + ':');
  254. module.error.apply(console, arguments);
  255. },
  256. performance: {
  257. log: function(message) {
  258. var
  259. currentTime,
  260. executionTime,
  261. previousTime
  262. ;
  263. if(settings.performance) {
  264. currentTime = new Date().getTime();
  265. previousTime = time || currentTime;
  266. executionTime = currentTime - previousTime;
  267. time = currentTime;
  268. performance.push({
  269. 'Element' : element,
  270. 'Name' : message[0],
  271. 'Arguments' : [].slice.call(message, 1) || '',
  272. 'Execution Time' : executionTime
  273. });
  274. }
  275. clearTimeout(module.performance.timer);
  276. module.performance.timer = setTimeout(module.performance.display, 100);
  277. },
  278. display: function() {
  279. var
  280. title = settings.name + ':',
  281. totalTime = 0
  282. ;
  283. time = false;
  284. clearTimeout(module.performance.timer);
  285. $.each(performance, function(index, data) {
  286. totalTime += data['Execution Time'];
  287. });
  288. title += ' ' + totalTime + 'ms';
  289. if(moduleSelector) {
  290. title += ' \'' + moduleSelector + '\'';
  291. }
  292. if($allModules.size() > 1) {
  293. title += ' ' + '(' + $allModules.size() + ')';
  294. }
  295. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  296. console.groupCollapsed(title);
  297. if(console.table) {
  298. console.table(performance);
  299. }
  300. else {
  301. $.each(performance, function(index, data) {
  302. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  303. });
  304. }
  305. console.groupEnd();
  306. }
  307. performance = [];
  308. }
  309. },
  310. invoke: function(query, passedArguments, context) {
  311. var
  312. maxDepth,
  313. found,
  314. response
  315. ;
  316. passedArguments = passedArguments || queryArguments;
  317. context = element || context;
  318. if(typeof query == 'string' && instance !== undefined) {
  319. query = query.split(/[\. ]/);
  320. maxDepth = query.length - 1;
  321. $.each(query, function(depth, value) {
  322. var camelCaseValue = (depth != maxDepth)
  323. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  324. : query
  325. ;
  326. if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) {
  327. instance = instance[value];
  328. }
  329. else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) {
  330. instance = instance[camelCaseValue];
  331. }
  332. else if( instance[value] !== undefined ) {
  333. found = instance[value];
  334. return false;
  335. }
  336. else if( instance[camelCaseValue] !== undefined ) {
  337. found = instance[camelCaseValue];
  338. return false;
  339. }
  340. else {
  341. module.error(error.method);
  342. return false;
  343. }
  344. });
  345. }
  346. if ( $.isFunction( found ) ) {
  347. response = found.apply(context, passedArguments);
  348. }
  349. else if(found !== undefined) {
  350. response = found;
  351. }
  352. if($.isArray(invokedResponse)) {
  353. invokedResponse.push(response);
  354. }
  355. else if(typeof invokedResponse == 'string') {
  356. invokedResponse = [invokedResponse, response];
  357. }
  358. else if(response !== undefined) {
  359. invokedResponse = response;
  360. }
  361. return found;
  362. }
  363. };
  364. if(methodInvoked) {
  365. if(instance === undefined) {
  366. module.initialize();
  367. }
  368. module.invoke(query);
  369. }
  370. else {
  371. if(instance !== undefined) {
  372. module.destroy();
  373. }
  374. module.initialize();
  375. }
  376. })
  377. ;
  378. return (invokedResponse !== undefined)
  379. ? invokedResponse
  380. : this
  381. ;
  382. };
  383. $.fn.video.settings = {
  384. name : 'Video',
  385. namespace : 'video',
  386. debug : true,
  387. verbose : true,
  388. performance : true,
  389. metadata : {
  390. source : 'source',
  391. id : 'id',
  392. url : 'url'
  393. },
  394. onPlay : function(){},
  395. onReset : function(){},
  396. onChange : function(){},
  397. // callbacks not coded yet (needs to use jsapi)
  398. onPause : function() {},
  399. onStop : function() {},
  400. width : 'auto',
  401. height : 'auto',
  402. autoplay : false,
  403. color : '#442359',
  404. hd : true,
  405. showUI : false,
  406. api : true,
  407. error : {
  408. noVideo : 'No video specified',
  409. method : 'The method you called is not defined'
  410. },
  411. className : {
  412. active : 'active'
  413. },
  414. selector : {
  415. embed : '.embed',
  416. placeholder : '.placeholder',
  417. playButton : '.play'
  418. }
  419. };
  420. })( jQuery, window , document );