Mercurial Hosting > sceditor
comparison src/sceditor.js @ 33:c23475f3f466
improve emoticons
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 14 Aug 2022 20:36:17 -0600 |
parents | 98f11d0cbbd8 |
children | 21090996a131 |
comparison
equal
deleted
inserted
replaced
32:98f11d0cbbd8 | 33:c23475f3f466 |
---|---|
2539 }, | 2539 }, |
2540 // END_COMMAND | 2540 // END_COMMAND |
2541 | 2541 |
2542 // START_COMMAND: Emoticons | 2542 // START_COMMAND: Emoticons |
2543 emoticon: { | 2543 emoticon: { |
2544 exec: function (editor, caller) { | 2544 base: function (editor, caller, targetToHtml) { |
2545 var createContent = function (includeMore) { | 2545 var createContent = function (includeMore) { |
2546 var moreLink, | 2546 var moreLink, |
2547 opts = editor.opts, | 2547 opts = editor.opts, |
2548 emoticonsRoot = opts.emoticonsRoot || '', | 2548 emoticonsRoot = opts.emoticonsRoot || '', |
2549 emoticonsCompat = opts.emoticonsCompat, | 2549 emoticonsCompat = opts.emoticonsCompat, |
2550 rangeHelper = editor.getRangeHelper(), | |
2551 startSpace = emoticonsCompat && | |
2552 rangeHelper.getOuterText(true, 1) !== ' ' ? ' ' : '', | |
2553 endSpace = emoticonsCompat && | |
2554 rangeHelper.getOuterText(false, 1) !== ' ' ? ' ' : '', | |
2555 content = createElement('div'), | 2550 content = createElement('div'), |
2556 line = createElement('div'), | 2551 line = createElement('div'), |
2557 perLine = 0, | 2552 perLine = 0, |
2558 emoticons = extend( | 2553 emoticons = extend( |
2559 {}, | 2554 {}, |
2564 appendChild(content, line); | 2559 appendChild(content, line); |
2565 | 2560 |
2566 perLine = Math.sqrt(Object.keys(emoticons).length); | 2561 perLine = Math.sqrt(Object.keys(emoticons).length); |
2567 | 2562 |
2568 onEvent1(content, 'click', 'img', function (target, e) { | 2563 onEvent1(content, 'click', 'img', function (target, e) { |
2569 editor.insert(startSpace + attr(target, 'alt') + endSpace, | 2564 editor.insert(targetToHtml(target), null, false); |
2570 null, false).closeDropDown(true); | 2565 editor.closeDropDown(true); |
2571 | 2566 |
2572 e.preventDefault(); | 2567 e.preventDefault(); |
2573 }); | 2568 }); |
2574 | 2569 |
2575 each(emoticons, function (code, emoticon) { | 2570 each(emoticons, function (code, emoticon) { |
2576 appendChild(line, createElement('img', { | 2571 appendChild(line, createElement('img', { |
2577 src: emoticonsRoot + (emoticon.url || emoticon), | 2572 src: emoticonsRoot + (emoticon.url || emoticon), |
2573 'data-sceditor-emoticon': code, | |
2578 alt: code, | 2574 alt: code, |
2579 title: emoticon.tooltip || code | 2575 title: emoticon.tooltip || code |
2580 })); | 2576 })); |
2581 | 2577 |
2582 if (line.children.length >= perLine) { | 2578 if (line.children.length >= perLine) { |
2607 return content; | 2603 return content; |
2608 }; | 2604 }; |
2609 | 2605 |
2610 editor.createDropDown(caller, 'emoticons', createContent(false)); | 2606 editor.createDropDown(caller, 'emoticons', createContent(false)); |
2611 }, | 2607 }, |
2608 exec: function (editor, caller) { | |
2609 editor.commands.emoticon.base(editor, caller | |
2610 , function(target) { return target.outerHTML; } | |
2611 ); | |
2612 }, | |
2612 txtExec: function (editor, caller) { | 2613 txtExec: function (editor, caller) { |
2613 defaultCmds.emoticon.exec(editor, caller); | 2614 editor.commands.emoticon.exec(editor, caller); |
2614 }, | 2615 }, |
2615 tooltip: 'Insert an emoticon' | 2616 tooltip: 'Insert an emoticon' |
2616 }, | 2617 }, |
2617 // END_COMMAND | 2618 // END_COMMAND |
2618 | 2619 |
4042 * @param {HTMLElement} root | 4043 * @param {HTMLElement} root |
4043 * @param {Object<string, string>} emoticons | 4044 * @param {Object<string, string>} emoticons |
4044 * @param {boolean} emoticonsCompat | 4045 * @param {boolean} emoticonsCompat |
4045 * @return {void} | 4046 * @return {void} |
4046 */ | 4047 */ |
4047 function replace(root, emoticons, emoticonsCompat) { | 4048 function doReplaceEmoticons(root, emoticons, emoticonsCompat) { |
4048 var doc = root.ownerDocument; | 4049 var doc = root.ownerDocument; |
4049 var space = '(^|\\s|\xA0|\u2002|\u2003|\u2009|$)'; | 4050 var space = '(^|\\s|\xA0|\u2002|\u2003|\u2009|$)'; |
4050 var emoticonCodes = []; | 4051 var emoticonCodes = []; |
4051 var emoticonRegex = {}; | 4052 var emoticonRegex = {}; |
4052 | 4053 |
4250 * The editors locale | 4251 * The editors locale |
4251 * | 4252 * |
4252 * @private | 4253 * @private |
4253 */ | 4254 */ |
4254 var locale; | 4255 var locale; |
4255 | |
4256 /** | |
4257 * Stores a cache of preloaded images | |
4258 * | |
4259 * @private | |
4260 * @type {Array.<HTMLImageElement>} | |
4261 */ | |
4262 var preLoadCache = []; | |
4263 | 4256 |
4264 /** | 4257 /** |
4265 * The editors rangeHelper instance | 4258 * The editors rangeHelper instance |
4266 * | 4259 * |
4267 * @type {RangeHelper} | 4260 * @type {RangeHelper} |
4996 key: key, | 4989 key: key, |
4997 // Prefix emoticon root to emoticon urls | 4990 // Prefix emoticon root to emoticon urls |
4998 url: root + (url.url || url), | 4991 url: root + (url.url || url), |
4999 tooltip: url.tooltip || key | 4992 tooltip: url.tooltip || key |
5000 }); | 4993 }); |
5001 | |
5002 // Preload the emoticon | |
5003 if (options.emoticonsEnabled) { | |
5004 preLoadCache.push(createElement('img', { | |
5005 src: root + (url.url || url) | |
5006 })); | |
5007 } | |
5008 }); | 4994 }); |
5009 }; | 4995 }; |
5010 | 4996 |
5011 /** | 4997 /** |
5012 * Autofocus the editor | 4998 * Autofocus the editor |
5096 | 5082 |
5097 wysiwygBody.contentEditable = !readOnly; | 5083 wysiwygBody.contentEditable = !readOnly; |
5098 sourceEditor.readonly = !readOnly; | 5084 sourceEditor.readonly = !readOnly; |
5099 | 5085 |
5100 updateToolBar(readOnly); | 5086 updateToolBar(readOnly); |
5101 | |
5102 return base; | |
5103 }; | 5087 }; |
5104 | 5088 |
5105 /** | 5089 /** |
5106 * Gets if the editor is in RTL mode | 5090 * Gets if the editor is in RTL mode |
5107 * | 5091 * |
5136 addClass(editorContainer, dir); | 5120 addClass(editorContainer, dir); |
5137 | 5121 |
5138 if (icons.rtl) { | 5122 if (icons.rtl) { |
5139 icons.rtl(rtl); | 5123 icons.rtl(rtl); |
5140 } | 5124 } |
5141 | |
5142 return base; | |
5143 }; | 5125 }; |
5144 | 5126 |
5145 /** | 5127 /** |
5146 * Updates the toolbar to disable/enable the appropriate buttons | 5128 * Updates the toolbar to disable/enable the appropriate buttons |
5147 * @private | 5129 * @private |
5191 if (!width$1 && width$1 !== 0) { | 5173 if (!width$1 && width$1 !== 0) { |
5192 return width(editorContainer); | 5174 return width(editorContainer); |
5193 } | 5175 } |
5194 | 5176 |
5195 base.dimensions(width$1, null, saveWidth); | 5177 base.dimensions(width$1, null, saveWidth); |
5196 | |
5197 return base; | |
5198 }; | 5178 }; |
5199 | 5179 |
5200 /** | 5180 /** |
5201 * Returns an object with the properties width and height | 5181 * Returns an object with the properties width and height |
5202 * which are the width and height of the editor in px. | 5182 * which are the width and height of the editor in px. |
5260 options.height = height$1; | 5240 options.height = height$1; |
5261 } | 5241 } |
5262 | 5242 |
5263 height(editorContainer, height$1); | 5243 height(editorContainer, height$1); |
5264 } | 5244 } |
5265 | |
5266 return base; | |
5267 }; | 5245 }; |
5268 | 5246 |
5269 /** | 5247 /** |
5270 * Gets the height of the editor in px | 5248 * Gets the height of the editor in px |
5271 * | 5249 * |
5305 if (!height$1 && height$1 !== 0) { | 5283 if (!height$1 && height$1 !== 0) { |
5306 return height(editorContainer); | 5284 return height(editorContainer); |
5307 } | 5285 } |
5308 | 5286 |
5309 base.dimensions(null, height$1, saveHeight); | 5287 base.dimensions(null, height$1, saveHeight); |
5310 | |
5311 return base; | |
5312 }; | 5288 }; |
5313 | 5289 |
5314 /** | 5290 /** |
5315 * Gets if the editor is maximised or not | 5291 * Gets if the editor is maximised or not |
5316 * | 5292 * |
5352 if (!maximize) { | 5328 if (!maximize) { |
5353 globalWin.scrollTo(0, maximizeScrollPosition); | 5329 globalWin.scrollTo(0, maximizeScrollPosition); |
5354 } | 5330 } |
5355 | 5331 |
5356 autoExpand(); | 5332 autoExpand(); |
5357 | |
5358 return base; | |
5359 }; | 5333 }; |
5360 | 5334 |
5361 autoExpand = function () { | 5335 autoExpand = function () { |
5362 if (options.autoExpand) { | 5336 if (options.autoExpand) { |
5363 base.expandToContent(); | 5337 base.expandToContent(); |
5818 if (base.inSourceMode()) { | 5792 if (base.inSourceMode()) { |
5819 base.sourceEditorInsertText(text, endText); | 5793 base.sourceEditorInsertText(text, endText); |
5820 } else { | 5794 } else { |
5821 base.wysiwygEditorInsertText(text, endText); | 5795 base.wysiwygEditorInsertText(text, endText); |
5822 } | 5796 } |
5823 | |
5824 return base; | |
5825 }; | 5797 }; |
5826 | 5798 |
5827 /** | 5799 /** |
5828 * Like wysiwygEditorInsertHtml but inserts text into the | 5800 * Like wysiwygEditorInsertHtml but inserts text into the |
5829 * source mode editor instead. | 5801 * source mode editor instead. |
5902 sourceEditor.focus(); | 5874 sourceEditor.focus(); |
5903 | 5875 |
5904 if (position) { | 5876 if (position) { |
5905 sourceEditor.selectionStart = position.start; | 5877 sourceEditor.selectionStart = position.start; |
5906 sourceEditor.selectionEnd = position.end; | 5878 sourceEditor.selectionEnd = position.end; |
5907 | 5879 return; |
5908 return base; | |
5909 } | 5880 } |
5910 | 5881 |
5911 return { | 5882 return { |
5912 start: sourceEditor.selectionStart, | 5883 start: sourceEditor.selectionStart, |
5913 end: sourceEditor.selectionEnd | 5884 end: sourceEditor.selectionEnd |
5958 | 5929 |
5959 base.setWysiwygEditorValue(val); | 5930 base.setWysiwygEditorValue(val); |
5960 } else { | 5931 } else { |
5961 base.setSourceEditorValue(val); | 5932 base.setSourceEditorValue(val); |
5962 } | 5933 } |
5963 | |
5964 return base; | |
5965 }; | 5934 }; |
5966 | 5935 |
5967 /** | 5936 /** |
5968 * Inserts HTML/BBCode into the editor | 5937 * Inserts HTML/BBCode into the editor |
5969 * | 5938 * |
6014 base.insert = function ( | 5983 base.insert = function ( |
6015 start, end, filter, convertEmoticons, allowMixed | 5984 start, end, filter, convertEmoticons, allowMixed |
6016 ) { | 5985 ) { |
6017 if (base.inSourceMode()) { | 5986 if (base.inSourceMode()) { |
6018 base.sourceEditorInsertText(start, end); | 5987 base.sourceEditorInsertText(start, end); |
6019 return base; | 5988 return; |
6020 } | 5989 } |
6021 | 5990 |
6022 // Add the selection between start and end | 5991 // Add the selection between start and end |
6023 if (end) { | 5992 if (end) { |
6024 var html = rangeHelper.selectedHtml(); | 5993 var html = rangeHelper.selectedHtml(); |
6041 .replace(/>/g, '>') | 6010 .replace(/>/g, '>') |
6042 .replace(/&/g, '&'); | 6011 .replace(/&/g, '&'); |
6043 } | 6012 } |
6044 | 6013 |
6045 base.wysiwygEditorInsertHtml(start); | 6014 base.wysiwygEditorInsertHtml(start); |
6046 | |
6047 return base; | |
6048 }; | 6015 }; |
6049 | 6016 |
6050 /** | 6017 /** |
6051 * Gets the WYSIWYG editors HTML value. | 6018 * Gets the WYSIWYG editors HTML value. |
6052 * | 6019 * |
6149 if (!value) { | 6116 if (!value) { |
6150 value = '<p><br /></p>'; | 6117 value = '<p><br /></p>'; |
6151 } | 6118 } |
6152 | 6119 |
6153 wysiwygBody.innerHTML = value; | 6120 wysiwygBody.innerHTML = value; |
6154 replaceEmoticons(); | 6121 //replaceEmoticons(); |
6155 | 6122 |
6156 appendNewLine(); | 6123 appendNewLine(); |
6157 triggerValueChanged(); | 6124 triggerValueChanged(); |
6158 autoExpand(); | 6125 autoExpand(); |
6159 }; | 6126 }; |
6190 * with their emoticon images | 6157 * with their emoticon images |
6191 * @private | 6158 * @private |
6192 */ | 6159 */ |
6193 replaceEmoticons = function () { | 6160 replaceEmoticons = function () { |
6194 if (options.emoticonsEnabled) { | 6161 if (options.emoticonsEnabled) { |
6195 replace(wysiwygBody, allEmoticons, options.emoticonsCompat); | 6162 doReplaceEmoticons(wysiwygBody, allEmoticons, options.emoticonsCompat); |
6196 } | 6163 } |
6197 }; | 6164 }; |
6198 | 6165 |
6199 /** | 6166 /** |
6200 * If the editor is in source code mode | 6167 * If the editor is in source code mode |
6233 } | 6200 } |
6234 | 6201 |
6235 if ((inSourceMode && !enable) || (!inSourceMode && enable)) { | 6202 if ((inSourceMode && !enable) || (!inSourceMode && enable)) { |
6236 base.toggleSourceMode(); | 6203 base.toggleSourceMode(); |
6237 } | 6204 } |
6238 | |
6239 return base; | |
6240 }; | 6205 }; |
6241 | 6206 |
6242 /** | 6207 /** |
6243 * Switches between the WYSIWYG and source modes | 6208 * Switches between the WYSIWYG and source modes |
6244 * | 6209 * |
6736 if (events[i] === 'valuechanged') { | 6701 if (events[i] === 'valuechanged') { |
6737 triggerValueChanged.hasHandler = true; | 6702 triggerValueChanged.hasHandler = true; |
6738 } | 6703 } |
6739 } | 6704 } |
6740 } | 6705 } |
6741 | |
6742 return base; | |
6743 }; | 6706 }; |
6744 | 6707 |
6745 /** | 6708 /** |
6746 * Unbinds an event that was bound using bind(). | 6709 * Unbinds an event that was bound using bind(). |
6747 * | 6710 * |
6773 arrayRemove( | 6736 arrayRemove( |
6774 eventHandlers['scesrc' + events[i]] || [], handler); | 6737 eventHandlers['scesrc' + events[i]] || [], handler); |
6775 } | 6738 } |
6776 } | 6739 } |
6777 } | 6740 } |
6778 | |
6779 return base; | |
6780 }; | 6741 }; |
6781 | 6742 |
6782 /** | 6743 /** |
6783 * Blurs the editors input area | 6744 * Blurs the editors input area |
6784 * | 6745 * |
6808 } else if (!base.sourceMode()) { | 6769 } else if (!base.sourceMode()) { |
6809 wysiwygBody.blur(); | 6770 wysiwygBody.blur(); |
6810 } else { | 6771 } else { |
6811 sourceEditor.blur(); | 6772 sourceEditor.blur(); |
6812 } | 6773 } |
6813 | |
6814 return base; | |
6815 }; | 6774 }; |
6816 | 6775 |
6817 /** | 6776 /** |
6818 * Focuses the editors input area | 6777 * Focuses the editors input area |
6819 * | 6778 * |
6873 } else { | 6832 } else { |
6874 sourceEditor.focus(); | 6833 sourceEditor.focus(); |
6875 } | 6834 } |
6876 | 6835 |
6877 updateActiveButtons(); | 6836 updateActiveButtons(); |
6878 | |
6879 return base; | |
6880 }; | 6837 }; |
6881 | 6838 |
6882 /** | 6839 /** |
6883 * Adds a handler to the key down event | 6840 * Adds a handler to the key down event |
6884 * | 6841 * |
7096 | 7053 |
7097 offEvent(wysiwygBody, 'keypress', emoticonsKeyPress); | 7054 offEvent(wysiwygBody, 'keypress', emoticonsKeyPress); |
7098 | 7055 |
7099 triggerValueChanged(); | 7056 triggerValueChanged(); |
7100 } | 7057 } |
7101 | |
7102 return base; | |
7103 }; | 7058 }; |
7104 | 7059 |
7105 /** | 7060 /** |
7106 * Gets the current WYSIWYG editors inline CSS | 7061 * Gets the current WYSIWYG editors inline CSS |
7107 * | 7062 * |
7138 if (inlineCss.styleSheet) { | 7093 if (inlineCss.styleSheet) { |
7139 inlineCss.styleSheet.cssText = css; | 7094 inlineCss.styleSheet.cssText = css; |
7140 } else { | 7095 } else { |
7141 inlineCss.innerHTML = css; | 7096 inlineCss.innerHTML = css; |
7142 } | 7097 } |
7143 | |
7144 return base; | |
7145 }; | 7098 }; |
7146 | 7099 |
7147 /** | 7100 /** |
7148 * Handles the keydown event, used for shortcuts | 7101 * Handles the keydown event, used for shortcuts |
7149 * @private | 7102 * @private |
7303 }; | 7256 }; |
7304 } else { | 7257 } else { |
7305 shortcutHandlers[shortcut] = cmd; | 7258 shortcutHandlers[shortcut] = cmd; |
7306 } | 7259 } |
7307 | 7260 |
7308 return base; | 7261 return true; |
7309 }; | 7262 }; |
7310 | 7263 |
7311 /** | 7264 /** |
7312 * Removes a shortcut handler | 7265 * Removes a shortcut handler |
7313 * @param {string} shortcut | 7266 * @param {string} shortcut |
7314 * @return {sceditor} | 7267 * @return {sceditor} |
7315 */ | 7268 */ |
7316 base.removeShortcut = function (shortcut) { | 7269 base.removeShortcut = function (shortcut) { |
7317 delete shortcutHandlers[shortcut.toLowerCase()]; | 7270 delete shortcutHandlers[shortcut.toLowerCase()]; |
7318 | |
7319 return base; | |
7320 }; | 7271 }; |
7321 | 7272 |
7322 /** | 7273 /** |
7323 * Handles the backspace key press | 7274 * Handles the backspace key press |
7324 * | 7275 * |
7390 */ | 7341 */ |
7391 base.clearBlockFormatting = function (block) { | 7342 base.clearBlockFormatting = function (block) { |
7392 block = block || currentStyledBlockNode(); | 7343 block = block || currentStyledBlockNode(); |
7393 | 7344 |
7394 if (!block || is(block, 'body')) { | 7345 if (!block || is(block, 'body')) { |
7395 return base; | 7346 return; |
7396 } | 7347 } |
7397 | 7348 |
7398 rangeHelper.saveRange(); | 7349 rangeHelper.saveRange(); |
7399 | 7350 |
7400 block.className = ''; | 7351 block.className = ''; |
7404 if (!is(block, 'p,div,td')) { | 7355 if (!is(block, 'p,div,td')) { |
7405 convertElement(block, 'p'); | 7356 convertElement(block, 'p'); |
7406 } | 7357 } |
7407 | 7358 |
7408 rangeHelper.restoreRange(); | 7359 rangeHelper.restoreRange(); |
7409 return base; | |
7410 }; | 7360 }; |
7411 | 7361 |
7412 /** | 7362 /** |
7413 * Triggers the valueChanged signal if there is | 7363 * Triggers the valueChanged signal if there is |
7414 * a plugin that handles it. | 7364 * a plugin that handles it. |
7538 base.updateOriginal(); | 7488 base.updateOriginal(); |
7539 }; | 7489 }; |
7540 | 7490 |
7541 // run the initializer | 7491 // run the initializer |
7542 init(); | 7492 init(); |
7493 | |
7494 base.allEmoticons = allEmoticons; | |
7543 | 7495 |
7544 return base; | 7496 return base; |
7545 } | 7497 } |
7546 | 7498 |
7547 /** | 7499 /** |