nodebb-plugin-composer-redactor
Version:
Redactor Composer for NodeBB
222 lines (187 loc) • 8.5 kB
JavaScript
/* globals define, socket, app, config, ajaxify, utils, templates, bootbox */
define('redactor', [
'composer',
'translator',
'composer/autocomplete',
'composer/resize',
'scrollStop'
], function (composer, translator, autocomplete, resize, scrollStop) {
function redactorify(textarea, data) {
var textDirection = $('html').attr('data-dir');
$(window).trigger('action:redactor.load', $.Redactor);
$(window).off('action:redactor.load');
var options = {
direction: textDirection || undefined,
imageUploadFields: {
'_csrf': config.csrf_token
},
fileUploadFields: {
'_csrf': config.csrf_token
},
};
if (data.height) {
options.maxHeight = parseInt(data.height, 10) || undefined;
}
if (data.onChange && typeof data.onChange === 'function') {
options.callbacks = options.callbacks || {};
options.callbacks.change = data.onChange;
}
textarea.redactor(options);
};
$(window).on('action:composer.loaded', function (ev, data) {
var postContainer = $('.composer[data-uuid="' + data.post_uuid + '"]')
var textarea = postContainer.find('textarea');
redactorify(textarea, data);
var cidEl = postContainer.find('.category-list');
if (cidEl.length) {
cidEl.attr('id', 'cmp-cid-' + data.post_uuid);
} else {
postContainer.append('<input id="cmp-cid-' + data.post_uuid + '" type="hidden" value="' + ajaxify.data.cid + '"/>');
}
if (config.allowTopicsThumbnail && data.composerData.isMain) {
var thumbToggleBtnEl = postContainer.find('.re-topic_thumb');
var url = data.composerData.topic_thumb || '';
postContainer.find('input#topic-thumb-url').val(url);
postContainer.find('img.topic-thumb-preview').attr('src', url);
if (url) {
postContainer.find('.topic-thumb-clear-btn').removeClass('hide');
}
thumbToggleBtnEl.addClass('show');
thumbToggleBtnEl.off('click').on('click', function() {
var container = postContainer.find('.topic-thumb-container');
container.toggleClass('hide', !container.hasClass('hide'));
});
}
var editor = postContainer.find('.redactor-layer');
editor.addClass('write');
scrollStop.apply(editor);
autocomplete.init(postContainer, data.post_uuid);
resize.reposition(postContainer);
});
$(window).on('action:composer.submit', function (e, data) {
// Remove all empty paragraph blocks from composer content
data.composerData.content = data.composerData.content.replace(/<p>(<br>| )+<\/p>/gm, '');
});
$(window).on('action:chat.loaded', function (e, containerEl) {
var composerEl = $(containerEl).find('[component="chat/composer"]');
var inputEl = composerEl.find('textarea.chat-input');
redactorify(inputEl, {
height: 120,
onChange: function () {
var element = composerEl.find('[component="chat/message/remaining"]');
var curLength = utils.stripHTMLTags(this.code.get()).length;
element.text(config.maximumChatMessageLength - curLength);
}
});
});
$(window).on('action:chat.sent', function (e, data) {
// Empty chat input
var redactor = $('.chat-modal[data-roomid="' + data.roomId + '"] .chat-input, .expanded-chat[data-roomid="' + data.roomId + '"] .chat-input');
redactor.each(function () {
$(this).redactor('core.object').code.set('');
});
});
// Topic Thumb
$.Redactor.prototype.topic_thumb = function () {
return {
init: function () {
var that = this;
translator.translate('[[topic:composer.thumb_title]]', function (translated) {
var btnEl = that.button.add('topic_thumb', translated);
that.button.setIcon(btnEl, '<i class="fa fa-th-large topic-thumb-btn topic-thumb-toggle-btn"></i>');
});
}
};
};
$.Redactor.prototype.underline = function()
{
return {
init: function()
{
var button = this.button.addAfter('italic', 'underline', 'U');
this.button.addCallback(button, this.underline.format);
},
format: function()
{
this.inline.format('u');
}
};
};
$.Redactor.prototype.iconic = function()
{
return {
init: function ()
{
var icons = {
'format': '<i class="fa fa-paragraph"></i>',
'ol': '<i class="fa fa-list-ol"></i>',
'ul': '<i class="fa fa-list-ul"></i>',
'link': '<i class="fa fa-link"></i>',
'horizontalrule': '<i class="fa fa-minus"></i>',
'image': '<i class="fa fa-picture-o"></i>',
'indent': '<i class="fa fa-indent"></i>',
'outdent': '<i class="fa fa-outdent"></i>',
'emoticons': '<i class="fa fa-smile-o"></i>',
'video': '<i class="fa fa-video-camera"></i>',
'file': '<i class="fa fa-upload"></i>',
'table': '<i class="fa fa-table"></i>'
};
$.each(this.button.all(), $.proxy(function(i,s)
{
var key = $(s).attr('rel');
if (typeof icons[key] !== 'undefined')
{
var icon = icons[key];
var button = this.button.get(key);
this.button.setIcon(button, icon);
}
}, this));
}
};
};
// Redactor Options
$.Redactor.opts.buttons.splice($.Redactor.opts.buttons.indexOf('lists'), 1, 'horizontalrule', 'ol', 'ul', 'indent', 'outdent');
$.Redactor.opts.plugins = ['video', 'table', 'topic_thumb', 'underline', 'emoticons', 'iconic'];
$.Redactor.opts.focusEnd = true;
$.Redactor.opts.imageUpload = config.relative_path + '/api/post/upload';
$.Redactor.opts.imageUploadParam = 'files[]';
$.Redactor.opts.imageUploadKey = 'url';
// Redactor error handling
const errorHandler = (payload) => {
app.alertError(payload.status.message);
}
$.Redactor.opts.callbacks.imageUploadError = errorHandler;
$.Redactor.opts.callbacks.fileUploadError = errorHandler;
if (app.user.privileges['upload:post:file']) {
$.Redactor.opts.fileUpload = config.relative_path + '/api/post/upload';
$.Redactor.opts.fileUploadParam = 'files[]';
}
var redactor = {};
redactor.addQuote = function (tid, pid, title, username, text) {
var uuid = composer.findByTid(tid) || composer.active;
var escapedTitle = (title || '').replace(/([\\`*_{}\[\]()#+\-.!])/g, '\\$1').replace(/\[/g, '[').replace(/\]/g, ']').replace(/%/g, '%').replace(/,/g, ',');
if (text) {
text = "<blockquote>" + text.replace(/[\u00A0-\u9999<>\&]/gim, function(i) {
return '&#'+i.charCodeAt(0)+';';
}) + "</blockquote>";
}
if (uuid === undefined) {
return composer.newReply(tid, pid, title, '[[modules:composer.user_said, ' + username + ']]\n' + text + '<p> </p>');
} else if (uuid !== composer.active) {
// If the composer is not currently active, activate it
composer.load(uuid);
}
// There is a composer open already, append this blockquote to the text
var postContainer = $('.composer[data-uuid="' + uuid + '"]');
var bodyEl = postContainer.find('textarea');
var prevText = bodyEl.val();
translator.translate('[[modules:composer.user_said, ' + username + ']]\n', config.defaultLang, onTranslated);
function onTranslated(translated) {
composer.posts[uuid].body = (prevText.length ? prevText + '\n\n' : '') + translated + text + '<p> </p>';
bodyEl.redactor('insert.html', translated + text + '<p> </p>');
bodyEl.redactor('focus.end');
}
};
return redactor;
});
;