diff --git a/customize.dist/header.js b/customize.dist/header.js deleted file mode 100644 index 5e0dcc881..000000000 --- a/customize.dist/header.js +++ /dev/null @@ -1,54 +0,0 @@ -define([ - 'jquery', - '/customize/application_config.js', - '/common/cryptpad-common.js', - '/api/config', -], function ($, Config, Cryptpad, ApiConfig) { - - window.APP = { - Cryptpad: Cryptpad, - }; - - var Messages = Cryptpad.Messages; - - $(function () { - // Language selector - var $sel = $('#language-selector'); - Cryptpad.createLanguageSelector(undefined, $sel); - $sel.find('button').addClass('btn').addClass('btn-secondary'); - $sel.show(); - - var $upgrade = $('#upgrade'); - - var showUpgrade = function (text, feedback, url) { - if (ApiConfig.removeDonateButton) { return; } - if (localStorage.plan) { return; } - if (!text) { return; } - $upgrade.text(text).show(); - $upgrade.click(function () { - Cryptpad.feedback(feedback); - window.open(url,'_blank'); - }); - }; - - // User admin menu - var $userMenu = $('#user-menu'); - var userMenuCfg = { - $initBlock: $userMenu, - 'static': true - }; - var $userAdmin = Cryptpad.createUserAdminMenu(userMenuCfg); - $userAdmin.find('button').addClass('btn').addClass('btn-secondary'); - - $(window).click(function () { - $('.cp-dropdown-content').hide(); - }); - - if (Cryptpad.isLoggedIn() && ApiConfig.allowSubscriptions) { - showUpgrade(Messages.upgradeAccount, "HOME_UPGRADE_ACCOUNT", Cryptpad.upgradeURL); - } else { - showUpgrade(Messages.supportCryptpad, "HOME_SUPPORT_CRYPTPAD", Cryptpad.donateURL); - } - }); -}); - diff --git a/customize.dist/main.js b/customize.dist/main.js index 5ac45af3a..77fd2eaa3 100644 --- a/customize.dist/main.js +++ b/customize.dist/main.js @@ -2,7 +2,6 @@ define([ 'jquery', '/customize/application_config.js', '/common/cryptpad-common.js', - '/customize/header.js', ], function ($, Config, Cryptpad) { window.APP = { diff --git a/www/common/common-codemirror.js b/www/common/common-codemirror.js deleted file mode 100644 index a32d89af1..000000000 --- a/www/common/common-codemirror.js +++ /dev/null @@ -1,308 +0,0 @@ -define([ - 'jquery', - '/common/modes.js', - '/common/themes.js', - - '/bower_components/file-saver/FileSaver.min.js' -], function ($, Modes, Themes) { - var saveAs = window.saveAs; - var module = {}; - - module.create = function (ifrw, Cryptpad, defaultMode, CMeditor) { - var exp = {}; - var Messages = Cryptpad.Messages; - - var CodeMirror = exp.CodeMirror = CMeditor; - CodeMirror.modeURL = "cm/mode/%N/%N"; - - var $pad = $('#pad-iframe'); - var $textarea = exp.$textarea = $('#editor1'); - if (!$textarea.length) { $textarea = exp.$textarea = $pad.contents().find('#editor1'); } - - var Title; - var onLocal = function () {}; - var $rightside; - var $drawer; - exp.init = function (local, title, toolbar) { - if (typeof local === "function") { - onLocal = local; - } - Title = title; - $rightside = toolbar.$rightside; - $drawer = toolbar.$drawer; - }; - - var editor = exp.editor = CMeditor.fromTextArea($textarea[0], { - lineNumbers: true, - lineWrapping: true, - autoCloseBrackets: true, - matchBrackets : true, - showTrailingSpace : true, - styleActiveLine : true, - search: true, - highlightSelectionMatches: {showToken: /\w+/}, - extraKeys: {"Shift-Ctrl-R": undefined}, - foldGutter: true, - gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], - mode: defaultMode || "javascript", - readOnly: true - }); - editor.setValue(Messages.codeInitialState); - - var setMode = exp.setMode = function (mode, cb) { - exp.highlightMode = mode; - if (mode !== "text") { - CMeditor.autoLoadMode(editor, mode); - } - editor.setOption('mode', mode); - if (exp.$language) { - var name = exp.$language.find('a[data-value="' + mode + '"]').text() || undefined; - name = name ? Messages.languageButton + ' ('+name+')' : Messages.languageButton; - exp.$language.setValue(mode, name); - } - if(cb) { cb(mode); } - }; - - var setTheme = exp.setTheme = (function () { - var path = '/common/theme/'; - - var $head = $(ifrw.document.head); - - var themeLoaded = exp.themeLoaded = function (theme) { - return $head.find('link[href*="'+theme+'"]').length; - }; - - var loadTheme = exp.loadTheme = function (theme) { - $head.append($('', { - rel: 'stylesheet', - href: path + theme + '.css', - })); - }; - - return function (theme, $select) { - if (!theme) { - editor.setOption('theme', 'default'); - } else { - if (!themeLoaded(theme)) { - loadTheme(theme); - } - editor.setOption('theme', theme); - } - if ($select) { - var name = theme || undefined; - name = name ? Messages.themeButton + ' ('+theme+')' : Messages.themeButton; - $select.setValue(theme, name); - } - }; - }()); - - exp.getHeadingText = function () { - var lines = editor.getValue().split(/\n/); - - var text = ''; - lines.some(function (line) { - // lines including a c-style comment are also valuable - var clike = /^\s*(\/\*|\/\/)(.*)?(\*\/)*$/; - if (clike.test(line)) { - line.replace(clike, function (a, one, two) { - if (!(two && two.replace)) { return; } - text = two.replace(/\*\/\s*$/, '').trim(); - }); - return true; - } - - // lisps? - var lispy = /^\s*(;|#\|)+(.*?)$/; - if (lispy.test(line)) { - line.replace(lispy, function (a, one, two) { - text = two; - }); - return true; - } - - // lines beginning with a hash are potentially valuable - // works for markdown, python, bash, etc. - var hash = /^#+(.*?)$/; - if (hash.test(line)) { - line.replace(hash, function (a, one) { - text = one; - }); - return true; - } - - // TODO make one more pass for multiline comments - }); - - return text.trim(); - }; - - exp.configureLanguage = function (cb, onModeChanged) { - var options = []; - Modes.list.forEach(function (l) { - options.push({ - tag: 'a', - attributes: { - 'data-value': l.mode, - 'href': '#', - }, - content: l.language // Pretty name of the language value - }); - }); - var dropdownConfig = { - text: 'Mode', // Button initial text - options: options, // Entries displayed in the menu - left: true, // Open to the left of the button - isSelect: true, - feedback: 'CODE_LANGUAGE', - }; - var $block = exp.$language = Cryptpad.createDropdown(dropdownConfig); - $block.find('button').attr('title', Messages.languageButtonTitle); - $block.find('a').click(function () { - setMode($(this).attr('data-value'), onModeChanged); - onLocal(); - }); - - if ($drawer) { $drawer.append($block); } - if (cb) { cb(); } - }; - - exp.configureTheme = function (cb) { - /* Remember the user's last choice of theme using localStorage */ - var themeKey = 'CRYPTPAD_CODE_THEME'; - var lastTheme = localStorage.getItem(themeKey) || 'default'; - - var options = []; - Themes.forEach(function (l) { - options.push({ - tag: 'a', - attributes: { - 'data-value': l.name, - 'href': '#', - }, - content: l.name // Pretty name of the language value - }); - }); - var dropdownConfig = { - text: 'Theme', // Button initial text - options: options, // Entries displayed in the menu - left: true, // Open to the left of the button - isSelect: true, - initialValue: lastTheme, - feedback: 'CODE_THEME', - }; - var $block = exp.$theme = Cryptpad.createDropdown(dropdownConfig); - $block.find('button').attr('title', Messages.themeButtonTitle); - - setTheme(lastTheme, $block); - - $block.find('a').click(function () { - var theme = $(this).attr('data-value'); - setTheme(theme, $block); - localStorage.setItem(themeKey, theme); - }); - - if ($drawer) { $drawer.append($block); } - if (cb) { cb(); } - }; - - exp.exportText = function () { - var text = editor.getValue(); - - var ext = Modes.extensionOf(exp.highlightMode); - - var title = Cryptpad.fixFileName(Title ? Title.suggestTitle('cryptpad') : "?") + (ext || '.txt'); - - Cryptpad.prompt(Messages.exportPrompt, title, function (filename) { - if (filename === null) { return; } - var blob = new Blob([text], { - type: 'text/plain;charset=utf-8' - }); - saveAs(blob, filename); - }); - }; - exp.importText = function (content, file) { - var $bar = ifrw.$('#cme_toolbox'); - var mode; - var mime = CodeMirror.findModeByMIME(file.type); - - if (!mime) { - var ext = /.+\.([^.]+)$/.exec(file.name); - if (ext[1]) { - mode = CMeditor.findModeByExtension(ext[1]); - mode = mode && mode.mode || null; - } - } else { - mode = mime && mime.mode || null; - } - - if (mode && Modes.list.some(function (o) { return o.mode === mode; })) { - setMode(mode); - $bar.find('#language-mode').val(mode); - } else { - console.log("Couldn't find a suitable highlighting mode: %s", mode); - setMode('text'); - $bar.find('#language-mode').val('text'); - } - - editor.setValue(content); - onLocal(); - }; - - var cursorToPos = function(cursor, oldText) { - var cLine = cursor.line; - var cCh = cursor.ch; - var pos = 0; - var textLines = oldText.split("\n"); - for (var line = 0; line <= cLine; line++) { - if(line < cLine) { - pos += textLines[line].length+1; - } - else if(line === cLine) { - pos += cCh; - } - } - return pos; - }; - - var posToCursor = function(position, newText) { - var cursor = { - line: 0, - ch: 0 - }; - var textLines = newText.substr(0, position).split("\n"); - cursor.line = textLines.length - 1; - cursor.ch = textLines[cursor.line].length; - return cursor; - }; - - exp.setValueAndCursor = function (oldDoc, remoteDoc, TextPatcher) { - var scroll = editor.getScrollInfo(); - //get old cursor here - var oldCursor = {}; - oldCursor.selectionStart = cursorToPos(editor.getCursor('from'), oldDoc); - oldCursor.selectionEnd = cursorToPos(editor.getCursor('to'), oldDoc); - - editor.setValue(remoteDoc); - editor.save(); - - var op = TextPatcher.diff(oldDoc, remoteDoc); - var selects = ['selectionStart', 'selectionEnd'].map(function (attr) { - return TextPatcher.transformCursor(oldCursor[attr], op); - }); - - if(selects[0] === selects[1]) { - editor.setCursor(posToCursor(selects[0], remoteDoc)); - } - else { - editor.setSelection(posToCursor(selects[0], remoteDoc), posToCursor(selects[1], remoteDoc)); - } - - editor.scrollTo(scroll.left, scroll.top); - }; - - return exp; - }; - - return module; -}); - diff --git a/www/common/common-file.js b/www/common/common-file.js deleted file mode 100644 index df2f94ee7..000000000 --- a/www/common/common-file.js +++ /dev/null @@ -1,366 +0,0 @@ -define([ - 'jquery', - '/file/file-crypto.js', - '/common/common-thumbnail.js', - '/bower_components/tweetnacl/nacl-fast.min.js', -], function ($, FileCrypto, Thumb) { - var Nacl = window.nacl; - var module = {}; - - var blobToArrayBuffer = module.blobToArrayBuffer = function (blob, cb) { - var reader = new FileReader(); - reader.onloadend = function () { - cb(void 0, this.result); - }; - reader.readAsArrayBuffer(blob); - }; - - var arrayBufferToString = function (AB) { - try { - return Nacl.util.encodeBase64(new Uint8Array(AB)); - } catch (e) { - console.error(e); - return null; - } - }; - - module.upload = function (file, noStore, common, updateProgress, onComplete, onError, onPending) { - var u8 = file.blob; // This is not a blob but a uint8array - var metadata = file.metadata; - - // if it exists, path contains the new pad location in the drive - var path = file.path; - - var key = Nacl.randomBytes(32); - var next = FileCrypto.encrypt(u8, metadata, key); - - var estimate = FileCrypto.computeEncryptedSize(u8.length, metadata); - - var sendChunk = function (box, cb) { - var enc = Nacl.util.encodeBase64(box); - common.rpc.send.unauthenticated('UPLOAD', enc, function (e, msg) { - cb(e, msg); - }); - }; - - var actual = 0; - var again = function (err, box) { - if (err) { throw new Error(err); } - if (box) { - actual += box.length; - var progressValue = (actual / estimate * 100); - updateProgress(progressValue); - - return void sendChunk(box, function (e) { - if (e) { return console.error(e); } - next(again); - }); - } - - if (actual !== estimate) { - console.error('Estimated size does not match actual size'); - } - - // if not box then done - common.uploadComplete(function (e, id) { - if (e) { return void console.error(e); } - var uri = ['', 'blob', id.slice(0,2), id].join('/'); - console.log("encrypted blob is now available as %s", uri); - - var b64Key = Nacl.util.encodeBase64(key); - - var hash = common.getFileHashFromKeys(id, b64Key); - var href = '/file/#' + hash; - - var title = metadata.name; - - if (noStore) { return void onComplete(href); } - - common.initialPath = path; - common.renamePad(title || "", href, function (err) { - if (err) { return void console.error(err); } - onComplete(href); - common.setPadAttribute('fileType', metadata.type, null, href); - }); - }); - }; - - common.uploadStatus(estimate, function (e, pending) { - if (e) { - console.error(e); - onError(e); - return; - } - - if (pending) { - return void onPending(function () { - // if the user wants to cancel the pending upload to execute that one - common.uploadCancel(function (e, res) { - if (e) { - return void console.error(e); - } - console.log(res); - next(again); - }); - }); - } - next(again); - }); - }; - - module.create = function (common, config) { - var File = {}; - - var Messages = common.Messages; - - var queue = File.queue = { - queue: [], - inProgress: false - }; - - var uid = function () { - return 'file-' + String(Math.random()).substring(2); - }; - - var $table = File.$table = $('', { id: 'uploadStatus' }); - var $thead = $('').appendTo($table); - $('', {id: id}).appendTo($table); - - var $cancel = $('', {'class': 'cancel fa fa-times'}).click(function () { - queue.queue = queue.queue.filter(function (el) { return el.id !== id; }); - $cancel.remove(); - $tr.find('.upCancel').text('-'); - $tr.find('.progressValue').text(Messages.upload_cancelled); - }); - - var $link = $('', { - 'class': 'upLink', - 'rel': 'noopener noreferrer' - }).text(obj.metadata.name); - - $('
').text(Messages.upload_name).appendTo($thead); - $('').text(Messages.upload_size).appendTo($thead); - $('').text(Messages.upload_progress).appendTo($thead); - $('').text(Messages.cancel).appendTo($thead); - - var createTableContainer = function ($body) { - File.$container = $('
', { id: 'uploadStatusContainer' }).append($table).appendTo($body); - return File.$container; - }; - - var getData = function (file, href) { - var data = {}; - - data.name = file.metadata.name; - data.url = href; - if (file.metadata.type.slice(0,6) === 'image/') { - data.mediatag = true; - } - - return data; - }; - - var upload = function (file) { - var blob = file.blob; // This is not a blob but an array buffer - var u8 = new Uint8Array(blob); - var metadata = file.metadata; - var id = file.id; - if (queue.inProgress) { return; } - queue.inProgress = true; - - var $row = $table.find('tr[id="'+id+'"]'); - - $row.find('.upCancel').html('-'); - var $pv = $row.find('.progressValue'); - var $pb = $row.find('.progressContainer'); - var $pc = $row.find('.upProgress'); - var $link = $row.find('.upLink'); - - var updateProgress = function (progressValue) { - $pv.text(Math.round(progressValue*100)/100 + '%'); - $pb.css({ - width: (progressValue/100)*$pc.width()+'px' - }); - }; - - var onComplete = function (href) { - $link.attr('href', href) - .click(function (e) { - e.preventDefault(); - window.open($link.attr('href'), '_blank'); - }); - var title = metadata.name; - common.log(Messages._getKey('upload_success', [title])); - common.prepareFeedback('upload')(); - - if (config.onUploaded) { - var data = getData(file, href); - config.onUploaded(file.dropEvent, data); - } - - queue.inProgress = false; - queue.next(); - }; - - var onError = function (e) { - queue.inProgress = false; - queue.next(); - if (e === 'TOO_LARGE') { - // TODO update table to say too big? - return void common.alert(Messages.upload_tooLarge); - } - if (e === 'NOT_ENOUGH_SPACE') { - // TODO update table to say not enough space? - return void common.alert(Messages.upload_notEnoughSpace); - } - console.error(e); - return void common.alert(Messages.upload_serverError); - }; - - var onPending = function (cb) { - common.confirm(Messages.upload_uploadPending, function (yes) { - if (!yes) { return; } - cb(); - }); - }; - - file.blob = u8; - module.upload(file, config.noStore, common, updateProgress, onComplete, onError, onPending); - }; - - var prettySize = function (bytes) { - var kB = common.bytesToKilobytes(bytes); - if (kB < 1024) { return kB + Messages.KB; } - var mB = common.bytesToMegabytes(bytes); - return mB + Messages.MB; - }; - - queue.next = function () { - if (queue.queue.length === 0) { - queue.to = window.setTimeout(function () { - if (config.keepTable) { return; } - File.$container.fadeOut(); - }, 3000); - return; - } - if (queue.inProgress) { return; } - File.$container.show(); - var file = queue.queue.shift(); - upload(file); - }; - queue.push = function (obj) { - var id = uid(); - obj.id = id; - queue.queue.push(obj); - - $table.show(); - var estimate = FileCrypto.computeEncryptedSize(obj.blob.byteLength, obj.metadata); - - var $progressBar = $('
', {'class':'progressContainer'}); - var $progressValue = $('', {'class':'progressValue'}).text(Messages.upload_pending); - - var $tr = $('
').append($link).appendTo($tr); - $('').text(prettySize(estimate)).appendTo($tr); - $('', {'class': 'upProgress'}).append($progressBar).append($progressValue).appendTo($tr); - $('', {'class': 'upCancel'}).append($cancel).appendTo($tr); - - queue.next(); - }; - - var handleFile = File.handleFile = function (file, e, thumbnail) { - var thumb; - var file_arraybuffer; - var finish = function () { - var metadata = { - name: file.name, - type: file.type, - }; - if (thumb) { metadata.thumbnail = thumb; } - queue.push({ - blob: file_arraybuffer, - metadata: metadata, - dropEvent: e - }); - }; - - blobToArrayBuffer(file, function (e, buffer) { - if (e) { console.error(e); } - file_arraybuffer = buffer; - if (thumbnail) { // there is already a thumbnail - return blobToArrayBuffer(thumbnail, function (e, buffer) { - if (e) { console.error(e); } - thumb = arrayBufferToString(buffer); - finish(); - }); - } - - if (!Thumb.isSupportedType(file.type)) { return finish(); } - // make a resized thumbnail from the image.. - Thumb.fromBlob(file, function (e, thumb64) { - if (e) { console.error(e); } - if (!thumb64) { return finish(); } - thumb = thumb64; - finish(); - }); - }); - }; - - var onFileDrop = File.onFileDrop = function (file, e) { - if (!common.isLoggedIn()) { - return common.alert(common.Messages.upload_mustLogin); - } - - Array.prototype.slice.call(file).forEach(function (d) { - handleFile(d, e); - }); - }; - - var createAreaHandlers = File.createDropArea = function ($area, $hoverArea) { - var counter = 0; - if (!$hoverArea) { $hoverArea = $area; } - if (!$area) { return; } - $hoverArea - .on('dragenter', function (e) { - e.preventDefault(); - e.stopPropagation(); - counter++; - $hoverArea.addClass('hovering'); - }) - .on('dragleave', function (e) { - e.preventDefault(); - e.stopPropagation(); - counter--; - if (counter <= 0) { - $hoverArea.removeClass('hovering'); - } - }); - - $area - .on('drag dragstart dragend dragover drop dragenter dragleave', function (e) { - e.preventDefault(); - e.stopPropagation(); - }) - .on('drop', function (e) { - e.stopPropagation(); - - var dropped = e.originalEvent.dataTransfer.files; - counter = 0; - $hoverArea.removeClass('hovering'); - onFileDrop(dropped, e); - }); - }; - - var createUploader = function ($area, $hover, $body) { - if (!config.noHandlers) { - createAreaHandlers($area, null); - } - createTableContainer($body); - }; - - createUploader(config.dropArea, config.hoverArea, config.body); - - return File; - }; - - return module; -}); diff --git a/www/common/common-hash.js b/www/common/common-hash.js index 2aa2155bf..c40919aa1 100644 --- a/www/common/common-hash.js +++ b/www/common/common-hash.js @@ -1,9 +1,8 @@ define([ '/common/common-util.js', - '/common/common-interface.js', '/bower_components/chainpad-crypto/crypto.js', '/bower_components/tweetnacl/nacl-fast.min.js' -], function (Util, UI, Crypto) { +], function (Util, Crypto) { var Nacl = window.nacl; var Hash = {}; @@ -211,14 +210,12 @@ Version 1 secret.keys = Crypto.createEditCryptor(parsed.key); secret.key = secret.keys.editKeyStr; if (secret.channel.length !== 32 || secret.key.length !== 24) { - UI.alert("The channel key and/or the encryption key is invalid"); throw new Error("The channel key and/or the encryption key is invalid"); } } else if (parsed.mode === 'view') { secret.keys = Crypto.createViewCryptor(parsed.key); if (secret.channel.length !== 32) { - UI.alert("The channel key is invalid"); throw new Error("The channel key is invalid"); } } diff --git a/www/common/common-history.js b/www/common/common-history.js deleted file mode 100644 index 6dea29ab7..000000000 --- a/www/common/common-history.js +++ /dev/null @@ -1,268 +0,0 @@ -define([ - 'jquery', - '/bower_components/chainpad-json-validator/json-ot.js', - '/bower_components/chainpad-crypto/crypto.js', - '/bower_components/chainpad/chainpad.dist.js', -], function ($, JsonOT, Crypto) { - var ChainPad = window.ChainPad; - var History = {}; - - var getStates = function (rt) { - var states = []; - var b = rt.getAuthBlock(); - if (b) { states.unshift(b); } - while (b.getParent()) { - b = b.getParent(); - states.unshift(b); - } - return states; - }; - - var loadHistory = function (config, common, cb) { - var network = common.getNetwork(); - var hkn = network.historyKeeper; - - var wcId = common.hrefToHexChannelId(config.href || window.location.href); - - var createRealtime = function () { - return ChainPad.create({ - userName: 'history', - initialState: '', - transformFunction: JsonOT.validate, - logLevel: 0, - noPrune: true - }); - }; - var realtime = createRealtime(); - - var parsed = config.href ? common.parsePadUrl(config.href) : {}; - var secret = common.getSecrets(parsed.type, parsed.hash); - - History.readOnly = 0; - if (!secret.keys) { - secret.keys = secret.key; - History.readOnly = 0; - } - else if (!secret.keys.validateKey) { - History.readOnly = 1; - } - - var crypto = Crypto.createEncryptor(secret.keys); - - var to = window.setTimeout(function () { - cb('[GET_FULL_HISTORY_TIMEOUT]'); - }, 30000); - - var parse = function (msg) { - try { - return JSON.parse(msg); - } catch (e) { - return null; - } - }; - var onMsg = function (msg) { - var parsed = parse(msg); - if (parsed[0] === 'FULL_HISTORY_END') { - console.log('END'); - window.clearTimeout(to); - cb(null, realtime); - return; - } - if (parsed[0] !== 'FULL_HISTORY') { return; } - if (parsed[1] && parsed[1].validateKey) { // First message - secret.keys.validateKey = parsed[1].validateKey; - return; - } - msg = parsed[1][4]; - if (msg) { - msg = msg.replace(/^cp\|/, ''); - var decryptedMsg = crypto.decrypt(msg, secret.keys.validateKey); - realtime.message(decryptedMsg); - } - }; - - network.on('message', function (msg) { - onMsg(msg); - }); - - network.sendto(hkn, JSON.stringify(['GET_FULL_HISTORY', wcId, secret.keys.validateKey])); - }; - - History.create = function (common, config) { - if (!config.$toolbar) { return void console.error("config.$toolbar is undefined");} - if (History.loading) { return void console.error("History is already being loaded..."); } - History.loading = true; - var $toolbar = config.$toolbar; - - if (!config.applyVal || !config.setHistory || !config.onLocal || !config.onRemote) { - throw new Error("Missing config element: applyVal, onLocal, onRemote, setHistory"); - } - - // config.setHistory(bool, bool) - // - bool1: history value - // - bool2: reset old content? - var render = function (val) { - if (typeof val === "undefined") { return; } - try { - config.applyVal(val); - } catch (e) { - // Probably a parse error - console.error(e); - } - }; - var onClose = function () { config.setHistory(false, true); }; - var onRevert = function () { - config.setHistory(false, false); - config.onLocal(); - config.onRemote(); - }; - var onReady = function () { - config.setHistory(true); - }; - - var Messages = common.Messages; - - var realtime; - - var states = []; - var c = states.length - 1; - - var $hist = $toolbar.find('.cryptpad-toolbar-history'); - var $left = $toolbar.find('.cryptpad-toolbar-leftside'); - var $right = $toolbar.find('.cryptpad-toolbar-rightside'); - var $cke = $toolbar.find('.cke_toolbox_main'); - - $hist.html('').show(); - $left.hide(); - $right.hide(); - $cke.hide(); - - common.spinner($hist).get().show(); - - var onUpdate; - - var update = function () { - if (!realtime) { return []; } - states = getStates(realtime); - if (typeof onUpdate === "function") { onUpdate(); } - return states; - }; - - // Get the content of the selected version, and change the version number - var get = function (i) { - i = parseInt(i); - if (isNaN(i)) { return; } - if (i < 0) { i = 0; } - if (i > states.length - 1) { i = states.length - 1; } - var val = states[i].getContent().doc; - c = i; - if (typeof onUpdate === "function") { onUpdate(); } - $hist.find('.next, .previous').css('visibility', ''); - if (c === states.length - 1) { $hist.find('.next').css('visibility', 'hidden'); } - if (c === 0) { $hist.find('.previous').css('visibility', 'hidden'); } - return val || ''; - }; - - var getNext = function (step) { - return typeof step === "number" ? get(c + step) : get(c + 1); - }; - var getPrevious = function (step) { - return typeof step === "number" ? get(c - step) : get(c - 1); - }; - - // Create the history toolbar - var display = function () { - $hist.html(''); - var $prev =$('