/*
- Redactor v10.0.9
- Updated: March 16, 2015
+ Redactor v10.1.0
+ Updated: April 16, 2015
http://imperavi.com/redactor/
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)
{
// Functionality
$.Redactor = Redactor;
- $.Redactor.VERSION = '10.0.9';
+ $.Redactor.VERSION = '10.1.0';
$.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 = {
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: /((?:http[s]?:\/\/(?:www\.)?|www\.){1}(?:[0-9A-Za-z\-%_]+\.)+[a-zA-Z]{2,}(?::[0-9]+)?(?:(?:\/[0-9A-Za-z\-#\.%\+_]*)+)?(?:\?(?:[0-9A-Za-z\-\.%_]+(?:=[0-9A-Za-z\-\.%_\+]*)?)?(?:&(?:[0-9A-Za-z\-\.%_]+(?:=[0-9A-Za-z\-\.%_\+]*)?)?)*)?(?:#[0-9A-Za-z\-\.%_\+=\?&;]*)?)/ig,
+ }
+ },
+
+ codemirror: false
};
// Functionality
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) return;
this.autosave.source = this.code.get();
if (this.autosave.html === this.autosave.source) return;
- if (this.utils.isEmpty(this.autosave.source)) return;
+ //if (this.utils.isEmpty(this.autosave.source)) return;
// data
var data = {};
},
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($('<br>')).contents().unwrap();
},
formatTableWrapping: function($formatted)
{
- if ($formatted.closest('table').length === 0) return;
+ if ($formatted.closest('table', this.$editor[0]).length === 0) return;
- if ($formatted.closest('tr').length === 0) $formatted.wrap('<tr>');
- if ($formatted.closest('td').length === 0 && $formatted.closest('th').length === 0)
+ if ($formatted.closest('tr', this.$editor[0]).length === 0) $formatted.wrap('<tr>');
+ if ($formatted.closest('td', this.$editor[0]).length === 0 && $formatted.closest('th').length === 0)
{
$formatted.wrap('<td>');
}
},
setHelpers: function()
{
- // autosave
- this.autosave.enable();
+ // linkify
+ if (this.linkify.isEnabled())
+ {
+ this.linkify.format();
+ }
// placeholder
this.placeholder.enable();
// dropdown
if (btnObject.dropdown)
{
- var $dropdown = $('<div class="redactor-dropdown redactor-dropdown-' + + this.uuid + ' redactor-dropdown-box-' + btnName + '" style="display: none;">');
+ var $dropdown = $('<div class="redactor-dropdown redactor-dropdown-' + this.uuid + ' redactor-dropdown-box-' + btnName + '" style="display: none;">');
$button.data('dropdown', $dropdown);
this.dropdown.build(btnName, $dropdown, btnObject.dropdown);
}
var key = $btn.attr('rel');
this.button.addCallback($btn, 'dropdown');
- var $dropdown = $('<div class="redactor-dropdown redactor-dropdown-' + + this.uuid + ' redactor-dropdown-box-' + key + '" style="display: none;">');
+ var $dropdown = $('<div class="redactor-dropdown redactor-dropdown-' + this.uuid + ' redactor-dropdown-box-' + key + '" style="display: none;">');
$btn.data('dropdown', $dropdown);
// build dropdown
html = html.replace(new RegExp('<br\\s?/?></li>', 'gi'), '</li>');
html = html.replace(new RegExp('</li><br\\s?/?>', 'gi'), '</li>');
// remove verified
- html = html.replace(new RegExp('<div(.*?[^>]) data-tagblock="redactor"(.*?[^>])>', 'gi'), '<div$1$2>');
- html = html.replace(new RegExp('<(.*?) data-verified="redactor"(.*?[^>])>', 'gi'), '<$1$2>');
- html = html.replace(new RegExp('<span(.*?[^>])\srel="(.*?[^>])"(.*?[^>])>', 'gi'), '<span$1$3>');
- html = html.replace(new RegExp('<img(.*?[^>])\srel="(.*?[^>])"(.*?[^>])>', 'gi'), '<img$1$3>');
- html = html.replace(new RegExp('<img(.*?[^>])\sstyle="" (.*?[^>])>', 'gi'), '<img$1 $2>');
- html = html.replace(new RegExp('<img(.*?[^>])\sstyle (.*?[^>])>', 'gi'), '<img$1 $2>');
- html = html.replace(new RegExp('<span class="redactor-invisible-space">(.*?)</span>', 'gi'), '$1');
+ html = html.replace(/<div(.*?[^>]) data-tagblock="redactor"(.*?[^>])>/gi, '<div$1$2>');
+ html = html.replace(/<(.*?) data-verified="redactor"(.*?[^>])>/gi, '<$1$2>');
+ html = html.replace(/<span(.*?[^>])\srel="(.*?[^>])"(.*?[^>])>/gi, '<span$1$3>');
+ html = html.replace(/<img(.*?[^>])\srel="(.*?[^>])"(.*?[^>])>/gi, '<img$1$3>');
+ html = html.replace(/<img(.*?[^>])\sstyle="" (.*?[^>])>'/gi, '<img$1 $2>');
+ html = html.replace(/<img(.*?[^>])\sstyle (.*?[^>])>'/gi, '<img$1 $2>');
+ html = html.replace(/<span class="redactor-invisible-space">(.*?)<\/span>/gi, '$1');
html = html.replace(/ data-save-url="(.*?[^>])"/gi, '');
// remove image resize
});
},
+ cleanEmptyParagraph: function()
+ {
+ var p = this.$editor.find("p").first();
+
+ if (this.utils.isEmpty(p.html()))
+ {
+ p.remove();
+ }
+ },
setVerified: function(html)
{
if (this.utils.browser('msie')) return html;
this.start = false;
- // autosave on change
+ if (this.autosave.html == false)
+ {
+ this.autosave.html = this.code.get();
+ }
+
+ //autosave
this.autosave.onChange();
+ this.autosave.enable();
},
toggle: function()
{
this.code.offset = this.caret.getOffset();
var scroll = $(window).scrollTop();
- var height = this.$editor.innerHeight();
+ var width = this.$editor.innerWidth(),
+ height = this.$editor.innerHeight();
this.$editor.hide();
// 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.$textarea.val(html);
- if (this.$textarea[0].setSelectionRange)
+ if (this.opts.codemirror)
{
- this.$textarea[0].setSelectionRange(0, 0);
+ this.$textarea.next('.CodeMirror').each(function(i, el)
+ {
+ $(el).show();
+ el.CodeMirror.setValue(html);
+ el.CodeMirror.setSize(width, height);
+ el.CodeMirror.refresh();
+ el.CodeMirror.focus();
+ });
}
+ else
+ {
+ this.$textarea.height(height).show().focus();
+ this.$textarea.on('keydown.redactor-textarea-indenting', this.code.textareaIndenting);
+
+ $(window).scrollTop(scroll);
+
+ if (this.$textarea[0].setSelectionRange)
+ {
+ this.$textarea[0].setSelectionRange(0, 0);
+ }
- this.$textarea[0].scrollTop = 0;
+ this.$textarea[0].scrollTop = 0;
+ }
this.opts.visual = false;
},
showVisual: function()
{
+ var html;
+
if (this.opts.visual) return;
- var html = this.$textarea.hide().val();
+ if (this.opts.codemirror)
+ {
+ this.$textarea.next('.CodeMirror').each(function(i, el)
+ {
+ html = el.CodeMirror.getValue();
+ });
+ }
+ else
+ {
+ html = this.$textarea.hide().val();
+ }
if (this.modified !== this.clean.removeSpaces(html))
{
this.code.set(html);
}
+ if (this.opts.codemirror)
+ {
+ this.$textarea.next('.CodeMirror').hide();
+ }
+
this.$editor.show();
if (!this.utils.isEmpty(html))
{
$.each(this.opts.formattingAdd, $.proxy(function(i,s)
{
- var name = s.tag;
+ var name = s.tag,
+ func;
+
if (typeof s['class'] != 'undefined')
{
name = name + '-' + s['class'];
}
s.type = (this.utils.isBlockTag(s.tag)) ? 'block' : 'inline';
- var func = (s.type == 'inline') ? 'inline.formatting' : 'block.formatting';
+
+ if (typeof s.func !== "undefined")
+ {
+ func = s.func;
+ }
+ else
+ {
+ func = (s.type == 'inline') ? 'inline.formatting' : 'block.formatting';
+ }
if (this.opts.linebreaks && s.type == 'block' && s.tag == 'p') return;
},
showEdit: function($image)
{
- var $link = $image.closest('a');
+ var $link = $image.closest('a', this.$editor[0]);
this.modal.load('imageEdit', this.lang.get('edit'), 705);
this.image.hideResize();
this.buffer.set();
- var $link = $image.closest('a');
+ var $link = $image.closest('a', this.$editor[0]);
$image.attr('alt', $('#redactor-image-title').val());
},
hideResize: function(e)
{
- if (e && $(e.target).closest('#redactor-image-box').length !== 0) return;
+ if (e && $(e.target).closest('#redactor-image-box', this.$editor[0]).length !== 0) return;
if (e && e.target.tagName == 'IMG')
{
var $image = $(e.target);
remove: function(image)
{
var $image = $(image);
- var $link = $image.closest('a');
- var $figure = $image.closest('figure');
+ var $link = $image.closest('a', this.$editor[0]);
+ var $figure = $image.closest('figure', this.$editor[0]);
var $parent = $image.parent();
if ($('#redactor-image-box').length !== 0)
{
var current = this.selection.getCurrent();
- var $item = $(current).closest('li');
+ var $item = $(current).closest('li', this.$editor[0]);
var $parent = $item.parent();
if ($item.length !== 0 && $parent.length !== 0 && $parent[0].tagName == 'LI')
{
formatCollapsed: function(tag)
{
var current = this.selection.getCurrent();
- var $parent = $(current).closest(tag + '[data-redactor-tag=' + tag + ']');
+ var $parent = $(current).closest(tag + '[data-redactor-tag=' + tag + ']', this.$editor[0]);
// inline there is
if ($parent.length !== 0 && (this.inline.type != 'style' && $parent[0].tagName != 'SPAN'))
var $table = false;
if (this.keydown.block && this.keydown.block.tagName === 'TD')
{
- $table = $(this.keydown.block).closest('table');
+ $table = $(this.keydown.block).closest('table', this.$editor[0]);
}
if ($table && $table.find('td').last()[0] === this.keydown.block)
else
{
current = this.selection.getCurrent();
- var $parent = $(current).closest('li');
- var $list = $parent.closest('ul,ol');
+ var $parent = $(current).closest('li', this.$editor[0]);
+ var $list = $parent.closest('ul,ol', this.$editor[0]);
- if ($parent.length !== 0 && this.utils.isEmpty($parent.html()) && $list.next().length === 0)
+ if ($parent.length !== 0 && this.utils.isEmpty($parent.html()) && $list.next().length === 0 && this.utils.isEmpty($list.find("li").last().html()))
{
+ $list.find("li").last().remove();
+
var node = $(this.opts.emptyHtml);
$list.after(node);
this.caret.setStart(node);
{
var $current = $(this.keydown.current);
var $parent = $(this.keydown.parent);
- var td = $current.closest('td');
+ var td = $current.closest('td', this.$editor[0]);
- if (td.length !== 0 && $current.closest('li') && $parent.children('li').length === 1)
+ if (td.length !== 0 && $current.closest('li', this.$editor[0]) && $parent.children('li').length === 1)
{
if (!this.utils.isEmpty($current.text())) return;
}
// linkify
- if (this.keyup.isLinkify(key))
- {
- this.formatLinkify(this.opts.linkProtocol, this.opts.convertLinks, this.opts.convertUrlLinks, this.opts.convertImageLinks, this.opts.convertVideoLinks, this.opts.linkSize);
-
- this.observe.load();
- this.code.sync();
- }
+ if (this.linkify.isEnabled() && this.linkify.isKey(key))
+ this.linkify.format();
if (key === this.keyCode.DELETE || key === this.keyCode.BACKSPACE)
{
return this.keyup.formatEmpty(e);
}
},
- isLinkify: function(key)
- {
- return this.opts.convertLinks && (this.opts.convertUrlLinks || this.opts.convertImageLinks || this.opts.convertVideoLinks) && key === this.keyCode.ENTER && !this.utils.isCurrentOrParent('PRE');
- },
replaceToParagraph: function(clone)
{
var $current = $(this.keyup.current);
{
this.link.$node = false;
- var $el = $(this.selection.getCurrent()).closest('a');
+ var $el = $(this.selection.getCurrent()).closest('a', this.$editor[0]);
if ($el.length !== 0 && $el[0].tagName === 'A')
{
this.link.$node = $el;
},
insert: function()
{
+ this.placeholder.remove();
+
var target = '';
var link = this.link.$inputUrl.val();
var text = this.link.$inputText.val();
{
this.buffer.set();
- this.link.$node.text(text).attr('href', link);
+ var $link = this.link.$node,
+ $el = $link.children();
+
+ if ($el.length > 0)
+ {
+ while ($el.length)
+ {
+ $el = $el.children();
+ }
+
+ $el = $el.end();
+ }
+ else
+ {
+ $el = $link;
+ }
+
+ $link.attr('href', link);
+ $el.text(text);
+
if (target !== '')
{
- this.link.$node.attr('target', target);
+ $link.attr('target', target);
}
else
{
- this.link.$node.removeAttr('target');
+ $link.removeAttr('target');
}
+ this.selection.selectElement($link);
+
this.code.sync();
}
else
if (target !== '') $a.attr('target', target);
$a = $(this.insert.node($a));
+
+ if (this.selection.getText().match(/\s$/))
+ {
+ $a.after(" ");
+ }
+
this.selection.selectElement($a);
}
else
{
document.execCommand('createLink', false, link);
- $a = $(this.selection.getCurrent()).closest('a');
+ $a = $(this.selection.getCurrent()).closest('a', this.$editor[0]);
if (this.utils.browser('mozilla'))
{
$a = $('a[_moz_dirty=""]');
if (target !== '') $a.attr('target', target);
$a.removeAttr('style').removeAttr('_moz_dirty');
- if (this.link.text !== '' || this.link.text != text)
+ if (this.selection.getText().match(/\s$/))
{
+ $a.after(" ");
+ }
+ if (this.link.text !== '' || this.link.text != text)
+ {
$a.text(text);
+
this.selection.selectElement($a);
}
}
var len = nodes.length;
for (var i = 0; i < len; i++)
{
- var $node = $(nodes[i]).closest('a');
+ var $node = $(nodes[i]).closest('a', this.$editor[0]);
$node.replaceWith($node.contents());
}
this.selection.save();
var parent = this.selection.getParent();
- var $list = $(parent).closest('ol, ul');
+ var $list = $(parent).closest('ol, ul', this.$editor[0]);
if (!this.utils.isRedactorParent($list) && $list.length !== 0)
{
}
}
-
this.selection.restore();
this.code.sync();
},
{
var parent = this.selection.getParent();
var current = this.selection.getCurrent();
- var $td = $(current).closest('td, th');
+ var $td = $(current).closest('td, th', this.$editor[0]);
if (this.utils.browser('msie') && this.opts.linebreaks)
{
document.execCommand('insert' + cmd);
}
- var $list = $(this.selection.getParent()).closest('ol, ul');
+ var $list = $(this.selection.getParent()).closest('ol, ul', this.$editor[0]);
if ($td.length !== 0)
{
this.indent.fixEmptyIndent();
- if (!this.opts.linebreaks && $current.closest('li, th, td').length === 0)
+ if (!this.opts.linebreaks && $current.closest('li, th, td', this.$editor[0]).length === 0)
{
document.execCommand('formatblock', false, 'p');
this.$editor.find('ul, ol, blockquote').each($.proxy(this.utils.removeEmpty, this));
}
- var $table = $(this.selection.getCurrent()).closest('table');
+ var $table = $(this.selection.getCurrent()).closest('table', this.$editor[0]);
var $prev = $table.prev();
if (!this.opts.linebreaks && $table.length !== 0 && $prev.length !== 0 && $prev[0].tagName == 'BR')
{
$.each(this.opts.activeButtonsStates, $.proxy(function(key, value)
{
- var parentEl = $(parent).closest(key);
- var currentEl = $(current).closest(key);
+ var parentEl = $(parent).closest(key, this.$editor[0]);
+ var currentEl = $(current).closest(key, this.$editor[0]);
if (parentEl.length !== 0 && !this.utils.isRedactorParent(parentEl)) return;
if (!this.utils.isRedactorParent(currentEl)) return;
- if (parentEl.length !== 0 || currentEl.closest(key).length !== 0)
+ if (parentEl.length !== 0 || currentEl.closest(key, this.$editor[0]).length !== 0)
{
this.button.setActive(value);
}
}, this));
- var $parent = $(parent).closest(this.opts.alignmentTags.toString().toLowerCase());
+ var $parent = $(parent).closest(this.opts.alignmentTags.toString().toLowerCase(), this.$editor[0]);
if (this.utils.isRedactorParent(parent) && $parent.length)
{
var align = ($parent.css('text-align') === '') ? 'left' : $parent.css('text-align');
var $img = $(img);
// IE fix (when we clicked on an image and then press backspace IE does goes to image's url)
- $img.closest('a').on('click', function(e) { e.preventDefault(); });
+ $img.closest('a', this.$editor[0]).on('click', function(e) { e.preventDefault(); });
if (this.utils.browser('msie')) $img.attr('unselectable', 'on');
},
showTooltip: function(e)
{
- var $link = $(e.target);
- var $parent = $link.closest('a');
- var tag = ($link.length !== 0) ? $link[0].tagName : false;
+ var $el = $(e.target);
- if ($parent[0].tagName === 'A')
- {
- if (tag === 'IMG') return;
- else if (tag !== 'A') $link = $parent;
- }
+ if ($el[0].tagName == 'IMG')
+ return;
- if (tag !== 'A')
- {
+ if ($el[0].tagName !== 'A')
+ $el = $el.closest('a', this.$editor[0]);
+
+ if ($el[0].tagName !== 'A')
return;
- }
+
+ var $link = $el;
var pos = this.observe.getTooltipPosition($link);
var tooltip = $('<span class="redactor-link-tooltip"></span>');
e = e.originalEvent || e;
var target = e.target;
- var $parent = $(target).closest('a');
+ var $parent = $(target).closest('a', this.$editor[0]);
if ($parent.length !== 0 && $parent[0].tagName === 'A' && target.tagName !== 'A')
{
return;
$(window).off('scroll.redactor-freeze');
- }, this), 1);
+ if (this.linkify.isEnabled())
+ this.linkify.format();
+ }, this), 1);
},
createPasteBox: function()
{
left: left
});
+ if (scrollTop > end)
+ $('.redactor-dropdown-' + this.uuid + ':visible').hide();
+
this.toolbar.setDropdownsFixed();
this.$toolbar.css('visibility', (scrollTop < end) ? 'visible' : 'hidden');
},
this.toolbar.unsetDropdownsFixed();
this.$toolbar.removeClass('toolbar-fixed-box');
-
-
},
setDropdownsFixed: function()
{
var xhr = new XMLHttpRequest();
xhr.open('POST', this.upload.url);
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
// complete
xhr.onreadystatechange = $.proxy(function()
// tag detection
isTag: function(current, tag)
{
- var element = $(current).closest(tag);
+ var element = $(current).closest(tag, this.$editor[0]);
if (element.length == 1)
{
return element[0];
return browser == match[1];
}
};
- }
- };
+ },
+ linkify: function()
+ {
+ return {
+ isKey: function(key)
+ {
+ return key == this.keyCode.ENTER || key == this.keyCode.SPACE;
+ },
+ isEnabled: function()
+ {
+ return this.opts.convertLinks && (this.opts.convertUrlLinks || this.opts.convertImageLinks || this.opts.convertVideoLinks) && !this.utils.isCurrentOrParent('PRE');
+ },
+ format: function()
+ {
+ var linkify = this.linkify,
+ opts = this.opts;
- $(window).on('load.tools.redactor', function()
- {
- $('[data-tools="redactor"]').redactor();
- });
+ this.$editor
+ .find(":not(iframe,img,a,pre)")
+ .addBack()
+ .contents()
+ .filter(function()
+ {
+ return this.nodeType === 3 && $.trim(this.nodeValue) != "" && !$(this).parent().is("pre") && (this.nodeValue.match(opts.linkify.regexps.youtube) || this.nodeValue.match(opts.linkify.regexps.vimeo) || this.nodeValue.match(opts.linkify.regexps.image) || this.nodeValue.match(opts.linkify.regexps.url));
+ })
+ .each(function()
+ {
+ var text = $(this).text(),
+ html = text;
- // constructor
- Redactor.prototype.init.prototype = Redactor.prototype;
- // LINKIFY
- $.Redactor.fn.formatLinkify = function(protocol, convertLinks, convertUrlLinks, convertImageLinks, convertVideoLinks, linkSize)
- {
- var urlCheck = '((?:http[s]?:\\/\\/(?:www\\.)?|www\\.){1}(?:[0-9A-Za-z\\-%_]+\\.)+[a-zA-Z]{2,}(?::[0-9]+)?(?:(?:/[0-9A-Za-z\\-#\\.%\+_]*)+)?(?:\\?(?:[0-9A-Za-z\\-\\.%_]+(?:=[0-9A-Za-z\\-\\.%_\\+]*)?)?(?:&(?:[0-9A-Za-z\\-\\.%_]+(?:=[0-9A-Za-z\\-\\.%_\\+]*)?)?)*)?(?:#[0-9A-Za-z\\-\\.%_\\+=\\?&;]*)?)';
- var regex = new RegExp(urlCheck, 'gi');
- var rProtocol = /(https?|ftp):\/\//i;
- var urlImage = new RegExp('(?:([^:/?#]+):)?(?:\/\/([^/?#]*))?([^?#]*\\.(?:jpg|gif|png))(?:\\?([^#]*))?(?:#(.*))?', 'gi');
+ if (opts.convertImageLinks && html.match(opts.linkify.regexps.image))
+ {
+ html = linkify.convertImages(html);
+ }
+ else if (opts.convertUrlLinks && !html.match(opts.linkify.regexps.youtube) && !html.match(opts.linkify.regexps.vimeo))
+ {
+ html = linkify.convertLinks(html);
+ }
- var childNodes = (this.$editor ? this.$editor[0] : this).childNodes, i = childNodes.length;
- while (i--)
- {
- var n = childNodes[i];
+ if (opts.convertVideoLinks)
+ {
+ html = linkify.convertVideoLinks(html);
+ }
- if (n.nodeType === 3 && n.parentNode !== 'PRE')
- {
- var html = n.nodeValue;
+ $(this).before(text.replace(text, html))
+ .remove();
+ });
- // youtube & vimeo
- if (convertVideoLinks && html)
+ this.linkify.after();
+ },
+ convertVideoLinks: function(html)
{
var iframeStart = '<iframe width="500" height="281" src="',
iframeEnd = '" frameborder="0" allowfullscreen></iframe>';
- if (html.match(reUrlYoutube))
+ if (html.match(this.opts.linkify.regexps.youtube))
{
- html = html.replace(reUrlYoutube, iframeStart + '//www.youtube.com/embed/$1' + iframeEnd);
- $(n).after(html).remove();
+ html = html.replace(this.opts.linkify.regexps.youtube, iframeStart + '//www.youtube.com/embed/$1' + iframeEnd);
}
- else if (html.match(reUrlVimeo))
+
+ if (html.match(this.opts.linkify.regexps.vimeo))
{
- html = html.replace(reUrlVimeo, iframeStart + '//player.vimeo.com/video/$2' + iframeEnd);
- $(n).after(html).remove();
+ html = html.replace(this.opts.linkify.regexps.vimeo, iframeStart + '//player.vimeo.com/video/$2' + iframeEnd);
}
- }
- // image
- if (convertImageLinks && html && html.match(urlImage))
+ return html;
+ },
+ convertImages: function(html)
{
- var matches = html.match(urlImage);
- html = html.replace(urlImage, '<img src="' + matches + '" />');
-
- $(n).after(html).remove();
- return;
- }
+ var matches = html.match(this.opts.linkify.regexps.image);
- // link
- if (html.search(/\$/g) != -1) html = html.replace(/\$/g, '$');
+ if (matches)
+ html = html.replace(html, '<img src="' + matches + '" />');
- var matches = html.match(regex);
- if (convertUrlLinks && html && matches)
+ return html;
+ },
+ convertLinks: function(html)
{
- var len = matches.length;
- for (var z = 0; z < len; z++)
+ var matches = html.match(this.opts.linkify.regexps.url);
+
+ if (matches)
{
- // remove dot in the end
- if (matches[z].match(/\.$/) !== null) matches[z] = matches[z].replace(/\.$/, '');
+ matches = $.grep(matches, function(v, k) { return $.inArray(v, matches) === k; });
- var href = matches[z];
- var text = href;
+ var length = matches.length;
- var space = '';
- if (href.match(/\s$/) !== null) space = ' ';
+ for (var i = 0; i < length; i++)
+ {
+ var href = matches[i],
+ text = href,
+ linkProtocol = this.opts.linkProtocol + '://';
- var addProtocol = protocol + '://';
- if (href.match(rProtocol) !== null) addProtocol = '';
+ if (href.match(/(https?|ftp):\/\//i) !== null)
+ linkProtocol = "";
- if (text.length > linkSize) text = text.substring(0, linkSize) + '...';
- text = text.replace(/$/g, '$').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
+ if (text.length > this.opts.linkSize)
+ text = text.substring(0, this.opts.linkSize) + '...';
- // buffer
- var buffer = [];
- var links = html.match('<a(.*?)</a>');
- if (links !== null)
- {
- var len = links.length;
- for (i = 0; i < len; i++)
- {
- buffer[i] = links[i];
- html = html.replace(links[i], '{abuffer' + i + '}');
- }
- }
+ text = decodeURIComponent(text);
- html = html.replace(href, '<a href=\"' + addProtocol + $.trim(href) + '\">' + $.trim(text) + '</a>' + space);
+ // escaping url
+ var regexp = new RegExp('(' + href.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&") + ')\\b', 'g');
- // rebuffer
- $.each(buffer, function(i,s)
- {
- html = html.replace('{abuffer' + i + '}', s);
- });
+ html = html.replace(regexp, '<a href="' + linkProtocol + $.trim(href) + '">' + $.trim(text) + '</a>');
+ }
}
- $(n).after(html).remove();
+ return html;
+ },
+ after: function()
+ {
+ this.observe.load();
+ this.code.sync();
}
}
- else if (n.nodeType === 1 && !/^(pre|a|button|textarea)$/i.test(n.tagName))
- {
- $.Redactor.fn.formatLinkify.call(n, protocol, convertLinks, convertUrlLinks, convertImageLinks, convertVideoLinks, linkSize);
- }
}
};
+ $(window).on('load.tools.redactor', function()
+ {
+ $('[data-tools="redactor"]').redactor();
+ });
+
+ // constructor
+ Redactor.prototype.init.prototype = Redactor.prototype;
})(jQuery);
\ No newline at end of file