editor.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. function bx_ex_editor_init(oEditor, oParams)
  2. {
  3. $(oParams.selector).after("<div id='" + oParams.name + "' class='" + oParams.name + " bx-def-font-inputs bx-form-input-textarea bx-form-input-html bx-form-input-html-editor mt-px text-gray-700 dark:text-gray-300 w-full p-4 ring-1 ring-gray-300 dark:ring-gray-700 dark:focus:placeholder-700 bg-gray-50 dark:bg-gray-900/50 placeholder-gray-500 focus:outline-none focus:bg-white dark:focus:bg-gray-900 focus:placeholder-gray-300 dark:focus:placeholder-gray-700 focus:text-gray-900 dark:focus:text-gray-100 text-base border-0 flex-wrap" + oParams.css_class + "'></div>" );
  4. $(oParams.selector).hide();
  5. var oImage = {
  6. class: ImageTool,
  7. config: {
  8. field: 'file',
  9. uploader: {
  10. uploadByFile(file){
  11. return new Promise((resolve, reject) => {
  12. const formData = new FormData();
  13. formData.append("file", file);
  14. fetch(oParams.root_url + "storage.php?o=sys_images_editor&t=sys_images_editor&a=upload", {
  15. method: "POST",
  16. body: formData
  17. }
  18. )
  19. .then(response => response.json())
  20. .then(result => {
  21. if ('undefined' != typeof(result.link))
  22. resolve({
  23. success: 1,
  24. file: {
  25. url: result.link,
  26. }
  27. });
  28. else
  29. reject("Upload failed");
  30. })
  31. .catch(error => {
  32. reject("Upload failed");
  33. });
  34. });
  35. },
  36. uploadByUrl(url){
  37. return new Promise((resolve, reject) => {
  38. resolve({
  39. success: 1,
  40. file: {
  41. url: url,
  42. }
  43. });
  44. });
  45. }
  46. }
  47. }
  48. };
  49. var oTools = {
  50. paragraph: {
  51. class: Paragraph,
  52. inlineToolbar: true,
  53. },
  54. mention: BxMention,
  55. marker: Marker,
  56. inlineCode: InlineCode,
  57. };
  58. if (oParams.toolbar){
  59. oParams.toolbar.forEach(function(item){
  60. switch(item) {
  61. case 'header':
  62. oTools.header = Header;
  63. break;
  64. case 'list':
  65. oTools.list = List;
  66. break;
  67. case 'image':
  68. oTools.image = oImage;
  69. break;
  70. case 'embed':
  71. oTools.embedblock = BxEmbedBlock;
  72. break;
  73. case 'code':
  74. oTools.code = CodeTool;
  75. break;
  76. case 'delimiter':
  77. oTools.delimiter = Delimiter;
  78. break;
  79. }
  80. })
  81. }
  82. oEditor = new EditorJS({
  83. holder : document.getElementById(oParams.name),
  84. inlineToolbar: oParams.toolbar_inline.concat(['mention']),
  85. tools: oTools,
  86. onReady: () => {
  87. if ($(oParams.selector).val() != '')
  88. oEditor.blocks.renderFromHTML($(oParams.selector).val());
  89. },
  90. onChange:() =>{
  91. oEditor.save().then((savedData) =>{
  92. const edjsParser = edjsHTML({embedblock: bx_ex_editor_custom_parser_embedblock});
  93. oData = edjsParser.parse(savedData);
  94. console.log(oData);
  95. var s ='';
  96. oData.forEach(function(item){
  97. s += item;
  98. })
  99. $(oParams.selector).val(s)
  100. }).catch((error) =>{
  101. console.log("error", error)
  102. })
  103. }
  104. });
  105. tribute = new Tribute({
  106. collection: [
  107. {
  108. selectTemplate: function(item) {
  109. if (this.range.isContentEditable(this.current.element)) {
  110. return ('<a class="bx-menthion-link" dchar="@" data-profile-id="' + item.original.value + '" href="' + item.original.url + '">@' + item.original.label + '</a>');
  111. }
  112. return "@" + item.original.value;
  113. },
  114. values: function (text, cb) {
  115. $.getJSON(oParams.root_url + "/searchExtended.php?action=get_mention&symbol=%40&", {term: text}, function(data) {
  116. cb(data);
  117. });
  118. },
  119. lookup: "label",
  120. fillAttr: "label"
  121. },
  122. {
  123. trigger: "#",
  124. selectTemplate: function(item) {
  125. if (this.range.isContentEditable(this.current.element)) {
  126. return ('<a class="bx-menthion-link" dchar="#" data-profile-id="' + item.original.value + '" href="' + item.original.url + '">#' + item.original.label + '</a>');
  127. }
  128. return "#" + item.original.value;
  129. },
  130. values: function (text, cb) {
  131. $.getJSON(oParams.root_url + "/searchExtended.php?action=get_mention&symbol=%23&", {term: text}, function(data) {
  132. cb(data);
  133. });
  134. },
  135. lookup: "label",
  136. fillAttr: "label"
  137. }
  138. ]
  139. })
  140. tribute.attach(document.getElementById(oParams.name));
  141. document.getElementById(oParams.name).removeAttribute("contenteditable");
  142. }
  143. function bx_ex_editor_custom_parser_embedblock(block)
  144. {
  145. if (block.data && block.data.source)
  146. return '<div class="bx-embed-link" source="' + block.data.source + '">' + block.data.source + '</div>';
  147. }
  148. var oLink ='';
  149. class BxEmbedBlock {
  150. constructor({ data, block }){
  151. console.log('--!constructor');
  152. console.log(data);
  153. this.blockAPI = block
  154. this.nodes = {
  155. linkContent: null,
  156. };
  157. if (this.data && this.data.source)
  158. this.source = data.source;
  159. this.wrapper = undefined;
  160. this.data = data;
  161. }
  162. static get toolbox() {
  163. return {
  164. title: 'Embed',
  165. icon: '<svg width="19" height="13" viewBox="0 0 19 13"><path d="M18.004 5.794c.24.422.18.968-.18 1.328l-4.943 4.943a1.105 1.105 0 1 1-1.562-1.562l4.162-4.162-4.103-4.103A1.125 1.125 0 1 1 12.97.648l4.796 4.796c.104.104.184.223.239.35zm-15.142.547l4.162 4.162a1.105 1.105 0 1 1-1.562 1.562L.519 7.122c-.36-.36-.42-.906-.18-1.328a1.13 1.13 0 0 1 .239-.35L5.374.647a1.125 1.125 0 0 1 1.591 1.591L2.862 6.341z"></path></svg>'
  166. };
  167. }
  168. render() {
  169. this.wrapper = document.createElement('p');
  170. if (this.data && this.data.source){
  171. this._createEmbed(this.data.source);
  172. return this.wrapper;
  173. }
  174. else{
  175. this._createInput();
  176. }
  177. return this.wrapper;
  178. }
  179. _createEmbed(sLink){
  180. var oObj = document.createElement('div');
  181. oObj.setAttribute('source', sLink)
  182. oObj.className = 'bx-embed-link';
  183. oObj.innerHTML = sLink;
  184. this.wrapper.removeChild(this.wrapper.querySelector('input'));
  185. this.wrapper.appendChild(oObj);
  186. }
  187. _createInput(){
  188. var oObj = document.createElement('input');
  189. oObj.className = 'bx-def-font-inputs bx-form-input-text';
  190. oObj.setAttribute('placeholder', _t('_bx_editor_embed_popup_header'));
  191. oObj.addEventListener('blur', (event) => {
  192. if (oObj.value != ''){
  193. this._createEmbed(oObj.value);
  194. }
  195. });
  196. this.wrapper.appendChild(oObj);
  197. }
  198. save(blockContent){
  199. const div = blockContent.querySelector('div');
  200. console.log(div);
  201. if (div){
  202. return {
  203. source: div.getAttribute('source')
  204. }
  205. }
  206. }
  207. static get pasteConfig() {
  208. return {
  209. tags: ['DIV'],
  210. }
  211. }
  212. onPaste(event) {
  213. console.log(8);
  214. if (event.detail.data.attributes.source){
  215. var sSource = event.detail.data.attributes.source.nodeValue;
  216. this._createEmbed(sSource);
  217. this.data.source = sSource;
  218. }
  219. }
  220. static get sanitize(){
  221. return {
  222. url: true, // disallow HTML
  223. }
  224. }
  225. validate(savedData) {
  226. return true;
  227. }
  228. }
  229. class BxMention {
  230. static get CSS() {
  231. return 'bx-menthion-link';
  232. };
  233. constructor({api}) {
  234. this.api = api;
  235. this.button = null;
  236. this.tag = 'a';
  237. this.iconClasses = {
  238. base: this.api.styles.inlineToolButton,
  239. active: this.api.styles.inlineToolButtonActive
  240. };
  241. }
  242. static get isInline() {
  243. return true;
  244. }
  245. render() {
  246. return;
  247. }
  248. surround(range) {
  249. if (!range) {
  250. return;
  251. }
  252. let termWrapper = this.api.selection.findParentTag(this.tag, BxMention.CSS);
  253. if (termWrapper) {
  254. this.unwrap(termWrapper);
  255. } else {
  256. this.wrap(range);
  257. }
  258. }
  259. wrap(range) {
  260. let marker = document.createElement(this.tag);
  261. marker.classList.add(BxMention.CSS);
  262. marker.appendChild(range.extractContents());
  263. range.insertNode(marker);
  264. this.api.selection.expandToTag(marker);
  265. }
  266. unwrap(termWrapper) {
  267. this.api.selection.expandToTag(termWrapper);
  268. let sel = window.getSelection();
  269. let range = sel.getRangeAt(0);
  270. let unwrappedContent = range.extractContents();
  271. termWrapper.parentNode.removeChild(termWrapper);
  272. range.insertNode(unwrappedContent);
  273. sel.removeAllRanges();
  274. sel.addRange(range);
  275. }
  276. checkState() {
  277. const termTag = this.api.selection.findParentTag(this.tag, BxMention.CSS);
  278. this.button.classList.toggle(this.iconClasses.active, !!termTag);
  279. }
  280. get toolboxIcon() {
  281. return require('./../assets/icon.svg').default;
  282. }
  283. static get sanitize() {
  284. return {
  285. a: function(el) {
  286. return {
  287. class: BxMention.CSS,
  288. href: el.getAttribute('href'),
  289. 'data-profile-id': el.getAttribute('data-profile-id'),
  290. title: el.getAttribute('title'),
  291. dchar: el.getAttribute('dchar')
  292. }
  293. }
  294. };
  295. }
  296. }