app/assets/javascripts/redactor.js in scrivito_editors-0.0.12 vs app/assets/javascripts/redactor.js in scrivito_editors-0.0.13
- old
+ new
@@ -1,17 +1,16 @@
/*
- Redactor v9.2.1
- Updated: Mar 19, 2014
+ Redactor v9.2.6
+ Updated: Jul 19, 2014
http://imperavi.com/redactor/
Copyright (c) 2009-2014, Imperavi LLC.
License: http://imperavi.com/redactor/license/
Usage: $('#content').redactor();
*/
-
(function($)
{
var uuid = 0;
"use strict";
@@ -29,10 +28,13 @@
Range.prototype.equals = function()
{
return this[0] === this[1];
};
+ 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)
{
var val = [];
var args = Array.prototype.slice.call(arguments, 1);
@@ -69,11 +71,11 @@
{
return new Redactor.prototype.init(el, options);
}
$.Redactor = Redactor;
- $.Redactor.VERSION = '9.2.1';
+ $.Redactor.VERSION = '9.2.6';
$.Redactor.opts = {
// settings
rangy: false,
@@ -82,11 +84,11 @@
css: false, // url
lang: 'en',
direction: 'ltr', // ltr or rtl
- placeholder: '',
+ placeholder: false,
typewriter: false,
wym: false,
mobile: true,
cleanup: true,
@@ -102,11 +104,21 @@
focus: false,
tabindex: false,
autoresize: true,
minHeight: false,
maxHeight: false,
- shortcuts: true,
+ shortcuts: {
+ 'ctrl+m, meta+m': "this.execCommand('removeFormat', false)",
+ 'ctrl+b, meta+b': "this.execCommand('bold', false)",
+ 'ctrl+i, meta+i': "this.execCommand('italic', false)",
+ 'ctrl+h, meta+h': "this.execCommand('superscript', false)",
+ 'ctrl+l, meta+l': "this.execCommand('subscript', false)",
+ 'ctrl+k, meta+k': "this.linkShow()",
+ 'ctrl+shift+7': "this.execCommand('insertorderedlist', false)",
+ 'ctrl+shift+8': "this.execCommand('insertunorderedlist', false)"
+ },
+ shortcutsAdd: false,
autosave: false, // false or url
autosaveInterval: 60, // seconds
plugins: false, // array
@@ -114,18 +126,20 @@
//linkAnchor: true,
//linkEmail: true,
linkProtocol: 'http://',
linkNofollow: false,
linkSize: 50,
+ predefinedLinks: false, // json url (ex. /some-url.json ) or false
imageFloatMargin: '10px',
- imageGetJson: false, // url (ex. /folder/images.json ) or false
+ imageGetJson: false, // json url (ex. /some-images.json ) or false
dragUpload: true, // false
imageTabLink: true,
imageUpload: false, // url
imageUploadParam: 'file', // input name
+ imageResizable: true,
fileUpload: false, // url
fileUploadParam: 'file', // input name
clipboardUpload: true, // or false
clipboardUploadUrl: false, // url
@@ -210,10 +224,11 @@
newLevel: ['blockquote', 'div', 'dl', 'fieldset', 'form', 'frameset', 'map', 'ol', 'p', 'pre', 'select', 'td', 'th', 'tr', 'ul'],
blockLevelElements: ['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'DD', 'DL', 'DT', 'DIV', 'LI',
'BLOCKQUOTE', 'OUTPUT', 'FIGCAPTION', 'PRE', 'ADDRESS', 'SECTION',
'HEADER', 'FOOTER', 'ASIDE', 'ARTICLE', 'TD'],
+
// lang
langs: {
en: {
html: 'HTML',
video: 'Insert Video',
@@ -381,10 +396,16 @@
}
// load lang
this.opts.curLang = this.opts.langs[this.opts.lang];
+ // extend shortcuts
+ $.extend(this.opts.shortcuts, this.opts.shortcutsAdd);
+
+ // init placeholder
+ this.placeholderInit();
+
// Build
this.buildStart();
},
toolbarInit: function(lang)
@@ -800,10 +821,16 @@
this.sync();
},
setFullpageOnInit: function(html)
{
+ this.fullpageDoctype = html.match(/^<\!doctype[^>]*>/i);
+ if (this.fullpageDoctype && this.fullpageDoctype.length == 1)
+ {
+ html = html.replace(/^<\!doctype[^>]*>/i, '');
+ }
+
html = this.cleanSavePreCode(html, true);
html = this.cleanConverters(html);
html = this.cleanEmpty(html);
// set code
@@ -812,10 +839,18 @@
// set no editable
this.setNonEditable();
this.setSpansVerified();
this.sync();
},
+ setFullpageDoctype: function()
+ {
+ if (this.fullpageDoctype && this.fullpageDoctype.length == 1)
+ {
+ var source = this.fullpageDoctype[0] + '\n' + this.$source.val();
+ this.$source.val(source);
+ }
+ },
setSpansVerified: function()
{
var spans = this.$editor.find('span');
var replacementTag = 'inline';
@@ -864,12 +899,10 @@
if (source == editor)
{
// do not sync
return false;
}
-
-
// fix second level up ul, ol
html = html.replace(/<\/li><(ul|ol)>([\w\W]*?)<\/(ul|ol)>/gi, '<$1>$2</$1></li>');
if ($.trim(html) === '<br>') html = '';
@@ -886,10 +919,11 @@
// before callback
html = this.callback('syncBefore', false, html);
this.$source.val(html);
+ this.setFullpageDoctype();
// onchange & after callback
this.callback('syncAfter', false, html);
if (this.start === false)
@@ -970,40 +1004,46 @@
html = html.replace(/<font(.*?)>([\w\W]*?)<\/font>/gi, '$2');
}
// remove spans
html = html.replace(/<span(.*?)>([\w\W]*?)<\/span>/gi, '$2');
+ html = html.replace(/<inline>([\w\W]*?)<\/inline>/gi, '$1');
html = html.replace(/<inline>/gi, '<span>');
html = html.replace(/<inline /gi, '<span ');
html = html.replace(/<\/inline>/gi, '</span>');
+
+ if (this.opts.removeEmptyTags)
+ {
+ html = html.replace(/<span>([\w\W]*?)<\/span>/gi, '$1');
+ }
+
html = html.replace(/<span(.*?)class="redactor_placeholder"(.*?)>([\w\W]*?)<\/span>/gi, '');
- html = html.replace(/<span>([\w\W]*?)<\/span>/gi, '$1');
+ html = html.replace(/<img(.*?)contenteditable="false"(.*?)>/gi, '<img$1$2>');
// special characters
- html = html.replace(/&/gi, '&');
- html = html.replace(/™/gi, '™');
- html = html.replace(/©/gi, '©');
- html = html.replace(/…/gi, '…');
- html = html.replace(/—/gi, '—');
- html = html.replace(/‐/gi, '‐');
+ html = html.replace(/&/gi, '&');
+ html = html.replace(/\u2122/gi, '™');
+ html = html.replace(/\u00a9/gi, '©');
+ html = html.replace(/\u2026/gi, '…');
+ html = html.replace(/\u2014/gi, '—');
+ html = html.replace(/\u2010/gi, '‐');
-
html = this.cleanReConvertProtected(html);
return html;
},
+
// BUILD
buildStart: function()
{
// content
this.content = '';
// container
this.$box = $('<div class="redactor_box" />');
- this.$box.css('z-index', 100-this.uuid);
// textarea test
if (this.$source[0].tagName === 'TEXTAREA') this.opts.textareamode = true;
// mobile
@@ -1173,15 +1213,21 @@
},
buildBindKeyboard: function()
{
this.dblEnter = 0;
- if (this.opts.dragUpload && this.opts.imageUpload !== false)
+ if (this.opts.dragUpload && (this.opts.imageUpload !== false || this.opts.s3 !== false))
{
this.$editor.on('drop.redactor', $.proxy(this.buildEventDrop, this));
}
+ this.$editor.on('click.redactor', $.proxy(function()
+ {
+ this.selectall = false;
+
+ }, this));
+
this.$editor.on('input.redactor', $.proxy(this.sync, this));
this.$editor.on('paste.redactor', $.proxy(this.buildEventPaste, this));
this.$editor.on('keydown.redactor', $.proxy(this.buildEventKeydown, this));
this.$editor.on('keyup.redactor', $.proxy(this.buildEventKeyup, this));
@@ -1231,16 +1277,15 @@
return true;
}
this.bufferSet();
- var progress = $('<div id="redactor-progress"><span></span></div>');
- $(document.body).append(progress);
+ this.showProgressBar();
if (this.opts.s3 === false)
{
- this.dragUploadAjax(this.opts.imageUpload, file, true, progress, e, this.opts.imageUploadParam);
+ this.dragUploadAjax(this.opts.imageUpload, file, true, e, this.opts.imageUploadParam);
}
else
{
this.s3uploadFile(file);
}
@@ -1303,10 +1348,11 @@
buildEventClipboardUpload: function(e)
{
var event = e.originalEvent || e;
this.clipboardFilePaste = false;
+
if (typeof(event.clipboardData) === 'undefined') return false;
if (event.clipboardData.items)
{
var file = event.clipboardData.items[0].getAsFile();
if (file !== null)
@@ -1336,17 +1382,42 @@
var block = this.getBlock();
var pre = false;
this.callback('keydown', e);
- // disabling cmd|ctrl + left
- if (this.browser('mozilla') && ctrl && key === 37)
+ /*
+ firefox cmd+left/Cmd+right browser back/forward fix -
+ http://joshrhoderick.wordpress.com/2010/05/05/how-firefoxs-command-key-bug-kills-usability-on-the-mac/
+ */
+ if (this.browser('mozilla') && "modify" in window.getSelection())
{
- e.preventDefault();
- return false;
+ if ((ctrl) && (e.keyCode===37 || e.keyCode===39))
+ {
+ var selection = this.getSelection();
+ var lineOrWord = (e.metaKey ? "line" : "word");
+ if (e.keyCode===37)
+ {
+ selection.modify("extend","left",lineOrWord);
+ if (!e.shiftKey)
+ {
+ selection.collapseToStart();
+ }
+ }
+ if (e.keyCode===39)
+ {
+ selection.modify("extend","right",lineOrWord);
+ if (!e.shiftKey)
+ {
+ selection.collapseToEnd();
+ }
+ }
+
+ e.preventDefault();
+ }
}
+
this.imageResizeHide(false);
// pre & down
if ((parent && $(parent).get(0).tagName === 'PRE') || (current && $(current).get(0).tagName === 'PRE'))
{
@@ -1369,11 +1440,11 @@
this.insertAfterLastElement(current, parent);
}
}
// shortcuts setup
- if (ctrl && !e.shiftKey) this.shortcuts(e, key);
+ this.shortcuts(e, key);
// buffer setup
if (ctrl && key === 90 && !e.shiftKey && !e.altKey) // z key
{
e.preventDefault();
@@ -1406,13 +1477,13 @@
{
this.selectall = false;
}
// enter
- if (key == this.keyCode.ENTER && !e.shiftKey && !e.ctrlKey && !e.metaKey )
+ if (key == this.keyCode.ENTER && !e.shiftKey && !e.ctrlKey && !e.metaKey)
{
- //
+ // remove selected content on enter
var range = this.getRange();
if (range && range.collapsed === false)
{
sel = this.getSelection();
if (sel.rangeCount)
@@ -1471,15 +1542,47 @@
}
else this.dblEnter++;
}
// pre
- if (pre === true) return this.buildEventKeydownPre(e, current);
+ if (pre === true)
+ {
+ return this.buildEventKeydownPre(e, current);
+ }
else
{
if (!this.opts.linebreaks)
{
+ // lists exit
+ if (block && block.tagName == 'LI')
+ {
+ var listCurrent = this.getBlock();
+ if (listCurrent !== false || listCurrent.tagName === 'LI')
+ {
+ var listText = $.trim($(block).text());
+ var listCurrentText = $.trim($(listCurrent).text());
+ if (listText == ''
+ && listCurrentText == ''
+ && $(listCurrent).next('li').size() == 0
+ && $(listCurrent).parents('li').size() == 0)
+ {
+ this.bufferSet();
+
+ var $list = $(listCurrent).closest('ol, ul');
+ $(listCurrent).remove();
+ var node = $('<p>' + this.opts.invisibleSpace + '</p>');
+ $list.after(node);
+ this.selectionStart(node);
+
+ this.sync();
+ this.callback('enter', e);
+ return false;
+ }
+ }
+
+ }
+
// replace div to p
if (block && this.opts.rBlockTest.test(block.tagName))
{
// hit enter
this.bufferSet();
@@ -1498,11 +1601,10 @@
}
else if (block === false)
{
// hit enter
this.bufferSet();
-
var node = $('<p>' + this.opts.invisibleSpace + '</p>');
this.insertNode(node[0]);
this.selectionStart(node);
this.callback('enter', e);
return false;
@@ -1557,11 +1659,11 @@
{
return this.buildEventKeydownTab(e, pre, key);
}
// delete zero-width space before the removing
- if (key === this.keyCode.BACKSPACE) this.buildEventKeydownBackspace(current);
+ if (key === this.keyCode.BACKSPACE) this.buildEventKeydownBackspace(e, current, parent);
},
buildEventKeydownPre: function(e, current)
{
e.preventDefault();
@@ -1605,29 +1707,44 @@
else this.indentingOutdent();
}
return false;
},
- buildEventKeydownBackspace: function(current)
+ buildEventKeydownBackspace: function(e, current, parent)
{
+ // remove empty list in table
+ if (parent && current && parent.parentNode.tagName == 'TD'
+ && parent.tagName == 'UL' && current.tagName == 'LI' && $(parent).children('li').size() == 1)
+ {
+ var text = $(current).text().replace(/[\u200B-\u200D\uFEFF]/g, '');
+ if (text == '')
+ {
+ var node = parent.parentNode;
+ $(parent).remove();
+ this.selectionStart(node);
+ this.sync();
+ return false;
+ }
+ }
+
if (typeof current.tagName !== 'undefined' && /^(H[1-6])$/i.test(current.tagName))
{
var node;
if (this.opts.linebreaks === false) node = $('<p>' + this.opts.invisibleSpace + '</p>');
else node = $('<br>' + this.opts.invisibleSpace);
$(current).replaceWith(node);
this.selectionStart(node);
+ this.sync();
}
if (typeof current.nodeValue !== 'undefined' && current.nodeValue !== null)
{
-
- //var value = $.trim(current.nodeValue.replace(/[^\u0000-\u1C7F]/g, ''));
if (current.remove && current.nodeType === 3 && current.nodeValue.match(/[^\u200B]/g) == null)
{
- current.remove();
+ $(current).prev().remove();
+ this.sync();
}
}
},
buildEventKeydownInsertLineBreak: function(e)
{
@@ -1785,36 +1902,56 @@
}
// iframe css
this.iframeAddCss();
- if (this.opts.fullpage) this.setFullpageOnInit(this.$editor.html());
+ if (this.opts.fullpage)
+ {
+ this.setFullpageOnInit(this.$source.val());
+ }
else this.set(this.content, true, false);
this.buildOptions();
this.buildAfter();
},
// PLACEHOLDER
- placeholderStart: function(html)
+ placeholderInit: function()
{
- if (this.isEmpty(html))
+ if (this.opts.placeholder !== false)
{
- if (this.$element.attr('placeholder'))
+ this.placeholderText = this.opts.placeholder;
+ this.opts.placeholder = true;
+ }
+ else
+ {
+ if (typeof this.$element.attr('placeholder') == 'undefined' || this.$element.attr('placeholder') == '')
{
- this.opts.placeholder = this.$element.attr('placeholder');
+ this.opts.placeholder = false;
}
-
- if (this.opts.placeholder !== '')
+ else
{
- this.opts.focus = false;
- this.placeholderOnFocus();
- this.placeholderOnBlur();
-
- return this.placeholderGet();
+ this.placeholderText = this.$element.attr('placeholder');
+ this.opts.placeholder = true;
}
}
+ },
+ placeholderStart: function(html)
+ {
+ if (this.opts.placeholder === false)
+ {
+ return false;
+ }
+
+ if (this.isEmpty(html))
+ {
+ this.opts.focus = false;
+ this.placeholderOnFocus();
+ this.placeholderOnBlur();
+
+ return this.placeholderGet();
+ }
else
{
this.placeholderOnBlur();
}
@@ -1828,11 +1965,18 @@
{
this.$editor.on('blur.redactor_placeholder', $.proxy(this.placeholderBlur, this));
},
placeholderGet: function()
{
- return $('<span class="redactor_placeholder">').data('redactor', 'verified').attr('contenteditable', false).text(this.opts.placeholder);
+ var ph = $('<span class="redactor_placeholder">').data('redactor', 'verified')
+ .attr('contenteditable', false).text(this.placeholderText);
+
+ if (this.opts.linebreaks === false)
+ {
+ return $('<p>').append(ph);
+ }
+ else return ph;
},
placeholderBlur: function()
{
var html = this.get();
if (this.isEmpty(html))
@@ -1878,37 +2022,103 @@
// SHORTCUTS
shortcuts: function(e, key)
{
+ // disable browser's hot keys for bold and italic
if (!this.opts.shortcuts)
{
- if (key === 66 || key === 73) e.preventDefault();
+ if ((e.ctrlKey || e.metaKey) && (key === 66 || key === 73))
+ {
+ e.preventDefault();
+ }
+
return false;
}
- if (key === 77) this.shortcutsLoad(e, 'removeFormat'); // Ctrl + m
- else if (key === 66) this.shortcutsLoad(e, 'bold'); // Ctrl + b
- else if (key === 73) this.shortcutsLoad(e, 'italic'); // Ctrl + i
+ $.each(this.opts.shortcuts, $.proxy(function(str, command)
+ {
+ var keys = str.split(',');
+ for (var i in keys)
+ {
+ if (typeof keys[i] === 'string')
+ {
+ this.shortcutsHandler(e, $.trim(keys[i]), $.proxy(function()
+ {
+ eval(command);
+ }, this));
+ }
- else if (key === 74) this.shortcutsLoad(e, 'insertunorderedlist'); // Ctrl + j
- else if (key === 75) this.shortcutsLoad(e, 'insertorderedlist'); // Ctrl + k
+ }
- else if (key === 72) this.shortcutsLoad(e, 'superscript'); // Ctrl + h
- else if (key === 76) this.shortcutsLoad(e, 'subscript'); // Ctrl + l
+ }, this));
+
},
- shortcutsLoad: function(e, cmd)
+ shortcutsHandler: function(e, keys, origHandler)
{
- e.preventDefault();
- this.execCommand(cmd, false);
+ // based on https://github.com/jeresig/jquery.hotkeys
+ var hotkeysSpecialKeys =
+ {
+ 8: "backspace", 9: "tab", 10: "return", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
+ 20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
+ 37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del", 59: ";", 61: "=",
+ 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
+ 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/",
+ 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
+ 120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 173: "-", 186: ";", 187: "=",
+ 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'"
+ };
+
+
+ var hotkeysShiftNums =
+ {
+ "`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&",
+ "8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<",
+ ".": ">", "/": "?", "\\": "|"
+ };
+
+ keys = keys.toLowerCase().split(" ");
+ var special = hotkeysSpecialKeys[e.keyCode],
+ character = String.fromCharCode( e.which ).toLowerCase(),
+ modif = "", possible = {};
+
+ $.each([ "alt", "ctrl", "meta", "shift"], function(index, specialKey)
+ {
+ if (e[specialKey + 'Key'] && special !== specialKey)
+ {
+ modif += specialKey + '+';
+ }
+ });
+
+
+ if (special)
+ {
+ possible[modif + special] = true;
+ }
+
+ if (character)
+ {
+ possible[modif + character] = true;
+ possible[modif + hotkeysShiftNums[character]] = true;
+
+ // "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
+ if (modif === "shift+")
+ {
+ possible[hotkeysShiftNums[character]] = true;
+ }
+ }
+
+ for (var i = 0, l = keys.length; i < l; i++)
+ {
+ if (possible[keys[i]])
+ {
+ e.preventDefault();
+ return origHandler.apply(this, arguments);
+ }
+ }
},
- shortcutsLoadFormat: function(e, cmd)
- {
- e.preventDefault();
- this.formatBlocks(cmd);
- },
// FOCUS
focus: function()
{
if (!this.browser('opera'))
@@ -1982,25 +2192,37 @@
else this.toggleVisual();
},
toggleVisual: function()
{
var html = this.$source.hide().val();
-
if (typeof this.modified !== 'undefined')
{
- this.modified = this.cleanRemoveSpaces(this.modified, false) !== this.cleanRemoveSpaces(html, false);
+ var modified = this.modified.replace(/\n/g, '');
+
+ var thtml = html.replace(/\n/g, '');
+ thtml = this.cleanRemoveSpaces(thtml, false);
+
+ this.modified = this.cleanRemoveSpaces(modified, false) !== thtml;
}
if (this.modified)
{
// don't remove the iframe even if cleared all.
- if (this.opts.fullpage && html === '') this.setFullpageOnInit(html);
+ if (this.opts.fullpage && html === '')
+ {
+ this.setFullpageOnInit(html);
+ }
else
{
this.set(html);
- if (this.opts.fullpage) this.buildBindKeyboard();
+ if (this.opts.fullpage)
+ {
+ this.buildBindKeyboard();
+ }
}
+
+ this.callback('change', false, html);
}
if (this.opts.iframe) this.$frame.show();
else this.$editor.show();
@@ -2013,10 +2235,12 @@
this.observeStart();
this.buttonActiveVisual();
this.buttonInactive('html');
this.opts.visual = true;
+
+
},
toggleCode: function(direct)
{
if (direct !== false) this.selectionSave();
@@ -2290,10 +2514,12 @@
},
airShow: function (e, keyboard)
{
if (!this.opts.air) return;
+ this.selectionSave();
+
var left, top;
$('.redactor_air').hide();
if (keyboard)
{
@@ -2395,20 +2621,26 @@
else
{
$item = $('<a href="#" class="' + btnObject.className + ' redactor_dropdown_' + btnName + '">' + btnObject.title + '</a>');
$item.on('click', $.proxy(function(e)
{
+ if (this.opts.air)
+ {
+ this.selectionRestore();
+ }
+
if (e.preventDefault) e.preventDefault();
if (this.browser('msie')) e.returnValue = false;
if (btnObject.callback) btnObject.callback.call(this, btnName, $item, btnObject, e);
if (btnObject.exec) this.execCommand(btnObject.exec, btnName);
if (btnObject.func) this[btnObject.func](btnName);
this.buttonActiveObserver();
if (this.opts.air) this.$air.fadeOut(100);
+
}, this));
}
$dropdown.append($item);
@@ -2420,27 +2652,25 @@
{
e.preventDefault();
return false;
}
- var $dropdown = this.$toolbar.find('.redactor_dropdown_box_' + key);
var $button = this.buttonGet(key);
+ // Always re-append it to the end of <body> so it always has the highest sub-z-index.
+ var $dropdown = $button.data('dropdown').appendTo(document.body);
+
if ($button.hasClass('dropact')) this.dropdownHideAll();
else
{
this.dropdownHideAll();
this.callback('dropdownShow', { dropdown: $dropdown, key: key, button: $button });
this.buttonActive(key);
$button.addClass('dropact');
- var keyPosition = $button.position();
- if (this.toolbarFixed)
- {
- keyPosition = $button.offset();
- }
+ var keyPosition = $button.offset();
// fix right placement
var dropdownWidth = $dropdown.width();
if ((keyPosition.left + dropdownWidth) > $(document).width())
{
@@ -2449,14 +2679,14 @@
var left = keyPosition.left + 'px';
var btnHeight = $button.innerHeight();
var position = 'absolute';
- var top = btnHeight + 'px';
+ var top = (btnHeight + this.opts.toolbarFixedTopOffset) + 'px';
if (this.opts.toolbarFixed && this.toolbarFixed) position = 'fixed';
- else if (!this.opts.air) top = keyPosition.top + btnHeight + 'px';
+ else top = keyPosition.top + btnHeight + 'px';
$dropdown.css({ position: position, left: left, top: top }).show();
this.callback('dropdownShown', { dropdown: $dropdown, key: key, button: $button });
}
@@ -2467,11 +2697,13 @@
}, this);
$(document).one('click', hdlHideDropDown);
this.$editor.one('click', hdlHideDropDown);
+ this.$editor.one('touchstart', hdlHideDropDown);
+
e.stopPropagation();
this.focusWithSaveScroll();
},
dropdownHideAll: function()
{
@@ -2541,11 +2773,11 @@
// dropdown
if (btnObject.dropdown)
{
var $dropdown = $('<div class="redactor_dropdown redactor_dropdown_box_' + btnName + '" style="display: none;">');
- $dropdown.appendTo(this.$toolbar);
+ $button.data('dropdown', $dropdown);
this.dropdownBuild($dropdown, btnObject.dropdown);
}
return $button;
},
@@ -2679,26 +2911,16 @@
var $parent = $(parent).closest(this.opts.alignmentTags.toString().toLowerCase(), this.$editor[0]);
if ($parent.length)
{
var align = $parent.css('text-align');
-
- switch (align)
+ if (align == '')
{
- case 'right':
- this.buttonActive('alignright');
- break;
- case 'center':
- this.buttonActive('aligncenter');
- break;
- case 'justify':
- this.buttonActive('alignjustify');
- break;
- default:
- this.buttonActive('alignleft');
- break;
+ align = 'left';
}
+
+ this.buttonActive('align' + align);
}
},
// EXEC
execPasteFrag: function(html)
@@ -2871,11 +3093,12 @@
{
data += this.outerHtml($('<p>').append(cloned.contents()));
}
else
{
- data += cloned.html() + '<br>';
+ var clonedHtml = cloned.html().replace(/<br\s?\/?>$/i, '');
+ data += clonedHtml + '<br>';
}
if (i == 0)
{
$s.addClass('redactor-replaced').empty();
@@ -2897,15 +3120,53 @@
// insert lists
else
{
var firstParent = $(this.getParent()).closest('td');
- this.document.execCommand(cmd);
+ if (this.browser('msie') && !this.isIe11() && this.opts.linebreaks)
+ {
+ var wrapper = this.selectionWrap('div');
+ var wrapperHtml = $(wrapper).html();
+ var tmpList = $('<ul>');
+ if (cmd == 'insertorderedlist')
+ {
+ tmpList = $('<ol>');
+ }
+ var tmpLi = $('<li>');
+
+ if ($.trim(wrapperHtml) == '')
+ {
+ tmpLi.append(wrapperHtml + '<span id="selection-marker-1">' + this.opts.invisibleSpace + '</span>');
+ tmpList.append(tmpLi);
+ this.$editor.find('#selection-marker-1').replaceWith(tmpList);
+ }
+ else
+ {
+ tmpLi.append(wrapperHtml);
+ tmpList.append(tmpLi);
+ $(wrapper).replaceWith(tmpList);
+ }
+ }
+ else
+ {
+ this.document.execCommand(cmd);
+ }
+
var parent = this.getParent();
var $list = $(parent).closest('ol, ul');
+ if (this.opts.linebreaks === false)
+ {
+ var listText = $.trim($list.text());
+ if (listText == '')
+ {
+ $list.children('li').find('br').remove();
+ $list.children('li').append('<span id="selection-marker-1">' + this.opts.invisibleSpace + '</span>');
+ }
+ }
+
if (firstParent.size() != 0)
{
$list.wrapAll('<td>');
}
@@ -2924,11 +3185,11 @@
this.$editor.focus();
}
}
this.selectionRestore();
-
+ this.$editor.find('#selection-marker-1').removeAttr('id');
this.sync();
this.callback('execCommand', cmd, param);
return;
},
@@ -3052,11 +3313,11 @@
if (left <= 0)
{
// linebreaks
if (this.opts.linebreaks === true && typeof($el.data('tagblock')) !== 'undefined')
{
- $el.replaceWith($el.html());
+ $el.replaceWith($el.html() + '<br>');
}
// all block tags
else
{
$el.css('margin-left', '');
@@ -3175,11 +3436,10 @@
}, this));
}
this.selectionRestore();
-
this.sync();
},
// CLEAN
cleanEmpty: function(html)
@@ -3196,11 +3456,15 @@
return html;
},
cleanConverters: function(html)
{
// convert div to p
- if (this.opts.convertDivs) html = html.replace(/<div(.*?)>([\w\W]*?)<\/div>/gi, '<p$1>$2</p>');
+ if (this.opts.convertDivs && !this.opts.gallery)
+ {
+ html = html.replace(/<div(.*?)>([\w\W]*?)<\/div>/gi, '<p$1>$2</p>');
+ }
+
if (this.opts.paragraphy) html = this.cleanParagraphy(html);
return html;
},
cleanConvertProtected: function(html)
@@ -3286,12 +3550,10 @@
return html;
},
cleanRemoveEmptyTags: function(html)
{
- html = html.replace(/<span>([\w\W]*?)<\/span>/gi, '$1');
-
// remove zero width-space
html = html.replace(/[\u200B-\u200D\uFEFF]/g, '');
var etagsInline = ["<b>\\s*</b>", "<b> </b>", "<em>\\s*</em>"]
var etags = ["<pre></pre>", "<blockquote>\\s*</blockquote>", "<dd></dd>", "<dt></dt>", "<ul></ul>", "<ol></ol>", "<li></li>", "<table></table>", "<tr></tr>", "<span>\\s*<span>", "<span> <span>", "<p>\\s*</p>", "<p></p>", "<p> </p>", "<p>\\s*<br>\\s*</p>", "<div>\\s*</div>", "<div>\\s*<br>\\s*</div>"];
@@ -3345,10 +3607,11 @@
html = html.replace(s, '{replace' + i + '}\n');
});
}
html = html.replace(/<br \/>\s*<br \/>/gi, "\n\n");
+ html = html.replace(/<br><br>/gi, "\n\n");
function R(str, mod, r)
{
return html.replace(new RegExp(str, mod), r);
}
@@ -3368,11 +3631,11 @@
{
if (htmls.hasOwnProperty(i))
{
if (htmls[i].search('{replace') == -1)
{
- htmls[i] = htmls[i].replace(/<p>\n\t<\/p>/gi, '');
+ htmls[i] = htmls[i].replace(/<p>\n\t?<\/p>/gi, '');
htmls[i] = htmls[i].replace(/<p><\/p>/gi, '');
if (htmls[i] != '')
{
html += '<p>' + htmls[i].replace(/^\n+|\n+$/g, "") + "</p>";
@@ -3433,19 +3696,15 @@
else html = html.replace(/<strong>([\w\W]*?)<\/strong>/gi, '<b>$1</b>');
if (this.opts.italicTag === 'em') html = html.replace(/<i>([\w\W]*?)<\/i>/gi, '<em>$1</em>');
else html = html.replace(/<em>([\w\W]*?)<\/em>/gi, '<i>$1</i>');
- if (set !== true)
- {
- html = html.replace(/<strike>([\w\W]*?)<\/strike>/gi, '<del>$1</del>');
- }
- else
- {
- html = html.replace(/<del>([\w\W]*?)<\/del>/gi, '<strike>$1</strike>');
- }
+ html = html.replace(/<span style="text-decoration: underline;">([\w\W]*?)<\/span>/gi, '<u>$1</u>');
+ if (set !== true) html = html.replace(/<strike>([\w\W]*?)<\/strike>/gi, '<del>$1</del>');
+ else html = html.replace(/<del>([\w\W]*?)<\/del>/gi, '<strike>$1</strike>');
+
return html;
},
cleanStripTags: function(html)
{
if (html == '' || typeof html == 'undefined') return html;
@@ -3512,10 +3771,18 @@
$.each($elem, $.proxy(function(i,s)
{
this.removeEmptyAttr(s, 'style');
}, this));
+ var $elem2 = this.$editor.find('b, strong, i, em, u, strike, del');
+ $elem2.css('font-size', '');
+
+ $.each($elem2, $.proxy(function(i,s)
+ {
+ this.removeEmptyAttr(s, 'style');
+ }, this));
+
// When we paste text in Safari is wrapping inserted div (remove it)
this.$editor.find('div[style="text-align: -webkit-auto;"]').contents().unwrap();
// Remove all styles in ul, ol, li
this.$editor.find('ul, ol, li').removeAttr('style');
@@ -3630,11 +3897,11 @@
tag = this.cleanTag(tag);
out = this.placeTag(tag, out);
}
}
- return this.cleanFinish( out );
+ return this.cleanFinish(out);
},
cleanGetTabs: function()
{
var s = '';
for ( var j = 0; j < this.cleanlevel; j++ )
@@ -3644,14 +3911,14 @@
return s;
},
cleanFinish: function(code)
{
- code = code.replace( /\n\s*\n/g, '\n' );
- code = code.replace( /^[\s\n]*/, '' );
- code = code.replace( /[\s\n]*$/, '' );
- code = code.replace( /<script(.*?)>\n<\/script>/gi, '<script$1></script>' );
+ code = code.replace(/\n\s*\n/g, '\n');
+ code = code.replace(/^[\s\n]*/, '');
+ code = code.replace(/[\s\n]*$/, '');
+ code = code.replace(/<script(.*?)>\n<\/script>/gi, '<script$1></script>');
this.cleanlevel = 0;
return code;
},
@@ -3736,10 +4003,15 @@
this.sync();
},
formatBlocks: function(tag)
{
+ if (this.browser('mozilla') && this.isFocused())
+ {
+ this.$editor.focus();
+ }
+
this.bufferSet();
var nodes = this.getBlocks();
this.selectionSave();
@@ -3840,10 +4112,15 @@
},
// QUOTE
formatQuote: function()
{
+ if (this.browser('mozilla') && this.isFocused())
+ {
+ this.$editor.focus();
+ }
+
this.bufferSet();
// paragraphy
if (this.opts.linebreaks === false)
{
@@ -4079,11 +4356,10 @@
});
this.selectionRestore();
this.sync();
},
-
inlineSetClass: function(className)
{
var current = this.getCurrent();
if (!$(current).hasClass(className)) this.inlineMethods('addClass', className);
},
@@ -4138,12 +4414,30 @@
{
$(el)[type](attr, value);
}
else
{
- this.document.execCommand('fontSize', false, 4 );
+ var cmd, arg = value;
+ switch (attr)
+ {
+ case 'font-size':
+ cmd = 'fontSize';
+ arg = 4;
+ break;
+ case 'font-family':
+ cmd = 'fontName';
+ break;
+ case 'color':
+ cmd = 'foreColor';
+ break;
+ case 'background-color':
+ cmd = 'backColor';
+ break;
+ }
+ this.document.execCommand(cmd, false, arg);
+
var fonts = this.$editor.find('font');
$.each(fonts, $.proxy(function(i, s)
{
this.inlineSetMethods(type, s, attr, value);
@@ -4265,10 +4559,11 @@
inlineRemoveFormatReplace: function(el)
{
$(el).replaceWith($(el).contents());
},
+
// INSERT
insertHtml: function (html, sync)
{
var current = this.getCurrent();
var parent = current.parentNode;
@@ -4359,13 +4654,13 @@
if (sel.getRangeAt && sel.rangeCount)
{
var range = sel.getRangeAt(0);
range.deleteContents();
- var el = this.document.createElement('div');
+ var el = document.createElement('div');
el.innerHTML = html;
- var frag = this.document.createDocumentFragment(), node, lastNode;
+ var frag = document.createDocumentFragment(), node, lastNode;
while ((node = el.firstChild))
{
lastNode = frag.appendChild(node);
}
@@ -4413,12 +4708,25 @@
if ($html.length) html = $html.text();
this.focusWithSaveScroll();
- if (this.browser('msie') && !this.isIe11()) this.document.selection.createRange().pasteHTML(html);
- else this.document.execCommand('inserthtml', false, html);
+ if (this.browser('msie'))
+ {
+ if (!this.isIe11())
+ {
+ this.document.selection.createRange().pasteHTML(html);
+ }
+ else
+ {
+ this.execPasteFrag(html);
+ }
+ }
+ else
+ {
+ this.document.execCommand('inserthtml', false, html);
+ }
this.sync();
},
insertNode: function(node)
{
@@ -4450,10 +4758,12 @@
range.setEndAfter(node);
range.setStartAfter(node);
sel.removeAllRanges();
sel.addRange(range);
}
+
+ return node;
},
insertNodeToCaretPositionFromPoint: function(e, node)
{
var range;
var x = e.clientX, y = e.clientY;
@@ -4669,13 +4979,21 @@
// remove google docs marker
html = html.replace(/<b\sid="internal-source-marker(.*?)">([\w\W]*?)<\/b>/gi, "$2");
html = html.replace(/<b(.*?)id="docs-internal-guid(.*?)">([\w\W]*?)<\/b>/gi, "$3");
+
+ html = html.replace(/<span[^>]*(font-style: italic; font-weight: bold|font-weight: bold; font-style: italic)[^>]*>/gi, '<span style="font-weight: bold;"><span style="font-style: italic;">');
+ html = html.replace(/<span[^>]*font-style: italic[^>]*>/gi, '<span style="font-style: italic;">');
+ html = html.replace(/<span[^>]*font-weight: bold[^>]*>/gi, '<span style="font-weight: bold;">');
+ html = html.replace(/<span[^>]*text-decoration: underline[^>]*>/gi, '<span style="text-decoration: underline;">');
+
// strip tags
- html = this.cleanStripTags(html);
+ //html = this.cleanStripTags(html);
+
+
// prevert
html = html.replace(/<td>\u200b*<\/td>/gi, '[td]');
html = html.replace(/<td> <\/td>/gi, '[td]');
html = html.replace(/<td><br><\/td>/gi, '[td]');
html = html.replace(/<td(.*?)colspan="(.*?)"(.*?)>([\w\W]*?)<\/td>/gi, '[td colspan="$2"]$4[/td]');
@@ -4685,10 +5003,11 @@
html = html.replace(/<video(.*?)>([\w\W]*?)<\/video>/gi, '[video$1]$2[/video]');
html = html.replace(/<audio(.*?)>([\w\W]*?)<\/audio>/gi, '[audio$1]$2[/audio]');
html = html.replace(/<embed(.*?)>([\w\W]*?)<\/embed>/gi, '[embed$1]$2[/embed]');
html = html.replace(/<object(.*?)>([\w\W]*?)<\/object>/gi, '[object$1]$2[/object]');
html = html.replace(/<param(.*?)>/gi, '[param$1]');
+
html = html.replace(/<img(.*?)>/gi, '[img$1]');
// remove classes
html = html.replace(/ class="(.*?)"/gi, '');
@@ -4740,10 +5059,13 @@
else
{
html = html.replace(/<div><\/div>/gi, '<br />');
}
+ // strip tags
+ html = this.cleanStripTags(html);
+
if (this.currentOrParentIs('LI'))
{
html = html.replace(/<p>([\w\W]*?)<\/p>/gi, '$1<br>');
}
else if (tablePaste === false)
@@ -4984,23 +5306,24 @@
this.insertHtml('<img src="' + result + '" />');
}
},
// BUFFER
- bufferSet: function(html, selectionSave)
+ bufferSet: function(selectionSave)
{
- if (html !== undefined || html === false) this.opts.buffer.push(html);
- else
+ if (selectionSave !== false)
{
- if (selectionSave !== false)
- {
- this.selectionSave();
- }
+ this.selectionSave();
+ }
- this.opts.buffer.push(this.$editor.html());
+ this.opts.buffer.push(this.$editor.html());
+
+ if (selectionSave !== false)
+ {
this.selectionRemoveMarkers('buffer');
}
+
},
bufferUndo: function()
{
if (this.opts.buffer.length === 0)
{
@@ -5044,15 +5367,17 @@
if (this.opts.observeLinks) this.observeLinks();
},
observeLinks: function()
{
this.$editor.find('a').on('click', $.proxy(this.linkObserver, this));
+
this.$editor.on('click.redactor', $.proxy(function(e)
{
this.linkObserverTooltipClose(e);
}, this));
+
$(document).on('click.redactor', $.proxy(function(e)
{
this.linkObserverTooltipClose(e);
}, this));
@@ -5062,18 +5387,33 @@
if (this.opts.observeImages === false) return false;
this.$editor.find('img').each($.proxy(function(i, elem)
{
if (this.browser('msie')) $(elem).attr('unselectable', 'on');
- this.imageResize(elem);
+ var parent = $(elem).parent();
+ if (!parent.hasClass('royalSlider') && !parent.hasClass('fotorama'))
+ {
+ this.imageResize(elem);
+ }
+
}, this));
+
+ // royalSlider and fotorama
+ this.$editor.find('.fotorama, .royalSlider').on('click', $.proxy(this.editGallery, this));
+
},
linkObserver: function(e)
{
var $link = $(e.target);
+ var parent = $(e.target).parent();
+ if (parent.hasClass('royalSlider') || parent.hasClass('fotorama'))
+ {
+ return;
+ }
+
if ($link.size() == 0 || $link[0].tagName !== 'A') return;
var pos = $link.offset();
if (this.opts.iframe)
{
@@ -5397,10 +5737,16 @@
if (newnodes.length === 0) newnodes = [this.getBlock()];
return newnodes;
},
+ isInlineNode: function(node)
+ {
+ if (node.nodeType != 1) return false;
+
+ return !this.rTestBlock.test(node.nodeName);
+ },
nodeTestBlocks: function(node)
{
return node.nodeType == 1 && this.rTestBlock.test(node.nodeName);
},
tagTestBlock: function(tag)
@@ -5550,11 +5896,14 @@
},
// SAVE & RESTORE
selectionSave: function()
{
- if (!this.isFocused()) this.focusWithSaveScroll();
+ if (!this.isFocused())
+ {
+ this.focusWithSaveScroll();
+ }
if (!this.opts.rangy)
{
this.selectionCreateMarker(this.getRange());
}
@@ -5587,14 +5936,23 @@
},
selectionSetMarker: function(range, node, type)
{
var boundaryRange = range.cloneRange();
- boundaryRange.collapse(type);
+ try {
+ boundaryRange.collapse(type);
+ boundaryRange.insertNode(node);
+ boundaryRange.detach();
+ }
+ catch (e)
+ {
+ var html = this.opts.emptyHtml;
+ if (this.opts.linebreaks) html = '<br>';
- boundaryRange.insertNode(node);
- boundaryRange.detach();
+ this.$editor.prepend(html);
+ this.focus();
+ }
},
selectionRestore: function(replace, remove)
{
if (!this.opts.rangy)
{
@@ -5615,10 +5973,11 @@
this.focusWithSaveScroll();
}
if (node1.length != 0 && node2.length != 0)
{
+
this.selectionSet(node1[0], 0, node2[0], 0);
}
else if (node1.length != 0)
{
this.selectionSet(node1[0], 0, null, 0);
@@ -5677,11 +6036,11 @@
}, this));
},
tableInsert: function()
{
- this.bufferSet(false, false);
+ this.bufferSet(false);
var rows = $('#redactor_table_rows').val(),
columns = $('#redactor_table_columns').val(),
$table_box = $('<div></div>'),
tableId = Math.floor(Math.random() * 99999),
@@ -5709,10 +6068,15 @@
}
$table_box.append($table);
var html = $table_box.html();
+ if (this.opts.linebreaks === false && this.browser('mozilla'))
+ {
+ html += '<p>' + this.opts.invisibleSpace + '</p>';
+ }
+
this.modalClose();
this.selectionRestore();
var current = this.getBlock() || this.getCurrent();
@@ -5725,10 +6089,11 @@
$(current).after(html)
}
else
{
+
this.insertHtmlAdvanced(html, false);
}
this.selectionRestore();
@@ -5773,10 +6138,11 @@
}
}
$current_tr.remove();
this.selectionRestore();
+ $table.find('span#selection-marker-1').remove();
this.sync();
},
tableDeleteColumn: function()
{
var parent = this.getParent();
@@ -5807,10 +6173,11 @@
$(elem).find('td').eq(index).remove();
}, this));
this.selectionRestore();
+ $table.find('span#selection-marker-1').remove();
this.sync();
},
tableAddHead: function()
{
var $table = $(this.getParent()).closest('table');
@@ -5933,10 +6300,23 @@
videoInsert: function ()
{
var data = $('#redactor_insert_video_area').val();
data = this.cleanStripTags(data);
+ // parse if it is link on youtube & vimeo
+ var iframeStart = '<iframe width="500" height="281" src="',
+ iframeEnd = '" frameborder="0" allowfullscreen></iframe>';
+
+ if (data.match(reUrlYoutube))
+ {
+ data = data.replace(reUrlYoutube, iframeStart + '//www.youtube.com/embed/$1' + iframeEnd);
+ }
+ else if (data.match(reUrlVimeo))
+ {
+ data = data.replace(reUrlVimeo, iframeStart + '//player.vimeo.com/video/$2' + iframeEnd);
+ }
+
this.selectionRestore();
var current = this.getBlock() || this.getCurrent();
if (current) $(current).after(data)
@@ -5952,10 +6332,44 @@
{
this.selectionSave();
var callback = $.proxy(function()
{
+ // Predefined links
+ if (this.opts.predefinedLinks !== false)
+ {
+ this.predefinedLinksStorage = {};
+ var that = this;
+ $.getJSON(this.opts.predefinedLinks, function(data)
+ {
+ var $select = $('#redactor-predefined-links');
+ $select .html('');
+ $.each(data, function(key, val)
+ {
+ that.predefinedLinksStorage[key] = val;
+ $select.append($('<option>').val(key).html(val.name));
+ });
+
+ $select.on('change', function()
+ {
+ var key = $(this).val();
+ var name = '', url = '';
+ if (key != 0)
+ {
+ name = that.predefinedLinksStorage[key].name;
+ url = that.predefinedLinksStorage[key].url;
+ }
+
+ $('#redactor_link_url').val(url);
+ $('#redactor_link_url_text').val(name);
+
+ });
+
+ $select.show();
+ });
+ }
+
this.insert_link_node = false;
var sel = this.getSelection();
var url = '', text = '', target = '';
@@ -5997,12 +6411,13 @@
{
$('#redactor_link_blank').prop('checked', true);
}
this.linkInsertPressed = false;
- $('#redactor_insert_link_btn').click($.proxy(this.linkProcess, this));
+ $('#redactor_insert_link_btn').on('click', $.proxy(this.linkProcess, this));
+
setTimeout(function()
{
$('#redactor_link_url').focus();
}, 200);
@@ -6024,11 +6439,11 @@
var link = $('#redactor_link_url').val();
var text = $('#redactor_link_url_text').val();
// mailto
- if (link.search('@') != -1)
+ if (link.search('@') != -1 && /(http|ftp|https):\/\//i.test(link) === false)
{
link = 'mailto:' + link;
}
// url, not anchor
else if (link.search('#') != 0)
@@ -6198,10 +6613,11 @@
var callback = $.proxy(function()
{
// json
if (this.opts.imageGetJson)
{
+
$.getJSON(this.opts.imageGetJson, $.proxy(function(data)
{
var folders = {}, count = 0;
// folders
@@ -6259,11 +6675,11 @@
}, this));
}
else
{
- $('#redactor-modal-tab-2').remove();
+ $('#redactor-tab-control-2').remove();
}
if (this.opts.imageUpload || this.opts.s3)
{
// dragupload
@@ -6314,12 +6730,12 @@
$('#redactor_tabs').remove();
$('#redactor_tab3').show();
}
else
{
- $('#redactor-modal-tab-1').remove();
- $('#redactor-modal-tab-2').addClass('redactor_tabs_act');
+ $('#redactor-tab-control-1').remove();
+ $('#redactor-tab-control-2').addClass('redactor_tabs_act');
$('#redactor_tab2').show();
}
}
if (!this.opts.imageTabLink && (this.opts.imageUpload || this.opts.imageGetJson))
@@ -6423,20 +6839,20 @@
this.modalClose();
this.sync();
},
imageSave: function(el)
{
+ this.imageResizeHide(false);
+
var $el = $(el);
var parent = $el.parent();
$el.attr('alt', $('#redactor_file_alt').val());
var floating = $('#redactor_form_image_align').val();
var margin = '';
- this.imageResizeHide(false);
-
if (floating === 'left')
{
margin = '0 ' + this.opts.imageFloatMargin + ' ' + this.opts.imageFloatMargin + ' 0';
$el.css({ 'float': 'left', 'margin': margin });
}
@@ -6579,76 +6995,79 @@
var imageResizer = this.imageResizeControls($image);
// resize
var isResizing = false;
- imageResizer.on('mousedown', function(e)
+ if (imageResizer !== false)
{
- isResizing = true;
- e.preventDefault();
+ imageResizer.on('mousedown', function(e)
+ {
+ isResizing = true;
+ e.preventDefault();
- ratio = $image.width() / $image.height();
+ ratio = $image.width() / $image.height();
- start_x = Math.round(e.pageX - $image.eq(0).offset().left);
- start_y = Math.round(e.pageY - $image.eq(0).offset().top);
+ start_x = Math.round(e.pageX - $image.eq(0).offset().left);
+ start_y = Math.round(e.pageY - $image.eq(0).offset().top);
- });
+ });
- $(this.document.body).on('mousemove', $.proxy(function(e)
- {
- if (isResizing)
+ $(this.document.body).on('mousemove', $.proxy(function(e)
{
- var mouse_x = Math.round(e.pageX - $image.eq(0).offset().left) - start_x;
- var mouse_y = Math.round(e.pageY - $image.eq(0).offset().top) - start_y;
+ if (isResizing)
+ {
+ var mouse_x = Math.round(e.pageX - $image.eq(0).offset().left) - start_x;
+ var mouse_y = Math.round(e.pageY - $image.eq(0).offset().top) - start_y;
- var div_h = $image.height();
+ var div_h = $image.height();
- var new_h = parseInt(div_h, 10) + mouse_y;
- var new_w = Math.round(new_h * ratio);
+ var new_h = parseInt(div_h, 10) + mouse_y;
+ var new_w = Math.round(new_h * ratio);
- if (new_w > min_w)
- {
- $image.width(new_w);
-
- if (new_w < 100)
+ if (new_w > min_w)
{
- this.imageEditter.css({
- marginTop: '-7px',
- marginLeft: '-13px',
- fontSize: '9px',
- padding: '3px 5px'
- });
+ $image.width(new_w);
+
+ if (new_w < 100)
+ {
+ this.imageEditter.css({
+ marginTop: '-7px',
+ marginLeft: '-13px',
+ fontSize: '9px',
+ padding: '3px 5px'
+ });
+ }
+ else
+ {
+ this.imageEditter.css({
+ marginTop: '-11px',
+ marginLeft: '-18px',
+ fontSize: '11px',
+ padding: '7px 10px'
+ });
+ }
}
- else
- {
- this.imageEditter.css({
- marginTop: '-11px',
- marginLeft: '-18px',
- fontSize: '11px',
- padding: '7px 10px'
- });
- }
- }
- start_x = Math.round(e.pageX - $image.eq(0).offset().left);
- start_y = Math.round(e.pageY - $image.eq(0).offset().top);
+ start_x = Math.round(e.pageX - $image.eq(0).offset().left);
+ start_y = Math.round(e.pageY - $image.eq(0).offset().top);
- this.sync()
- }
- }, this)).on('mouseup', function()
- {
- isResizing = false;
- });
+ this.sync()
+ }
+ }, this)).on('mouseup', function()
+ {
+ isResizing = false;
+ });
+ }
this.$editor.on('keydown.redactor-image-delete', $.proxy(function(e)
{
var key = e.which;
if (this.keyCode.BACKSPACE == key || this.keyCode.DELETE == key)
{
- this.bufferSet(false, false);
+ this.bufferSet(false);
this.imageResizeHide(false);
this.imageRemove($image);
}
}, this));
@@ -6711,29 +7130,38 @@
this.imageEdit($image);
}, this));
imageBox.append(this.imageEditter);
// resizer
- var imageResizer = $('<span id="redactor-image-resizer" data-redactor="verified"></span>');
- imageResizer.css({
- position: 'absolute',
- zIndex: 2,
- lineHeight: 1,
- cursor: 'nw-resize',
- bottom: '-4px',
- right: '-5px',
- border: '1px solid #fff',
- backgroundColor: '#000',
- width: '8px',
- height: '8px'
- });
- imageResizer.attr('contenteditable', false);
- imageBox.append(imageResizer);
+ if (this.opts.imageResizable)
+ {
+ var imageResizer = $('<span id="redactor-image-resizer" data-redactor="verified"></span>');
+ imageResizer.css({
+ position: 'absolute',
+ zIndex: 2,
+ lineHeight: 1,
+ cursor: 'nw-resize',
+ bottom: '-4px',
+ right: '-5px',
+ border: '1px solid #fff',
+ backgroundColor: '#000',
+ width: '8px',
+ height: '8px'
+ });
+ imageResizer.attr('contenteditable', false);
+ imageBox.append(imageResizer);
- imageBox.append($image);
+ imageBox.append($image);
- return imageResizer;
+ return imageResizer;
+ }
+ else
+ {
+ imageBox.append($image);
+
+ return false;
+ }
},
imageThumbClick: function(e)
{
var img = '<img id="image-marker" src="' + $(e.target).attr('rel') + '" alt="' + $(e.target).attr('title') + '" />';
@@ -6797,18 +7225,35 @@
this.modalClose();
this.observeImages();
},
+ // PROGRESS BAR
+ buildProgressBar: function()
+ {
+ if ($('#redactor-progress').size() != 0) return;
+
+ this.$progressBar = $('<div id="redactor-progress"><span></span></div>');
+ $(document.body).append(this.$progressBar);
+ },
+ showProgressBar: function()
+ {
+ this.buildProgressBar();
+ $('#redactor-progress').fadeIn();
+ },
+ hideProgressBar: function()
+ {
+ $('#redactor-progress').fadeOut(1500);
+ },
+
// MODAL
modalTemplatesInit: function()
{
$.extend( this.opts,
{
modal_file: String()
+ '<section id="redactor-modal-file-insert">'
- + '<div id="redactor-progress" class="redactor-progress-inline" style="display: none;"><span></span></div>'
+ '<form id="redactorUploadFileForm" method="post" action="" enctype="multipart/form-data">'
+ '<label>' + this.opts.curLang.filename + '</label>'
+ '<input type="text" id="redactor_filename" class="redactor_input" />'
+ '<div style="margin-top: 7px;">'
+ '<input type="file" id="redactor_file" name="' + this.opts.fileUploadParam + '" />'
@@ -6842,11 +7287,10 @@
+ '<div id="redactor_tabs">'
+ '<a href="#" id="redactor-tab-control-1" class="redactor_tabs_act">' + this.opts.curLang.upload + '</a>'
+ '<a href="#" id="redactor-tab-control-2">' + this.opts.curLang.choose + '</a>'
+ '<a href="#" id="redactor-tab-control-3">' + this.opts.curLang.link + '</a>'
+ '</div>'
- + '<div id="redactor-progress" class="redactor-progress-inline" style="display: none;"><span></span></div>'
+ '<form id="redactorInsertImageForm" method="post" action="" enctype="multipart/form-data">'
+ '<div id="redactor_tab1" class="redactor_tab">'
+ '<input type="file" id="redactor_file" name="' + this.opts.imageUploadParam + '" />'
+ '</div>'
+ '<div id="redactor_tab2" class="redactor_tab" style="display: none;">'
@@ -6863,10 +7307,11 @@
+ '<button class="redactor_modal_btn redactor_modal_action_btn" id="redactor_upload_btn">' + this.opts.curLang.insert + '</button>'
+ '</footer>',
modal_link: String()
+ '<section id="redactor-modal-link-insert">'
+ + '<select id="redactor-predefined-links" style="width: 99.5%; display: none;"></select>'
+ '<label>URL</label>'
+ '<input type="text" class="redactor_input" id="redactor_link_url" />'
+ '<label>' + this.opts.curLang.text + '</label>'
+ '<input type="text" class="redactor_input" id="redactor_link_url_text" />'
+ '<label><input type="checkbox" id="redactor_link_blank"> ' + this.opts.curLang.link_new_tab + '</label>'
@@ -6902,48 +7347,111 @@
});
},
modalInit: function(title, content, width, callback)
{
- var $redactorModalOverlay = $('#redactor_modal_overlay');
+ this.modalSetOverlay();
- // modal overlay
- if (!$redactorModalOverlay.length)
+ this.$redactorModalWidth = width;
+ this.$redactorModal = $('#redactor_modal');
+
+ if (!this.$redactorModal.length)
{
- this.$overlay = $redactorModalOverlay = $('<div id="redactor_modal_overlay" style="display: none;"></div>');
- $('body').prepend(this.$overlay);
+ this.$redactorModal = $('<div id="redactor_modal" style="display: none;" />');
+ this.$redactorModal.append($('<div id="redactor_modal_close">×</div>'));
+ this.$redactorModal.append($('<header id="redactor_modal_header" />'));
+ this.$redactorModal.append($('<div id="redactor_modal_inner" />'));
+ this.$redactorModal.appendTo(document.body);
}
- if (this.opts.modalOverlay)
+ $('#redactor_modal_close').on('click', $.proxy(this.modalClose, this));
+ $(document).on('keyup', $.proxy(this.modalCloseHandler, this));
+ this.$editor.on('keyup', $.proxy(this.modalCloseHandler, this));
+
+ this.modalSetContent(content);
+ this.modalSetTitle(title);
+ this.modalSetDraggable();
+ this.modalLoadTabs();
+ this.modalOnCloseButton();
+ this.modalSetButtonsWidth();
+
+ this.saveModalScroll = this.document.body.scrollTop;
+ if (this.opts.autoresize === false)
{
- $redactorModalOverlay.show().on('click', $.proxy(this.modalClose, this));
+ this.saveModalScroll = this.$editor.scrollTop();
}
- var $redactorModal = $('#redactor_modal');
+ if (this.isMobile() === false) this.modalShowOnDesktop();
+ else this.modalShowOnMobile();
- if (!$redactorModal.length)
+ // modal actions callback
+ if (typeof callback === 'function')
{
- this.$modal = $redactorModal = $('<div id="redactor_modal" style="display: none;"><div id="redactor_modal_close">×</div><header id="redactor_modal_header"></header><div id="redactor_modal_inner"></div></div>');
- $('body').append(this.$modal);
+ callback();
}
- $('#redactor_modal_close').on('click', $.proxy(this.modalClose, this));
+ // modal shown callback
+ setTimeout($.proxy(function()
+ {
+ this.callback('modalOpened', this.$redactorModal);
- this.hdlModalClose = $.proxy(function(e)
+ }, this), 11);
+
+ // fix bootstrap modal focus
+ $(document).off('focusin.modal');
+
+ // enter
+ this.$redactorModal.find('input[type=text]').on('keypress', $.proxy(function(e)
{
- if (e.keyCode === this.keyCode.ESC)
+ if (e.which === 13)
{
- this.modalClose();
- return false;
+ this.$redactorModal.find('.redactor_modal_action_btn').click();
+ e.preventDefault();
}
+ }, this));
- }, this);
+ return this.$redactorModal;
- $(document).keyup(this.hdlModalClose);
- this.$editor.keyup(this.hdlModalClose);
+ },
+ modalShowOnDesktop: function()
+ {
+ this.$redactorModal.css({
+ position: 'fixed',
+ top: '-2000px',
+ left: '50%',
+ width: this.$redactorModalWidth + 'px',
+ marginLeft: '-' + (this.$redactorModalWidth / 2) + 'px'
+ }).show();
- // set content
+ this.modalSaveBodyOveflow = $(document.body).css('overflow');
+ $(document.body).css('overflow', 'hidden');
+
+ setTimeout($.proxy(function()
+ {
+ var height = this.$redactorModal.outerHeight();
+ this.$redactorModal.css({
+ top: '50%',
+ height: 'auto',
+ minHeight: 'auto',
+ marginTop: '-' + (height + 10) / 2 + 'px'
+ });
+ }, this), 15);
+ },
+ modalShowOnMobile: function()
+ {
+ this.$redactorModal.css({
+ position: 'fixed',
+ width: '100%',
+ height: '100%',
+ top: '0',
+ left: '0',
+ margin: '0',
+ minHeight: '300px'
+ }).show();
+ },
+ modalSetContent: function(content)
+ {
this.modalcontent = false;
if (content.indexOf('#') == 0)
{
this.modalcontent = $(content);
$('#redactor_modal_inner').empty().append(this.modalcontent.html());
@@ -6952,133 +7460,85 @@
}
else
{
$('#redactor_modal_inner').empty().append(content);
}
-
- $redactorModal.find('#redactor_modal_header').html(title);
-
- // draggable
- if (typeof $.fn.draggable !== 'undefined')
- {
- $redactorModal.draggable({ handle: '#redactor_modal_header' });
- $redactorModal.find('#redactor_modal_header').css('cursor', 'move');
- }
-
- var $redactor_tabs = $('#redactor_tabs');
-
- // tabs
- if ($redactor_tabs.length )
- {
- var that = this;
- $redactor_tabs.find('a').each(function(i, s)
- {
- i++;
- $(s).on('click', function(e)
- {
- e.preventDefault();
-
- $redactor_tabs.find('a').removeClass('redactor_tabs_act');
- $(this).addClass('redactor_tabs_act');
- $('.redactor_tab').hide();
- $('#redactor_tab' + i ).show();
- $('#redactor_tab_selected').val(i);
-
- if (that.isMobile() === false)
- {
- var height = $redactorModal.outerHeight();
- $redactorModal.css('margin-top', '-' + (height + 10) / 2 + 'px');
- }
- });
- });
- }
-
- $redactorModal.find('.redactor_btn_modal_close').on('click', $.proxy(this.modalClose, this));
-
- var buttons = $redactorModal.find('footer button');
+ },
+ modalSetTitle: function(title)
+ {
+ this.$redactorModal.find('#redactor_modal_header').html(title);
+ },
+ modalSetButtonsWidth: function()
+ {
+ var buttons = this.$redactorModal.find('footer button').not('.redactor_modal_btn_hidden');
var buttonsSize = buttons.size();
if (buttonsSize > 0)
{
- $(buttons).css('width', (width/buttonsSize) + 'px')
+ $(buttons).css('width', (this.$redactorModalWidth/buttonsSize) + 'px')
}
-
- // save scroll
- if (this.opts.autoresize === true)
+ },
+ modalOnCloseButton: function()
+ {
+ this.$redactorModal.find('.redactor_btn_modal_close').on('click', $.proxy(this.modalClose, this));
+ },
+ modalSetOverlay: function()
+ {
+ if (this.opts.modalOverlay)
{
- this.saveModalScroll = this.document.body.scrollTop;
- }
- else
- {
- this.saveModalScroll = this.$editor.scrollTop();
- }
+ this.$redactorModalOverlay = $('#redactor_modal_overlay');
+ if (!this.$redactorModalOverlay.length)
+ {
+ this.$redactorModalOverlay = $('<div id="redactor_modal_overlay" style="display: none;"></div>');
+ $('body').prepend(this.$redactorModalOverlay);
+ }
- if (this.isMobile() === false)
- {
- $redactorModal.css({
- position: 'fixed',
- top: '-2000px',
- left: '50%',
- width: width + 'px',
- marginLeft: '-' + (width / 2) + 'px'
- }).show();
-
- this.modalSaveBodyOveflow = $(document.body).css('overflow');
- $(document.body).css('overflow', 'hidden');
-
+ this.$redactorModalOverlay.show().on('click', $.proxy(this.modalClose, this));
}
- else
+ },
+ modalSetDraggable: function()
+ {
+ if (typeof $.fn.draggable !== 'undefined')
{
- $redactorModal.css({
- position: 'fixed',
- width: '100%',
- height: '100%',
- top: '0',
- left: '0',
- margin: '0',
- minHeight: '300px'
- }).show();
+ this.$redactorModal.draggable({ handle: '#redactor_modal_header' });
+ this.$redactorModal.find('#redactor_modal_header').css('cursor', 'move');
}
+ },
+ modalLoadTabs: function()
+ {
+ var $redactor_tabs = $('#redactor_tabs');
+ if (!$redactor_tabs.length) return false;
- // modal actions callback
- if (typeof callback === 'function')
+ var that = this;
+ $redactor_tabs.find('a').each(function(i, s)
{
- callback();
- }
+ i++;
+ $(s).on('click', function(e)
+ {
+ e.preventDefault();
- // modal shown callback
- setTimeout($.proxy(function()
- {
- this.callback('modalOpened');
+ $redactor_tabs.find('a').removeClass('redactor_tabs_act');
+ $(this).addClass('redactor_tabs_act');
+ $('.redactor_tab').hide();
+ $('#redactor_tab' + i ).show();
+ $('#redactor_tab_selected').val(i);
- }, this), 11);
+ if (that.isMobile() === false)
+ {
+ var height = that.$redactorModal.outerHeight();
+ that.$redactorModal.css('margin-top', '-' + (height + 10) / 2 + 'px');
+ }
+ });
+ });
- // fix bootstrap modal focus
- $(document).off('focusin.modal');
-
- if (this.isMobile() === false)
+ },
+ modalCloseHandler: function(e)
+ {
+ if (e.keyCode === this.keyCode.ESC)
{
- setTimeout(function()
- {
- var height = $redactorModal.outerHeight();
- $redactorModal.css({
- top: '50%',
- height: 'auto',
- minHeight: 'auto',
- marginTop: '-' + (height + 10) / 2 + 'px'
- });
- }, 10);
+ this.modalClose();
+ return false;
}
-
- $redactorModal.find('input[type=text]').keypress(function(e)
- {
- if (e.which === 13 )
- {
- $redactorModal.find('.redactor_modal_action_btn').click();
- e.preventDefault();
- }
- });
-
},
modalClose: function()
{
$('#redactor_modal_close').off('click', this.modalClose);
$('#redactor_modal').fadeOut('fast', $.proxy(function()
@@ -7096,12 +7556,12 @@
if (this.opts.modalOverlay)
{
$('#redactor_modal_overlay').hide().off('click', this.modalClose);
}
- $(document).unbind('keyup', this.hdlModalClose);
- this.$editor.unbind('keyup', this.hdlModalClose);
+ $(document).off('keyup', this.modalCloseHandler);
+ this.$editor.off('keyup', this.modalCloseHandler);
this.selectionRestore();
// restore scroll
if (this.opts.autoresize && this.saveModalScroll)
@@ -7159,15 +7619,16 @@
xhr.open('GET', this.opts.s3 + mark + 'name=' + file.name + '&type=' + file.type, true);
// Hack to pass bytes through unprocessed.
if (xhr.overrideMimeType) xhr.overrideMimeType('text/plain; charset=x-user-defined');
+ var that = this;
xhr.onreadystatechange = function(e)
{
if (this.readyState == 4 && this.status == 200)
{
- $('#redactor-progress').fadeIn();
+ that.showProgressBar();
callback(decodeURIComponent(this.responseText));
}
else if(this.readyState == 4 && this.status != 200)
{
//setProgress(0, 'Could not contact signing script. Status = ' + this.status);
@@ -7208,11 +7669,11 @@
{
if (xhr.status == 200)
{
//setProgress(100, 'Upload completed.');
- $('#redactor-progress, #redactor-progress-drag').hide();
+ this.hideProgressBar();
var s3image = url.split('?');
if (!s3image[0])
{
@@ -7318,11 +7779,11 @@
$('#' + this.uploadOptions.trigger).click($.proxy(this.uploadSubmit, this));
}
},
uploadSubmit: function(e)
{
- $('#redactor-progress').fadeIn();
+ this.showProgressBar();
this.uploadForm(this.element, this.uploadFrame());
},
uploadFrame: function()
{
this.id = 'f' + Math.floor(Math.random() * 99999);
@@ -7399,11 +7860,11 @@
else d = window.frames[this.id].document;
// Success
if (this.uploadOptions.success)
{
- $('#redactor-progress').hide();
+ this.hideProgressBar();
if (typeof d !== 'undefined')
{
// Remove bizarre <pre> tag wrappers around our json data:
var rawString = d.body.innerHTML;
@@ -7475,16 +7936,16 @@
this.dropareabox.get(0).ondrop = $.proxy(function(e)
{
e.preventDefault();
this.dropareabox.removeClass('hover').addClass('drop');
+ this.showProgressBar();
+ this.dragUploadAjax(this.draguploadOptions.url, e.dataTransfer.files[0], false, e, this.draguploadOptions.uploadParam);
- this.dragUploadAjax(this.draguploadOptions.url, e.dataTransfer.files[0], false, false, false, this.draguploadOptions.uploadParam);
-
}, this );
},
- dragUploadAjax: function(url, file, directupload, progress, e, uploadParam)
+ dragUploadAjax: function(url, file, directupload, e, uploadParam)
{
if (!directupload)
{
var xhr = $.ajaxSettings.xhr();
if (xhr.upload)
@@ -7536,17 +7997,14 @@
data = data.replace(/^\[/, '');
data = data.replace(/\]$/, '');
var json = (typeof data === 'string' ? $.parseJSON(data) : data);
+ this.hideProgressBar();
+
if (directupload)
{
- progress.fadeOut('slow', function()
- {
- $(this).remove();
- });
-
var $img = $('<img>');
$img.attr('src', json.filelink).attr('id', 'drag-image-marker');
this.insertNodeToCaretPositionFromPoint(e, $img[0]);
@@ -7629,10 +8087,25 @@
html = html.replace(/\s/g, '');
html = html.replace(/^<p>[^\W\w\D\d]*?<\/p>$/i, '');
return html == '';
},
+ getInternetExplorerVersion: function()
+ {
+ var rv = false;
+ if (navigator.appName == 'Microsoft Internet Explorer')
+ {
+ var ua = navigator.userAgent;
+ var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
+ if (re.exec(ua) != null)
+ {
+ rv = parseFloat(RegExp.$1);
+ }
+ }
+
+ return rv;
+ },
isIe11: function()
{
return !!navigator.userAgent.match(/Trident\/7\./);
},
browser: function(browser)
@@ -7743,15 +8216,13 @@
Redactor.prototype.init.prototype = Redactor.prototype;
// LINKIFY
$.Redactor.fn.formatLinkify = function(protocol, convertLinks, convertImageLinks, convertVideoLinks, linkSize)
{
- var url1 = /(^|<|\s)(www\..+?\..+?)([.),]?)(\s|\.\s+|\)|>|$)/,
- url2 = /(^|<|\s)(((https?|ftp):\/\/|mailto:).+?)([.),]?)(\s|\.\s+|\)|>|$)/,
- urlImage = /(https?:\/\/.*\.(?:png|jpg|jpeg|gif))/gi,
- urlYoutube = /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube\.com\S*[^\w\-\s])([\w\-]{11})(?=[^\w\-]|$)(?![?=&+%\w.-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig,
- urlVimeo = /https?:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/;
+ var url = /(((https?|ftps?):\/\/)|www[.][^\s])(.+?\..+?)([.),]?)(\s|\.\s+|\)|$)/gi,
+ rProtocol = /(https?|ftp):\/\//i,
+ urlImage = /(https?:\/\/.*\.(?:png|jpg|jpeg|gif))/gi;
var childNodes = (this.$editor ? this.$editor.get(0) : this).childNodes, i = childNodes.length;
while (i--)
{
var n = childNodes[i];
@@ -7763,18 +8234,18 @@
if (convertVideoLinks && html)
{
var iframeStart = '<iframe width="500" height="281" src="',
iframeEnd = '" frameborder="0" allowfullscreen></iframe>';
- if (html.match(urlYoutube))
+ if (html.match(reUrlYoutube))
{
- html = html.replace(urlYoutube, iframeStart + '//www.youtube.com/embed/$1' + iframeEnd);
+ html = html.replace(reUrlYoutube, iframeStart + '//www.youtube.com/embed/$1' + iframeEnd);
$(n).after(html).remove();
}
- else if (html.match(urlVimeo))
+ else if (html.match(reUrlVimeo))
{
- html = html.replace(urlVimeo, iframeStart + '//player.vimeo.com/video/$2' + iframeEnd);
+ html = html.replace(reUrlVimeo, iframeStart + '//player.vimeo.com/video/$2' + iframeEnd);
$(n).after(html).remove();
}
}
// image
@@ -7784,77 +8255,35 @@
$(n).after(html).remove();
}
// link
- if (convertLinks && html && (html.match(url1) || html.match(url2)))
+ if (convertLinks && html && html.match(url))
{
- var found = true;
- var first = true;
+ var matches = html.match(url);
- while (found)
+ for (var i in matches)
{
- var href;
- var url = url1;
- var href1 = url1.exec(html);
- var href2 = url2.exec(html);
+ var href = matches[i];
+ var text = href;
- if (href1 && href1[2] && href2 && href2[2])
- {
- //process whichever came first sequentially *first*
- var index1 = html.indexOf(href1[2]);
- var index2 = html.indexOf(href2[2]);
- if (index1 < index2)
- {
- href = href1;
- url = url1;
- }
- else
- {
- href = href2;
- url = url2
- }
- }
- else if (href1 && href1[2])
- {
- href = href1;
- url = url1
- }
- else if (href2 && href2[2])
- {
- href = href2;
- url = url2
- }
+ var space = '';
+ if (href.match(/\s$/) !== null) space = ' ';
- found = (href && href.length);
- if (found)
- {
- href = href[2];
- }
+ var addProtocol = protocol;
+ if (href.match(rProtocol) !== null) addProtocol = '';
- if (found && href && href.length > linkSize)
- {
- href = href.substring(0, linkSize) + '...';
- }
+ if (text.length > linkSize) text = text.substring(0, linkSize) + '...';
- if (first)
- {
- html = html.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
- }
+ text = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
- if (found && href)
- {
- if (url == url1)
- {
- html = html.replace(url1, '$1<a href="' + protocol + '$2">' + $.trim(href) + '</a>$3$4')
- }
- else
- {
- html = html.replace(url2, '$1<a href="$2">' + $.trim(href) + '</a>$5$6');
- }
- }
+ /*
+ To handle URLs which may have $ characters in them, need to escape $ -> $$ to prevent $1 from getting treated as a backreference.
+ See http://gotofritz.net/blog/code-snippets/escaping-in-replace-strings-in-javascript/
+ */
+ var escapedBackReferences = text.replace('$', '$$$');
- first = false;
+ html = html.replace(href, '<a href=\"' + addProtocol + $.trim(href) + '\">' + $.trim(escapedBackReferences) + '</a>' + space);
}
$(n).after(html).remove();
}
}
\ No newline at end of file