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.

457 lines
13 KiB

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