From 4a67fef8fd811f397ccf8aaec59dc39c0c9eb950 Mon Sep 17 00:00:00 2001 From: Peter Halloran Date: Fri, 23 Jun 2017 17:02:55 -0400 Subject: [PATCH 1/2] fix: update angular-redactor add inline styles plugin and add newer version of Redactor --- .../legacy/controllers/posts/edit.js | 3 +- .../javascripts/legacy/vendor/inlinestyle.js | 67 + .../javascripts/legacy/vendor/redactor.js | 1819 ++++++++++++----- bower.json | 2 +- 4 files changed, 1390 insertions(+), 501 deletions(-) create mode 100755 app/assets/javascripts/legacy/vendor/inlinestyle.js diff --git a/app/assets/javascripts/legacy/controllers/posts/edit.js b/app/assets/javascripts/legacy/controllers/posts/edit.js index c73141c7e..f2d0c6b8e 100644 --- a/app/assets/javascripts/legacy/controllers/posts/edit.js +++ b/app/assets/javascripts/legacy/controllers/posts/edit.js @@ -55,8 +55,9 @@ angular.module('cortex.controllers.posts.edit', [ ImageFitService.initRedactorImageFitPlugin(); $scope.redactorOptions = { - plugins: ['media', 'imageFit'], + plugins: ['media', 'imageFit', 'inlinestyle'], minHeight: 800, + focus: true, buttonSource: true, deniedTags: ['html', 'head', 'link', 'body', 'applet'] // Allow script, style }; diff --git a/app/assets/javascripts/legacy/vendor/inlinestyle.js b/app/assets/javascripts/legacy/vendor/inlinestyle.js new file mode 100755 index 000000000..993258e64 --- /dev/null +++ b/app/assets/javascripts/legacy/vendor/inlinestyle.js @@ -0,0 +1,67 @@ +(function($) +{ + $.Redactor.prototype.inlinestyle = function() + { + return { + langs: { + en: { + "style": "Style" + } + }, + init: function() + { + var tags = { + "marked": { + title: "Marked", + args: ['mark'] + }, + "code": { + title: "Code", + args: ['code'] + }, + "sample": { + title: "Sample", + args: ['samp'] + }, + "variable": { + title: "Variable", + args: ['var'] + }, + "shortcut": { + title: "Shortcut", + args: ['kbd'] + }, + "cite": { + title: "Cite", + args: ['cite'] + }, + "sup": { + title: "Superscript", + args: ['sup'] + }, + "sub": { + title: "Subscript", + args: ['sub'] + } + }; + + + var that = this; + var dropdown = {}; + + $.each(tags, function(i, s) + { + dropdown[i] = { title: s.title, func: 'inline.format', args: s.args }; + }); + + + var button = this.button.addAfter('format', 'inline', this.lang.get('style')); + this.button.setIcon(button, ''); + this.button.addDropdown(button, dropdown); + + } + + + }; + }; +})(jQuery); \ No newline at end of file diff --git a/app/assets/javascripts/legacy/vendor/redactor.js b/app/assets/javascripts/legacy/vendor/redactor.js index 2ac60a744..553e3248e 100644 --- a/app/assets/javascripts/legacy/vendor/redactor.js +++ b/app/assets/javascripts/legacy/vendor/redactor.js @@ -1,6 +1,6 @@ /* - Redactor v10.0.6 - Updated: January 7, 2015 + Redactor v10.1.3 + Updated: June 4, 2015 http://imperavi.com/redactor/ @@ -28,9 +28,6 @@ var uuid = 0; - var reUrlYoutube = /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube\.com\S*[^\w\-\s])([\w\-]{11})(?=[^\w\-]|$)(?![?=&+%\w.\-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig; - var reUrlVimeo = /https?:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/; - // Plugin $.fn.redactor = function(options) { @@ -94,13 +91,13 @@ // Functionality $.Redactor = Redactor; - $.Redactor.VERSION = '10.0.6'; + $.Redactor.VERSION = '10.1.3'; $.Redactor.modules = ['alignment', 'autosave', 'block', 'buffer', 'build', 'button', 'caret', 'clean', 'code', 'core', 'dropdown', 'file', 'focus', 'image', 'indent', 'inline', 'insert', 'keydown', 'keyup', 'lang', 'line', 'link', 'list', 'modal', 'observe', 'paragraphize', 'paste', 'placeholder', 'progress', 'selection', 'shortcuts', - 'tabifier', 'tidy', 'toolbar', 'upload', 'utils']; + 'tabifier', 'tidy', 'toolbar', 'upload', 'utils', 'linkify']; $.Redactor.opts = { @@ -135,6 +132,7 @@ autosaveName: false, autosaveInterval: 60, // seconds autosaveOnChange: false, + autosaveFields: false, linkTooltip: true, linkProtocol: 'http', @@ -147,14 +145,14 @@ imageFloatMargin: '10px', imageResizable: true, - imageUpload: false, + imageUpload: null, imageUploadParam: 'file', uploadImageField: false, dragImageUpload: true, - fileUpload: false, + fileUpload: null, fileUploadParam: 'file', dragFileUpload: true, @@ -179,7 +177,7 @@ toolbarExternal: false, // ID selector toolbarOverflow: false, - buttonSource: false, + source: true, buttons: ['html', 'formatting', 'bold', 'italic', 'deleted', 'unorderedlist', 'orderedlist', 'outdent', 'indent', 'image', 'file', 'link', 'alignment', 'horizontalrule'], // + 'underline' @@ -191,12 +189,17 @@ tabifier: true, - deniedTags: ['html', 'head', 'link', 'body', 'meta', 'script', 'style', 'applet'], + deniedTags: ['script', 'style'], allowedTags: false, // or array + paragraphizeBlocks: ['table', 'div', 'pre', 'form', 'ul', 'ol', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'dl', 'blockquote', 'figcaption', + 'address', 'section', 'header', 'footer', 'aside', 'article', 'object', 'style', 'script', 'iframe', 'select', 'input', 'textarea', + 'button', 'option', 'map', 'area', 'math', 'hr', 'fieldset', 'legend', 'hgroup', 'nav', 'figure', 'details', 'menu', 'summary', 'p'], + removeComments: false, replaceTags: [ - ['strike', 'del'] + ['strike', 'del'], + ['b', 'strong'] ], replaceStyles: [ ['font-weight:\\s?bold', "strong"], @@ -323,9 +326,22 @@ underline: 'Underline', alignment: 'Alignment', filename: 'Name (optional)', - edit: 'Edit' + edit: 'Edit', + upload_label: 'Drop file here or ' + } - } + }, + + linkify: { + regexps: { + youtube: /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube\.com\S*[^\w\-\s])([\w\-]{11})(?=[^\w\-]|$)(?![?=&+%\w.\-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig, + vimeo: /https?:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/, + image: /((https?|www)[^\s]+\.)(jpe?g|png|gif)(\?[^\s-]+)?/ig, + url: /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/ig, + } + }, + + codemirror: false }; // Functionality @@ -371,6 +387,16 @@ // setup allowed and denied tags this.tidy.setupAllowed(); + // setup denied tags + if (this.opts.deniedTags !== false) + { + var tags = ['html', 'head', 'link', 'body', 'meta', 'applet']; + for (var i = 0; i < tags.length; i++) + { + this.opts.deniedTags.push(tags[i]); + } + } + // load lang this.lang.load(); @@ -447,92 +473,130 @@ }, set: function(type) { + // focus if (!this.utils.browser('msie')) this.$editor.focus(); this.buffer.set(); this.selection.save(); + // get blocks this.alignment.blocks = this.selection.getBlocks(); - if (this.opts.linebreaks && this.alignment.blocks[0] === false) + this.alignment.type = type; + + // set alignment + if (this.alignment.isLinebreaksOrNoBlocks()) { - this.alignment.setText(type); + this.alignment.setText(); } else { - this.alignment.setBlocks(type); + this.alignment.setBlocks(); } + // sync this.selection.restore(); this.code.sync(); }, - setText: function(type) + setText: function() { var wrapper = this.selection.wrap('div'); - $(wrapper).attr('data-tagblock', 'redactor'); - $(wrapper).css('text-align', type); + $(wrapper).attr('data-tagblock', 'redactor').css('text-align', this.alignment.type); }, - setBlocks: function(type) + setBlocks: function() { $.each(this.alignment.blocks, $.proxy(function(i, el) { var $el = this.utils.getAlignmentElement(el); - if (!$el) return; - if (type === '' && typeof($el.data('tagblock')) !== 'undefined') + if (this.alignment.isNeedReplaceElement($el)) { - $el.replaceWith($el.html()); + this.alignment.replaceElement($el); } else { - $el.css('text-align', type); - this.utils.removeEmptyAttr($el, 'style'); + this.alignment.alignElement($el); } - }, this)); + }, + isLinebreaksOrNoBlocks: function() + { + return (this.opts.linebreaks && this.alignment.blocks[0] === false); + }, + isNeedReplaceElement: function($el) + { + return (this.alignment.type === '' && typeof($el.data('tagblock')) !== 'undefined'); + }, + replaceElement: function($el) + { + $el.replaceWith($el.html()); + }, + alignElement: function($el) + { + $el.css('text-align', this.alignment.type); + this.utils.removeEmptyAttr($el, 'style'); } }; }, autosave: function() { return { + html: false, enable: function() { if (!this.opts.autosave) return; - this.autosave.html = false; this.autosave.name = (this.opts.autosaveName) ? this.opts.autosaveName : this.$textarea.attr('name'); - if (!this.opts.autosaveOnChange) - { - this.autosaveInterval = setInterval($.proxy(this.autosave.load, this), this.opts.autosaveInterval * 1000); - } + if (this.opts.autosaveOnChange) return; + this.autosaveInterval = setInterval(this.autosave.load, this.opts.autosaveInterval * 1000); }, onChange: function() { if (!this.opts.autosaveOnChange) return; - this.autosave.load(); }, load: function() { - var html = this.code.get(); - if (this.autosave.html === html) return; - if (this.utils.isEmpty(html)) return; + this.autosave.source = this.code.get(); + + if (this.autosave.html === this.autosave.source) return; + //if (this.utils.isEmpty(this.autosave.source)) return; - $.ajax({ + // data + var data = {}; + data['name'] = this.autosave.name; + data[this.autosave.name] = this.autosave.source; + data = this.autosave.getHiddenFields(data); + + // ajax + var jsxhr = $.ajax({ url: this.opts.autosave, type: 'post', - data: 'name=' + this.autosave.name + '&' + this.autosave.name + '=' + escape(encodeURIComponent(html)), - success: $.proxy(function(data) - { - this.autosave.success(data, html); - - }, this) + data: data }); + + jsxhr.done(this.autosave.success); + }, + getHiddenFields: function(data) + { + if (this.opts.autosaveFields === false || typeof this.opts.autosaveFields !== 'object') + { + return data; + } + + $.each(this.opts.autosaveFields, $.proxy(function(k, v) + { + if (v !== null && v.toString().indexOf('#') === 0) v = $(v).val(); + data[k] = v; + + }, this)); + + return data; + }, - success: function(data, html) + success: function(data) { var json; try @@ -548,7 +612,7 @@ var callbackName = (typeof json.error == 'undefined') ? 'autosave' : 'autosaveError'; this.core.setCallback(callbackName, this.autosave.name, json); - this.autosave.html = html; + this.autosave.html = this.autosave.source; }, disable: function() { @@ -566,7 +630,7 @@ if (typeof this.formatting[name].data != 'undefined') type = 'data'; else if (typeof this.formatting[name].attr != 'undefined') type = 'attr'; - else if (typeof this.formatting[name].class != 'undefined') type = 'class'; + else if (typeof this.formatting[name]['class'] != 'undefined') type = 'class'; if (typeof this.formatting[name].clear != 'undefined') { @@ -681,6 +745,11 @@ this.block.toggle($(block)); } + if (typeof this.block.type == 'undefined' && typeof this.block.value == 'undefined') + { + $(block).removeAttr('class').removeAttr('style'); + } + }, setMultiple: function(tag) { @@ -756,14 +825,20 @@ { $.each(this.block.blocks, $.proxy(function(i,s) { + var $formatted = false; if (this.opts.linebreaks) { $(s).prepend('
').append('
'); - this.utils.replaceWithContents(s); + $formatted = this.utils.replaceWithContents(s); } else { - this.utils.replaceToTag(s, 'p'); + $formatted = this.utils.replaceToTag(s, 'p'); + } + + if ($formatted && typeof this.block.type == 'undefined' && typeof this.block.value == 'undefined') + { + $formatted.removeAttr('class').removeAttr('style'); } }, this)); @@ -782,7 +857,7 @@ if (this.block.type == 'class') { toggleType = 'toggle'; - classSize = $(this.block.blocks).filter('.' + this.block.value).size(); + classSize = $(this.block.blocks).filter('.' + this.block.value).length; if (this.block.blocksSize == classSize) toggleType = 'toggle'; else if (this.block.blocksSize > classSize) toggleType = 'set'; @@ -809,6 +884,11 @@ if (this.block.isRemoveInline) this.utils.removeInlineTags($formatted); if (tag == 'p' || this.block.headTag) $formatted.find('p').contents().unwrap(); + if (typeof this.block.type == 'undefined' && typeof this.block.value == 'undefined') + { + $formatted.removeAttr('class').removeAttr('style'); + } + }, this)); } @@ -871,7 +951,7 @@ }, formatListToBlockquote: function() { - var block = $(this.block.blocks[0]).closest('ul, ol'); + var block = $(this.block.blocks[0]).closest('ul, ol', this.$editor[0]); $(block).find('ul, ol').contents().unwrap(); $(block).find('li').append($('
')).contents().unwrap(); @@ -964,10 +1044,10 @@ }, formatTableWrapping: function($formatted) { - if ($formatted.closest('table').size() === 0) return; + if ($formatted.closest('table', this.$editor[0]).length === 0) return; - if ($formatted.closest('tr').size() === 0) $formatted.wrap(''); - if ($formatted.closest('td').size() === 0 && $formatted.closest('th').size() === 0) + if ($formatted.closest('tr', this.$editor[0]).length === 0) $formatted.wrap(''); + if ($formatted.closest('td', this.$editor[0]).length === 0 && $formatted.closest('th').length === 0) { $formatted.wrap(''); } @@ -1122,13 +1202,11 @@ return { run: function() { - this.build.createContainerBox(); this.build.loadContent(); this.build.loadEditor(); this.build.enableEditor(); this.build.setCodeAndCall(); - }, isTextarea: function() { @@ -1144,13 +1222,7 @@ }, getTextareaName: function() { - var name = this.$element.attr('id'); - if (typeof(name) == 'undefined') - { - name = 'content-' + this.uuid; - } - - return name; + return ((typeof(name) == 'undefined')) ? 'content-' + this.uuid : this.$element.attr('id'); }, loadContent: function() { @@ -1193,14 +1265,13 @@ this.build.callEditor(); // code mode - if (!this.opts.visual) - { - setTimeout($.proxy(this.code.showCode, this), 200); - } + if (this.opts.visual) return; + setTimeout($.proxy(this.code.showCode, this), 200); }, callEditor: function() { this.build.disableMozillaEditing(); + this.build.disableIeLinks(); this.build.setEvents(); this.build.setHelpers(); @@ -1236,6 +1307,21 @@ if (this.opts.maxHeight) this.$editor.css('maxHeight', this.opts.maxHeight); }, + setEventDropUpload: function(e) + { + e.preventDefault(); + + if (!this.opts.dragImageUpload || !this.opts.dragFileUpload) return; + + var files = e.dataTransfer.files; + this.upload.directUpload(files[0], e); + }, + setEventDrop: function(e) + { + this.code.sync(); + setTimeout(this.clean.clearUnverified, 1); + this.core.setCallback('drop', e); + }, setEvents: function() { // drop @@ -1245,28 +1331,16 @@ if (window.FormData === undefined || !e.dataTransfer) return true; - var length = e.dataTransfer.files.length; - if (length === 0) + if (e.dataTransfer.files.length === 0) { - this.code.sync(); - setTimeout($.proxy(this.clean.clearUnverified, this), 1); - this.core.setCallback('drop', e); - - return true; + return this.build.setEventDrop(e); } else { - e.preventDefault(); - - if (this.opts.dragImageUpload || this.opts.dragFileUpload) - { - var files = e.dataTransfer.files; - this.upload.directUpload(files[0], e); - } + this.build.setEventDropUpload(e); } - setTimeout($.proxy(this.clean.clearUnverified, this), 1); - + setTimeout(this.clean.clearUnverified, 1); this.core.setCallback('drop', e); }, this)); @@ -1275,11 +1349,8 @@ // click this.$editor.on('click.redactor', $.proxy(function(e) { - var type = 'click'; - if ((this.core.getEvent() == 'click' || this.core.getEvent() == 'arrow')) - { - type = false; - } + var event = this.core.getEvent(); + var type = (event == 'click' || event == 'arrow') ? false : 'click'; this.core.addEvent(type); this.utils.disableSelectAll(); @@ -1290,6 +1361,9 @@ // paste this.$editor.on('paste.redactor', $.proxy(this.paste.init, this)); + // cut + this.$editor.on('cut.redactor', $.proxy(this.code.sync, this)); + // keydown this.$editor.on('keydown.redactor', $.proxy(this.keydown.init, this)); @@ -1315,34 +1389,39 @@ } var clickedElement; - $(document).on('mousedown', function(e) { - clickedElement = $(e.target); - }); + $(document).on('mousedown', function(e) { clickedElement = e.target; }); // blur this.$editor.on('blur.redactor', $.proxy(function(e) { if (this.rtePaste) return; + if (!this.build.isBlured(clickedElement)) return; + + this.utils.disableSelectAll(); + if ($.isFunction(this.opts.blurCallback)) this.core.setCallback('blur', e); - var $el = $(clickedElement); - if (!$el.hasClass('redactor-toolbar, redactor-dropdown') && !$el.is('#redactor-modal') && $el.parents('.redactor-toolbar, .redactor-dropdown, #redactor-modal').size() === 0) - { - this.utils.disableSelectAll(); - if ($.isFunction(this.opts.blurCallback)) this.core.setCallback('blur', e); - } }, this)); }, + isBlured: function(clickedElement) + { + var $el = $(clickedElement); + + return (!$el.hasClass('redactor-toolbar, redactor-dropdown') && !$el.is('#redactor-modal') && $el.parents('.redactor-toolbar, .redactor-dropdown, #redactor-modal').length === 0); + }, setHelpers: function() { - // autosave - this.autosave.enable(); + // linkify + if (this.linkify.isEnabled()) + { + this.linkify.format(); + } // placeholder this.placeholder.enable(); // focus - if (this.opts.focus) setTimeout($.proxy(this.focus.setStart, this), 100); - if (this.opts.focusEnd) setTimeout($.proxy(this.focus.setEnd, this), 100); + if (this.opts.focus) setTimeout(this.focus.setStart, 100); + if (this.opts.focusEnd) setTimeout(this.focus.setEnd, 100); }, plugins: function() @@ -1364,6 +1443,7 @@ this[s] = RedactorPlugins[s](); + // get methods var methods = this.getModuleMethods(this[s]); var len = methods.length; @@ -1378,7 +1458,6 @@ }, this)); - }, disableMozillaEditing: function() { @@ -1389,6 +1468,13 @@ document.execCommand('enableObjectResizing', false, false); document.execCommand('enableInlineTableEditing', false, false); } catch (e) {} + }, + disableIeLinks: function() + { + if (!this.utils.browser('ie')) return; + + // IE prevent converting links + document.execCommand("AutoUrlDetect", false, false); } }; }, @@ -1399,34 +1485,16 @@ { var $button = $('').attr('tabindex', '-1'); + // click if (btnObject.func || btnObject.command || btnObject.dropdown) { - $button.on('touchstart click', $.proxy(function(e) - { - if ($button.hasClass('redactor-button-disabled')) return false; - - var type = 'func'; - var callback = btnObject.func; - if (btnObject.command) - { - type = 'command'; - callback = btnObject.command; - } - else if (btnObject.dropdown) - { - type = 'dropdown'; - callback = false; - } - - this.button.onClick(e, btnName, type, callback); - - }, this)); + this.button.setEvent($button, btnName, btnObject); } // dropdown if (btnObject.dropdown) { - var $dropdown = $('