From 07fcdb8e648e97d374512830c97d7a072bd3f82d Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Thu, 26 May 2016 16:47:38 +0200 Subject: [PATCH] Upgraded to Redactor 1.2.4 --- .../files/js/3rdParty/redactor2/redactor.js | 252 +++++++++++++----- .../js/3rdParty/redactor2/redactor.min.js | 8 +- 2 files changed, 191 insertions(+), 69 deletions(-) diff --git a/wcfsetup/install/files/js/3rdParty/redactor2/redactor.js b/wcfsetup/install/files/js/3rdParty/redactor2/redactor.js index 1b93c9882b..cf88d46b68 100644 --- a/wcfsetup/install/files/js/3rdParty/redactor2/redactor.js +++ b/wcfsetup/install/files/js/3rdParty/redactor2/redactor.js @@ -1,11 +1,11 @@ /* Redactor II - Version 1.2.1 - Updated: January 20, 2015 + Version 1.2.4 + Updated: May 21, 2015 http://imperavi.com/redactor/ - Copyright (c) 2009-2015, Imperavi LLC. + Copyright (c) 2009-2016, Imperavi LLC. License: http://imperavi.com/redactor/license/ Usage: $('#content').redactor(); @@ -101,7 +101,7 @@ // Options $.Redactor = Redactor; - $.Redactor.VERSION = '1.2.1'; + $.Redactor.VERSION = '1.2.4'; $.Redactor.modules = ['air', 'autosave', 'block', 'buffer', 'build', 'button', 'caret', 'clean', 'code', 'core', 'detect', 'dropdown', 'events', 'file', 'focus', 'image', 'indent', 'inline', 'insert', 'keydown', 'keyup', 'lang', 'line', 'link', 'linkify', 'list', 'marker', 'modal', 'observe', 'offset', 'paragraphize', 'paste', 'placeholder', @@ -142,8 +142,8 @@ pastePlainText: false, pasteImages: true, pasteLinks: true, - pasteBlockTags: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'table', 'tbody', 'thead', 'tfoot', 'th', 'tr', 'td', 'ul', 'ol', 'li', 'blockquote', 'pre'], - pasteInlineTags: ['strong', 'b', 'u', 'em', 'i', 'code', 'del', 'ins', 'samp', 'kbd', 'sup', 'sub', 'mark', 'var', 'cite', 'small'], + pasteBlockTags: ['pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'table', 'tbody', 'thead', 'tfoot', 'th', 'tr', 'td', 'ul', 'ol', 'li', 'blockquote', 'p', 'figure', 'figcaption'], + pasteInlineTags: ['br', 'strong', 'ins', 'code', 'del', 'samp', 'kbd', 'sup', 'sub', 'mark', 'var', 'cite', 'small', 'b', 'u', 'em', 'i'], preClass: false, // string preSpaces: 4, // or false @@ -191,7 +191,7 @@ formatting: ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'], formattingAdd: false, - buttons: ['format', 'bold', 'italic', 'deleted', 'lists', 'image', 'file', 'link', 'horizontalrule'], // + 'underline' + buttons: ['format', 'bold', 'italic', 'deleted', 'lists', 'image', 'file', 'link', 'horizontalrule'], // + 'underline', 'ol', 'ul', 'indent', 'outdent' buttonsHide: [], buttonsHideOnMobile: [], @@ -269,6 +269,9 @@ "upload-label": "Drop file here or ", "caption": "Caption", + "bulletslist": "Bullets", + "numberslist": "Numbers", + "accessibility-help-label": "Rich text editor" } }, @@ -1046,6 +1049,11 @@ return { set: function(type) { + if (typeof type === 'undefined') + { + this.buffer.clear(); + } + if (typeof type === 'undefined' || type === 'undo') { this.buffer.setUndo(); @@ -1109,6 +1117,10 @@ this.buffer.getRedo(); this.selection.restore(); + }, + clear: function() + { + this.opts.rebuffer = []; } }; }, @@ -1570,6 +1582,26 @@ } } }, + ul: + { + title: '• ' + this.lang.get('bulletslist'), + func: 'list.toggle' + }, + ol: + { + title: '1. ' + this.lang.get('numberslist'), + func: 'list.toggle' + }, + outdent: + { + title: this.lang.get('outdent'), + func: 'indent.decrease' + }, + indent: + { + title: this.lang.get('indent'), + func: 'indent.increase' + }, image: { title: this.lang.get('image'), @@ -1681,12 +1713,13 @@ return; } - var $button = $('').html(btnObject.title); + var $button = $('').html(btnObject.title); $button.attr({ 'role': 'button', 'aria-label': btnObject.title, 'tabindex': '-1' }); if (typeof btnObject.label !== 'undefined') { $button.attr('aria-label', btnObject.label); + $button.attr('title', btnObject.label); } // click @@ -2072,6 +2105,7 @@ var inline = this.utils.isInlineTag(node.tagName); if (node.innerHTML === '' || inline) { + sel = window.getSelection(); range = document.createRange(); var textNode = document.createTextNode('\u200B'); @@ -2079,7 +2113,7 @@ range.insertNode(textNode); range.setStartAfter(textNode); range.collapse(true); - sel = window.getSelection(); + sel.removeAllRanges(); sel.addRange(range); @@ -2103,7 +2137,6 @@ range.selectNodeContents(node); range.collapse(true); sel.addRange(range); - } @@ -2341,9 +2374,9 @@ 'strike': 'del' }; - $div.find('b, i, strike').replaceWith(function() + $div.find('b, i, strike').each(function(i,s) { - return self.utils.replaceToTag(this, replacement[this.tagName.toLowerCase()]); + self.utils.replaceToTag(s, replacement[s.tagName.toLowerCase()]); }); html = $div.html(); @@ -2468,6 +2501,10 @@ // if paste event if (insert !== true) { + // remove google docs markers + html = html.replace(/([\w\W]*?)<\/b>/gi, "$2"); + html = html.replace(/([\w\W]*?)<\/b>/gi, "$3"); + var msword = this.clean.isHtmlMsWord(html); if (msword) { @@ -2644,6 +2681,8 @@ }, cleanMsWord: function(html) { + html = html.replace(//g, ""); + html = html.replace(/[\s\S]*?<\/o:p>/gi, ''); html = html.replace(/\n/g, " "); html = html.replace(/|<\/p>|<\/div>|<\/li>|<\/td>/gi, '\n\n'); @@ -2708,7 +2747,6 @@ } } - return html; }, @@ -2731,6 +2769,7 @@ return html; } + var blockTags = (data.lists) ? ['ul', 'ol', 'li'] : this.opts.pasteBlockTags; var tags; @@ -2747,16 +2786,16 @@ for (var i = 0; i < len; i++) { html = html.replace(new RegExp('###/' + tags[i] + '###', 'gi'), ''); + html = html.replace(new RegExp('###' + tags[i] + '###', 'gi'), '<' + tags[i] + '>'); + } - if (tags[i] === 'td' || tags[i] === 'th') - { - html = html.replace(new RegExp('###' + tags[i] + '\s?(.*?[^#])###', 'gi'), '<' + tags[i] + '$1>'); - } - else - { - html = html.replace(new RegExp('###' + tags[i] + '###', 'gi'), '<' + tags[i] + '>'); - } - } + for (var i = 0; i < len; i++) + { + if (tags[i] === 'td' || tags[i] === 'th') + { + html = html.replace(new RegExp('###' + tags[i] + '\s?(.*?[^#])###', 'gi'), '<' + tags[i] + '$1>'); + } + } return html; @@ -2965,6 +3004,7 @@ start: function(html) { html = $.trim(html); + html = html.replace(/^(​<\/span>)/, ''); // clean if (this.opts.type === 'textarea') @@ -3009,7 +3049,7 @@ if (this.opts.type === 'textarea') { return this.core.textarea().val(); - } + } else { var html = this.core.editor().html(); @@ -3388,6 +3428,18 @@ buildItem: function(btnName, btnObject) { var $itemContainer = $('
  • '); + if (typeof btnObject.classname !== 'undefined') + { + $itemContainer.addClass(btnObject.classname); + } + + if (btnName.search(/^divider/i) !== -1) + { + $itemContainer.addClass('redactor-dropdown-divider'); + + return $itemContainer; + } + var $item = $(''); var $itemSpan = $('').html(btnObject.title); @@ -3818,7 +3870,7 @@ this.observe.load(); // target - if ((this.opts.type === 'textarea' || this.opts.type === 'div') && mutation.target === this.core.editor()[0]) + if ((this.opts.type === 'textarea' || this.opts.type === 'div') && (!this.detect.isFirefox() && mutation.target === this.core.editor()[0])) { stop = true; } @@ -4236,7 +4288,7 @@ if (this.opts.imageCaption === false) { - $('#redactor-image-caption').val('').hide(); + $('#redactor-image-caption').val('').hide().prev().hide(); } else { @@ -4372,7 +4424,7 @@ this.events.stopDetectChanges(); var $link = $image.closest('a', this.core.editor()[0]); - var $figure = $image.closest('figure, p', this.core.editor()[0]); + var $figure = $image.closest('figure', this.core.editor()[0]); var $parent = $image.parent(); if ($('#redactor-image-box').length !== 0) @@ -4683,28 +4735,29 @@ this.inline.formatConvert(tag); - this.selection.save(); + document.execCommand('strikethrough'); - document.execCommand('strikethrough'); + this.selection.save(); + var converted = true; var $formatted = this.core.editor().find('strike'); $formatted.each(function(i,s) { var $oldEl = $(s); - var newEl = document.createElement(tag); - if (!$oldEl.hasClass('redactor-inline-converted')) { - newEl = self.inline.setAttr(newEl, attr, value, type); + converted = false; } - var $newEl = $(newEl); - - $oldEl.replaceWith($newEl.html($oldEl.contents())); + var $newEl = self.utils.replaceToTag($oldEl, tag); + if (!converted) + { + $newEl = self.inline.setAttr($newEl[0], attr, value, type); + } }); - // restore del tag + // restore del tag if (tag !== 'del') { this.core.editor().find('inline').each(function(i,s) @@ -4793,12 +4846,12 @@ // convert tag this.core.editor().find(tag).each(function() { - var $el = $(this); - $el.replaceWith($('').addClass('redactor-inline-converted').html($el.contents())); - + var $el = self.utils.replaceToTag(this, 'strike'); + $el.addClass('redactor-inline-converted'); }); this.selection.restore(); + }, insertBreakpoint: function(inline, currentTag) { @@ -5064,13 +5117,14 @@ if (inline) { // remove same tag inside - var $div = $("
    ").html($.parseHTML(html, document, true)); + var $div = $("
    ").html(html); $div.find(inline.tagName.toLowerCase()).each(function() { $(this).contents().unwrap(); }); html = $div.html(); + } if (this.utils.isSelectAll()) @@ -5111,6 +5165,7 @@ } this.placeholder.hide(); + this.core.editor().focus(); // blocks var blocks = this.selection.blocks(); @@ -5603,7 +5658,7 @@ this.code.syncFire = false; this.keydown.removeEmptyLists(); - this.core.editor().find('*[style]').not('#redactor-image-box, #redactor-image-editter').removeAttr('style'); + this.core.editor().find('*[style]').not('img, #redactor-image-box, #redactor-image-editter').removeAttr('style'); this.keydown.formatEmpty(e); this.code.syncFire = true; @@ -5671,6 +5726,7 @@ return false; } } + } // outside else if (!this.keydown.block) @@ -5678,7 +5734,6 @@ return this.keydown.insertParagraph(e); } - // remove inline tags in new-empty paragraph setTimeout($.proxy(function() { @@ -5687,7 +5742,20 @@ { var parent = this.selection.block(); $(inline).remove(); - this.caret.start(parent); + //this.caret.start(parent); + + var range = document.createRange(); + range.setStart(parent, 0); + + var textNode = document.createTextNode('\u200B'); + + range.insertNode(textNode); + range.setStartAfter(textNode); + range.collapse(true); + + var sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); } }, this), 1); @@ -5996,12 +6064,26 @@ replaceToParagraph: function(tag) { var blockElem = this.selection.block(); + var blockHtml = blockElem.innerHTML.replace(//gi, ''); if (blockElem.tagName === tag && this.utils.isEmpty(blockHtml) && !$(blockElem).hasClass('redactor-in')) { var p = document.createElement('p'); $(blockElem).replaceWith(p); - this.caret.start(p); + + // caret to p + var range = document.createRange(); + range.setStart(p, 0); + + var textNode = document.createTextNode('\u200B'); + + range.insertNode(textNode); + range.setStartAfter(textNode); + range.collapse(true); + + var sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); return false; } @@ -6087,6 +6169,7 @@ return { init: function(e) { + if (this.rtePaste) { return; @@ -6105,6 +6188,21 @@ return false; } + // replace a prev figure to paragraph if caret is before image + if (key === this.keyCode.ENTER) + { + if (this.keyup.block && this.keyup.block.tagName === 'FIGURE') + { + var $prev = $(this.keyup.block).prev(); + if ($prev.length !== 0 && $prev[0].tagName === 'FIGURE') + { + var $newTag = this.utils.replaceToTag($prev, 'p'); + this.caret.start($newTag); + return; + } + } + } + // replace figure to paragraph if (key === this.keyCode.BACKSPACE || key === this.keyCode.DELETE) { @@ -6115,13 +6213,13 @@ return; } - // if caret before figure - delete image if (this.keyup.block && this.keydown.block && this.keyup.block.tagName === 'FIGURE' && this.utils.isStartOfElement(this.keydown.block)) { e.preventDefault(); this.selection.save(); + $(this.keyup.block).find('figcaption').remove(); $(this.keyup.block).find('img').first().remove(); this.utils.replaceToTag(this.keyup.block, 'p'); @@ -6417,18 +6515,20 @@ isUrl: function(url) { var pattern = '((xn--)?[\\W\\w\\D\\d]+(-[\\W\\w\\D\\d]+)*\\.)+[\\W\\w]{2,}'; + var re1 = new RegExp('^(http|ftp|https)://' + pattern, 'i'); var re2 = new RegExp('^' + pattern, 'i'); var re3 = new RegExp('\.(html|php)$', 'i'); var re4 = new RegExp('^/', 'i'); + var re5 = new RegExp('^tel:(.*?)', 'i'); - // ad protocol + // add protocol if (url.search(re1) === -1 && url.search(re2) !== -1) { url = 'http://' + url; } - if (url.search(re1) !== -1 || url.search(re3) !== -1 || url.search(re4) !== -1) + if (url.search(re1) !== -1 || url.search(re3) !== -1 || url.search(re4) !== -1 || url.search(re5) !== -1) { return url; } @@ -6747,13 +6847,15 @@ return; } - var tag = (cmd === 'orderedlist') ? 'OL' : 'UL'; - var $list = $(this.selection.current()).parentsUntil('.redactor-in', 'ul, ol').first(); + var tag = (cmd === 'orderedlist' || cmd === 'ol') ? 'OL' : 'UL'; + cmd = (tag === 'OL') ? 'orderedlist' : 'unorderedlist' + var $list = $(this.selection.current()).parentsUntil('.redactor-in', 'ul, ol').first(); this.placeholder.hide(); this.buffer.set(); + if ($list.length !== 0 && $list[0].tagName === tag && this.utils.isRedactorParent($list)) { this.selection.save(); @@ -6769,7 +6871,6 @@ }); $list.find('ul, ol').remove(); - $list.find('li').each(function() { return $(this).replaceWith(function() @@ -6788,8 +6889,22 @@ return; } + this.selection.save(); - document.execCommand('insert' + cmd); + + if ($list.length !== 0 && $list[0].tagName !== tag) + { + $list.each($.proxy(function(i,s) + { + this.utils.replaceToTag(s, tag); + + }, this)); + } + else + { + document.execCommand('insert' + cmd); + } + this.selection.restore(); var $insertedList = this.list.get(); @@ -6894,6 +7009,7 @@ { this.marker.insertNode(range, this.marker.get(2), false); } + }, remove: function() { @@ -6914,7 +7030,6 @@ try { range.collapse(collapse); range.insertNode(node); - } catch (e) { @@ -7739,7 +7854,7 @@ this.paragraphize.z++; this.paragraphize.safes[this.paragraphize.z] = s.outerHTML; - return $(s).replaceWith('\n{replace' + this.paragraphize.z + '}\n\n'); + return $(s).replaceWith('\n#####replace' + this.paragraphize.z + '#####\n\n'); }, this)); @@ -7752,7 +7867,7 @@ $.each(this.paragraphize.safes, function(i,s) { s = (typeof s !== 'undefined') ? s.replace(/\$/g, '$') : s; - html = html.replace('{replace' + i + '}', s); + html = html.replace('#####replace' + i + '#####', s); }); @@ -7791,7 +7906,9 @@ }, clear: function(html) { - html = html.replace(/

    (.*?){replace(.*?)\}\s?<\/p>/gi, '{replace$2}'); + + html = html.replace(/

    (.*?)#####replace(.*?)#####\s?<\/p>/gi, '

    $1

    #####replace$2#####'); + html = html.replace(/(){2,}<\/p>/gi, '

    '); html = html.replace(new RegExp('

    ', 'gi'), ''); html = html.replace(new RegExp('

    ', 'gi'), ''); @@ -7818,10 +7935,10 @@ init: function(e) { this.rtePaste = true; - var pre = (this.opts.type === 'pre' || this.utils.isCurrentOrParent('pre')); + var pre = (this.opts.type === 'pre' || this.utils.isCurrentOrParent('pre')) ? true : false; // clipboard event - if (!this.paste.pre && this.opts.clipboardImageUpload && this.opts.imageUpload && this.paste.detectClipboardUpload(e)) + if (!this.paste.pre && !this.detect.isMobile() && this.opts.clipboardImageUpload && this.opts.imageUpload && this.paste.detectClipboardUpload(e)) { if (this.detect.isIe()) { @@ -7845,10 +7962,10 @@ { var html = this.paste.getPasteBoxCode(pre); - // buffer this.buffer.set(); this.selection.restore(); + this.utils.restoreScroll(); // paste info @@ -7886,9 +8003,9 @@ { var css = { position: 'fixed', width: 0, top: 0, left: '-9999px' }; - this.$pasteBox = (pre) ? $('