1 {event name='beforeEditorJavaScript'}
3 <script data-relocate="true">
7 '{@$__wcf->getPath()}js/3rdParty/redactor2/redactor.js?v={@LAST_UPDATE_TIME}',
8 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/alignment.js?v={@LAST_UPDATE_TIME}',
9 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/source.js?v={@LAST_UPDATE_TIME}',
10 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/table.js?v={@LAST_UPDATE_TIME}',
13 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabAttachment.js?v={@LAST_UPDATE_TIME}',
14 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabAutosave.js?v={@LAST_UPDATE_TIME}',
15 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabBlock.js?v={@LAST_UPDATE_TIME}',
16 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabButton.js?v={@LAST_UPDATE_TIME}',
17 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabCaret.js?v={@LAST_UPDATE_TIME}',
18 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabClean.js?v={@LAST_UPDATE_TIME}',
19 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabCode.js?v={@LAST_UPDATE_TIME}',
20 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabColor.js?v={@LAST_UPDATE_TIME}',
21 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabDragAndDrop.js?v={@LAST_UPDATE_TIME}',
22 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabEvent.js?v={@LAST_UPDATE_TIME}',
23 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabFont.js?v={@LAST_UPDATE_TIME}',
24 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabFullscreen.js?v={@LAST_UPDATE_TIME}',
25 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabHtml.js?v={@LAST_UPDATE_TIME}',
26 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabImage.js?v={@LAST_UPDATE_TIME}',
27 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabIndent.js?v={@LAST_UPDATE_TIME}',
28 //'{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabInlineCode.js?v={@LAST_UPDATE_TIME}',
29 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabInsert.js?v={@LAST_UPDATE_TIME}',
30 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabKeydown.js?v={@LAST_UPDATE_TIME}',
31 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabKeyup.js?v={@LAST_UPDATE_TIME}',
32 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabLine.js?v={@LAST_UPDATE_TIME}',
33 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabLink.js?v={@LAST_UPDATE_TIME}',
34 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabList.js?v={@LAST_UPDATE_TIME}',
35 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabMedia.js?v={@LAST_UPDATE_TIME}',
36 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabMention.js?v={@LAST_UPDATE_TIME}',
37 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabModal.js?v={@LAST_UPDATE_TIME}',
38 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabObserve.js?v={@LAST_UPDATE_TIME}',
39 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabPaste.js?v={@LAST_UPDATE_TIME}',
40 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabQuote.js?v={@LAST_UPDATE_TIME}',
41 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabReply.js?v={@LAST_UPDATE_TIME}',
42 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabSize.js?v={@LAST_UPDATE_TIME}',
43 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabSmiley.js?v={@LAST_UPDATE_TIME}',
44 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabSource.js?v={@LAST_UPDATE_TIME}',
45 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabSpoiler.js?v={@LAST_UPDATE_TIME}',
46 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabTable.js?v={@LAST_UPDATE_TIME}',
47 '{@$__wcf->getPath()}js/3rdParty/redactor2/plugins/WoltLabUtils.js?v={@LAST_UPDATE_TIME}'
49 '{@$__wcf->getPath()}js/3rdParty/redactor2/redactor.combined.min.js?v={@LAST_UPDATE_TIME}'
52 {if $__redactorJavaScript|isset}{@$__redactorJavaScript}{/if}
53 {assign var=__redactorJavaScript value=''}
55 {event name='redactorJavaScript'}
57 require(['Environment', 'Language', 'WoltLabSuite/Core/Ui/Redactor/Autosave', 'WoltLabSuite/Core/Ui/Redactor/Metacode'], function(Environment, Language, UiRedactorAutosave, UiRedactorMetacode) {
59 'wcf.attachment.dragAndDrop.dropHere': '{jslang}wcf.attachment.dragAndDrop.dropHere{/jslang}',
60 'wcf.attachment.dragAndDrop.dropNow': '{jslang}wcf.attachment.dragAndDrop.dropNow{/jslang}',
62 'wcf.editor.autosave.discard': '{jslang}wcf.editor.autosave.discard{/jslang}',
63 'wcf.editor.autosave.keep': '{jslang}wcf.editor.autosave.keep{/jslang}',
64 'wcf.editor.autosave.restored': '{jslang}wcf.editor.autosave.restored{/jslang}',
66 'wcf.editor.code.edit': '{jslang}wcf.editor.code.edit{/jslang}',
67 'wcf.editor.code.file': '{jslang}wcf.editor.code.file{/jslang}',
68 'wcf.editor.code.file.description': '{jslang}wcf.editor.code.file.description{/jslang}',
69 'wcf.editor.code.highlighter': '{jslang}wcf.editor.code.highlighter{/jslang}',
70 'wcf.editor.code.highlighter.description': '{jslang}wcf.editor.code.highlighter.description{/jslang}',
71 'wcf.editor.code.highlighter.detect': '{jslang}wcf.editor.code.highlighter.detect{/jslang}',
72 'wcf.editor.code.highlighter.plain': '{jslang}wcf.editor.code.highlighter.plain{/jslang}',
73 'wcf.editor.code.line': '{jslang}wcf.editor.code.line{/jslang}',
74 'wcf.editor.code.line.description': '{jslang}wcf.editor.code.line.description{/jslang}',
75 'wcf.editor.code.title': '{jslang __literal=true}wcf.editor.code.title{/jslang}',
77 'wcf.editor.html.description': '{jslang}wcf.editor.html.description{/jslang}',
78 'wcf.editor.html.title': '{jslang}wcf.editor.html.title{/jslang}',
80 'wcf.editor.image.edit': '{jslang}wcf.editor.image.edit{/jslang}',
81 'wcf.editor.image.insert': '{jslang}wcf.editor.image.insert{/jslang}',
82 'wcf.editor.image.link': '{jslang}wcf.editor.image.link{/jslang}',
83 'wcf.editor.image.link.error.invalid': '{jslang}wcf.editor.image.link.error.invalid{/jslang}',
84 'wcf.editor.image.float': '{jslang}wcf.editor.image.float{/jslang}',
85 'wcf.editor.image.float.left': '{jslang}wcf.editor.image.float.left{/jslang}',
86 'wcf.editor.image.float.right': '{jslang}wcf.editor.image.float.right{/jslang}',
87 'wcf.editor.image.source': '{jslang}wcf.editor.image.source{/jslang}',
88 'wcf.editor.image.source.error.blocked': '{jslang}wcf.editor.image.source.error.blocked{/jslang}',
89 'wcf.editor.image.source.error.insecure': '{jslang}wcf.editor.image.source.error.insecure{/jslang}',
90 'wcf.editor.image.source.error.invalid': '{jslang}wcf.editor.image.source.error.invalid{/jslang}',
92 'wcf.editor.link.add': '{jslang}wcf.editor.link.add{/jslang}',
93 'wcf.editor.link.edit': '{jslang}wcf.editor.link.edit{/jslang}',
94 'wcf.editor.link.error.invalid': '{jslang}wcf.editor.link.error.invalid{/jslang}',
95 'wcf.editor.link.url': '{jslang}wcf.editor.link.url{/jslang}',
96 'wcf.editor.link.text': '{jslang}wcf.editor.link.text{/jslang}',
98 'wcf.editor.list.indent': '{jslang}wcf.editor.list.indent{/jslang}',
99 'wcf.editor.list.outdent': '{jslang}wcf.editor.list.outdent{/jslang}',
101 'wcf.editor.quote.author': '{jslang}wcf.editor.quote.author{/jslang}',
102 'wcf.editor.quote.edit': '{jslang}wcf.editor.quote.edit{/jslang}',
103 'wcf.editor.quote.title': '{jslang __literal=true}wcf.editor.quote.title{/jslang}',
104 'wcf.editor.quote.url': '{jslang}wcf.editor.quote.url{/jslang}',
105 'wcf.editor.quote.url.description': '{jslang}wcf.editor.quote.url.description{/jslang}',
106 'wcf.editor.quote.url.error.invalid': '{jslang}wcf.editor.quote.url.error.invalid{/jslang}',
108 'wcf.editor.table.cols': '{jslang}wcf.editor.table.cols{/jslang}',
109 'wcf.editor.table.insertTable': '{jslang}wcf.editor.table.insertTable{/jslang}',
110 'wcf.editor.table.rows': '{jslang}wcf.editor.table.rows{/jslang}',
112 'wcf.editor.source.error.active': '{jslang}wcf.editor.source.error.active{/jslang}',
114 'wcf.editor.spoiler.label': '{jslang}wcf.editor.spoiler.label{/jslang}',
115 'wcf.editor.spoiler.label.description': '{jslang}wcf.editor.spoiler.label.description{/jslang}',
116 'wcf.editor.spoiler.edit': '{jslang}wcf.editor.spoiler.edit{/jslang}',
117 'wcf.editor.spoiler.title': '{jslang __literal=true}wcf.editor.spoiler.title{/jslang}'
120 var allowedInlineStyles = [], buttons = [], buttonMobile = [], buttonOptions = [], customButtons = [];
121 {include file='wysiwygToolbar'}
123 var highlighters = '{@MESSAGE_PUBLIC_HIGHLIGHTERS|encodeJS}'.split(/\n/).filter(function (item) { return item != ''; });
125 {include file='mediaJavaScript'}
127 var element = elById('{if $wysiwygSelector|isset}{$wysiwygSelector|encodeJS}{else}text{/if}');
129 var autosave = elData(element, 'autosave') || null;
131 autosave = new UiRedactorAutosave(element);
132 element.value = autosave.getInitialValue();
135 var disableMedia = elDataBool(element, 'disable-media');
139 clipboardImageUpload: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('attach')}true{else}false{/if},
140 direction: '{jslang}wcf.global.pageDirection{/jslang}',
141 formatting: ['p', 'h2', 'h3', 'h4'],
143 imageUpload: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('attach')}true{else}false{/if},
144 lang: 'wsc', // fake language to offload phrases
148 edit: '{jslang}wcf.global.button.edit{/jslang}',
150 // formatting dropdown
151 heading2: '{jslang}wcf.editor.format.heading2{/jslang}',
152 heading3: '{jslang}wcf.editor.format.heading3{/jslang}',
153 heading4: '{jslang}wcf.editor.format.heading4{/jslang}',
154 paragraph: '{jslang}wcf.editor.format.paragraph{/jslang}',
157 'link-edit': '{jslang}wcf.editor.link.edit{/jslang}',
158 'link-insert': '{jslang}wcf.editor.link.add{/jslang}',
159 unlink: '{jslang}wcf.editor.link.unlink{/jslang}',
162 'align-center': '{jslang}wcf.editor.alignment.center{/jslang}',
163 'align-justify': '{jslang}wcf.editor.alignment.justify{/jslang}',
164 'align-left': '{jslang}wcf.editor.alignment.left{/jslang}',
165 'align-right': '{jslang}wcf.editor.alignment.right{/jslang}',
168 'add-head': '{jslang}wcf.editor.table.addHead{/jslang}',
169 'delete-column': '{jslang}wcf.editor.table.deleteColumn{/jslang}',
170 'delete-head': '{jslang}wcf.editor.table.deleteHead{/jslang}',
171 'delete-row': '{jslang}wcf.editor.table.deleteRow{/jslang}',
172 'delete-table': '{jslang}wcf.editor.table.deleteTable{/jslang}',
173 'insert-table': '{jslang}wcf.editor.table.insertTable{/jslang}',
174 'insert-column-left': '{jslang}wcf.editor.table.insertColumnLeft{/jslang}',
175 'insert-column-right': '{jslang}wcf.editor.table.insertColumnRight{/jslang}',
176 'insert-row-above': '{jslang}wcf.editor.table.insertRowAbove{/jslang}',
177 'insert-row-below': '{jslang}wcf.editor.table.insertRowBelow{/jslang}',
180 'remove-size': '{jslang}wcf.editor.button.size.removeSize{/jslang}',
183 'remove-color': '{jslang}wcf.editor.button.color.removeColor{/jslang}',
186 'remove-font': '{jslang}wcf.editor.button.font.removeFont{/jslang}'
190 linkSize: 0xBADC0DED, // some random value to disable truncating
192 pasteImages: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('attach')}true{else}false{/if},
193 pastePlainText: {if !$__wcf->user->userID || $__wcf->user->editorPastePreserveFormatting}false{else}true{/if},
211 {if $__wcf->getBBCodeHandler()->isAvailableBBCode('color')}'WoltLabColor',{/if}
212 'WoltLabDragAndDrop',
213 {if $__wcf->getBBCodeHandler()->isAvailableBBCode('font')}'WoltLabFont',{/if}
215 {if $__wcf->getBBCodeHandler()->isAvailableBBCode('html')}'WoltLabHtml',{/if}
218 //'WoltLabInlineCode',
222 {if $__wcf->getBBCodeHandler()->isAvailableBBCode('url')}'WoltLabLink',{/if}
229 {if $__wcf->getBBCodeHandler()->isAvailableBBCode('size')}'WoltLabSize',{/if}
238 allowImages: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('img')}true{else}false{/if},
239 attachments: (elDataBool(element, 'disable-attachments') === false),
240 attachmentThumbnailWidth: {@ATTACHMENT_THUMBNAIL_WIDTH},
242 allowedInlineStyles: allowedInlineStyles,
243 buttons: buttonOptions,
244 buttonMobile: buttonMobile,
245 customButtons: customButtons,
246 forceSecureImages: {if MESSAGE_FORCE_SECURE_IMAGES}true{else}false{/if},
247 highlighters: highlighters,
249 external: {if IMAGE_ALLOW_EXTERNAL_SOURCE}true{else}false{/if},
250 secureOnly: {if MESSAGE_FORCE_SECURE_IMAGES}true{else}false{/if},
252 {implode from=$__wcf->getBBCodeHandler()->getImageExternalSourceWhitelist() item=$hostname}'{$hostname|encodeJS}'{/implode}
255 media: {if $__wcf->session->getPermission('admin.content.cms.canUseMedia')}true{else}false{/if},
256 mediaUrl: '{link controller='Media' id=-123456789 thumbnail='void' forceFrontend=true}{/link}'
260 // The caret is misaligned in Safari 13+ when using \u200b.
261 if (Environment.browser() === 'safari') {
262 config.emptyHtml = '<p><br></p>';
266 if (elDataBool(element, 'support-mention')) {
267 config.plugins.push('WoltLabMention');
271 {if $__wcf->session->getPermission('admin.content.cms.canUseMedia')}
273 var index = config.buttons.indexOf('woltlabMedia');
275 config.buttons.splice(index, 1);
279 config.plugins.push('WoltLabMedia');
283 {if $__redactorConfig|isset}{@$__redactorConfig}{/if}
284 {assign var=__redactorConfig value=''}
286 {event name='redactorConfig'}
288 // load the button plugin last to ensure all buttons have been initialized
289 // already and we can safely add all icons
290 config.plugins.push('WoltLabButton');
292 var content = element.value;
295 config.callbacks = config.callbacks || { };
296 config.callbacks.init = function() {
297 // slight delay to allow Redactor to initialize itself
298 window.setTimeout(function() {
299 if (content === '' && (Environment.platform() === 'ios' || Environment.browser() === 'safari')) {
300 content = '<p><br></p>';
303 content = UiRedactorMetacode.convertFromHtml(element.id, content);
305 var redactor = $(element).data('redactor');
308 redactor.code.start(content);
309 redactor.WoltLabImage.validateImages();
312 redactor.core.textarea().val(redactor.clean.onSync(redactor.$editor.html()));
313 redactor.code.html = false;
315 // work-around for autosave notice being stuck
316 window.setTimeout(function() {
317 var autosaveNotice = elBySel('.redactorAutosaveRestored.active', element.parentNode);
318 if (autosaveNotice) {
319 autosaveNotice.style.setProperty('position', 'static', '');
322 //noinspection BadExpressionStatementJS
323 autosaveNotice.offsetTop;
325 autosaveNotice.style.removeProperty('position');
332 $(element).redactor(config);