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.

659 lines
18 KiB

  1. /*!
  2. * # Semantic UI 2.1.6 - Video
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2015 Contributors
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. ;(function ($, window, document, undefined) {
  12. "use strict";
  13. $.fn.embed = 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. returnedValue
  23. ;
  24. $allModules
  25. .each(function() {
  26. var
  27. settings = ( $.isPlainObject(parameters) )
  28. ? $.extend(true, {}, $.fn.embed.settings, parameters)
  29. : $.extend({}, $.fn.embed.settings),
  30. selector = settings.selector,
  31. className = settings.className,
  32. sources = settings.sources,
  33. error = settings.error,
  34. metadata = settings.metadata,
  35. namespace = settings.namespace,
  36. templates = settings.templates,
  37. eventNamespace = '.' + namespace,
  38. moduleNamespace = 'module-' + namespace,
  39. $window = $(window),
  40. $module = $(this),
  41. $placeholder = $module.find(selector.placeholder),
  42. $icon = $module.find(selector.icon),
  43. $embed = $module.find(selector.embed),
  44. element = this,
  45. instance = $module.data(moduleNamespace),
  46. module
  47. ;
  48. module = {
  49. initialize: function() {
  50. module.debug('Initializing embed');
  51. module.determine.autoplay();
  52. module.create();
  53. module.bind.events();
  54. module.instantiate();
  55. },
  56. instantiate: function() {
  57. module.verbose('Storing instance of module', module);
  58. instance = module;
  59. $module
  60. .data(moduleNamespace, module)
  61. ;
  62. },
  63. destroy: function() {
  64. module.verbose('Destroying previous instance of embed');
  65. module.reset();
  66. $module
  67. .removeData(moduleNamespace)
  68. .off(eventNamespace)
  69. ;
  70. },
  71. refresh: function() {
  72. module.verbose('Refreshing selector cache');
  73. $placeholder = $module.find(selector.placeholder);
  74. $icon = $module.find(selector.icon);
  75. $embed = $module.find(selector.embed);
  76. },
  77. bind: {
  78. events: function() {
  79. if( module.has.placeholder() ) {
  80. module.debug('Adding placeholder events');
  81. $module
  82. .on('click' + eventNamespace, selector.placeholder, module.createAndShow)
  83. .on('click' + eventNamespace, selector.icon, module.createAndShow)
  84. ;
  85. }
  86. }
  87. },
  88. create: function() {
  89. var
  90. placeholder = module.get.placeholder()
  91. ;
  92. if(placeholder) {
  93. module.createPlaceholder();
  94. }
  95. else {
  96. module.createAndShow();
  97. }
  98. },
  99. createPlaceholder: function(placeholder) {
  100. var
  101. icon = module.get.icon(),
  102. url = module.get.url(),
  103. embed = module.generate.embed(url)
  104. ;
  105. placeholder = placeholder || module.get.placeholder();
  106. $module.html( templates.placeholder(placeholder, icon) );
  107. module.debug('Creating placeholder for embed', placeholder, icon);
  108. },
  109. createEmbed: function(url) {
  110. module.refresh();
  111. url = url || module.get.url();
  112. $embed = $('<div/>')
  113. .addClass(className.embed)
  114. .html( module.generate.embed(url) )
  115. .appendTo($module)
  116. ;
  117. settings.onCreate.call(element, url);
  118. module.debug('Creating embed object', $embed);
  119. },
  120. createAndShow: function() {
  121. module.createEmbed();
  122. module.show();
  123. },
  124. // sets new embed
  125. change: function(source, id, url) {
  126. module.debug('Changing video to ', source, id, url);
  127. $module
  128. .data(metadata.source, source)
  129. .data(metadata.id, id)
  130. .data(metadata.url, url)
  131. ;
  132. module.create();
  133. },
  134. // clears embed
  135. reset: function() {
  136. module.debug('Clearing embed and showing placeholder');
  137. module.remove.active();
  138. module.remove.embed();
  139. module.showPlaceholder();
  140. settings.onReset.call(element);
  141. },
  142. // shows current embed
  143. show: function() {
  144. module.debug('Showing embed');
  145. module.set.active();
  146. settings.onDisplay.call(element);
  147. },
  148. hide: function() {
  149. module.debug('Hiding embed');
  150. module.showPlaceholder();
  151. },
  152. showPlaceholder: function() {
  153. module.debug('Showing placeholder image');
  154. module.remove.active();
  155. settings.onPlaceholderDisplay.call(element);
  156. },
  157. get: {
  158. id: function() {
  159. return settings.id || $module.data(metadata.id);
  160. },
  161. placeholder: function() {
  162. return settings.placeholder || $module.data(metadata.placeholder);
  163. },
  164. icon: function() {
  165. return (settings.icon)
  166. ? settings.icon
  167. : ($module.data(metadata.icon) !== undefined)
  168. ? $module.data(metadata.icon)
  169. : module.determine.icon()
  170. ;
  171. },
  172. source: function(url) {
  173. return (settings.source)
  174. ? settings.source
  175. : ($module.data(metadata.source) !== undefined)
  176. ? $module.data(metadata.source)
  177. : module.determine.source()
  178. ;
  179. },
  180. type: function() {
  181. var source = module.get.source();
  182. return (sources[source] !== undefined)
  183. ? sources[source].type
  184. : false
  185. ;
  186. },
  187. url: function() {
  188. return (settings.url)
  189. ? settings.url
  190. : ($module.data(metadata.url) !== undefined)
  191. ? $module.data(metadata.url)
  192. : module.determine.url()
  193. ;
  194. }
  195. },
  196. determine: {
  197. autoplay: function() {
  198. if(module.should.autoplay()) {
  199. settings.autoplay = true;
  200. }
  201. },
  202. source: function(url) {
  203. var
  204. matchedSource = false
  205. ;
  206. url = url || module.get.url();
  207. if(url) {
  208. $.each(sources, function(name, source) {
  209. if(url.search(source.domain) !== -1) {
  210. matchedSource = name;
  211. return false;
  212. }
  213. });
  214. }
  215. return matchedSource;
  216. },
  217. icon: function() {
  218. var
  219. source = module.get.source()
  220. ;
  221. return (sources[source] !== undefined)
  222. ? sources[source].icon
  223. : false
  224. ;
  225. },
  226. url: function() {
  227. var
  228. id = settings.id || $module.data(metadata.id),
  229. source = settings.source || $module.data(metadata.source),
  230. url
  231. ;
  232. url = (sources[source] !== undefined)
  233. ? sources[source].url.replace('{id}', id)
  234. : false
  235. ;
  236. if(url) {
  237. $module.data(metadata.url, url);
  238. }
  239. return url;
  240. }
  241. },
  242. set: {
  243. active: function() {
  244. $module.addClass(className.active);
  245. }
  246. },
  247. remove: {
  248. active: function() {
  249. $module.removeClass(className.active);
  250. },
  251. embed: function() {
  252. $embed.empty();
  253. }
  254. },
  255. encode: {
  256. parameters: function(parameters) {
  257. var
  258. urlString = [],
  259. index
  260. ;
  261. for (index in parameters) {
  262. urlString.push( encodeURIComponent(index) + '=' + encodeURIComponent( parameters[index] ) );
  263. }
  264. return urlString.join('&amp;');
  265. }
  266. },
  267. generate: {
  268. embed: function(url) {
  269. module.debug('Generating embed html');
  270. var
  271. source = module.get.source(),
  272. html,
  273. parameters
  274. ;
  275. url = module.get.url(url);
  276. if(url) {
  277. parameters = module.generate.parameters(source);
  278. html = templates.iframe(url, parameters);
  279. }
  280. else {
  281. module.error(error.noURL, $module);
  282. }
  283. return html;
  284. },
  285. parameters: function(source, extraParameters) {
  286. var
  287. parameters = (sources[source] && sources[source].parameters !== undefined)
  288. ? sources[source].parameters(settings)
  289. : {}
  290. ;
  291. extraParameters = extraParameters || settings.parameters;
  292. if(extraParameters) {
  293. parameters = $.extend({}, parameters, extraParameters);
  294. }
  295. parameters = settings.onEmbed(parameters);
  296. return module.encode.parameters(parameters);
  297. }
  298. },
  299. has: {
  300. placeholder: function() {
  301. return settings.placeholder || $module.data(metadata.placeholder);
  302. }
  303. },
  304. should: {
  305. autoplay: function() {
  306. return (settings.autoplay === 'auto')
  307. ? (settings.placeholder || $module.data(metadata.placeholder) !== undefined)
  308. : settings.autoplay
  309. ;
  310. }
  311. },
  312. is: {
  313. video: function() {
  314. return module.get.type() == 'video';
  315. }
  316. },
  317. setting: function(name, value) {
  318. module.debug('Changing setting', name, value);
  319. if( $.isPlainObject(name) ) {
  320. $.extend(true, settings, name);
  321. }
  322. else if(value !== undefined) {
  323. settings[name] = value;
  324. }
  325. else {
  326. return settings[name];
  327. }
  328. },
  329. internal: function(name, value) {
  330. if( $.isPlainObject(name) ) {
  331. $.extend(true, module, name);
  332. }
  333. else if(value !== undefined) {
  334. module[name] = value;
  335. }
  336. else {
  337. return module[name];
  338. }
  339. },
  340. debug: function() {
  341. if(settings.debug) {
  342. if(settings.performance) {
  343. module.performance.log(arguments);
  344. }
  345. else {
  346. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  347. module.debug.apply(console, arguments);
  348. }
  349. }
  350. },
  351. verbose: function() {
  352. if(settings.verbose && settings.debug) {
  353. if(settings.performance) {
  354. module.performance.log(arguments);
  355. }
  356. else {
  357. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  358. module.verbose.apply(console, arguments);
  359. }
  360. }
  361. },
  362. error: function() {
  363. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  364. module.error.apply(console, arguments);
  365. },
  366. performance: {
  367. log: function(message) {
  368. var
  369. currentTime,
  370. executionTime,
  371. previousTime
  372. ;
  373. if(settings.performance) {
  374. currentTime = new Date().getTime();
  375. previousTime = time || currentTime;
  376. executionTime = currentTime - previousTime;
  377. time = currentTime;
  378. performance.push({
  379. 'Name' : message[0],
  380. 'Arguments' : [].slice.call(message, 1) || '',
  381. 'Element' : element,
  382. 'Execution Time' : executionTime
  383. });
  384. }
  385. clearTimeout(module.performance.timer);
  386. module.performance.timer = setTimeout(module.performance.display, 500);
  387. },
  388. display: function() {
  389. var
  390. title = settings.name + ':',
  391. totalTime = 0
  392. ;
  393. time = false;
  394. clearTimeout(module.performance.timer);
  395. $.each(performance, function(index, data) {
  396. totalTime += data['Execution Time'];
  397. });
  398. title += ' ' + totalTime + 'ms';
  399. if(moduleSelector) {
  400. title += ' \'' + moduleSelector + '\'';
  401. }
  402. if($allModules.length > 1) {
  403. title += ' ' + '(' + $allModules.length + ')';
  404. }
  405. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  406. console.groupCollapsed(title);
  407. if(console.table) {
  408. console.table(performance);
  409. }
  410. else {
  411. $.each(performance, function(index, data) {
  412. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  413. });
  414. }
  415. console.groupEnd();
  416. }
  417. performance = [];
  418. }
  419. },
  420. invoke: function(query, passedArguments, context) {
  421. var
  422. object = instance,
  423. maxDepth,
  424. found,
  425. response
  426. ;
  427. passedArguments = passedArguments || queryArguments;
  428. context = element || context;
  429. if(typeof query == 'string' && object !== undefined) {
  430. query = query.split(/[\. ]/);
  431. maxDepth = query.length - 1;
  432. $.each(query, function(depth, value) {
  433. var camelCaseValue = (depth != maxDepth)
  434. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  435. : query
  436. ;
  437. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  438. object = object[camelCaseValue];
  439. }
  440. else if( object[camelCaseValue] !== undefined ) {
  441. found = object[camelCaseValue];
  442. return false;
  443. }
  444. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  445. object = object[value];
  446. }
  447. else if( object[value] !== undefined ) {
  448. found = object[value];
  449. return false;
  450. }
  451. else {
  452. module.error(error.method, query);
  453. return false;
  454. }
  455. });
  456. }
  457. if ( $.isFunction( found ) ) {
  458. response = found.apply(context, passedArguments);
  459. }
  460. else if(found !== undefined) {
  461. response = found;
  462. }
  463. if($.isArray(returnedValue)) {
  464. returnedValue.push(response);
  465. }
  466. else if(returnedValue !== undefined) {
  467. returnedValue = [returnedValue, response];
  468. }
  469. else if(response !== undefined) {
  470. returnedValue = response;
  471. }
  472. return found;
  473. }
  474. };
  475. if(methodInvoked) {
  476. if(instance === undefined) {
  477. module.initialize();
  478. }
  479. module.invoke(query);
  480. }
  481. else {
  482. if(instance !== undefined) {
  483. instance.invoke('destroy');
  484. }
  485. module.initialize();
  486. }
  487. })
  488. ;
  489. return (returnedValue !== undefined)
  490. ? returnedValue
  491. : this
  492. ;
  493. };
  494. $.fn.embed.settings = {
  495. name : 'Embed',
  496. namespace : 'embed',
  497. debug : false,
  498. verbose : false,
  499. performance : true,
  500. icon : false,
  501. source : false,
  502. url : false,
  503. id : false,
  504. // standard video settings
  505. autoplay : 'auto',
  506. color : '#444444',
  507. hd : true,
  508. brandedUI : false,
  509. // additional parameters to include with the embed
  510. parameters: false,
  511. onDisplay : function() {},
  512. onPlaceholderDisplay : function() {},
  513. onReset : function() {},
  514. onCreate : function(url) {},
  515. onEmbed : function(parameters) {
  516. return parameters;
  517. },
  518. metadata : {
  519. id : 'id',
  520. icon : 'icon',
  521. placeholder : 'placeholder',
  522. source : 'source',
  523. url : 'url'
  524. },
  525. error : {
  526. noURL : 'No URL specified',
  527. method : 'The method you called is not defined'
  528. },
  529. className : {
  530. active : 'active',
  531. embed : 'embed'
  532. },
  533. selector : {
  534. embed : '.embed',
  535. placeholder : '.placeholder',
  536. icon : '.icon'
  537. },
  538. sources: {
  539. youtube: {
  540. name : 'youtube',
  541. type : 'video',
  542. icon : 'video play',
  543. domain : 'youtube.com',
  544. url : '//www.youtube.com/embed/{id}',
  545. parameters: function(settings) {
  546. return {
  547. autohide : !settings.brandedUI,
  548. autoplay : settings.autoplay,
  549. color : settings.colors || undefined,
  550. hq : settings.hd,
  551. jsapi : settings.api,
  552. modestbranding : !settings.brandedUI
  553. };
  554. }
  555. },
  556. vimeo: {
  557. name : 'vimeo',
  558. type : 'video',
  559. icon : 'video play',
  560. domain : 'vimeo.com',
  561. url : '//player.vimeo.com/video/{id}',
  562. parameters: function(settings) {
  563. return {
  564. api : settings.api,
  565. autoplay : settings.autoplay,
  566. byline : settings.brandedUI,
  567. color : settings.colors || undefined,
  568. portrait : settings.brandedUI,
  569. title : settings.brandedUI
  570. };
  571. }
  572. }
  573. },
  574. templates: {
  575. iframe : function(url, parameters) {
  576. return ''
  577. + '<iframe src="' + url + '?' + parameters + '"'
  578. + ' width="100%" height="100%"'
  579. + ' frameborder="0" scrolling="no" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'
  580. ;
  581. },
  582. placeholder : function(image, icon) {
  583. var
  584. html = ''
  585. ;
  586. if(icon) {
  587. html += '<i class="' + icon + ' icon"></i>';
  588. }
  589. if(image) {
  590. html += '<img class="placeholder" src="' + image + '">';
  591. }
  592. return html;
  593. }
  594. },
  595. // NOT YET IMPLEMENTED
  596. api : true,
  597. onPause : function() {},
  598. onPlay : function() {},
  599. onStop : function() {}
  600. };
  601. })( jQuery, window, document );