plugin.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * Youtube Embed Plugin
  3. *
  4. * @author Jonnas Fonini <contato@fonini.net>
  5. * @version 2.0.0
  6. */
  7. ( function() {
  8. CKEDITOR.plugins.add( 'youtube',
  9. {
  10. lang: [ 'en', 'pt', 'ja', 'hu', 'it', 'fr', 'tr', 'ru', 'de', 'ar', 'nl', 'pl', 'vi', 'zh', 'el'],
  11. init: function( editor )
  12. {
  13. editor.addCommand( 'youtube', new CKEDITOR.dialogCommand( 'youtube', {
  14. allowedContent: 'iframe[!width,!height,!src,!frameborder,!allowfullscreen]; object param[*]'
  15. }));
  16. editor.ui.addButton( 'Youtube',
  17. {
  18. label : editor.lang.youtube.button,
  19. toolbar : 'insert',
  20. command : 'youtube',
  21. icon : this.path + 'images/icon.png'
  22. });
  23. CKEDITOR.dialog.add( 'youtube', function ( instance )
  24. {
  25. var video;
  26. return {
  27. title : editor.lang.youtube.title,
  28. minWidth : 500,
  29. minHeight : 200,
  30. contents :
  31. [{
  32. id : 'youtubePlugin',
  33. expand : true,
  34. elements :
  35. [{
  36. id : 'txtEmbed',
  37. type : 'textarea',
  38. label : editor.lang.youtube.txtEmbed,
  39. autofocus : 'autofocus',
  40. onChange : function ( api )
  41. {
  42. handleEmbedChange( this, api );
  43. },
  44. onKeyUp : function ( api )
  45. {
  46. handleEmbedChange( this, api );
  47. },
  48. validate : function ()
  49. {
  50. if ( this.isEnabled() )
  51. {
  52. if ( !this.getValue() )
  53. {
  54. alert( editor.lang.youtube.noCode );
  55. return false;
  56. }
  57. else
  58. if ( this.getValue().length === 0 || this.getValue().indexOf( '//' ) === -1 )
  59. {
  60. alert( editor.lang.youtube.invalidEmbed );
  61. return false;
  62. }
  63. }
  64. }
  65. },
  66. {
  67. type : 'html',
  68. html : editor.lang.youtube.or + '<hr>'
  69. },
  70. {
  71. type : 'hbox',
  72. widths : [ '70%', '15%', '15%' ],
  73. children :
  74. [
  75. {
  76. id : 'txtUrl',
  77. type : 'text',
  78. label : editor.lang.youtube.txtUrl,
  79. onChange : function ( api )
  80. {
  81. handleLinkChange( this, api );
  82. },
  83. onKeyUp : function ( api )
  84. {
  85. handleLinkChange( this, api );
  86. },
  87. validate : function ()
  88. {
  89. if ( this.isEnabled() )
  90. {
  91. if ( !this.getValue() )
  92. {
  93. alert( editor.lang.youtube.noCode );
  94. return false;
  95. }
  96. else{
  97. video = ytVidId(this.getValue());
  98. if ( this.getValue().length === 0 || video === false)
  99. {
  100. alert( editor.lang.youtube.invalidUrl );
  101. return false;
  102. }
  103. }
  104. }
  105. }
  106. },
  107. {
  108. type : 'text',
  109. id : 'txtWidth',
  110. width : '60px',
  111. label : editor.lang.youtube.txtWidth,
  112. 'default' : editor.config.youtube_width != null ? editor.config.youtube_width : '640',
  113. validate : function ()
  114. {
  115. if ( this.getValue() )
  116. {
  117. var width = parseInt ( this.getValue() ) || 0;
  118. if ( width === 0 )
  119. {
  120. alert( editor.lang.youtube.invalidWidth );
  121. return false;
  122. }
  123. }
  124. else {
  125. alert( editor.lang.youtube.noWidth );
  126. return false;
  127. }
  128. }
  129. },
  130. {
  131. type : 'text',
  132. id : 'txtHeight',
  133. width : '60px',
  134. label : editor.lang.youtube.txtHeight,
  135. 'default' : editor.config.youtube_height != null ? editor.config.youtube_height : '360',
  136. validate : function ()
  137. {
  138. if ( this.getValue() )
  139. {
  140. var height = parseInt ( this.getValue() ) || 0;
  141. if ( height === 0 )
  142. {
  143. alert( editor.lang.youtube.invalidHeight );
  144. return false;
  145. }
  146. }
  147. else {
  148. alert( editor.lang.youtube.noHeight );
  149. return false;
  150. }
  151. }
  152. }
  153. ]
  154. },
  155. {
  156. type : 'hbox',
  157. widths : [ '100%' ],
  158. children :
  159. [
  160. {
  161. id : 'chkResponsive',
  162. type : 'checkbox',
  163. label : editor.lang.youtube.txtResponsive,
  164. 'default' : editor.config.youtube_responsive != null ? editor.config.youtube_responsive : false
  165. }
  166. ]
  167. },
  168. {
  169. type : 'hbox',
  170. widths : [ '55%', '45%' ],
  171. children :
  172. [
  173. {
  174. id : 'chkRelated',
  175. type : 'checkbox',
  176. 'default' : editor.config.youtube_related != null ? editor.config.youtube_related : true,
  177. label : editor.lang.youtube.chkRelated
  178. },
  179. {
  180. id : 'chkOlderCode',
  181. type : 'checkbox',
  182. 'default' : editor.config.youtube_older != null ? editor.config.youtube_older : false,
  183. label : editor.lang.youtube.chkOlderCode
  184. }
  185. ]
  186. },
  187. {
  188. type : 'hbox',
  189. widths : [ '55%', '45%' ],
  190. children :
  191. [
  192. {
  193. id : 'chkPrivacy',
  194. type : 'checkbox',
  195. label : editor.lang.youtube.chkPrivacy,
  196. 'default' : editor.config.youtube_privacy != null ? editor.config.youtube_privacy : false
  197. },
  198. {
  199. id : 'chkAutoplay',
  200. type : 'checkbox',
  201. 'default' : editor.config.youtube_autoplay != null ? editor.config.youtube_autoplay : false,
  202. label : editor.lang.youtube.chkAutoplay
  203. }
  204. ]
  205. },
  206. {
  207. type : 'hbox',
  208. widths : [ '55%', '45%'],
  209. children :
  210. [
  211. {
  212. id : 'txtStartAt',
  213. type : 'text',
  214. label : editor.lang.youtube.txtStartAt,
  215. validate : function ()
  216. {
  217. if ( this.getValue() )
  218. {
  219. var str = this.getValue();
  220. if ( !/^(?:(?:([01]?\d|2[0-3]):)?([0-5]?\d):)?([0-5]?\d)$/i.test( str ) )
  221. {
  222. alert( editor.lang.youtube.invalidTime );
  223. return false;
  224. }
  225. }
  226. }
  227. },
  228. {
  229. id: 'empty',
  230. type: 'html',
  231. html: ''
  232. }
  233. ]
  234. }
  235. ]
  236. }
  237. ],
  238. onOk: function()
  239. {
  240. var content = '';
  241. var responsiveStyle='';
  242. if ( this.getContentElement( 'youtubePlugin', 'txtEmbed' ).isEnabled() )
  243. {
  244. content = this.getValueOf( 'youtubePlugin', 'txtEmbed' );
  245. }
  246. else {
  247. var url = '//', params = [], startSecs;
  248. var width = this.getValueOf( 'youtubePlugin', 'txtWidth' );
  249. var height = this.getValueOf( 'youtubePlugin', 'txtHeight' );
  250. if ( this.getContentElement( 'youtubePlugin', 'chkPrivacy' ).getValue() === true )
  251. {
  252. url += 'www.youtube-nocookie.com/';
  253. }
  254. else {
  255. url += 'www.youtube.com/';
  256. }
  257. url += 'embed/' + video;
  258. if ( this.getContentElement( 'youtubePlugin', 'chkRelated' ).getValue() === false )
  259. {
  260. params.push('rel=0');
  261. }
  262. if ( this.getContentElement( 'youtubePlugin', 'chkAutoplay' ).getValue() === true )
  263. {
  264. params.push('autoplay=1');
  265. }
  266. startSecs = this.getValueOf( 'youtubePlugin', 'txtStartAt' );
  267. if ( startSecs ){
  268. var seconds = hmsToSeconds( startSecs );
  269. params.push('start=' + seconds);
  270. }
  271. if ( params.length > 0 )
  272. {
  273. url = url + '?' + params.join( '&' );
  274. }
  275. if ( this.getContentElement( 'youtubePlugin', 'chkResponsive').getValue() === true ) {
  276. content += '<div style="position:relative;padding-bottom:56.25%;padding-top:30px;height:0;overflow:hidden;">';
  277. responsiveStyle = 'style="position: absolute;top: 0;left: 0;width: 100%;height: 100%;"';
  278. }
  279. if ( this.getContentElement( 'youtubePlugin', 'chkOlderCode' ).getValue() === true )
  280. {
  281. url = url.replace('embed/', 'v/');
  282. url = url.replace(/&/g, '&amp;');
  283. if ( url.indexOf('?') === -1 )
  284. {
  285. url += '?';
  286. }
  287. else {
  288. url += '&amp;';
  289. }
  290. url += 'hl=' + (this.getParentEditor().config.language ? this.getParentEditor().config.language : 'en') + '&amp;version=3';
  291. content += '<object width="' + width + '" height="' + height + '" ' + responsiveStyle + '>';
  292. content += '<param name="movie" value="' + url + '"></param>';
  293. content += '<param name="allowFullScreen" value="true"></param>';
  294. content += '<param name="allowscriptaccess" value="always"></param>';
  295. content += '<embed src="' + url + '" type="application/x-shockwave-flash" ';
  296. content += 'width="' + width + '" height="' + height + '" '+ responsiveStyle + ' allowscriptaccess="always" ';
  297. content += 'allowfullscreen="true"></embed>';
  298. content += '</object>';
  299. }
  300. else {
  301. content += '<iframe width="' + width + '" height="' + height + '" src="' + url + '" ' + responsiveStyle;
  302. content += 'frameborder="0" allowfullscreen></iframe>';
  303. }
  304. if ( this.getContentElement( 'youtubePlugin', 'chkResponsive').getValue() === true ) {
  305. content += '</div>';
  306. }
  307. }
  308. var element = CKEDITOR.dom.element.createFromHtml( content );
  309. var instance = this.getParentEditor();
  310. instance.insertElement(element);
  311. }
  312. };
  313. });
  314. }
  315. });
  316. })();
  317. function handleLinkChange( el, api )
  318. {
  319. if ( el.getValue().length > 0 )
  320. {
  321. el.getDialog().getContentElement( 'youtubePlugin', 'txtEmbed' ).disable();
  322. }
  323. else {
  324. el.getDialog().getContentElement( 'youtubePlugin', 'txtEmbed' ).enable();
  325. }
  326. }
  327. function handleEmbedChange( el, api )
  328. {
  329. if ( el.getValue().length > 0 )
  330. {
  331. el.getDialog().getContentElement( 'youtubePlugin', 'txtUrl' ).disable();
  332. }
  333. else {
  334. el.getDialog().getContentElement( 'youtubePlugin', 'txtUrl' ).enable();
  335. }
  336. }
  337. /**
  338. * JavaScript function to match (and return) the video Id
  339. * of any valid Youtube Url, given as input string.
  340. * @author: Stephan Schmitz <eyecatchup@gmail.com>
  341. * @url: http://stackoverflow.com/a/10315969/624466
  342. */
  343. function ytVidId( url )
  344. {
  345. var p = /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;
  346. return ( url.match( p ) ) ? RegExp.$1 : false;
  347. }
  348. /**
  349. * Converts time in hms format to seconds only
  350. */
  351. function hmsToSeconds( time )
  352. {
  353. var arr = time.split(':'), s = 0, m = 1;
  354. while (arr.length > 0)
  355. {
  356. s += m * parseInt(arr.pop(), 10);
  357. m *= 60;
  358. }
  359. return s;
  360. }