embed.js 20 KB

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