cryptpad/www/pad/inner.js

761 lines
30 KiB
JavaScript
Raw Normal View History

2017-08-28 18:25:05 +08:00
require(['/api/config'], function (ApiConfig) {
// see ckeditor_base.js getUrl()
window.CKEDITOR_GETURL = function (resource) {
if (resource.indexOf( '/' ) === 0) {
resource = window.CKEDITOR.basePath.replace(/\/bower_components\/.*/, '') + resource;
} else if (resource.indexOf(':/') === -1) {
resource = window.CKEDITOR.basePath + resource;
}
if (resource[resource.length - 1] !== '/' && resource.indexOf('ver=') === -1) {
var args = ApiConfig.requireConf.urlArgs;
if (resource.indexOf('/bower_components/') !== -1) {
args = 'ver=' + window.CKEDITOR.timestamp;
}
resource += (resource.indexOf('?') >= 0 ? '&' : '?') + args;
}
return resource;
};
require(['/bower_components/ckeditor/ckeditor.js']);
});
define([
2017-08-28 18:25:05 +08:00
'jquery',
'/bower_components/hyperjson/hyperjson.js',
'/common/sframe-app-framework.js',
2017-08-28 18:25:05 +08:00
'/common/cursor.js',
'/common/TypingTests.js',
'/customize/messages.js',
2017-08-28 18:25:05 +08:00
'/pad/links.js',
'/bower_components/nthen/index.js',
2017-09-15 19:21:37 +08:00
'/common/media-tag.js',
2017-08-28 18:25:05 +08:00
'/api/config',
'/common/common-hash.js',
'/common/common-util.js',
'/bower_components/chainpad/chainpad.dist.js',
'/customize/application_config.js',
2017-08-28 18:25:05 +08:00
'/bower_components/diff-dom/diffDOM.js',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
2018-03-22 01:31:53 +08:00
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
2017-09-04 21:09:54 +08:00
'less!/customize/src/less2/main.less',
2017-08-28 18:25:05 +08:00
], function (
$,
Hyperjson,
Framework,
2017-08-28 18:25:05 +08:00
Cursor,
TypingTest,
Messages,
2017-08-28 18:25:05 +08:00
Links,
nThen,
2017-09-15 19:21:37 +08:00
MediaTag,
2017-09-25 23:35:25 +08:00
ApiConfig,
Hash,
Util,
ChainPad,
AppConfig)
2017-08-28 18:25:05 +08:00
{
var DiffDom = window.diffDOM;
var slice = function (coll) {
return Array.prototype.slice.call(coll);
};
var removeListeners = function (root) {
slice(root.attributes).map(function (attr) {
if (/^on/.test(attr.name)) {
root.attributes.removeNamedItem(attr.name);
}
});
slice(root.children).forEach(removeListeners);
};
var hjsonToDom = function (H) {
var dom = Hyperjson.toDOM(H);
removeListeners(dom);
return dom;
};
var module = window.REALTIME_MODULE = window.APP = {
Hyperjson: Hyperjson,
logFights: true,
fights: [],
Cursor: Cursor,
};
// MEDIATAG: Filter elements to serialize
// * Remove the drag&drop and resizers from the hyperjson
2018-04-20 21:33:14 +08:00
var isWidget = function (el) {
return typeof (el.getAttribute) === "function" &&
(el.getAttribute('data-cke-hidden-sel') ||
(el.getAttribute('class') &&
(/cke_widget_drag/.test(el.getAttribute('class')) ||
/cke_image_resizer/.test(el.getAttribute('class')))
)
);
};
2017-08-28 18:25:05 +08:00
var isNotMagicLine = function (el) {
return !(el && typeof(el.getAttribute) === 'function' &&
el.getAttribute('class') &&
el.getAttribute('class').split(' ').indexOf('non-realtime') !== -1);
};
2018-04-20 21:33:14 +08:00
var shouldSerialize = function (el) {
return isNotMagicLine(el) && !isWidget(el);
};
// MEDIATAG: Filter attributes in the serialized elements
2018-04-20 21:33:14 +08:00
var widgetFilter = function (hj) {
// Send a widget ID == 0 to avoid a fight between browsers and
2018-04-20 21:33:14 +08:00
// prevent the container from having the "selected" class (blue border)
if (hj[1].class) {
var split = hj[1].class.split(' ');
if (split.indexOf('cke_widget_wrapper') !== -1 &&
split.indexOf('cke_widget_block') !== -1) {
hj[1].class = "cke_widget_wrapper cke_widget_block";
hj[1]['data-cke-widget-id'] = "0";
}
if (split.indexOf('cke_widget_wrapper') !== -1 &&
split.indexOf('cke_widget_inline') !== -1) {
hj[1].class = "cke_widget_wrapper cke_widget_inline";
2018-04-23 20:33:39 +08:00
delete hj[1]['data-cke-widget-id'];
//hj[1]['data-cke-widget-id'] = "0";
2018-04-20 21:33:14 +08:00
}
// Remove the title attribute of the drag&drop icons (translation conflicts)
2018-04-20 21:33:14 +08:00
if (split.indexOf('cke_widget_drag_handler') !== -1 ||
split.indexOf('cke_image_resizer') !== -1) {
hj[1].title = undefined;
}
}
return hj;
};
2017-09-15 19:21:37 +08:00
var hjsonFilters = function (hj) {
2017-09-25 23:35:25 +08:00
/* catch `type="_moz"` before it goes over the wire */
var brFilter = function (hj) {
if (hj[1].type === '_moz') { hj[1].type = undefined; }
return hj;
};
var mediatagContentFilter = function (hj) {
if (hj[0] === 'MEDIA-TAG') { hj[2] = []; }
return hj;
};
2017-09-15 19:21:37 +08:00
brFilter(hj);
mediatagContentFilter(hj);
2018-04-20 21:33:14 +08:00
widgetFilter(hj);
2017-08-28 18:25:05 +08:00
return hj;
};
var domFromHTML = function (html) {
return new DOMParser().parseFromString(html, 'text/html');
};
var forbiddenTags = [
'SCRIPT',
2017-09-15 19:21:37 +08:00
//'IFRAME',
2017-08-28 18:25:05 +08:00
'OBJECT',
'APPLET',
2017-09-15 19:21:37 +08:00
//'VIDEO',
//'AUDIO'
2017-08-28 18:25:05 +08:00
];
var getHTML = function (inner) {
return ('<!DOCTYPE html>\n' + '<html>\n' + inner.innerHTML);
};
var CKEDITOR_CHECK_INTERVAL = 100;
var ckEditorAvailable = function (cb) {
var intr;
var check = function () {
if (window.CKEDITOR) {
clearTimeout(intr);
cb(window.CKEDITOR);
}
};
intr = setInterval(function () {
console.log("Ckeditor was not defined. Trying again in %sms", CKEDITOR_CHECK_INTERVAL);
check();
}, CKEDITOR_CHECK_INTERVAL);
check();
};
2018-02-28 00:38:29 +08:00
var mkHelpMenu = function (framework) {
var $toolbarContainer = $('.cke_toolbox_main');
var helpMenu = framework._.sfCommon.createHelpMenu(['text', 'pad']);
2018-02-28 00:38:29 +08:00
$toolbarContainer.before(helpMenu.menu);
framework._.toolbar.$drawer.append(helpMenu.button);
2018-02-28 00:38:29 +08:00
};
2017-08-28 18:25:05 +08:00
var mkDiffOptions = function (cursor, readOnly) {
return {
preDiffApply: function (info) {
/*
Don't accept attributes that begin with 'on'
these are probably listeners, and we don't want to
send scripts over the wire.
*/
if (['addAttribute', 'modifyAttribute'].indexOf(info.diff.action) !== -1) {
if (info.diff.name === 'href') {
// console.log(info.diff);
//var href = info.diff.newValue;
// TODO normalize HTML entities
if (/javascript *: */.test(info.diff.newValue)) {
// TODO remove javascript: links
}
}
if (/^on/.test(info.diff.name)) {
console.log("Rejecting forbidden element attribute with name (%s)", info.diff.name);
return true;
}
}
2018-04-19 23:45:08 +08:00
// MEDIATAG
// Never modify widget ids
2018-04-23 20:33:39 +08:00
if (info.node && info.node.tagName === 'SPAN' && info.diff.name === 'data-cke-widget-id') {
return true;
}
if (info.node && info.node.tagName === 'SPAN' &&
info.node.getAttribute('class') &&
/cke_widget_wrapper/.test(info.node.getAttribute('class'))) {
if (info.diff.action === 'modifyAttribute' && info.diff.name === 'class') {
2018-04-20 21:33:14 +08:00
return true;
}
//console.log(info);
}
// CkEditor drag&drop icon container
if (info.node && info.node.tagName === 'SPAN' &&
2018-04-20 21:33:14 +08:00
info.node.getAttribute('class') &&
info.node.getAttribute('class').split(' ').indexOf('cke_widget_drag_handler_container') !== -1) {
return true;
}
// CkEditor drag&drop title (language fight)
if (info.node && info.node.getAttribute &&
info.node.getAttribute('class') &&
(info.node.getAttribute('class').split(' ').indexOf('cke_widget_drag_handler') !== -1 ||
info.node.getAttribute('class').split(' ').indexOf('cke_image_resizer') !== -1 ) ) {
return true;
}
2018-04-19 23:45:08 +08:00
2017-08-28 18:25:05 +08:00
/*
Also reject any elements which would insert any one of
our forbidden tag types: script, iframe, object,
applet, video, or audio
*/
if (['addElement', 'replaceElement'].indexOf(info.diff.action) !== -1) {
if (info.diff.element && forbiddenTags.indexOf(info.diff.element.nodeName) !== -1) {
console.log("Rejecting forbidden tag of type (%s)", info.diff.element.nodeName);
return true;
} else if (info.diff.newValue && forbiddenTags.indexOf(info.diff.newValue.nodeType) !== -1) {
console.log("Rejecting forbidden tag of type (%s)", info.diff.newValue.nodeName);
return true;
}
}
if (info.node && info.node.tagName === 'BODY') {
if (info.diff.action === 'removeAttribute' &&
['class', 'spellcheck'].indexOf(info.diff.name) !== -1) {
return true;
}
}
/* DiffDOM will filter out magicline plugin elements
in practice this will make it impossible to use it
while someone else is typing, which could be annoying.
we should check when such an element is going to be
removed, and prevent that from happening. */
if (info.node && info.node.tagName === 'SPAN' &&
info.node.getAttribute('contentEditable') === "false") {
// it seems to be a magicline plugin element...
// but it can also be a widget (MEDIATAG), in which case the removal was
2018-04-20 21:33:14 +08:00
// probably intentional
2017-08-28 18:25:05 +08:00
if (info.diff.action === 'removeElement') {
// and you're about to remove it...
2018-04-20 21:33:14 +08:00
if (!info.node.getAttribute('class') ||
!/cke_widget_wrapper/.test(info.node.getAttribute('class'))) {
// This element is not a widget!
// this probably isn't what you want
/*
I have never seen this in the console, but the
magic line is still getting removed on remote
edits. This suggests that it's getting removed
by something other than diffDom.
*/
console.log("preventing removal of the magic line!");
// return true to prevent diff application
return true;
}
2017-08-28 18:25:05 +08:00
}
}
// Do not change the contenteditable value in view mode
if (readOnly && info.node && info.node.tagName === 'BODY' &&
info.diff.action === 'modifyAttribute' && info.diff.name === 'contenteditable') {
return true;
}
cursor.update();
2017-08-28 18:25:05 +08:00
// no use trying to recover the cursor if it doesn't exist
if (!cursor.exists()) { return; }
/* frame is either 0, 1, 2, or 3, depending on which
cursor frames were affected: none, first, last, or both
*/
var frame = info.frame = cursor.inNode(info.node);
if (!frame) { return; }
if (typeof info.diff.oldValue === 'string' && typeof info.diff.newValue === 'string') {
var pushes = cursor.pushDelta(info.diff.oldValue, info.diff.newValue);
if (frame & 1) {
// push cursor start if necessary
if (pushes.commonStart < cursor.Range.start.offset) {
cursor.Range.start.offset += pushes.delta;
}
}
if (frame & 2) {
// push cursor end if necessary
if (pushes.commonStart < cursor.Range.end.offset) {
cursor.Range.end.offset += pushes.delta;
}
}
}
},
postDiffApply: function (info) {
if (info.frame) {
if (info.node) {
if (info.frame & 1) { cursor.fixStart(info.node); }
if (info.frame & 2) { cursor.fixEnd(info.node); }
} else { console.error("info.node did not exist"); }
var sel = cursor.makeSelection();
var range = cursor.makeRange();
cursor.fixSelection(sel, range);
}
}
};
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
var addToolbarHideBtn = function (framework, $bar) {
// Expand / collapse the toolbar
var cfg = {
element: $bar.find('.cke_toolbox_main')
};
var onClick = function (visible) {
framework._.sfCommon.setAttribute(['pad', 'showToolbar'], visible);
};
framework._.sfCommon.getAttribute(['pad', 'showToolbar'], function (err, data) {
2018-03-20 22:13:00 +08:00
if (($(window).height() >= 800 || $(window).width() >= 800) &&
2018-03-20 22:07:20 +08:00
(typeof(data) === "undefined" || data)) { $('.cke_toolbox_main').show(); }
else { $('.cke_toolbox_main').hide(); }
var $collapse = framework._.sfCommon.createButton('toggle', true, cfg, onClick);
framework._.toolbar.$rightside.append($collapse);
});
};
2017-08-28 18:25:05 +08:00
var displayMediaTags = function (framework, dom, mediaTagMap) {
setTimeout(function () { // Just in case
var tags = dom.querySelectorAll('media-tag:empty');
Array.prototype.slice.call(tags).forEach(function (el) {
MediaTag(el);
$(el).on('keydown', function (e) {
if ([8,46].indexOf(e.which) !== -1) {
$(el).remove();
framework.localChange();
}
});
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type === 'childList') {
var list_values = [].slice.call(el.children);
mediaTagMap[el.getAttribute('src')] = list_values;
}
});
});
observer.observe(el, {
attributes: false,
childList: true,
characterData: false
});
});
});
};
var restoreMediaTags = function (tempDom, mediaTagMap) {
var tags = tempDom.querySelectorAll('media-tag:empty');
Array.prototype.slice.call(tags).forEach(function (tag) {
var src = tag.getAttribute('src');
if (mediaTagMap[src]) {
mediaTagMap[src].forEach(function (n) {
2018-04-23 21:35:55 +08:00
tag.appendChild(n.cloneNode());
});
}
});
};
var andThen2 = function (editor, Ckeditor, framework) {
var mediaTagMap = {};
2017-08-28 18:25:05 +08:00
var $bar = $('#cke_1_toolbox');
2018-02-28 00:38:29 +08:00
var $contentContainer = $('#cke_1_contents');
2017-08-28 18:25:05 +08:00
var $html = $bar.closest('html');
var $faLink = $html.find('head link[href*="/bower_components/components-font-awesome/css/font-awesome.min.css"]');
if ($faLink.length) {
$html.find('iframe').contents().find('head').append($faLink.clone());
}
var ml = Ckeditor.instances.editor1.plugins.magicline.backdoor.that.line.$;
[ml, ml.parentElement].forEach(function (el) {
el.setAttribute('class', 'non-realtime');
});
var ifrWindow = $html.find('iframe')[0].contentWindow;
var documentBody = ifrWindow.document.body;
var inner = window.inner = documentBody;
var cursor = module.cursor = Cursor(inner);
var openLink = function (e) {
var el = e.currentTarget;
if (!el || el.nodeName !== 'A') { return; }
var href = el.getAttribute('href');
if (href) {
framework._.sfCommon.openUnsafeURL(href);
}
2017-08-28 18:25:05 +08:00
};
2018-02-28 00:38:29 +08:00
mkHelpMenu(framework);
2017-10-13 18:40:51 +08:00
framework.onEditableChange(function (unlocked) {
if (!framework.isReadOnly()) {
$(inner).attr('contenteditable', '' + Boolean(unlocked));
}
$(inner).css({ background: unlocked ? '#fff' : '#eee' });
});
framework.setMediaTagEmbedder(function ($mt) {
$mt.attr('contenteditable', 'false');
2018-04-19 23:45:08 +08:00
//$mt.attr('tabindex', '1');
2018-04-23 21:38:21 +08:00
//MEDIATAG
2018-04-23 20:33:39 +08:00
var element = new window.CKEDITOR.dom.element($mt[0]);
editor.insertElement(element);
2018-04-23 21:38:21 +08:00
editor.widgets.initOn( element, 'mediatag' );
});
2017-08-28 18:25:05 +08:00
framework.setTitleRecommender(function () {
2017-08-28 18:25:05 +08:00
var text;
if (['h1', 'h2', 'h3'].some(function (t) {
var $header = $(inner).find(t + ':first-of-type');
if ($header.length && $header.text()) {
text = $header.text();
return true;
}
})) { return text; }
});
2017-08-28 18:25:05 +08:00
var DD = new DiffDom(mkDiffOptions(cursor, framework.isReadOnly()));
2017-08-28 18:25:05 +08:00
// apply patches, and try not to lose the cursor in the process!
framework.onContentUpdate(function (hjson) {
if (!Array.isArray(hjson)) { throw new Error(Messages.typeError); }
var userDocStateDom = hjsonToDom(hjson);
userDocStateDom.setAttribute("contenteditable",
inner.getAttribute('contenteditable'));
2017-08-28 18:25:05 +08:00
restoreMediaTags(userDocStateDom, mediaTagMap);
// Deal with adjasent text nodes
userDocStateDom.normalize();
inner.normalize();
2017-08-28 18:25:05 +08:00
var patch = (DD).diff(inner, userDocStateDom);
(DD).apply(inner, patch);
// MEDIATAG: Migrate old mediatags to the widget system
$(inner).find('media-tag:not(.cke_widget_element)').each(function (i, el) {
var element = new window.CKEDITOR.dom.element(el);
2018-04-23 21:38:21 +08:00
editor.widgets.initOn( element, 'mediatag' );
});
displayMediaTags(framework, inner, mediaTagMap);
// MEDIATAG: Initialize mediatag widgets inserted in the document by other users
2018-04-19 23:45:08 +08:00
editor.widgets.checkWidgets();
if (framework.isReadOnly()) {
2017-08-28 18:25:05 +08:00
var $links = $(inner).find('a');
// off so that we don't end up with multiple identical handlers
$links.off('click', openLink).on('click', openLink);
}
});
2017-08-28 18:25:05 +08:00
2018-02-01 17:09:08 +08:00
framework.setTextContentGetter(function () {
var innerCopy = inner.cloneNode(true);
displayMediaTags(framework, innerCopy, mediaTagMap);
innerCopy.normalize();
$(innerCopy).find('*').each(function (i, el) {
$(el).append(' ');
});
var str = $(innerCopy).text();
str = str.replace(/\s\s+/g, ' ');
return str;
});
framework.setContentGetter(function () {
displayMediaTags(framework, inner, mediaTagMap);
inner.normalize();
return Hyperjson.fromDOM(inner, shouldSerialize, hjsonFilters);
});
2017-08-28 18:25:05 +08:00
$bar.find('#cke_1_toolbar_collapser').hide();
if (!framework.isReadOnly()) {
2018-02-28 00:38:29 +08:00
addToolbarHideBtn(framework, $contentContainer);
} else {
$('.cke_toolbox_main').hide();
}
2017-08-28 18:25:05 +08:00
framework.onReady(function (newPad) {
2018-02-28 20:16:30 +08:00
editor.focus();
2017-08-28 18:25:05 +08:00
if (!module.isMaximized) {
module.isMaximized = true;
$('iframe.cke_wysiwyg_frame').css('width', '');
$('iframe.cke_wysiwyg_frame').css('height', '');
}
$('body').addClass('app-pad');
if (newPad) {
cursor.setToEnd();
} else if (framework.isReadOnly()) {
2017-08-28 18:25:05 +08:00
cursor.setToStart();
}
2017-12-20 19:15:43 +08:00
if (framework.isReadOnly()) {
$(inner).attr('contenteditable', 'false');
}
var fmConfig = {
ckeditor: editor,
body: $('body'),
onUploaded: function (ev, data) {
// PASSWORD_FILES
var parsed = Hash.parsePadUrl(data.url);
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
var mt = '<media-tag contenteditable="false" src="' + src + '" data-crypto-key="cryptpad:' + parsed.hashData.key + '" tabindex="1"></media-tag>';
2018-04-23 21:38:21 +08:00
// MEDIATAG
2018-04-23 20:33:39 +08:00
var element = window.CKEDITOR.dom.element.createFromHtml(mt);
editor.insertElement(element);
2018-04-23 21:38:21 +08:00
editor.widgets.initOn( element, 'mediatag' );
}
};
2017-09-25 23:35:25 +08:00
window.APP.FM = framework._.sfCommon.createFileManager(fmConfig);
framework._.sfCommon.getAttribute(['pad', 'width'], function (err, data) {
if (data) {
var $iframe = $('html').find('iframe').contents();
$iframe.find('html').addClass('cke_body_width');
}
});
2018-02-28 20:16:30 +08:00
/*setTimeout(function () {
$('iframe.cke_wysiwyg_frame').focus();
editor.focus();
console.log(editor);
console.log(editor.focusManager);
$(window).trigger('resize');
});*/
});
2017-08-28 18:25:05 +08:00
2018-02-28 20:16:30 +08:00
framework.onDefaultContentNeeded(function () {
inner.innerHTML = '<p></p>';
});
2017-08-28 18:25:05 +08:00
var importMediaTags = function (dom, cb) {
var $dom = $(dom);
$dom.find('media-tag').each(function (i, el) {
$(el).empty();
});
cb($dom[0]);
};
framework.setFileImporter({ accept: 'text/html' }, function (content, f, cb) {
importMediaTags(domFromHTML(content).body, function (dom) {
cb(Hyperjson.fromDOM(dom));
});
}, true);
var exportMediaTags = function (inner, cb) {
var $clone = $(inner).clone();
nThen(function (waitFor) {
$(inner).find('media-tag').each(function (i, el) {
if (!$(el).data('blob')) { return; }
Util.blobToImage($(el).data('blob'), waitFor(function (imgSrc) {
$clone.find('media-tag[src="' + $(el).attr('src') + '"] img')
.attr('src', imgSrc);
2018-04-30 17:40:41 +08:00
$clone.find('media-tag').parent()
.find('.cke_widget_drag_handler_container').remove();
}));
});
}).nThen(function () {
cb($clone[0]);
});
};
framework.setFileExporter('html', function (cb) {
exportMediaTags(inner, function (toExport) {
cb(new Blob([ getHTML(toExport) ], { type: "text/html;charset=utf-8" }));
});
}, true);
framework.setNormalizer(function (hjson) {
return [
'BODY',
{
"class": "cke_editable cke_editable_themed cke_contents_ltr cke_show_borders",
"contenteditable": "true",
"spellcheck":"false"
},
hjson[2]
];
});
2017-08-28 18:25:05 +08:00
/* hitting enter makes a new line, but places the cursor inside
of the <br> instead of the <p>. This makes it such that you
cannot type until you click, which is rather unnacceptable.
If the cursor is ever inside such a <br>, you probably want
to push it out to the parent element, which ought to be a
paragraph tag. This needs to be done on keydown, otherwise
the first such keypress will not be inserted into the P. */
inner.addEventListener('keydown', cursor.brFix);
editor.on('change', framework.localChange);
2017-08-28 18:25:05 +08:00
// export the typing tests to the window.
// call like `test = easyTest()`
// terminate the test like `test.cancel()`
window.easyTest = function () {
cursor.update();
var start = cursor.Range.start;
var test = TypingTest.testInput(inner, start.el, start.offset, framework.localChange);
framework.localChange();
2017-08-28 18:25:05 +08:00
return test;
};
$bar.find('.cke_button').click(function () {
var e = this;
var classString = e.getAttribute('class');
var classes = classString.split(' ').filter(function (c) {
return /cke_button__/.test(c);
});
var id = classes[0];
if (typeof(id) === 'string') {
framework.feedback(id.toUpperCase());
2017-08-28 18:25:05 +08:00
}
});
framework.start();
2017-08-28 18:25:05 +08:00
};
var main = function () {
var Ckeditor;
var editor;
var framework;
2017-08-28 18:25:05 +08:00
nThen(function (waitFor) {
Framework.create({
toolbarContainer: '#cke_1_toolbox',
2018-02-28 00:38:29 +08:00
contentContainer: '#cke_editor1 > .cke_inner',
patchTransformer: ChainPad.NaiveJSONTransformer,
2018-02-28 00:38:29 +08:00
/*thumbnail: {
2017-10-26 18:31:16 +08:00
getContainer: function () { return $('iframe').contents().find('html')[0]; },
filter: function (el, before) {
if (before) {
2017-11-03 02:11:27 +08:00
module.cursor.update();
2017-10-26 18:31:16 +08:00
$(el).parents().css('overflow', 'visible');
$(el).css('max-width', '1200px');
$(el).css('max-height', Math.max(600, $(el).width()) + 'px');
$(el).css('overflow', 'hidden');
$(el).find('body').css('background-color', 'transparent');
return;
}
$(el).parents().css('overflow', '');
$(el).css('max-width', '');
$(el).css('max-height', '');
$(el).css('overflow', '');
$(el).find('body').css('background-color', '#fff');
2017-11-03 02:11:27 +08:00
var sel = module.cursor.makeSelection();
var range = module.cursor.makeRange();
module.cursor.fixSelection(sel, range);
2017-10-26 18:31:16 +08:00
}
2018-02-28 00:38:29 +08:00
}*/
}, waitFor(function (fw) { window.APP.framework = framework = fw; }));
nThen(function (waitFor) {
ckEditorAvailable(waitFor(function (ck) {
Ckeditor = ck;
require(['/pad/wysiwygarea-plugin.js'], waitFor());
}));
$(waitFor());
}).nThen(function (waitFor) {
Ckeditor.config.toolbarCanCollapse = true;
if (screen.height < 800) {
Ckeditor.config.toolbarStartupExpanded = false;
$('meta[name=viewport]').attr('content',
'width=device-width, initial-scale=1.0, user-scalable=no');
} else {
$('meta[name=viewport]').attr('content',
'width=device-width, initial-scale=1.0, user-scalable=yes');
}
// Used in ckeditor-config.js
Ckeditor.CRYPTPAD_URLARGS = ApiConfig.requireConf.urlArgs;
var backColor = AppConfig.appBackgroundColor;
var newCss = '.cke_body_width { background: '+ backColor +'; height: 100%; }' +
'.cke_body_width body {' +
2018-02-28 20:16:30 +08:00
'max-width: 50em; padding: 20px 30px; margin: 0 auto; min-height: 100%;'+
'box-sizing: border-box; overflow: auto;'+
'}' +
'.cke_body_width body > *:first-child { margin-top: 0; }';
Ckeditor.addCss(newCss);
Ckeditor.plugins.addExternal('mediatag','/pad/', 'mediatag-plugin.js');
module.ckeditor = editor = Ckeditor.replace('editor1', {
customConfig: '/customize/ckeditor-config.js',
});
editor.on('instanceReady', waitFor());
}).nThen(function () {
editor.plugins.mediatag.translations = {
title: Messages.pad_mediatagTitle,
width: Messages.pad_mediatagWidth,
height: Messages.pad_mediatagHeight
};
Links.addSupportForOpeningLinksInNewTab(Ckeditor)({editor: editor});
2018-02-28 00:38:29 +08:00
}).nThen(function () {
// Move ckeditor parts to have a structure like the other apps
var $toolbarContainer = $('#cke_1_top');
var $contentContainer = $('#cke_1_contents');
var $mainContainer = $('#cke_editor1');
$contentContainer.prepend($toolbarContainer.find('.cke_toolbox_main'));
$mainContainer.prepend($toolbarContainer);
$contentContainer.find('.cke_toolbox_main').addClass('cke_reset_all');
$toolbarContainer.removeClass('cke_reset_all');
}).nThen(waitFor());
}).nThen(function (/*waitFor*/) {
andThen2(editor, Ckeditor, framework);
2017-08-28 18:25:05 +08:00
});
};
main();
});