diff --git a/modules/backend/formwidgets/richeditor/assets/vendor/redactor/redactor-iframe.css b/modules/backend/formwidgets/richeditor/assets/vendor/redactor/redactor-iframe.css
deleted file mode 100644
index 1ce460939..000000000
--- a/modules/backend/formwidgets/richeditor/assets/vendor/redactor/redactor-iframe.css
+++ /dev/null
@@ -1,203 +0,0 @@
-html {
- margin: 0;
- padding: 0;
-}
-body {
- margin: 0;
- padding: 10px;
- font-family: Arial, Helvetica, Verdana, Tahoma, sans-serif;
-}
-
-code,
-pre {
- font-family: Menlo, Monaco, monospace, sans-serif;
-}
-
-div,
-p,
-ul,
-ol,
-table,
-dl,
-blockquote,
-pre {
- font-size: 15px;
- line-height: 1.5rem;
-}
-div {
- border: 1px dashed #bbb !important;
-}
-a {
- color: #15c;
- text-decoration: underline;
-}
-.redactor_placeholder {
- color: #999 !important;
- display: block !important;
- margin-bottom: 10px !important;
-}
-
-object,
-embed,
-video,
-img {
- max-width: 100%;
- width: auto;
-}
-video,
-img {
- height: auto;
-}
-
-div,
-p,
-ul,
-ol,
-table,
-dl,
-blockquote,
-pre {
- margin: 0;
- margin-bottom: 15px;
- border: none;
- background: none;
- box-shadow: none;
-}
-iframe,
-object,
-hr {
- margin-bottom: 15px;
-}
-blockquote {
- margin-left: 1.5em !important;
- padding-left: 0;
- color: #777;
- font-style: italic;
-}
-ul,
-ol {
- padding-left: 2em;
-}
-ul ul,
-ol ol,
-ul ol,
-ol ul {
- margin: 2px;
- padding: 0;
- padding-left: 2em;
- border: none;
-}
-dl dt { font-weight: bold; }
-dd { margin-left: 1em;}
-
-table {
- border-collapse: collapse;
- font-size: 1em;
-}
-table td {
- padding: 5px;
- border: 1px solid #ddd;
- vertical-align: top;
-}
-table thead td {
- border-bottom: 2px solid #000;
- font-weight: bold;
-}
-code {
- background-color: #d8d7d7;
-}
-pre {
- overflow: auto;
- padding: 1em;
- border: 1px solid #ddd;
- border-radius: 3px;
- background: #f8f8f8;
- white-space: pre;
- font-size: 90%;
-}
-hr {
- display: block;
- height: 1px;
- border: 0;
- border-top: 1px solid #ccc;
-}
-
-h1,
-h2,
-h3,
-h4,
-h5 {
- margin: 0;
- padding: 0;
- background: none;
- color: #000;
- font-weight: bold;
-}
-
-h1 {
- margin-bottom: 10px;
- font-size: 36px;
- line-height: 40px;
-}
-h2 {
- margin-bottom: 15px;
- font-size: 30px;
- line-height: 38px;
-}
-h3 {
- margin-bottom: 10px;
- font-size: 24px;
- line-height: 30px;
-}
-h4 {
- margin-bottom: 10px;
- font-size: 18px;
- line-height: 24px;
-}
-h5 {
- margin-bottom: 10px;
- font-size: 1em;
-}
-
-body.redactor_editor_wym {
- background: #f4f4f4;
-}
-.redactor_editor_wym div,
-.redactor_editor_wym p,
-.redactor_editor_wym ul,
-.redactor_editor_wym ol,
-.redactor_editor_wym table,
-.redactor_editor_wym dl,
-.redactor_editor_wym pre,
-.redactor_editor_wym h1,
-.redactor_editor_wym h2,
-.redactor_editor_wym h3,
-.redactor_editor_wym h4,
-.redactor_editor_wym h5,
-.redactor_editor_wym blockquote {
- margin: 0 0 10px 0;
- padding: 7px 10px;
- border: 1px solid #e4e4e4;
- background-color: #fff;
-}
-.redactor_editor_wym div {
- border: 1px dashed #bbb !important;
-}
-.redactor_editor_wym pre {
- border: 2px dashed #e4e4e4 !important;
- background-color: #fafafa !important;
-}
-.redactor_editor_wym code {
- background-color: #f4f4f4 !important;
-}
-.redactor_editor_wym ul,
-.redactor_editor_wym ol {
- padding-left: 2em !important;
-}
-.redactor_editor_wym ul li ul,
-.redactor_editor_wym ul li ol,
-.redactor_editor_wym ol li ol,
-.redactor_editor_wym ol li ul {
- border: none !important;
-}
-
diff --git a/modules/backend/formwidgets/richeditor/assets/vendor/redactor/redactor.css b/modules/backend/formwidgets/richeditor/assets/vendor/redactor/redactor.css
index cd8dfbf1a..57aa6e29d 100644
--- a/modules/backend/formwidgets/richeditor/assets/vendor/redactor/redactor.css
+++ b/modules/backend/formwidgets/richeditor/assets/vendor/redactor/redactor.css
@@ -17,21 +17,14 @@
.redactor-box {
position: relative;
overflow: visible;
- background: #fff;
margin-bottom: 24px;
}
-.redactor-box iframe,
.redactor-box textarea {
display: block;
position: relative;
margin: 0;
padding: 0;
width: 100%;
-}
-.redactor-box iframe {
- border: 1px solid #eee;
-}
-.redactor-box textarea {
overflow: auto;
outline: none;
border: none;
@@ -49,21 +42,25 @@
Z-index setup
*/
.redactor-editor,
+.redactor-box {
+ background: #fff;
+}
+.redactor-editor,
.redactor-box,
.redactor-box textarea {
z-index: auto !important;
}
.redactor-box-fullscreen {
- z-index: 99 !important;
+ z-index: 1052 !important;
}
.redactor-toolbar,
.redactor-dropdown {
- z-index: 1050 !important;
+ z-index: 1053 !important;
}
#redactor-modal-overlay,
#redactor-modal-box,
#redactor-modal {
- z-index: 1051 !important;
+ z-index: 1054 !important;
}
/*
Resize
@@ -90,6 +87,12 @@ body .redactor-box-fullscreen {
left: 0;
width: 100%;
}
+/*
+ Utils
+*/
+.body-redactor-hidden {
+ overflow: hidden;
+}
/*
Editor
*/
@@ -124,8 +127,8 @@ body .redactor-box-fullscreen {
}
/* Placeholder in linebreaks mode */
.redactor-linebreaks.redactor-placeholder:after {
- top: 10px;
- left: 10px;
+ top: 20px;
+ left: 20px;
}
/*
Toolbar
@@ -339,7 +342,7 @@ body .redactor-box-fullscreen {
*/
.redactor-toolbar-tooltip {
position: absolute;
- z-index: 100;
+ z-index: 1054;
text-align: center;
top: 0;
left: 0;
@@ -383,6 +386,42 @@ body .redactor-box-fullscreen {
color: #fff !important;
text-decoration: none;
}
+/*
+ IMAGE BOX
+*/
+#redactor-image-box {
+ position: relative;
+ max-width: 100%;
+ display: inline-block;
+ line-height: 0;
+ outline: 1px dashed rgba(0, 0, 0, 0.6);
+}
+#redactor-image-editter {
+ position: absolute;
+ z-index: 5;
+ top: 50%;
+ left: 50%;
+ margin-top: -11px;
+ margin-left: -18px;
+ line-height: 1;
+ background-color: #000;
+ color: #fff;
+ font-size: 11px;
+ padding: 7px 10px;
+ cursor: pointer;
+}
+#redactor-image-resizer {
+ position: absolute;
+ z-index: 2;
+ line-height: 1;
+ cursor: nw-resize;
+ bottom: -4px;
+ right: -5px;
+ border: 1px solid #fff;
+ background-color: #000;
+ width: 8px;
+ height: 8px;
+}
/*
LINK TOOLTIP
*/
@@ -782,9 +821,6 @@ body .redactor-box-fullscreen {
.redactor-editor hr {
margin-bottom: 15px;
}
-.redactor-editor iframe {
- width: auto;
-}
.redactor-editor blockquote {
margin-left: 1.6em !important;
padding-left: 0;
@@ -851,7 +887,7 @@ body .redactor-box-fullscreen {
.redactor-editor h5,
.redactor-editor h6 {
font-weight: bold;
- color: #0000;
+ color: #000;
padding: 0;
background: none;
text-rendering: optimizeLegibility;
diff --git a/modules/backend/formwidgets/richeditor/assets/vendor/redactor/redactor.js b/modules/backend/formwidgets/richeditor/assets/vendor/redactor/redactor.js
index 869ee18d7..23baa5c45 100644
--- a/modules/backend/formwidgets/richeditor/assets/vendor/redactor/redactor.js
+++ b/modules/backend/formwidgets/richeditor/assets/vendor/redactor/redactor.js
@@ -1,10 +1,10 @@
/*
- Redactor v10.0
- Updated: September 24, 2014
+ Redactor v10.0.7
+ Updated: January 31, 2015
http://imperavi.com/redactor/
- Copyright (c) 2009-2014, Imperavi LLC.
+ Copyright (c) 2009-2015, Imperavi LLC.
License: http://imperavi.com/redactor/license/
Usage: $('#content').redactor();
@@ -94,11 +94,13 @@
// Functionality
$.Redactor = Redactor;
- $.Redactor.VERSION = '10.0';
- $.Redactor.modules = ['core', 'build', 'lang', 'toolbar', 'button', 'dropdown', 'code',
- 'clean', 'tidy', 'paragraphize', 'tabifier', 'focus', 'placeholder', 'autosave', 'buffer', 'indent', 'alignment', 'paste',
- 'keydown', 'keyup', 'shortcuts', 'line', 'list', 'block', 'inline', 'insert', 'caret', 'selection', 'observe',
- 'link', 'image', 'file', 'modal', 'progress', 'upload', 'utils'];
+ $.Redactor.VERSION = '10.0.7';
+ $.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'];
$.Redactor.opts = {
@@ -145,15 +147,14 @@
imageFloatMargin: '10px',
imageResizable: true,
- imageUpload: false,
+ imageUpload: null,
imageUploadParam: 'file',
uploadImageField: false,
dragImageUpload: true,
- clipboardImageUpload: false,
- fileUpload: false,
+ fileUpload: null,
fileUploadParam: 'file',
dragFileUpload: true,
@@ -167,7 +168,7 @@
preSpaces: 4, // or false
tabAsSpaces: false, // true or number of spaces
- tabFocus: true,
+ tabKey: true,
scrollTarget: false,
@@ -178,7 +179,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'
@@ -342,6 +343,7 @@
META: 91,
SHIFT: 16,
ALT: 18,
+ RIGHT: 39,
LEFT: 37,
LEFT_WIN: 91
},
@@ -424,93 +426,716 @@
}
},
- core: function()
+ alignment: function()
{
return {
- getObject: function()
+ left: function()
{
- return $.extend({}, this);
+ this.alignment.set('');
},
- getEditor: function()
+ right: function()
{
- return this.$editor;
+ this.alignment.set('right');
},
- getBox: function()
+ center: function()
{
- return this.$box;
+ this.alignment.set('center');
},
- getElement: function()
+ justify: function()
{
- return this.$element;
+ this.alignment.set('justify');
},
- getTextarea: function()
+ set: function(type)
{
- return this.$textarea;
- },
- getToolbar: function()
- {
- return (this.$toolbar) ? this.$toolbar : false;
- },
- addEvent: function(name)
- {
- this.core.event = name;
- },
- getEvent: function()
- {
- return this.core.event;
- },
- setCallback: function(type, e, data)
- {
- var callback = this.opts[type + 'Callback'];
- if ($.isFunction(callback))
+ // focus
+ if (!this.utils.browser('msie')) this.$editor.focus();
+
+ this.buffer.set();
+ this.selection.save();
+
+ // get blocks
+ this.alignment.blocks = this.selection.getBlocks();
+ this.alignment.type = type;
+
+ // set alignment
+ if (this.alignment.isLinebreaksOrNoBlocks())
{
- return (typeof data == 'undefined') ? callback.call(this, e) : callback.call(this, e, data);
+ this.alignment.setText();
}
else
{
- return (typeof data == 'undefined') ? e : data;
+ this.alignment.setBlocks();
}
+
+ // sync
+ this.selection.restore();
+ this.code.sync();
},
- destroy: function()
+ setText: function()
{
- this.core.setCallback('destroy');
-
- // off events and remove data
- this.$element.off('.redactor').removeData('redactor');
- this.$editor.off('.redactor');
-
- // common
- this.$editor.removeClass('redactor-editor redactor-linebreaks redactor-placeholder');
- this.$editor.removeAttr('contenteditable');
-
- var html = this.code.get();
-
- if (this.build.isTextarea())
+ var wrapper = this.selection.wrap('div');
+ $(wrapper).attr('data-tagblock', 'redactor').css('text-align', this.alignment.type);
+ },
+ setBlocks: function()
+ {
+ $.each(this.alignment.blocks, $.proxy(function(i, el)
{
- this.$box.after(this.$element);
- this.$box.remove();
- this.$element.val(html).show();
+ var $el = this.utils.getAlignmentElement(el);
+ if (!$el) return;
+
+ if (this.alignment.isNeedReplaceElement($el))
+ {
+ this.alignment.replaceElement($el);
+ }
+ else
+ {
+ 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 {
+ 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) return;
+ this.autosaveInterval = setInterval(this.autosave.load, this.opts.autosaveInterval * 1000);
+ },
+ onChange: function()
+ {
+ if (!this.opts.autosaveOnChange) return;
+ this.autosave.load();
+ },
+ load: function()
+ {
+ this.autosave.source = this.code.get();
+
+ if (this.autosave.html === this.autosave.source) return;
+ if (this.utils.isEmpty(this.autosave.source)) return;
+
+ // data
+ var data = {};
+ data['name'] = this.autosave.name;
+ data[this.autosave.name] = escape(encodeURIComponent(this.autosave.source));
+
+ // ajax
+ var jsxhr = $.ajax({
+ url: this.opts.autosave,
+ type: 'post',
+ data: data
+ });
+
+ jsxhr.done(this.autosave.success);
+ },
+ success: function(data)
+ {
+ var json;
+ try
+ {
+ json = $.parseJSON(data);
}
- else
+ catch(e)
{
- this.$box.after(this.$editor);
- this.$box.remove();
- this.$element.html(html).show();
+ //data has already been parsed
+ json = data;
}
- // paste box
- if (this.$pasteBox) this.$pasteBox.remove();
+ var callbackName = (typeof json.error == 'undefined') ? 'autosave' : 'autosaveError';
- // modal
- if (this.$modalBox) this.$modalBox.remove();
- if (this.$modalOverlay) this.$modalOverlay.remove();
-
- // buttons tooltip
- $('.redactor-toolbar-tooltip').remove();
-
- // autosave
+ this.core.setCallback(callbackName, this.autosave.name, json);
+ this.autosave.html = this.autosave.source;
+ },
+ disable: function()
+ {
clearInterval(this.autosaveInterval);
+ }
+ };
+ },
+ block: function()
+ {
+ return {
+ formatting: function(name)
+ {
+ this.block.clearStyle = false;
+ var type, value;
+ 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';
+
+ if (typeof this.formatting[name].clear != 'undefined')
+ {
+ this.block.clearStyle = true;
+ }
+
+ if (type) value = this.formatting[name][type];
+
+ this.block.format(this.formatting[name].tag, type, value);
+
+ },
+ format: function(tag, type, value)
+ {
+ if (tag == 'quote') tag = 'blockquote';
+
+ var formatTags = ['p', 'pre', 'blockquote', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
+ if ($.inArray(tag, formatTags) == -1) return;
+
+ this.block.isRemoveInline = (tag == 'pre' || tag.search(/h[1-6]/i) != -1);
+
+ // focus
+ if (!this.utils.browser('msie')) this.$editor.focus();
+
+ this.block.blocks = this.selection.getBlocks();
+
+ this.block.blocksSize = this.block.blocks.length;
+ this.block.type = type;
+ this.block.value = value;
+
+ this.buffer.set();
+ this.selection.save();
+
+ this.block.set(tag);
+
+ this.selection.restore();
+ this.code.sync();
+
+ },
+ set: function(tag)
+ {
+ this.selection.get();
+ this.block.containerTag = this.range.commonAncestorContainer.tagName;
+
+ if (this.range.collapsed)
+ {
+ this.block.setCollapsed(tag);
+ }
+ else
+ {
+ this.block.setMultiple(tag);
+ }
+ },
+ setCollapsed: function(tag)
+ {
+ var block = this.block.blocks[0];
+ if (block === false) return;
+
+ if (block.tagName == 'LI')
+ {
+ if (tag != 'blockquote') return;
+
+ this.block.formatListToBlockquote();
+ return;
+ }
+
+ var isContainerTable = (this.block.containerTag == 'TD' || this.block.containerTag == 'TH');
+ if (isContainerTable && !this.opts.linebreaks)
+ {
+
+ document.execCommand('formatblock', false, '<' + tag + '>');
+
+ block = this.selection.getBlock();
+ this.block.toggle($(block));
+
+ }
+ else if (block.tagName.toLowerCase() != tag)
+ {
+ if (this.opts.linebreaks && tag == 'p')
+ {
+ $(block).prepend('
').append('
');
+ this.utils.replaceWithContents(block);
+ }
+ else
+ {
+ var $formatted = this.utils.replaceToTag(block, tag);
+
+ this.block.toggle($formatted);
+
+ if (tag != 'p' && tag != 'blockquote') $formatted.find('img').remove();
+ if (this.block.isRemoveInline) this.utils.removeInlineTags($formatted);
+ if (tag == 'p' || this.block.headTag) $formatted.find('p').contents().unwrap();
+
+ this.block.formatTableWrapping($formatted);
+ }
+ }
+ else if (tag == 'blockquote' && block.tagName.toLowerCase() == tag)
+ {
+ // blockquote off
+ if (this.opts.linebreaks)
+ {
+ $(block).prepend('
').append('
');
+ this.utils.replaceWithContents(block);
+ }
+ else
+ {
+ var $el = this.utils.replaceToTag(block, 'p');
+ this.block.toggle($el);
+ }
+ }
+ else if (block.tagName.toLowerCase() == tag)
+ {
+ this.block.toggle($(block));
+ }
+
+ },
+ setMultiple: function(tag)
+ {
+ var block = this.block.blocks[0];
+ var isContainerTable = (this.block.containerTag == 'TD' || this.block.containerTag == 'TH');
+
+ if (block !== false && this.block.blocksSize === 1)
+ {
+ if (block.tagName.toLowerCase() == tag && tag == 'blockquote')
+ {
+ // blockquote off
+ if (this.opts.linebreaks)
+ {
+ $(block).prepend('
').append('
');
+ this.utils.replaceWithContents(block);
+ }
+ else
+ {
+ var $el = this.utils.replaceToTag(block, 'p');
+ this.block.toggle($el);
+ }
+ }
+ else if (block.tagName == 'LI')
+ {
+ if (tag != 'blockquote') return;
+
+ this.block.formatListToBlockquote();
+ }
+ else if (this.block.containerTag == 'BLOCKQUOTE')
+ {
+ this.block.formatBlockquote(tag);
+ }
+ else if (this.opts.linebreaks && ((isContainerTable) || (this.range.commonAncestorContainer != block)))
+ {
+ this.block.formatWrap(tag);
+ }
+ else
+ {
+ if (this.opts.linebreaks && tag == 'p')
+ {
+ $(block).prepend('
').append('
');
+ this.utils.replaceWithContents(block);
+ }
+ else if (block.tagName === 'TD')
+ {
+ this.block.formatWrap(tag);
+ }
+ else
+ {
+ var $formatted = this.utils.replaceToTag(block, tag);
+
+ this.block.toggle($formatted);
+
+ if (this.block.isRemoveInline) this.utils.removeInlineTags($formatted);
+ if (tag == 'p' || this.block.headTag) $formatted.find('p').contents().unwrap();
+ }
+ }
+ }
+ else
+ {
+
+ if (this.opts.linebreaks || tag != 'p')
+ {
+ if (tag == 'blockquote')
+ {
+ var count = 0;
+ for (var i = 0; i < this.block.blocksSize; i++)
+ {
+ if (this.block.blocks[i].tagName == 'BLOCKQUOTE') count++;
+ }
+
+ // only blockquote selected
+ if (count == this.block.blocksSize)
+ {
+ $.each(this.block.blocks, $.proxy(function(i,s)
+ {
+ if (this.opts.linebreaks)
+ {
+ $(s).prepend('
').append('
');
+ this.utils.replaceWithContents(s);
+ }
+ else
+ {
+ this.utils.replaceToTag(s, 'p');
+ }
+
+ }, this));
+
+ return;
+ }
+
+ }
+
+
+ this.block.formatWrap(tag);
+ }
+ else
+ {
+ var classSize = 0;
+ var toggleType = false;
+ if (this.block.type == 'class')
+ {
+ toggleType = 'toggle';
+ classSize = $(this.block.blocks).filter('.' + this.block.value).length;
+
+ if (this.block.blocksSize == classSize) toggleType = 'toggle';
+ else if (this.block.blocksSize > classSize) toggleType = 'set';
+ else if (classSize === 0) toggleType = 'set';
+
+ }
+
+ var exceptTags = ['ul', 'ol', 'li', 'td', 'th', 'dl', 'dt', 'dd'];
+ $.each(this.block.blocks, $.proxy(function(i,s)
+ {
+ if ($.inArray(s.tagName.toLowerCase(), exceptTags) != -1) return;
+
+ var $formatted = this.utils.replaceToTag(s, tag);
+
+ if (toggleType)
+ {
+ if (toggleType == 'toggle') this.block.toggle($formatted);
+ else if (toggleType == 'remove') this.block.remove($formatted);
+ else if (toggleType == 'set') this.block.setForce($formatted);
+ }
+ else this.block.toggle($formatted);
+
+ if (tag != 'p' && tag != 'blockquote') $formatted.find('img').remove();
+ if (this.block.isRemoveInline) this.utils.removeInlineTags($formatted);
+ if (tag == 'p' || this.block.headTag) $formatted.find('p').contents().unwrap();
+
+
+ }, this));
+ }
+ }
+ },
+ setForce: function($el)
+ {
+ // remove style and class if the specified setting
+ if (this.block.clearStyle)
+ {
+ $el.removeAttr('class').removeAttr('style');
+ }
+
+ if (this.block.type == 'class')
+ {
+ $el.addClass(this.block.value);
+ return;
+ }
+ else if (this.block.type == 'attr' || this.block.type == 'data')
+ {
+ $el.attr(this.block.value.name, this.block.value.value);
+ return;
+ }
+ },
+ toggle: function($el)
+ {
+ // remove style and class if the specified setting
+ if (this.block.clearStyle)
+ {
+ $el.removeAttr('class').removeAttr('style');
+ }
+
+ if (this.block.type == 'class')
+ {
+ $el.toggleClass(this.block.value);
+ return;
+ }
+ else if (this.block.type == 'attr' || this.block.type == 'data')
+ {
+ if ($el.attr(this.block.value.name) == this.block.value.value)
+ {
+ $el.removeAttr(this.block.value.name);
+ }
+ else
+ {
+ $el.attr(this.block.value.name, this.block.value.value);
+ }
+
+ return;
+ }
+ else
+ {
+ $el.removeAttr('style class');
+ return;
+ }
+ },
+ remove: function($el)
+ {
+ $el.removeClass(this.block.value);
+ },
+ formatListToBlockquote: function()
+ {
+ var block = $(this.block.blocks[0]).closest('ul, ol');
+
+ $(block).find('ul, ol').contents().unwrap();
+ $(block).find('li').append($('
')).contents().unwrap();
+
+ var $el = this.utils.replaceToTag(block, 'blockquote');
+ this.block.toggle($el);
+ },
+ formatBlockquote: function(tag)
+ {
+ document.execCommand('outdent');
+ document.execCommand('formatblock', false, tag);
+
+ this.clean.clearUnverified();
+ this.$editor.find('p:empty').remove();
+
+ var formatted = this.selection.getBlock();
+
+ if (tag != 'p')
+ {
+ $(formatted).find('img').remove();
+ }
+
+ if (!this.opts.linebreaks)
+ {
+ this.block.toggle($(formatted));
+ }
+
+ this.$editor.find('ul, ol, tr, blockquote, p').each($.proxy(this.utils.removeEmpty, this));
+
+ if (this.opts.linebreaks && tag == 'p')
+ {
+ this.utils.replaceWithContents(formatted);
+ }
+
+ },
+ formatWrap: function(tag)
+ {
+ if (this.block.containerTag == 'UL' || this.block.containerTag == 'OL')
+ {
+ if (tag == 'blockquote')
+ {
+ this.block.formatListToBlockquote();
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ var formatted = this.selection.wrap(tag);
+ if (formatted === false) return;
+
+ var $formatted = $(formatted);
+
+ this.block.formatTableWrapping($formatted);
+
+ var $elements = $formatted.find(this.opts.blockLevelElements.join(',') + ', td, table, thead, tbody, tfoot, th, tr');
+
+ if ((this.opts.linebreaks && tag == 'p') || tag == 'pre' || tag == 'blockquote')
+ {
+ $elements.append('
');
+ }
+
+ $elements.contents().unwrap();
+
+ if (tag != 'p' && tag != 'blockquote') $formatted.find('img').remove();
+
+ $.each(this.block.blocks, $.proxy(this.utils.removeEmpty, this));
+
+ $formatted.append(this.selection.getMarker(2));
+
+ if (!this.opts.linebreaks)
+ {
+ this.block.toggle($formatted);
+ }
+
+ this.$editor.find('ul, ol, tr, blockquote, p').each($.proxy(this.utils.removeEmpty, this));
+ $formatted.find('blockquote:empty').remove();
+
+ if (this.block.isRemoveInline)
+ {
+ this.utils.removeInlineTags($formatted);
+ }
+
+ if (this.opts.linebreaks && tag == 'p')
+ {
+ this.utils.replaceWithContents($formatted);
+ }
+
+ },
+ formatTableWrapping: function($formatted)
+ {
+ if ($formatted.closest('table').length === 0) return;
+
+ if ($formatted.closest('tr').length === 0) $formatted.wrap('
');
+ if ($formatted.closest('td').length === 0 && $formatted.closest('th').length === 0)
+ {
+ $formatted.wrap('');
+ }
+ },
+ removeData: function(name, value)
+ {
+ var blocks = this.selection.getBlocks();
+ $(blocks).removeAttr('data-' + name);
+
+ this.code.sync();
+ },
+ setData: function(name, value)
+ {
+ var blocks = this.selection.getBlocks();
+ $(blocks).attr('data-' + name, value);
+
+ this.code.sync();
+ },
+ toggleData: function(name, value)
+ {
+ var blocks = this.selection.getBlocks();
+ $.each(blocks, function()
+ {
+ if ($(this).attr('data-' + name))
+ {
+ $(this).removeAttr('data-' + name);
+ }
+ else
+ {
+ $(this).attr('data-' + name, value);
+ }
+ });
+ },
+ removeAttr: function(attr, value)
+ {
+ var blocks = this.selection.getBlocks();
+ $(blocks).removeAttr(attr);
+
+ this.code.sync();
+ },
+ setAttr: function(attr, value)
+ {
+ var blocks = this.selection.getBlocks();
+ $(blocks).attr(attr, value);
+
+ this.code.sync();
+ },
+ toggleAttr: function(attr, value)
+ {
+ var blocks = this.selection.getBlocks();
+ $.each(blocks, function()
+ {
+ if ($(this).attr(name))
+ {
+ $(this).removeAttr(name);
+ }
+ else
+ {
+ $(this).attr(name, value);
+ }
+ });
+ },
+ removeClass: function(className)
+ {
+ var blocks = this.selection.getBlocks();
+ $(blocks).removeClass(className);
+
+ this.utils.removeEmptyAttr(blocks, 'class');
+
+ this.code.sync();
+ },
+ setClass: function(className)
+ {
+ var blocks = this.selection.getBlocks();
+ $(blocks).addClass(className);
+
+ this.code.sync();
+ },
+ toggleClass: function(className)
+ {
+ var blocks = this.selection.getBlocks();
+ $(blocks).toggleClass(className);
+
+ this.code.sync();
+ }
+ };
+ },
+ buffer: function()
+ {
+ return {
+ set: function(type)
+ {
+ if (typeof type == 'undefined' || type == 'undo')
+ {
+ this.buffer.setUndo();
+ }
+ else
+ {
+ this.buffer.setRedo();
+ }
+ },
+ setUndo: function()
+ {
+ this.selection.save();
+ this.opts.buffer.push(this.$editor.html());
+ this.selection.restore();
+ },
+ setRedo: function()
+ {
+ this.selection.save();
+ this.opts.rebuffer.push(this.$editor.html());
+ this.selection.restore();
+ },
+ getUndo: function()
+ {
+ this.$editor.html(this.opts.buffer.pop());
+ },
+ getRedo: function()
+ {
+ this.$editor.html(this.opts.rebuffer.pop());
+ },
+ add: function()
+ {
+ this.opts.buffer.push(this.$editor.html());
+ },
+ undo: function()
+ {
+ if (this.opts.buffer.length === 0) return;
+
+ this.buffer.set('redo');
+ this.buffer.getUndo();
+
+ this.selection.restore();
+
+ setTimeout($.proxy(this.observe.load, this), 50);
+ },
+ redo: function()
+ {
+ if (this.opts.rebuffer.length === 0) return;
+
+ this.buffer.set('undo');
+ this.buffer.getRedo();
+
+ this.selection.restore();
+
+ setTimeout($.proxy(this.observe.load, this), 50);
}
};
},
@@ -519,13 +1144,11 @@
return {
run: function()
{
-
this.build.createContainerBox();
this.build.loadContent();
this.build.loadEditor();
this.build.enableEditor();
this.build.setCodeAndCall();
-
},
isTextarea: function()
{
@@ -541,13 +1164,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()
{
@@ -590,10 +1207,8 @@
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()
{
@@ -633,6 +1248,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
@@ -642,21 +1272,16 @@
if (window.FormData === undefined || !e.dataTransfer) return true;
- var length = e.dataTransfer.files.length;
- if (length === 0) return true;
+ if (e.dataTransfer.files.length === 0)
+ {
+ 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));
@@ -665,11 +1290,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();
@@ -705,23 +1327,25 @@
}
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
@@ -731,8 +1355,8 @@
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()
@@ -742,26 +1366,32 @@
$.each(this.opts.plugins, $.proxy(function(i, s)
{
- if (RedactorPlugins[s])
+ if (typeof RedactorPlugins[s] === 'undefined') return;
+
+ if ($.inArray(s, $.Redactor.modules) !== -1)
{
- if (!$.isFunction(RedactorPlugins[s])) return;
-
- this[s] = RedactorPlugins[s]();
-
- var methods = this.getModuleMethods(this[s]);
- var len = methods.length;
-
- // bind methods
- for (var z = 0; z < len; z++)
- {
- this[s][methods[z]] = this[s][methods[z]].bind(this);
- }
-
- if ($.isFunction(this[s].init)) this[s].init();
+ $.error('Plugin name "' + s + '" matches the name of the Redactor\'s module.');
+ return;
}
- }, this));
+ if (!$.isFunction(RedactorPlugins[s])) return;
+ this[s] = RedactorPlugins[s]();
+
+ // get methods
+ var methods = this.getModuleMethods(this[s]);
+ var len = methods.length;
+
+ // bind methods
+ for (var z = 0; z < len; z++)
+ {
+ this[s][methods[z]] = this[s][methods[z]].bind(this);
+ }
+
+ if ($.isFunction(this[s].init)) this[s].init();
+
+
+ }, this));
},
disableMozillaEditing: function()
@@ -776,389 +1406,17 @@
}
};
},
- lang: function()
- {
- return {
- load: function()
- {
- this.opts.curLang = this.opts.langs[this.opts.lang];
- },
- get: function(name)
- {
- return (typeof this.opts.curLang[name] != 'undefined') ? this.opts.curLang[name] : '';
- }
- };
- },
- toolbar: function()
- {
- return {
- init: function()
- {
- return {
- html:
- {
- title: this.lang.get('html'),
- func: 'code.toggle'
- },
- formatting:
- {
- title: this.lang.get('formatting'),
- dropdown:
- {
- p:
- {
- title: this.lang.get('paragraph'),
- func: 'block.format'
- },
- blockquote:
- {
- title: this.lang.get('quote'),
- func: 'block.format'
- },
- pre:
- {
- title: this.lang.get('code'),
- func: 'block.format'
- },
- h1:
- {
- title: this.lang.get('header1'),
- func: 'block.format'
- },
- h2:
- {
- title: this.lang.get('header2'),
- func: 'block.format'
- },
- h3:
- {
- title: this.lang.get('header3'),
- func: 'block.format'
- },
- h4:
- {
- title: this.lang.get('header4'),
- func: 'block.format'
- },
- h5:
- {
- title: this.lang.get('header5'),
- func: 'block.format'
- }
- }
- },
- bold:
- {
- title: this.lang.get('bold'),
- func: 'inline.format'
- },
- italic:
- {
- title: this.lang.get('italic'),
- func: 'inline.format'
- },
- deleted:
- {
- title: this.lang.get('deleted'),
- func: 'inline.format'
- },
- underline:
- {
- title: this.lang.get('underline'),
- func: 'inline.format'
- },
- unorderedlist:
- {
- title: '• ' + this.lang.get('unorderedlist'),
- func: 'list.toggle'
- },
- orderedlist:
- {
- title: '1. ' + this.lang.get('orderedlist'),
- 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'),
- func: 'image.show'
- },
- file:
- {
- title: this.lang.get('file'),
- func: 'file.show'
- },
- link:
- {
- title: this.lang.get('link'),
- dropdown:
- {
- link:
- {
- title: this.lang.get('link_insert'),
- func: 'link.show'
- },
- unlink:
- {
- title: this.lang.get('unlink'),
- func: 'link.unlink'
- }
- }
- },
- alignment:
- {
- title: this.lang.get('alignment'),
- dropdown:
- {
- left:
- {
- title: this.lang.get('align_left'),
- func: 'alignment.left'
- },
- center:
- {
- title: this.lang.get('align_center'),
- func: 'alignment.center'
- },
- right:
- {
- title: this.lang.get('align_right'),
- func: 'alignment.right'
- },
- justify:
- {
- title: this.lang.get('align_justify'),
- func: 'alignment.justify'
- }
- }
- },
- horizontalrule:
- {
- title: this.lang.get('horizontalrule'),
- func: 'line.insert'
- }
- };
- },
- build: function()
- {
- this.toolbar.hideButtons();
- this.toolbar.hideButtonsOnMobile();
- this.toolbar.isButtonSourceNeeded();
-
- if (this.opts.buttons.length === 0) return;
-
- this.$toolbar = this.toolbar.createContainer();
-
- this.toolbar.setOverflow();
- this.toolbar.append();
- this.toolbar.setFormattingTags();
- this.toolbar.loadButtons();
- this.toolbar.setTabindex();
- this.toolbar.setFixed();
-
- // buttons response
- if (this.opts.activeButtons)
- {
- this.$editor.on('mouseup.redactor keyup.redactor focus.redactor', $.proxy(this.observe.buttons, this));
- }
-
- },
- createContainer: function()
- {
- return $('').addClass('redactor-toolbar').attr('id', 'redactor-toolbar-' + this.uuid);
- },
- setFormattingTags: function()
- {
- $.each(this.opts.toolbar.formatting.dropdown, $.proxy(function (i, s)
- {
- if ($.inArray(i, this.opts.formatting) == -1) delete this.opts.toolbar.formatting.dropdown[i];
- }, this));
-
- },
- loadButtons: function()
- {
- $.each(this.opts.buttons, $.proxy(function(i, btnName)
- {
- if (!this.opts.toolbar[btnName]) return;
-
- if (this.opts.fileUpload === false && btnName === 'file') return true;
- if (this.opts.imageUpload === false && btnName === 'image') return true;
-
- var btnObject = this.opts.toolbar[btnName];
- this.$toolbar.append($('- ').append(this.button.build(btnName, btnObject)));
-
- }, this));
- },
- append: function()
- {
- if (this.opts.toolbarExternal)
- {
- this.$toolbar.addClass('redactor-toolbar-external');
- $(this.opts.toolbarExternal).html(this.$toolbar);
- }
- else
- {
- this.$box.prepend(this.$toolbar);
- }
- },
- setFixed: function()
- {
- if (this.utils.isMobile()) return;
- if (this.opts.toolbarExternal) return;
- if (!this.opts.toolbarFixed) return;
-
- this.toolbar.observeScroll();
- $(this.opts.toolbarFixedTarget).on('scroll.redactor', $.proxy(this.toolbar.observeScroll, this));
-
- },
- setTabindex: function()
- {
- this.$toolbar.find('a').attr('tabindex', '-1');
- },
- setOverflow: function()
- {
- if (this.utils.isMobile() && this.opts.toolbarOverflow)
- {
- this.$toolbar.addClass('redactor-toolbar-overflow');
- }
- },
- isButtonSourceNeeded: function()
- {
- if (this.opts.buttonSource) return;
-
- var index = this.opts.buttons.indexOf('html');
- this.opts.buttons.splice(index, 1);
- },
- hideButtons: function()
- {
- if (this.opts.buttonsHide.length === 0) return;
-
- $.each(this.opts.buttonsHide, $.proxy(function(i, s)
- {
- var index = this.opts.buttons.indexOf(s);
- this.opts.buttons.splice(index, 1);
-
- }, this));
- },
- hideButtonsOnMobile: function()
- {
- if (!this.utils.isMobile() && this.opts.buttonsHideOnMobile.length === 0) return;
-
- $.each(this.opts.buttonsHideOnMobile, $.proxy(function(i, s)
- {
- var index = this.opts.buttons.indexOf(s);
- this.opts.buttons.splice(index, 1);
-
- }, this));
- },
- observeScroll: function()
- {
- var scrollTop = $(this.opts.toolbarFixedTarget).scrollTop();
- var boxTop = 1;
-
- if (this.opts.toolbarFixedTarget === document)
- {
- boxTop = this.$box.offset().top;
- }
-
- if (scrollTop > boxTop)
- {
- this.toolbar.observeScrollEnable(scrollTop, boxTop);
- }
- else
- {
- this.toolbar.observeScrollDisable();
- }
- },
- observeScrollEnable: function(scrollTop, boxTop)
- {
- var top = this.opts.toolbarFixedTopOffset + scrollTop - boxTop;
- var left = 0;
- var end = boxTop + this.$box.height() + 30;
- var width = this.$box.innerWidth();
-
- this.$toolbar.addClass('toolbar-fixed-box');
- this.$toolbar.css({
- position: 'absolute',
- width: width,
- top: top + 'px',
- left: left
- });
-
- this.toolbar.setDropdownsFixed();
- this.$toolbar.css('visibility', (scrollTop < end) ? 'visible' : 'hidden');
- },
- observeScrollDisable: function()
- {
- this.$toolbar.css({
- position: 'relative',
- width: 'auto',
- top: 0,
- left: 0,
- visibility: 'visible'
- });
-
- this.toolbar.unsetDropdownsFixed();
- this.$toolbar.removeClass('toolbar-fixed-box');
-
- },
- setDropdownsFixed: function()
- {
- var self = this;
- $('.redactor-dropdown').each(function()
- {
- $(this).css({ position: 'fixed', top: self.$toolbar.innerHeight() + self.opts.toolbarFixedTopOffset });
- });
- },
- unsetDropdownsFixed: function()
- {
- var self = this;
- $('.redactor-dropdown').each(function()
- {
- var top = (self.$toolbar.innerHeight() + self.$toolbar.offset().top) + 'px';
- $(this).css({ position: 'absolute', top: top });
- });
- }
- };
- },
button: function()
{
return {
build: function(btnName, btnObject)
{
- var $button = $('');
+ 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
@@ -1177,6 +1435,30 @@
return $button;
},
+ setEvent: function($button, btnName, btnObject)
+ {
+ $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));
+ },
createTooltip: function($button, name, title)
{
var $tooltip = $('').addClass('redactor-toolbar-tooltip redactor-toolbar-tooltip-' + name).hide().html(title);
@@ -1187,13 +1469,11 @@
if ($(this).hasClass('redactor-button-disabled')) return;
var pos = $button.offset();
- var height = $button.innerHeight();
- var width = $button.innerWidth();
$tooltip.show();
$tooltip.css({
- top: (pos.top + height) + 'px',
- left: (pos.left + width/2 - $tooltip.innerWidth()/2) + 'px'
+ top: (pos.top + $button.innerHeight()) + 'px',
+ left: (pos.left + $button.innerWidth()/2 - $tooltip.innerWidth()/2) + 'px'
});
});
@@ -1205,42 +1485,31 @@
},
onClick: function(e, btnName, type, callback)
{
+ this.button.caretOffset = this.caret.getOffset();
+
e.preventDefault();
if (this.utils.browser('msie')) e.returnValue = false;
- if (type == 'command')
- {
- this.inline.format(callback);
- }
- else if (type == 'dropdown')
- {
- this.dropdown.show(e, btnName);
- }
- else
- {
- var func;
- if ($.isFunction(callback))
- {
- callback.call(this, btnName);
- this.observe.buttons(e, btnName);
- }
- else if (callback.search(/\./) != '-1')
- {
- func = callback.split('.');
- if (typeof this[func[0]] != 'undefined')
- {
- this[func[0]][func[1]](btnName);
- this.observe.buttons(e, btnName);
- }
- }
- else
- {
- this[callback](btnName);
- this.observe.buttons(e, btnName);
- }
- }
+ if (type == 'command') this.inline.format(callback);
+ else if (type == 'dropdown') this.dropdown.show(e, btnName);
+ else this.button.onClickCallback(e, callback, btnName);
+ },
+ onClickCallback: function(e, callback, btnName)
+ {
+ var func;
+ if ($.isFunction(callback)) callback.call(this, btnName);
+ else if (callback.search(/\./) != '-1')
+ {
+ func = callback.split('.');
+ if (typeof this[func[0]] == 'undefined') return;
+
+ this[func[0]][func[1]](btnName);
+ }
+ else this[callback](btnName);
+
+ this.observe.buttons(e, btnName);
},
get: function(key)
{
@@ -1306,10 +1575,8 @@
var $dropdown = $('
');
$btn.data('dropdown', $dropdown);
- if (dropdown)
- {
- this.dropdown.build(key, $dropdown, dropdown);
- }
+ // build dropdown
+ if (dropdown) this.dropdown.build(key, $dropdown, dropdown);
return $dropdown;
},
@@ -1340,7 +1607,7 @@
var btn = this.button.build(key, { title: title });
var $btn = this.button.get(afterkey);
- if ($btn.size() !== 0) $btn.parent().after($(' - ').append(btn));
+ if ($btn.length !== 0) $btn.parent().after($('
- ').append(btn));
else this.$toolbar.append($('
- ').append(btn));
return btn;
@@ -1352,7 +1619,7 @@
var btn = this.button.build(key, { title: title });
var $btn = this.button.get(beforekey);
- if ($btn.size() !== 0) $btn.parent().before($('
- ').append(btn));
+ if ($btn.length !== 0) $btn.parent().before($('
- ').append(btn));
else this.$toolbar.append($('
- ').append(btn));
return btn;
@@ -1363,289 +1630,201 @@
}
};
},
- dropdown: function()
+ caret: function()
{
return {
- build: function(name, $dropdown, dropdownObject)
+ setStart: function(node)
{
- if (name == 'formatting' && this.opts.formattingAdd)
+ // inline tag
+ if (!this.utils.isBlock(node))
{
- $.each(this.opts.formattingAdd, $.proxy(function(i,s)
- {
- var name = s.tag;
- if (typeof s.class != 'undefined')
- {
- name = name + '-' + s.class;
- }
+ var space = this.utils.createSpaceElement();
- s.type = (this.utils.isBlockTag(s.tag)) ? 'block' : 'inline';
- var func = (s.type == 'inline') ? 'inline.formatting' : 'block.formatting';
-
- if (this.opts.linebreaks && s.type == 'block' && s.tag == 'p') return;
-
- this.formatting[name] = {
- tag: s.tag,
- style: s.style,
- 'class': s.class,
- attr: s.attr,
- data: s.data
- };
-
- dropdownObject[name] = {
- func: func,
- title: s.title
- };
-
- }, this));
-
- }
-
- $.each(dropdownObject, $.proxy(function(btnName, btnObject)
- {
- var $item = $('' + btnObject.title + '');
- if (name == 'formatting') $item.addClass('redactor-formatting-' + btnName);
-
- $item.on('click', $.proxy(function(e)
- {
- var type = 'func';
- var callback = btnObject.func;
- if (btnObject.command)
- {
- type = 'command';
- callback = btnObject.command;
- }
- else if (btnObject.dropdown)
- {
- type = 'dropdown';
- callback = btnObject.dropdown;
- }
-
- this.button.onClick(e, btnName, type, callback);
-
- }, this));
-
- $dropdown.append($item);
-
- }, this));
- },
- show: function(e, key)
- {
- if (!this.opts.visual)
- {
- e.preventDefault();
- return false;
- }
-
- var $button = this.button.get(key);
-
- // Always re-append it to the end of so it always has the highest sub-z-index.
- var $dropdown = $button.data('dropdown').appendTo(document.body);
-
- if ($button.hasClass('dropact'))
- {
- this.dropdown.hideAll();
+ $(node).prepend(space);
+ this.caret.setEnd(space);
}
else
{
- this.dropdown.hideAll();
- this.core.setCallback('dropdownShow', { dropdown: $dropdown, key: key, button: $button });
+ this.caret.set(node, 0, node, 0);
+ }
+ },
+ setEnd: function(node)
+ {
+ this.caret.set(node, 1, node, 1);
+ },
+ set: function(orgn, orgo, focn, foco)
+ {
+ // focus
+ // disabled in 10.0.7
+ // if (!this.utils.browser('msie')) this.$editor.focus();
- this.button.setActive(key);
+ orgn = orgn[0] || orgn;
+ focn = focn[0] || focn;
- $button.addClass('dropact');
+ if (this.utils.isBlockTag(orgn.tagName) && orgn.innerHTML === '')
+ {
+ orgn.innerHTML = this.opts.invisibleSpace;
+ }
- var keyPosition = $button.offset();
+ if (orgn.tagName == 'BR' && this.opts.linebreaks === false)
+ {
+ var parent = $(this.opts.emptyHtml)[0];
+ $(orgn).replaceWith(parent);
+ orgn = parent;
+ focn = orgn;
+ }
- // fix right placement
- var dropdownWidth = $dropdown.width();
- if ((keyPosition.left + dropdownWidth) > $(document).width())
+ this.selection.get();
+
+ try
+ {
+ this.range.setStart(orgn, orgo);
+ this.range.setEnd(focn, foco);
+ }
+ catch (e) {}
+
+ this.selection.addRange();
+ },
+ setAfter: function(node)
+ {
+ try
+ {
+ var tag = $(node)[0].tagName;
+
+ // inline tag
+ if (tag != 'BR' && !this.utils.isBlock(node))
{
- keyPosition.left -= dropdownWidth;
- }
+ var space = this.utils.createSpaceElement();
- var left = keyPosition.left + 'px';
- if (this.$toolbar.hasClass('toolbar-fixed-box'))
- {
- $dropdown.css({ position: 'fixed', left: left, top: this.$toolbar.innerHeight() + this.opts.toolbarFixedTopOffset }).show();
+ $(node).after(space);
+ this.caret.setEnd(space);
}
else
{
- var top = ($button.innerHeight() + keyPosition.top) + 'px';
-
- $dropdown.css({ position: 'absolute', left: left, top: top }).show();
+ if (tag != 'BR' && this.utils.browser('msie'))
+ {
+ this.caret.setStart($(node).next());
+ }
+ else
+ {
+ this.caret.setAfterOrBefore(node, 'after');
+ }
}
-
-
- this.core.setCallback('dropdownShown', { dropdown: $dropdown, key: key, button: $button });
}
-
- $(document).one('click', $.proxy(this.dropdown.hide, this));
- this.$editor.one('click', $.proxy(this.dropdown.hide, this));
-
- $dropdown.on('mouseover', function() { $('html').css('overflow', 'hidden'); });
- $dropdown.on('mouseout', function() { $('html').css('overflow', ''); });
-
- e.stopPropagation();
- },
- hideAll: function()
- {
- this.$toolbar.find('a.dropact').removeClass('redactor-act').removeClass('dropact');
-
- $('.redactor-dropdown').hide();
- this.core.setCallback('dropdownHide');
- },
- hide: function (e)
- {
- var $dropdown = $(e.target);
- if (!$dropdown.hasClass('dropact'))
+ catch (e)
{
- $dropdown.removeClass('dropact');
- this.dropdown.hideAll();
+ var space = this.utils.createSpaceElement();
+ $(node).after(space);
+ this.caret.setEnd(space);
}
- }
- };
- },
- code: function()
- {
- return {
- set: function(html)
- {
- html = $.trim(html.toString());
-
- // clean
- html = this.clean.onSet(html);
-
- this.$editor.html(html);
- this.code.sync();
-
- setTimeout($.proxy(this.buffer.add, this), 15);
- if (this.start === false) this.observe.load();
-
},
- get: function()
+ setBefore: function(node)
{
- var code = this.$textarea.val();
-
- // indent code
- code = this.tabifier.get(code);
-
- return code;
- },
- sync: function()
- {
- setTimeout($.proxy(this.code.startSync, this), 10);
- },
- startSync: function()
- {
- var html = this.$editor.html();
-
- // is there a need to synchronize
- if (this.code.syncCode && this.code.syncCode == html)
+ // block tag
+ if (this.utils.isBlock(node))
{
- // do not sync
- return;
- }
-
- // save code
- this.code.syncCode = html;
-
- // before clean callback
- html = this.core.setCallback('syncBefore', html);
-
- // clean
- html = this.clean.onSync(html);
-
- // set code
- this.$textarea.val(html);
-
- // after sync callback
- this.core.setCallback('sync', html);
-
- if (this.start === false)
- {
- this.core.setCallback('change', html);
- }
-
- this.start = false;
-
- // autosave on change
- this.autosave.onChange();
- },
- toggle: function()
- {
- if (this.opts.visual)
- {
- this.code.showCode();
+ this.caret.setEnd($(node).prev());
}
else
{
- this.code.showVisual();
+ this.caret.setAfterOrBefore(node, 'before');
}
},
- showCode: function()
+ setAfterOrBefore: function(node, type)
{
- this.code.offset = this.caret.getOffset();
- var scroll = $(window).scrollTop();
+ // focus
+ if (!this.utils.browser('msie')) this.$editor.focus();
- var height = this.$editor.innerHeight();
+ node = node[0] || node;
- this.$editor.hide();
+ this.selection.get();
- var html = this.$textarea.val();
- this.modified = this.clean.removeSpaces(html);
-
- // indent code
- html = this.tabifier.get(html);
-
- this.$textarea.val(html).height(height).show().focus();
- this.$textarea.on('keydown.redactor-textarea-indenting', this.code.textareaIndenting);
-
- $(window).scrollTop(scroll);
-
- this.opts.visual = false;
-
- this.button.setInactiveInCode();
- this.button.setActive('html');
- this.core.setCallback('source', html);
- },
- showVisual: function()
- {
- if (this.opts.visual) return;
-
- var html = this.$textarea.hide().val();
-
- if (this.modified !== this.clean.removeSpaces(html))
+ if (type == 'after')
{
- this.code.set(html);
+ try {
+
+ this.range.setStartAfter(node);
+ this.range.setEndAfter(node);
+ }
+ catch (e) {}
}
-
- this.$editor.show();
-
- if (!this.utils.isEmpty(html))
+ else
{
- this.placeholder.remove();
+ try {
+ this.range.setStartBefore(node);
+ this.range.setEndBefore(node);
+ }
+ catch (e) {}
}
- this.caret.setOffset(this.code.offset);
- this.$textarea.off('keydown.redactor-textarea-indenting');
-
- this.button.setActiveInVisual();
- this.button.setInactive('html');
-
- this.observe.load();
- this.opts.visual = true;
+ this.range.collapse(false);
+ this.selection.addRange();
},
- textareaIndenting: function(e)
+ getOffsetOfElement: function(node)
{
- if (e.keyCode !== 9) return true;
+ node = node[0] || node;
- var $el = this.$textarea;
- var start = $el.get(0).selectionStart;
- $el.val($el.val().substring(0, start) + "\t" + $el.val().substring($el.get(0).selectionEnd));
- $el.get(0).selectionStart = $el.get(0).selectionEnd = start + 1;
+ this.selection.get();
- return false;
+ var cloned = this.range.cloneRange();
+ cloned.selectNodeContents(node);
+ cloned.setEnd(this.range.endContainer, this.range.endOffset);
+
+ return $.trim(cloned.toString()).length;
+ },
+ getOffset: function()
+ {
+ var offset = 0;
+ var sel = window.getSelection();
+
+ if (sel.rangeCount > 0)
+ {
+ var range = window.getSelection().getRangeAt(0);
+ var caretRange = range.cloneRange();
+ caretRange.selectNodeContents(this.$editor[0]);
+ caretRange.setEnd(range.endContainer, range.endOffset);
+ offset = caretRange.toString().length;
+ }
+
+ return offset;
+ },
+ setOffset: function(start, end)
+ {
+ if (typeof end == 'undefined') end = start;
+ if (!this.focus.isFocused()) this.focus.setStart();
+
+ var sel = this.selection.get();
+ var node, offset = 0;
+ var walker = document.createTreeWalker(this.$editor[0], NodeFilter.SHOW_TEXT, null, null);
+
+ while (node = walker.nextNode())
+ {
+ offset += node.nodeValue.length;
+ if (offset > start)
+ {
+ this.range.setStart(node, node.nodeValue.length + start - offset);
+ start = Infinity;
+ }
+
+ if (offset >= end)
+ {
+ this.range.setEnd(node, node.nodeValue.length + end - offset);
+ break;
+ }
+ }
+
+ this.range.collapse(false);
+ this.selection.addRange();
+ },
+ // deprecated
+ setToPoint: function(start, end)
+ {
+ this.caret.setOffset(start, end);
+ },
+ getCoords: function()
+ {
+ return this.caret.getOffset();
}
};
},
@@ -1656,6 +1835,9 @@
{
html = this.clean.savePreCode(html);
+ // convert script tag
+ html = html.replace(/');
+
// restore form tag
html = this.clean.restoreFormTags(html);
@@ -1720,12 +1923,13 @@
// remove br in the of li
html = html.replace(new RegExp('
', 'gi'), '');
html = html.replace(new RegExp(' ', 'gi'), '');
-
// remove verified
- html = html.replace(new RegExp(' ])>', 'gi'), ' ');
+ html = html.replace(new RegExp(' ]) data-tagblock="redactor"(.*?[^>])>', 'gi'), ' ');
html = html.replace(new RegExp('<(.*?) data-verified="redactor"(.*?[^>])>', 'gi'), '<$1$2>');
- html = html.replace(new RegExp(' ])>', 'gi'), '');
- html = html.replace(new RegExp(' ])>', 'gi'), ' ');
+ html = html.replace(new RegExp('])\srel="(.*?[^>])"(.*?[^>])>', 'gi'), '');
+ html = html.replace(new RegExp(' ])\srel="(.*?[^>])"(.*?[^>])>', 'gi'), ' ');
+ html = html.replace(new RegExp(' ])\sstyle="" (.*?[^>])>', 'gi'), ' ');
+ html = html.replace(new RegExp(' ])\sstyle (.*?[^>])>', 'gi'), ' ');
html = html.replace(new RegExp('(.*?)', 'gi'), '$1');
html = html.replace(/ data-save-url="(.*?[^>])"/gi, '');
@@ -1734,6 +1938,10 @@
html = html.replace(/])>(.*?)<\/span>/gi, '');
html = html.replace(/])>(.*?)<\/span>/gi, '');
+ // remove font tag
+ html = html.replace(//gi, '');
+ html = html.replace(/<\/font>/gi, '');
+
// tidy html
html = this.tidy.load(html);
@@ -1745,9 +1953,7 @@
}
// reconvert inline
- html = html.replace(/<(.*?) data-redactor-tag="(.*?)"(.*?[^>])>/gi, '<$1$3>');
- html = html.replace(/<(.*?) data-redactor-class="(.*?)"(.*?[^>])>/gi, '<$1$3>');
- html = html.replace(/<(.*?) data-redactor-style="(.*?)"(.*?[^>])>/gi, '<$1$3>');
+ html = html.replace(/\sdata-redactor-(tag|class|style)="(.*?[^>])"/gi, '');
html = html.replace(new RegExp('<(.*?) data-verified="redactor"(.*?[^>])>', 'gi'), '<$1$2>');
html = html.replace(new RegExp('<(.*?) data-verified="redactor">', 'gi'), '<$1>');
@@ -1758,12 +1964,11 @@
html = $.trim(html);
html = html.replace(/\$/g, '$');
- html = html.replace(/”/g, '"');
- html = html.replace(/“/g, '"');
html = html.replace(/‘/g, '\'');
html = html.replace(/’/g, '\'');
// convert dirty spaces
+ html = html.replace(//gi, '');
html = html.replace(/ <\/span>/gi, ' ');
html = html.replace(/]*>\t<\/span>/gi, '\t');
html = html.replace(/]*>(\s| )<\/span>/gi, ' ');
@@ -1782,6 +1987,9 @@
if (this.utils.isCurrentOrParent('PRE'))
{
+ html = html.replace(/”/g, '"');
+ html = html.replace(/“/g, '"');
+
return this.clean.getPreCode(html);
}
@@ -1830,12 +2038,13 @@
html = this.clean.saveFormTags(html);
}
- html = this.clean.onPasteIeFixLinks(html);
+
html = this.clean.onPasteWord(html);
html = this.clean.onPasteExtra(html);
html = this.clean.onPasteTidy(html, 'all');
+
// paragraphize
if (!this.clean.singleLine && this.opts.paragraphize)
{
@@ -1858,26 +2067,37 @@
// style
html = html.replace(/ |