trumbowyg.plugins.js 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355
  1. /* ===========================================================
  2. * trumbowyg.pasteImageKiss.js v1.0 basé sur trumbowyg.pasteImage.js v1.0
  3. * Basic base64 paste plugin for Trumbowyg
  4. * http://alex-d.github.com/Trumbowyg
  5. * ===========================================================
  6. * Author : Valentin CARRUESCO depuis Alexandre Demode (Alex-D)
  7. */
  8. (function ($) {
  9. 'use strict';
  10. $.extend(true, $.trumbowyg, {
  11. plugins: {
  12. pasteImageKiss: {
  13. init: function (trumbowyg) {
  14. trumbowyg.pasteHandlers.push(function (pasteEvent) {
  15. try {
  16. var items = (pasteEvent.originalEvent || pasteEvent).clipboardData.items,
  17. mustPreventDefault = false,
  18. reader;
  19. for (var i = items.length - 1; i >= 0; i -= 1) {
  20. if (items[i].type.match(/^image\//)) {
  21. var file = items[i].getAsFile();
  22. if(file.size > 5000 && !trumbowyg.o.allowBigPaste){
  23. //mode upload, fichier lourd
  24. if(trumbowyg.o.uploadAction){
  25. $.action({
  26. action : trumbowyg.o.uploadAction,
  27. stream : file,
  28. name : Date.now().getTime()+(Math.floor(Math.random() * Math.floor(1000)))+'.png'
  29. },function(response){
  30. trumbowyg.execCmd('insertHtml',response.html, false, true);
  31. });
  32. }else{
  33. //Si aucune action d'upload prévue
  34. trumbowyg.execCmd('insertHtml','<span class="text-danger">Image Trop lourde ('+file.size+' octets) et upload non implémenté</span>', false, true);
  35. }
  36. }else{
  37. //mode base 64 fichier léger
  38. reader = new FileReader();
  39. reader.onloadend = function (event) {
  40. var base64 = event.target.result;
  41. trumbowyg.execCmd('insertImage',base64, false, true);
  42. };
  43. reader.readAsDataURL(file);
  44. }
  45. mustPreventDefault = true;
  46. }
  47. }
  48. if (mustPreventDefault) {
  49. pasteEvent.stopPropagation();
  50. pasteEvent.preventDefault();
  51. }
  52. } catch (c) {
  53. }
  54. });
  55. }
  56. }
  57. }
  58. });
  59. })(jQuery);
  60. /* ===========================================================
  61. * trumbowyg.core.cleanpaste.js v1.0
  62. * Clean les balises word
  63. * ===========================================================
  64. * Authors : Valentin CARRUESCO
  65. */
  66. (function ($) {
  67. 'use strict';
  68. // clean editor
  69. // this will clean the inserted contents
  70. // it does a compare, before and after paste to determine the
  71. // pasted contents
  72. $.extend(true, $.trumbowyg, {
  73. plugins: {
  74. cleanPaste: {
  75. init: function (trumbowyg) {
  76. trumbowyg.pasteHandlers.push(function () {
  77. setTimeout(function () {
  78. try {
  79. trumbowyg.$ed.find("*").filter(function(){
  80. return /([^><]*):([^>]*)/i.test(this.nodeName);
  81. }).remove();
  82. } catch (c) {
  83. }
  84. }, 0);
  85. });
  86. }
  87. }
  88. }
  89. });
  90. })(jQuery);
  91. /* ===========================================================
  92. * trumbowyg drag & drop
  93. * Permet l'upload en drag & drop
  94. * ===========================================================
  95. * Authors : Valentin CARRUESCO
  96. */
  97. (function ($) {
  98. 'use strict';
  99. $.extend(true, $.trumbowyg, {
  100. plugins: {
  101. dragAndDrop: {
  102. init: function (trumbowyg) {
  103. //Attens que le dom soit chargé (sinon trumbowyg.$ed n'est pas accessible)
  104. trumbowyg.$c.on('tbwinit', function () {
  105. //test if d&d is enabled n browser
  106. var div = document.createElement('div');
  107. var dragAndDropEnabled = (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && 'FormData' in window && 'FileReader' in window;
  108. if (!dragAndDropEnabled) return;
  109. trumbowyg.$ed
  110. .off('click drag dragstart dragend dragenter dragleave drop dragover').on('click', function (e) {
  111. e.preventDefault();
  112. e.stopPropagation();
  113. })
  114. .on('drag dragstart dragend dragover dragenter dragleave drop', function (e) {
  115. e.preventDefault();
  116. e.stopPropagation();
  117. })
  118. .on('dragover dragenter', function () {
  119. trumbowyg.$ed.addClass('wysiwyg-dragover');
  120. })
  121. .on('dragleave dragend drop', function () {
  122. trumbowyg.$ed.removeClass('wysiwyg-dragover');
  123. })
  124. .on('drop', function (e) {
  125. var droppedFiles = e.originalEvent.dataTransfer.files;
  126. if(trumbowyg.o.uploadAction){
  127. $.each(droppedFiles, function (i, file) {
  128. var uid = btoa(file.name);
  129. trumbowyg.execCmd('insertHtml','<span class="text-muted wysiwyg-upload" data-uid="'+uid+'"><i class="fas fa-circle-notch fa-spin"></i> '+file.name+' envois en cours...</span>', false, true);
  130. $.action({
  131. action : trumbowyg.o.uploadAction,
  132. stream : file,
  133. name : file.name
  134. },function(response){
  135. $('.wysiwyg-upload[data-uid="'+uid+'"]').remove();
  136. trumbowyg.execCmd('insertHtml',response.html, false, true);
  137. },function(error){
  138. $('.wysiwyg-upload[data-uid="'+uid+'"]').remove();
  139. });
  140. });
  141. }else{
  142. //Si aucune action d'upload prévue
  143. trumbowyg.execCmd('insertHtml','<span class="text-danger">Upload non implémenté dans ce composant</span>', false, true);
  144. }
  145. });
  146. });
  147. }
  148. }
  149. }
  150. });
  151. })(jQuery);
  152. /**/
  153. /* ===========================================================
  154. * resize image
  155. * Permet le resize des images
  156. * ===========================================================
  157. * Authors : Valentin CARRUESCO
  158. */
  159. (function ($) {
  160. 'use strict';
  161. $.extend(true, $.trumbowyg, {
  162. plugins: {
  163. resizeImage: {
  164. init: function (trumbowyg) {
  165. //Attens que le dom soit chargé (sinon trumbowyg.$ed n'est pas accessible)
  166. trumbowyg.$c.on('tbwinit', function () {
  167. trumbowyg.$ed.on('click','img',function(){
  168. $(this).resizable({
  169. aspectRatio : true,
  170. resize : function(event, ui ){
  171. ui.originalElement.css({
  172. height : ui.size.height+'px',
  173. width : ui.size.width+'px'
  174. });
  175. }
  176. });
  177. });
  178. trumbowyg.$ed.click(function(e){
  179. if($(e.target).hasClass('ui-resizable')) return;
  180. trumbowyg.$ed.find('.ui-resizable').resizable('destroy');
  181. });
  182. });
  183. }
  184. }
  185. }
  186. });
  187. })(jQuery);
  188. /* ===========================================================
  189. * trumbowyg.fontfamily.js v1.2
  190. */
  191. (function ($) {
  192. 'use strict';
  193. $.extend(true, $.trumbowyg, {
  194. langs: {
  195. // jshint camelcase:false
  196. en: {
  197. fontFamily: 'Font'
  198. },
  199. da: {
  200. fontFamily: 'Skrifttype'
  201. },
  202. fr: {
  203. fontFamily: 'Police'
  204. },
  205. de: {
  206. fontFamily: 'Schriftart'
  207. },
  208. nl: {
  209. fontFamily: 'Lettertype'
  210. },
  211. tr: {
  212. fontFamily: 'Yazı Tipi'
  213. },
  214. zh_tw: {
  215. fontFamily: '字體',
  216. },
  217. pt_br: {
  218. fontFamily: 'Fonte',
  219. },
  220. ko: {
  221. fontFamily: '글꼴'
  222. },
  223. }
  224. });
  225. // jshint camelcase:true
  226. var defaultOptions = {
  227. fontList: [
  228. {name: 'Arial', family: 'Arial, Helvetica, sans-serif'},
  229. {name: 'Arial Black', family: 'Arial Black, Gadget, sans-serif'},
  230. {name: 'Comic Sans', family: 'Comic Sans MS, Textile, cursive, sans-serif'},
  231. {name: 'Courier New', family: 'Courier New, Courier, monospace'},
  232. {name: 'Georgia', family: 'Georgia, serif'},
  233. {name: 'Impact', family: 'Impact, Charcoal, sans-serif'},
  234. {name: 'Lucida Console', family: 'Lucida Console, Monaco, monospace'},
  235. {name: 'Lucida Sans', family: 'Lucida Sans Uncide, Lucida Grande, sans-serif'},
  236. {name: 'Palatino', family: 'Palatino Linotype, Book Antiqua, Palatino, serif'},
  237. {name: 'Tahoma', family: 'Tahoma, Geneva, sans-serif'},
  238. {name: 'Times New Roman', family: 'Times New Roman, Times, serif'},
  239. {name: 'Trebuchet', family: 'Trebuchet MS, Helvetica, sans-serif'},
  240. {name: 'Verdana', family: 'Verdana, Geneva, sans-serif'}
  241. ]
  242. };
  243. // Add dropdown with web safe fonts
  244. $.extend(true, $.trumbowyg, {
  245. plugins: {
  246. fontfamily: {
  247. init: function (trumbowyg) {
  248. trumbowyg.o.plugins.fontfamily = $.extend({},
  249. defaultOptions,
  250. trumbowyg.o.plugins.fontfamily || {}
  251. );
  252. trumbowyg.addBtnDef('fontfamily', {
  253. dropdown: buildDropdown(trumbowyg),
  254. hasIcon: false,
  255. text: trumbowyg.lang.fontFamily
  256. });
  257. }
  258. }
  259. }
  260. });
  261. function buildDropdown(trumbowyg) {
  262. var dropdown = [];
  263. $.each(trumbowyg.o.plugins.fontfamily.fontList, function (index, font) {
  264. trumbowyg.addBtnDef('fontfamily_' + index, {
  265. title: '<span style="font-family: ' + font.family + ';">' + font.name + '</span>',
  266. hasIcon: false,
  267. fn: function () {
  268. trumbowyg.execCmd('fontName', font.family, false);
  269. }
  270. });
  271. dropdown.push('fontfamily_' + index);
  272. });
  273. return dropdown;
  274. }
  275. })(jQuery);
  276. /* ===========================================================
  277. * trumbowyg.mention.js v1.0
  278. * Allow mention with @,# or any key
  279. * ===========================================================
  280. * Authors : Valentin CARRUESCO
  281. */
  282. (function ($) {
  283. 'use strict';
  284. var o = {
  285. //Supprime la totalité du mention si un backspace entame le mention
  286. autoDelete : true,
  287. //Ne déclenche la touche que si elle est précédée d'un espace, d'un saut de ligne ou d'une nouvelle balise
  288. triggerBreak : true
  289. };
  290. $.extend(true, $.trumbowyg, {
  291. plugins: {
  292. mention: {
  293. init: function (trumbowyg) {
  294. var object = this;
  295. object.altGrPressed = false;
  296. trumbowyg.o.plugins.mention = $.extend(true, {},o,trumbowyg.o.plugins.mention || {});
  297. var keyMap = {
  298. 48 : {
  299. label : '@',
  300. check : function(event){
  301. return object.altGrPressed;
  302. }
  303. },
  304. 51 : {
  305. label : '#',
  306. check : function(event){
  307. return object.altGrPressed;
  308. }
  309. }
  310. }
  311. $(trumbowyg.$ta).parent().on('keydown', function (e) {
  312. var code = e.which || e.keyCode ;
  313. //verifie si alt+gr est enfoncé
  314. if(code==18){
  315. object.altGrPressed = true;
  316. return;
  317. }
  318. //Supprime les mentions en totalité sur un backspace
  319. if(trumbowyg.o.plugins.mention.autoDelete && code==8){
  320. var editor = trumbowyg.$ed;
  321. var textarea = trumbowyg.$ta;
  322. textarea.trumbowyg('saveRange');
  323. if(!textarea.trumbowyg('getRange') || !textarea.trumbowyg('getRange').endContainer) return;
  324. var parent = $(textarea.trumbowyg('getRange').endContainer.parentElement);
  325. if(parent.attr('data-mention-type')!= null){
  326. parent.remove();
  327. editor.trigger('keyup');
  328. }
  329. }
  330. //if(Object.keys(trumbowyg.o.plugins.mention.keys).indexOf(""+code) == -1) return;
  331. if(keyMap[code] == null) return;
  332. var char = keyMap[code].label;
  333. if(!trumbowyg.o.plugins.mention.keys || Object.keys(trumbowyg.o.plugins.mention.keys).indexOf(char) == -1) return;
  334. if(keyMap[code].check && !keyMap[code].check(event)) return;
  335. var editor = trumbowyg.$ed;
  336. var textarea = trumbowyg.$ta;
  337. var range = trumbowyg.$ta.trumbowyg('getRange');
  338. var lastChar = !range || !range.startContainer || !range.startContainer.data ? '' : range.startContainer.data;
  339. lastChar = lastChar.length>0 ? lastChar.substring(lastChar.length-1) : '';
  340. //si le caractere trigger n'est pas lancé apres un espace ou un saut de ligne on ne fait rien
  341. if(trumbowyg.o.plugins.mention.triggerBreak && lastChar != '' && lastChar != ' ') return;
  342. var key = trumbowyg.o.plugins.mention.keys[char];
  343. if(!key.load) return;
  344. var data = {
  345. editor : editor,
  346. event : e,
  347. textarea : textarea,
  348. lastChar : lastChar
  349. }
  350. data.textarea.trumbowyg('saveRange');
  351. key.load(data);
  352. }).on('keyup', function (e) {
  353. var code = e.which || e.keyCode ;
  354. //désactive le altgr mode si relaché
  355. if(code==18){
  356. object.altGrPressed = false;
  357. return;
  358. }
  359. });
  360. }
  361. }
  362. }
  363. })
  364. })(jQuery);
  365. /**
  366. Font size core, ne pas upgrade !!
  367. */
  368. (function ($) {
  369. 'use strict';
  370. $.extend(true, $.trumbowyg, {
  371. langs: {
  372. fr: {
  373. fontsize: 'Taille de la police',
  374. fontsizes: {
  375. 'x-small': 'Très petit',
  376. 'small': 'Petit',
  377. 'medium': 'Normal',
  378. 'large': 'Grand',
  379. 'x-large': 'Très grand',
  380. 'custom': 'Taille personnalisée'
  381. },
  382. fontCustomSize: {
  383. title: 'Taille de police personnalisée',
  384. label: 'Taille de la police',
  385. value: '48px'
  386. }
  387. }
  388. }
  389. });
  390. // Add dropdown with font sizes
  391. $.extend(true, $.trumbowyg, {
  392. plugins: {
  393. fontsize: {
  394. init: function (trumbowyg) {
  395. trumbowyg.o.plugins.fontsize = $.extend({},
  396. {
  397. sizeList: [
  398. '8px',
  399. '9px',
  400. '10px',
  401. '11px',
  402. '12px',
  403. '14px',
  404. '16px',
  405. '18px',
  406. '20px',
  407. '22px',
  408. '24px',
  409. '26px',
  410. '28px',
  411. '36px',
  412. '48px',
  413. '72px'
  414. ],
  415. allowCustomSize: true
  416. },
  417. trumbowyg.o.plugins.fontsize || {}
  418. );
  419. trumbowyg.addBtnDef('fontsize', {
  420. dropdown: buildDropdown(trumbowyg)
  421. });
  422. }
  423. }
  424. }
  425. });
  426. function setFontSize(trumbowyg, size) {
  427. trumbowyg.$ed.focus();
  428. trumbowyg.saveRange();
  429. // Temporary size
  430. trumbowyg.execCmd('fontSize', '1');
  431. // Find <font> elements that were added and change to <span> with chosen size
  432. trumbowyg.$ed.find('font[size="1"]').replaceWith(function() {
  433. return $('<span/>', {
  434. css: { 'font-size': size },
  435. html: this.innerHTML,
  436. });
  437. });
  438. // Remove and leftover <span> elements
  439. $(trumbowyg.range.startContainer.parentElement).find('span[style=""]').contents().unwrap();
  440. trumbowyg.restoreRange();
  441. trumbowyg.syncCode();
  442. trumbowyg.$c.trigger('tbwchange');
  443. }
  444. function buildDropdown(trumbowyg) {
  445. var dropdown = [];
  446. $.each(trumbowyg.o.plugins.fontsize.sizeList, function (index, size) {
  447. trumbowyg.addBtnDef('fontsize_' + size, {
  448. text: '<span style="">' + (trumbowyg.lang.fontsizes[size] || size) + '</span>',
  449. hasIcon: false,
  450. fn: function () {
  451. setFontSize(trumbowyg, size);
  452. }
  453. });
  454. dropdown.push('fontsize_' + size);
  455. });
  456. if (trumbowyg.o.plugins.fontsize.allowCustomSize) {
  457. var customSizeButtonName = 'fontsize_custom';
  458. var customSizeBtnDef = {
  459. fn: function () {
  460. trumbowyg.openModalInsert(trumbowyg.lang.fontCustomSize.title,
  461. {
  462. size: {
  463. label: trumbowyg.lang.fontCustomSize.label,
  464. value: trumbowyg.lang.fontCustomSize.value
  465. }
  466. },
  467. function (form) {
  468. setFontSize(trumbowyg, form.size);
  469. return true;
  470. }
  471. );
  472. },
  473. text: '<span style="font-size: medium;">' + trumbowyg.lang.fontsizes.custom + '</span>',
  474. hasIcon: false
  475. };
  476. trumbowyg.addBtnDef(customSizeButtonName, customSizeBtnDef);
  477. dropdown.push(customSizeButtonName);
  478. }
  479. return dropdown;
  480. }
  481. })(jQuery);
  482. /* ===========================================================
  483. * trumbowyg.colors.js v1.2
  484. * Colors picker plugin for Trumbowyg
  485. * http://alex-d.github.com/Trumbowyg
  486. * ===========================================================
  487. * Author : Alexandre Demode (Alex-D)
  488. * Twitter : @AlexandreDemode
  489. * Website : alex-d.fr
  490. */
  491. (function ($) {
  492. 'use strict';
  493. $.extend(true, $.trumbowyg, {
  494. langs: {
  495. // jshint camelcase:false
  496. cs: {
  497. foreColor: 'Barva textu',
  498. backColor: 'Barva pozadí'
  499. },
  500. en: {
  501. foreColor: 'Text color',
  502. backColor: 'Background color'
  503. },
  504. fr: {
  505. foreColor: 'Couleur du texte',
  506. backColor: 'Couleur de fond'
  507. },
  508. nl: {
  509. foreColor: 'Tekstkleur',
  510. backColor: 'Achtergrondkleur'
  511. },
  512. sk: {
  513. foreColor: 'Farba textu',
  514. backColor: 'Farba pozadia'
  515. },
  516. zh_cn: {
  517. foreColor: '文字颜色',
  518. backColor: '背景颜色'
  519. },
  520. ru: {
  521. foreColor: 'Цвет текста',
  522. backColor: 'Цвет выделения текста'
  523. },
  524. ja: {
  525. foreColor: '文字色',
  526. backColor: '背景色'
  527. },
  528. tr: {
  529. foreColor: 'Yazı rengi',
  530. backColor: 'Arkaplan rengi'
  531. }
  532. }
  533. });
  534. // jshint camelcase:true
  535. function hex(x) {
  536. return ('0' + parseInt(x).toString(16)).slice(-2);
  537. }
  538. function colorToHex(rgb) {
  539. if (rgb.search('rgb') === -1) {
  540. return rgb.replace('#', '');
  541. } else if (rgb === 'rgba(0, 0, 0, 0)') {
  542. return 'transparent';
  543. } else {
  544. rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
  545. return hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
  546. }
  547. }
  548. function colorTagHandler(element, trumbowyg) {
  549. var tags = [];
  550. if (!element.style) {
  551. return tags;
  552. }
  553. // background color
  554. if (element.style.backgroundColor !== '') {
  555. var backColor = colorToHex(element.style.backgroundColor);
  556. if (trumbowyg.o.plugins.colors.colorList.indexOf(backColor) >= 0) {
  557. tags.push('backColor' + backColor);
  558. } else {
  559. tags.push('backColorFree');
  560. }
  561. }
  562. // text color
  563. var foreColor;
  564. if (element.style.color !== '') {
  565. foreColor = colorToHex(element.style.color);
  566. } else if (element.hasAttribute('color')) {
  567. foreColor = colorToHex(element.getAttribute('color'));
  568. }
  569. if (foreColor) {
  570. if (trumbowyg.o.plugins.colors.colorList.indexOf(foreColor) >= 0) {
  571. tags.push('foreColor' + foreColor);
  572. } else {
  573. tags.push('foreColorFree');
  574. }
  575. }
  576. return tags;
  577. }
  578. var defaultOptions = {
  579. colorList: ['ffffff', '000000', 'eeece1', '1f497d', '4f81bd', 'c0504d', '9bbb59', '8064a2', '4bacc6', 'f79646', 'ffff00', 'f2f2f2', '7f7f7f', 'ddd9c3', 'c6d9f0', 'dbe5f1', 'f2dcdb', 'ebf1dd', 'e5e0ec', 'dbeef3', 'fdeada', 'fff2ca', 'd8d8d8', '595959', 'c4bd97', '8db3e2', 'b8cce4', 'e5b9b7', 'd7e3bc', 'ccc1d9', 'b7dde8', 'fbd5b5', 'ffe694', 'bfbfbf', '3f3f3f', '938953', '548dd4', '95b3d7', 'd99694', 'c3d69b', 'b2a2c7', 'b7dde8', 'fac08f', 'f2c314', 'a5a5a5', '262626', '494429', '17365d', '366092', '953734', '76923c', '5f497a', '92cddc', 'e36c09', 'c09100', '7f7f7f', '0c0c0c', '1d1b10', '0f243e', '244061', '632423', '4f6128', '3f3151', '31859b', '974806', '7f6000']
  580. };
  581. // Add all colors in two dropdowns
  582. $.extend(true, $.trumbowyg, {
  583. plugins: {
  584. color: {
  585. init: function (trumbowyg) {
  586. trumbowyg.o.plugins.colors = trumbowyg.o.plugins.colors || defaultOptions;
  587. var foreColorBtnDef = {
  588. dropdown: buildDropdown('foreColor', trumbowyg)
  589. },
  590. backColorBtnDef = {
  591. dropdown: buildDropdown('backColor', trumbowyg)
  592. };
  593. trumbowyg.addBtnDef('foreColor', foreColorBtnDef);
  594. trumbowyg.addBtnDef('backColor', backColorBtnDef);
  595. },
  596. tagHandler: colorTagHandler
  597. }
  598. }
  599. });
  600. function buildDropdown(fn, trumbowyg) {
  601. var dropdown = [];
  602. $.each(trumbowyg.o.plugins.colors.colorList, function (i, color) {
  603. var btn = fn + color,
  604. btnDef = {
  605. fn: fn,
  606. forceCss: true,
  607. param: '#' + color,
  608. style: 'background-color: #' + color + ';'
  609. };
  610. trumbowyg.addBtnDef(btn, btnDef);
  611. dropdown.push(btn);
  612. });
  613. var removeColorButtonName = fn + 'Remove',
  614. removeColorBtnDef = {
  615. fn: 'removeFormat',
  616. param: fn,
  617. style: 'background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAG0lEQVQIW2NkQAAfEJMRmwBYhoGBYQtMBYoAADziAp0jtJTgAAAAAElFTkSuQmCC);'
  618. };
  619. trumbowyg.addBtnDef(removeColorButtonName, removeColorBtnDef);
  620. dropdown.push(removeColorButtonName);
  621. // add free color btn
  622. var freeColorButtonName = fn + 'Free',
  623. freeColorBtnDef = {
  624. fn: function () {
  625. trumbowyg.openModalInsert(trumbowyg.lang[fn],
  626. {
  627. color: {
  628. label: fn,
  629. value: '#FFFFFF'
  630. }
  631. },
  632. // callback
  633. function (values) {
  634. trumbowyg.execCmd(fn, values.color);
  635. return true;
  636. }
  637. );
  638. },
  639. text: '#',
  640. // style adjust for displaying the text
  641. style: 'text-indent: 0;line-height: 20px;padding: 0 5px;'
  642. };
  643. trumbowyg.addBtnDef(freeColorButtonName, freeColorBtnDef);
  644. dropdown.push(freeColorButtonName);
  645. return dropdown;
  646. }
  647. })(jQuery);
  648. /* ===========================================================
  649. * trumbowyg.table.custom.js v2.0
  650. * Table plugin for Trumbowyg
  651. * http://alex-d.github.com/Trumbowyg
  652. * ===========================================================
  653. * Author : Sven Dunemann [dunemann@forelabs.eu]
  654. */
  655. (function ($) {
  656. 'use strict';
  657. var defaultOptions = {
  658. rows: 8,
  659. columns: 8,
  660. styler: 'table'
  661. };
  662. $.extend(true, $.trumbowyg, {
  663. langs: {
  664. // jshint camelcase:false
  665. en: {
  666. table: 'Insert table',
  667. tableAddRow: 'Add row',
  668. tableAddRowAbove: 'Add row above',
  669. tableAddColumnLeft: 'Add column to the left',
  670. tableAddColumn: 'Add column to the right',
  671. tableDeleteRow: 'Delete row',
  672. tableDeleteColumn: 'Delete column',
  673. tableDestroy: 'Delete table',
  674. error: 'Error'
  675. },
  676. da: {
  677. table: 'Indsæt tabel',
  678. tableAddRow: 'Tilføj række',
  679. tableAddRowAbove: 'Tilføj række',
  680. tableAddColumnLeft: 'Tilføj kolonne',
  681. tableAddColumn: 'Tilføj kolonne',
  682. tableDeleteRow: 'Slet række',
  683. tableDeleteColumn: 'Slet kolonne',
  684. tableDestroy: 'Slet tabel',
  685. error: 'Fejl'
  686. },
  687. de: {
  688. table: 'Tabelle einfügen',
  689. tableAddRow: 'Zeile hinzufügen',
  690. tableAddRowAbove: 'Zeile hinzufügen',
  691. tableAddColumnLeft: 'Spalte hinzufügen',
  692. tableAddColumn: 'Spalte hinzufügen',
  693. tableDeleteRow: 'Zeile löschen',
  694. tableDeleteColumn: 'Spalte löschen',
  695. tableDestroy: 'Tabelle löschen',
  696. error: 'Error'
  697. },
  698. sk: {
  699. table: 'Vytvoriť tabuľky',
  700. tableAddRow: 'Pridať riadok',
  701. tableAddRowAbove: 'Pridať riadok',
  702. tableAddColumnLeft: 'Pridať stĺpec',
  703. tableAddColumn: 'Pridať stĺpec',
  704. error: 'Chyba'
  705. },
  706. fr: {
  707. table: 'Insérer un tableau',
  708. tableAddRow: 'Ajouter un ligne en dessous',
  709. tableAddRowAbove: 'Ajouter une ligne au dessus',
  710. tableAddColumnLeft: 'Ajouter une colonne à gauche',
  711. tableAddColumn: 'Ajouter une colonne à droite',
  712. tableDeleteRow: 'Effacer la ligne',
  713. tableDeleteColumn: 'Effacer la colonne',
  714. tableDestroy: 'Effacer le tableau',
  715. error: 'Erreur'
  716. },
  717. cs: {
  718. table: 'Vytvořit příkaz Table',
  719. tableAddRow: 'Přidat řádek',
  720. tableAddRowAbove: 'Přidat řádek',
  721. tableAddColumnLeft: 'Přidat sloupec',
  722. tableAddColumn: 'Přidat sloupec',
  723. error: 'Chyba'
  724. },
  725. ru: {
  726. table: 'Вставить таблицу',
  727. tableAddRow: 'Добавить строку',
  728. tableAddRowAbove: 'Добавить строку',
  729. tableAddColumnLeft: 'Добавить столбец',
  730. tableAddColumn: 'Добавить столбец',
  731. tableDeleteRow: 'Удалить строку',
  732. tableDeleteColumn: 'Удалить столбец',
  733. tableDestroy: 'Удалить таблицу',
  734. error: 'Ошибка'
  735. },
  736. ja: {
  737. table: '表の挿入',
  738. tableAddRow: '行の追加',
  739. tableAddRowAbove: '行の追加',
  740. tableAddColumnLeft: '列の追加',
  741. tableAddColumn: '列の追加',
  742. error: 'エラー'
  743. },
  744. tr: {
  745. table: 'Tablo ekle',
  746. tableAddRow: 'Satır ekle',
  747. tableAddRowAbove: 'Satır ekle',
  748. tableAddColumnLeft: 'Kolon ekle',
  749. tableAddColumn: 'Kolon ekle',
  750. error: 'Hata'
  751. },
  752. zh_tw: {
  753. table: '插入表格',
  754. tableAddRow: '加入行',
  755. tableAddRowAbove: '加入行',
  756. tableAddColumnLeft: '加入列',
  757. tableAddColumn: '加入列',
  758. tableDeleteRow: '刪除行',
  759. tableDeleteColumn: '刪除列',
  760. tableDestroy: '刪除表格',
  761. error: '錯誤'
  762. },
  763. id: {
  764. table: 'Sisipkan tabel',
  765. tableAddRow: 'Sisipkan baris',
  766. tableAddRowAbove: 'Sisipkan baris',
  767. tableAddColumnLeft: 'Sisipkan kolom',
  768. tableAddColumn: 'Sisipkan kolom',
  769. tableDeleteRow: 'Hapus baris',
  770. tableDeleteColumn: 'Hapus kolom',
  771. tableDestroy: 'Hapus tabel',
  772. error: 'Galat'
  773. },
  774. pt_br: {
  775. table: 'Inserir tabela',
  776. tableAddRow: 'Adicionar linha',
  777. tableAddRowAbove: 'Adicionar linha',
  778. tableAddColumnLeft: 'Adicionar coluna',
  779. tableAddColumn: 'Adicionar coluna',
  780. tableDeleteRow: 'Deletar linha',
  781. tableDeleteColumn: 'Deletar coluna',
  782. tableDestroy: 'Deletar tabela',
  783. error: 'Erro'
  784. },
  785. ko: {
  786. table: '표 넣기',
  787. tableAddRow: '줄 추가',
  788. tableAddRowAbove: '줄 추가',
  789. tableAddColumnLeft: '칸 추가',
  790. tableAddColumn: '칸 추가',
  791. tableDeleteRow: '줄 삭제',
  792. tableDeleteColumn: '칸 삭제',
  793. tableDestroy: '표 지우기',
  794. error: '에러'
  795. },
  796. // jshint camelcase:true
  797. },
  798. plugins: {
  799. table: {
  800. init: function (t) {
  801. t.o.plugins.table = $.extend(true, {}, defaultOptions, t.o.plugins.table || {});
  802. var buildButtonDef = {
  803. fn: function () {
  804. t.saveRange();
  805. var btnName = 'table';
  806. var dropdownPrefix = t.o.prefix + 'dropdown',
  807. dropdownOptions = { // the dropdown
  808. class: dropdownPrefix + '-' + btnName + ' ' + dropdownPrefix + ' ' + t.o.prefix + 'fixed-top'
  809. };
  810. dropdownOptions['data-' + dropdownPrefix] = btnName;
  811. var $dropdown = $('<div/>', dropdownOptions);
  812. if (t.$box.find('.' + dropdownPrefix + '-' + btnName).length === 0) {
  813. t.$box.append($dropdown.hide());
  814. } else {
  815. $dropdown = t.$box.find('.' + dropdownPrefix + '-' + btnName);
  816. }
  817. // clear dropdown
  818. $dropdown.html('');
  819. // when active table show AddRow / AddColumn
  820. if (t.$box.find('.' + t.o.prefix + 'table-button').hasClass(t.o.prefix + 'active-button')) {
  821. $dropdown.append(t.buildSubBtn('tableAddRowAbove'));
  822. $dropdown.append(t.buildSubBtn('tableAddRow'));
  823. $dropdown.append(t.buildSubBtn('tableAddColumnLeft'));
  824. $dropdown.append(t.buildSubBtn('tableAddColumn'));
  825. $dropdown.append(t.buildSubBtn('tableDeleteRow'));
  826. $dropdown.append(t.buildSubBtn('tableDeleteColumn'));
  827. $dropdown.append(t.buildSubBtn('tableDestroy'));
  828. } else {
  829. var tableSelect = $('<table/>');
  830. $('<tbody/>').appendTo(tableSelect);
  831. for (var i = 0; i < t.o.plugins.table.rows; i += 1) {
  832. var row = $('<tr/>').appendTo(tableSelect);
  833. for (var j = 0; j < t.o.plugins.table.columns; j += 1) {
  834. $('<td/>').appendTo(row);
  835. }
  836. }
  837. tableSelect.find('td').on('mouseover', tableAnimate);
  838. tableSelect.find('td').on('mousedown', tableBuild);
  839. $dropdown.append(tableSelect);
  840. $dropdown.append($('<div class="trumbowyg-table-size">1x1</div>'));
  841. }
  842. t.dropdown(btnName);
  843. }
  844. };
  845. var tableAnimate = function(columnEvent) {
  846. var column = $(columnEvent.target),
  847. table = column.closest('table'),
  848. colIndex = this.cellIndex,
  849. rowIndex = this.parentNode.rowIndex;
  850. // reset all columns
  851. table.find('td').removeClass('active');
  852. for (var i = 0; i <= rowIndex; i += 1) {
  853. for (var j = 0; j <= colIndex; j += 1) {
  854. table.find('tr:nth-of-type('+(i+1)+')').find('td:nth-of-type('+(j+1)+')').addClass('active');
  855. }
  856. }
  857. // set label
  858. table.next('.trumbowyg-table-size').html((colIndex+1) + 'x' + (rowIndex+1));
  859. };
  860. var tableBuild = function() {
  861. t.saveRange();
  862. var tabler = $('<table/>');
  863. $('<tbody/>').appendTo(tabler);
  864. if (t.o.plugins.table.styler) {
  865. tabler.attr('class', t.o.plugins.table.styler);
  866. }
  867. var colIndex = this.cellIndex,
  868. rowIndex = this.parentNode.rowIndex;
  869. for (var i = 0; i <= rowIndex; i += 1) {
  870. var row = $('<tr></tr>').appendTo(tabler);
  871. for (var j = 0; j <= colIndex; j += 1) {
  872. $('<td/>').appendTo(row);
  873. }
  874. }
  875. t.range.deleteContents();
  876. t.range.insertNode(tabler[0]);
  877. t.$c.trigger('tbwchange');
  878. };
  879. var addRow = {
  880. title: t.lang.tableAddRow,
  881. text: t.lang.tableAddRow,
  882. ico: 'row-below',
  883. fn: function () {
  884. t.saveRange();
  885. var node = t.doc.getSelection().focusNode;
  886. var focusedRow = $(node).closest('tr');
  887. var table = $(node).closest('table');
  888. if(table.length > 0) {
  889. var row = $('<tr/>');
  890. // add columns according to current columns count
  891. for (var i = 0; i < table.find('tr')[0].childElementCount; i += 1) {
  892. $('<td/>').appendTo(row);
  893. }
  894. // add row to table
  895. focusedRow.after(row);
  896. }
  897. t.syncCode();
  898. }
  899. };
  900. var addRowAbove = {
  901. title: t.lang.tableAddRowAbove,
  902. text: t.lang.tableAddRowAbove,
  903. ico: 'row-above',
  904. fn: function () {
  905. t.saveRange();
  906. var node = t.doc.getSelection().focusNode;
  907. var focusedRow = $(node).closest('tr');
  908. var table = $(node).closest('table');
  909. if(table.length > 0) {
  910. var row = $('<tr/>');
  911. // add columns according to current columns count
  912. for (var i = 0; i < table.find('tr')[0].childElementCount; i += 1) {
  913. $('<td/>').appendTo(row);
  914. }
  915. // add row to table
  916. focusedRow.before(row);
  917. }
  918. t.syncCode();
  919. }
  920. };
  921. var addColumn = {
  922. title: t.lang.tableAddColumn,
  923. text: t.lang.tableAddColumn,
  924. ico: 'col-right',
  925. fn: function () {
  926. t.saveRange();
  927. var node = t.doc.getSelection().focusNode;
  928. var focusedCol = $(node).closest('td');
  929. var table = $(node).closest('table');
  930. var focusedColIdx = focusedCol.index();
  931. if(table.length > 0) {
  932. $(table).find('tr').each(function() {
  933. $($(this).children()[focusedColIdx]).after('<td></td>');
  934. });
  935. }
  936. t.syncCode();
  937. }
  938. };
  939. var addColumnLeft = {
  940. title: t.lang.tableAddColumnLeft,
  941. text: t.lang.tableAddColumnLeft,
  942. ico: 'col-left',
  943. fn: function () {
  944. t.saveRange();
  945. var node = t.doc.getSelection().focusNode;
  946. var focusedCol = $(node).closest('td');
  947. var table = $(node).closest('table');
  948. var focusedColIdx = focusedCol.index();
  949. if(table.length > 0) {
  950. $(table).find('tr').each(function() {
  951. $($(this).children()[focusedColIdx]).before('<td></td>');
  952. });
  953. }
  954. t.syncCode();
  955. }
  956. };
  957. var destroy = {
  958. title: t.lang.tableDestroy,
  959. text: t.lang.tableDestroy,
  960. ico: 'table-delete',
  961. fn: function () {
  962. t.saveRange();
  963. var node = t.doc.getSelection().focusNode,
  964. table = $(node).closest('table');
  965. table.remove();
  966. t.syncCode();
  967. }
  968. };
  969. var deleteRow = {
  970. title: t.lang.tableDeleteRow,
  971. text: t.lang.tableDeleteRow,
  972. ico: 'row-delete',
  973. fn: function () {
  974. t.saveRange();
  975. var node = t.doc.getSelection().focusNode,
  976. row = $(node).closest('tr');
  977. row.remove();
  978. t.syncCode();
  979. }
  980. };
  981. var deleteColumn = {
  982. title: t.lang.tableDeleteColumn,
  983. text: t.lang.tableDeleteColumn,
  984. ico: 'col-delete',
  985. fn: function () {
  986. t.saveRange();
  987. var node = t.doc.getSelection().focusNode,
  988. table = $(node).closest('table'),
  989. td = $(node).closest('td'),
  990. cellIndex = td.index();
  991. $(table).find('tr').each(function() {
  992. $(this).find('td:eq(' + cellIndex + ')').remove();
  993. });
  994. t.syncCode();
  995. }
  996. };
  997. t.addBtnDef('table', buildButtonDef);
  998. t.addBtnDef('tableAddRowAbove', addRowAbove);
  999. t.addBtnDef('tableAddRow', addRow);
  1000. t.addBtnDef('tableAddColumnLeft', addColumnLeft);
  1001. t.addBtnDef('tableAddColumn', addColumn);
  1002. t.addBtnDef('tableDeleteRow', deleteRow);
  1003. t.addBtnDef('tableDeleteColumn', deleteColumn);
  1004. t.addBtnDef('tableDestroy', destroy);
  1005. }
  1006. }
  1007. }
  1008. });
  1009. })(jQuery);
  1010. /**
  1011. Vertical align custom, NE PAS UPGRADE !!
  1012. */
  1013. (function ($) {
  1014. 'use strict';
  1015. //Création d'un boutton spécial pour les sauts de page
  1016. $.extend(true, $.trumbowyg, {
  1017. plugins: {
  1018. alignDropdown: {
  1019. init: function (trumbowyg) {
  1020. var dropdownButtonName = {
  1021. dropdown: ['alignTop', 'alignBottom', 'alignMiddle'],
  1022. title: 'Alignement vertical',
  1023. // ico: 'iconName',
  1024. text: '<strong>↨</strong>',
  1025. hasIcon: false
  1026. }
  1027. var alignTopBtnDef = {
  1028. fn: function () {
  1029. trumbowyg.saveRange();
  1030. $(trumbowyg.range.startContainer.parentElement).css('vertical-align', 'top');
  1031. trumbowyg.syncCode();
  1032. },
  1033. title: 'Alignement en haut',
  1034. class: 'trumbowyg-aligntop-button fas fa-long-arrow-alt-up',
  1035. text: '<strong>↑</strong> Aligné en haut',
  1036. hasIcon: false
  1037. };
  1038. var alignBottomBtnDef = {
  1039. fn: function () {
  1040. trumbowyg.saveRange();
  1041. $(trumbowyg.range.startContainer.parentElement).css('vertical-align', 'bottom');
  1042. trumbowyg.syncCode();
  1043. },
  1044. title: 'Alignement en bas',
  1045. class: 'trumbowyg-aligntop-button fas fa-long-arrow-alt-up',
  1046. text: '<strong>↓</strong> Aligné en bas',
  1047. hasIcon: false
  1048. };
  1049. var alignMiddleBtnDef = {
  1050. fn: function () {
  1051. trumbowyg.saveRange();
  1052. $(trumbowyg.range.startContainer.parentElement).css('vertical-align', 'middle');
  1053. trumbowyg.syncCode();
  1054. },
  1055. title: 'Alignement au milieu',
  1056. class: 'trumbowyg-aligntop-button fas fa-long-arrow-alt-up',
  1057. text: '<strong>↔</strong> Aligné au milieu',
  1058. hasIcon: false
  1059. };
  1060. trumbowyg.addBtnDef('alignDropdown',dropdownButtonName);
  1061. trumbowyg.addBtnDef('alignTop',alignTopBtnDef);
  1062. trumbowyg.addBtnDef('alignBottom',alignBottomBtnDef);
  1063. trumbowyg.addBtnDef('alignMiddle',alignMiddleBtnDef);
  1064. }
  1065. }
  1066. }
  1067. });
  1068. })(jQuery);
  1069. /**
  1070. Line height custom, NE PAS UPGRADE !!
  1071. */
  1072. (function ($) {
  1073. 'use strict';
  1074. $.extend(true, $.trumbowyg, {
  1075. langs: {
  1076. en: {
  1077. lineheight: 'Line height',
  1078. lineheights: {
  1079. '0.4': 'Extra small',
  1080. '0.9': 'Small',
  1081. 'normal': 'Regular',
  1082. '1.5': 'Large',
  1083. '2.0': 'Extra large'
  1084. }
  1085. },
  1086. fr: {
  1087. lineheight: 'Hauteur de ligne',
  1088. lineheights: {
  1089. '0.5': 'Très petite',
  1090. '0.9': 'Petite',
  1091. 'normal': 'Normale',
  1092. '1.5': 'Grande',
  1093. '2.0': 'Très grande'
  1094. }
  1095. },
  1096. }
  1097. });
  1098. var defaultOptions = {
  1099. sizeList: [
  1100. '0.5',
  1101. '0.9',
  1102. 'normal',
  1103. '1.5',
  1104. '2.0'
  1105. ]
  1106. };
  1107. $.extend(true, $.trumbowyg, {
  1108. plugins: {
  1109. lineheight: {
  1110. init: function (trumbowyg) {
  1111. trumbowyg.o.plugins.lineheight = $.extend({},
  1112. defaultOptions,
  1113. trumbowyg.o.plugins.lineheight || {}
  1114. );
  1115. trumbowyg.addBtnDef('lineheight', {
  1116. dropdown: buildDropdown(trumbowyg)
  1117. });
  1118. }
  1119. }
  1120. }
  1121. });
  1122. // Build the dropdown
  1123. function buildDropdown(trumbowyg) {
  1124. var dropdown = [];
  1125. $.each(trumbowyg.o.plugins.lineheight.sizeList, function(index, size) {
  1126. trumbowyg.addBtnDef('lineheight_' + size, {
  1127. text: trumbowyg.lang.lineheights[size] || size,
  1128. hasIcon: false,
  1129. fn: function(){
  1130. trumbowyg.saveRange();
  1131. var text = trumbowyg.getRangeText();
  1132. if (text.replace(/\s/g, '') !== '') {
  1133. var parent = trumbowyg.doc.getSelection().getRangeAt(0).commonAncestorContainer;
  1134. $(parent).css('lineHeight', size);
  1135. try {
  1136. var parent = trumbowyg.doc.getSelection().getRangeAt(0).commonAncestorContainer;
  1137. $(parent).css('lineHeight', size);
  1138. } catch (e) {
  1139. }
  1140. }
  1141. }
  1142. });
  1143. dropdown.push('lineheight_' + size);
  1144. });
  1145. return dropdown;
  1146. }
  1147. })(jQuery);