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.

532 lines
15 KiB

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