processmaker-builder
Version:
The gulp task runner for ProcessMaker building
1,976 lines (1,545 loc) • 524 kB
JavaScript
// FILE IS GENERATED BY COMBINING THE SOURCES IN THE "classes" DIRECTORY SO DON'T MODIFY THIS FILE DIRECTLY
(function(win) {
var whiteSpaceRe = /^\s*|\s*$/g,
undef, isRegExpBroken = 'B'.replace(/A(.)|B/, '$1') === '$1';
var tinymce = {
majorVersion : '3',
minorVersion : '5.7',
releaseDate : '2012-09-20',
_init : function() {
var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
t.isOpera = win.opera && opera.buildNumber;
t.isWebKit = /WebKit/.test(ua);
t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName);
t.isIE6 = t.isIE && /MSIE [56]/.test(ua);
t.isIE7 = t.isIE && /MSIE [7]/.test(ua);
t.isIE8 = t.isIE && /MSIE [8]/.test(ua);
t.isIE9 = t.isIE && /MSIE [9]/.test(ua);
t.isGecko = !t.isWebKit && /Gecko/.test(ua);
t.isMac = ua.indexOf('Mac') != -1;
t.isAir = /adobeair/i.test(ua);
t.isIDevice = /(iPad|iPhone)/.test(ua);
t.isIOS5 = t.isIDevice && ua.match(/AppleWebKit\/(\d*)/)[1]>=534;
// TinyMCE .NET webcontrol might be setting the values for TinyMCE
if (win.tinyMCEPreInit) {
t.suffix = tinyMCEPreInit.suffix;
t.baseURL = tinyMCEPreInit.base;
t.query = tinyMCEPreInit.query;
return;
}
// Get suffix and base
t.suffix = '';
// If base element found, add that infront of baseURL
nl = d.getElementsByTagName('base');
for (i=0; i<nl.length; i++) {
v = nl[i].href;
if (v) {
// Host only value like http://site.com or http://site.com:8008
if (/^https?:\/\/[^\/]+$/.test(v))
v += '/';
base = v ? v.match(/.*\//)[0] : ''; // Get only directory
}
}
function getBase(n) {
if (n.src && /tiny_mce(|_gzip|_jquery|_prototype|_full)(_dev|_src)?.js/.test(n.src)) {
if (/_(src|dev)\.js/g.test(n.src))
t.suffix = '_src';
if ((p = n.src.indexOf('?')) != -1)
t.query = n.src.substring(p + 1);
t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));
// If path to script is relative and a base href was found add that one infront
// the src property will always be an absolute one on non IE browsers and IE 8
// so this logic will basically only be executed on older IE versions
if (base && t.baseURL.indexOf('://') == -1 && t.baseURL.indexOf('/') !== 0)
t.baseURL = base + t.baseURL;
return t.baseURL;
}
return null;
};
// Check document
nl = d.getElementsByTagName('script');
for (i=0; i<nl.length; i++) {
if (getBase(nl[i]))
return;
}
// Check head
n = d.getElementsByTagName('head')[0];
if (n) {
nl = n.getElementsByTagName('script');
for (i=0; i<nl.length; i++) {
if (getBase(nl[i]))
return;
}
}
return;
},
is : function(o, t) {
if (!t)
return o !== undef;
if (t == 'array' && tinymce.isArray(o))
return true;
return typeof(o) == t;
},
isArray: Array.isArray || function(obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
},
makeMap : function(items, delim, map) {
var i;
items = items || [];
delim = delim || ',';
if (typeof(items) == "string")
items = items.split(delim);
map = map || {};
i = items.length;
while (i--)
map[items[i]] = {};
return map;
},
each : function(o, cb, s) {
var n, l;
if (!o)
return 0;
s = s || o;
if (o.length !== undef) {
// Indexed arrays, needed for Safari
for (n=0, l = o.length; n < l; n++) {
if (cb.call(s, o[n], n, o) === false)
return 0;
}
} else {
// Hashtables
for (n in o) {
if (o.hasOwnProperty(n)) {
if (cb.call(s, o[n], n, o) === false)
return 0;
}
}
}
return 1;
},
map : function(a, f) {
var o = [];
tinymce.each(a, function(v) {
o.push(f(v));
});
return o;
},
grep : function(a, f) {
var o = [];
tinymce.each(a, function(v) {
if (!f || f(v))
o.push(v);
});
return o;
},
inArray : function(a, v) {
var i, l;
if (a) {
for (i = 0, l = a.length; i < l; i++) {
if (a[i] === v)
return i;
}
}
return -1;
},
extend : function(obj, ext) {
var i, l, name, args = arguments, value;
for (i = 1, l = args.length; i < l; i++) {
ext = args[i];
for (name in ext) {
if (ext.hasOwnProperty(name)) {
value = ext[name];
if (value !== undef) {
obj[name] = value;
}
}
}
}
return obj;
},
trim : function(s) {
return (s ? '' + s : '').replace(whiteSpaceRe, '');
},
create : function(s, p, root) {
var t = this, sp, ns, cn, scn, c, de = 0;
// Parse : <prefix> <class>:<super class>
s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name
// Create namespace for new class
ns = t.createNS(s[3].replace(/\.\w+$/, ''), root);
// Class already exists
if (ns[cn])
return;
// Make pure static class
if (s[2] == 'static') {
ns[cn] = p;
if (this.onCreate)
this.onCreate(s[2], s[3], ns[cn]);
return;
}
// Create default constructor
if (!p[cn]) {
p[cn] = function() {};
de = 1;
}
// Add constructor and methods
ns[cn] = p[cn];
t.extend(ns[cn].prototype, p);
// Extend
if (s[5]) {
sp = t.resolve(s[5]).prototype;
scn = s[5].match(/\.(\w+)$/i)[1]; // Class name
// Extend constructor
c = ns[cn];
if (de) {
// Add passthrough constructor
ns[cn] = function() {
return sp[scn].apply(this, arguments);
};
} else {
// Add inherit constructor
ns[cn] = function() {
this.parent = sp[scn];
return c.apply(this, arguments);
};
}
ns[cn].prototype[cn] = ns[cn];
// Add super methods
t.each(sp, function(f, n) {
ns[cn].prototype[n] = sp[n];
});
// Add overridden methods
t.each(p, function(f, n) {
// Extend methods if needed
if (sp[n]) {
ns[cn].prototype[n] = function() {
this.parent = sp[n];
return f.apply(this, arguments);
};
} else {
if (n != cn)
ns[cn].prototype[n] = f;
}
});
}
// Add static methods
t.each(p['static'], function(f, n) {
ns[cn][n] = f;
});
if (this.onCreate)
this.onCreate(s[2], s[3], ns[cn].prototype);
},
walk : function(o, f, n, s) {
s = s || this;
if (o) {
if (n)
o = o[n];
tinymce.each(o, function(o, i) {
if (f.call(s, o, i, n) === false)
return false;
tinymce.walk(o, f, n, s);
});
}
},
createNS : function(n, o) {
var i, v;
o = o || win;
n = n.split('.');
for (i=0; i<n.length; i++) {
v = n[i];
if (!o[v])
o[v] = {};
o = o[v];
}
return o;
},
resolve : function(n, o) {
var i, l;
o = o || win;
n = n.split('.');
for (i = 0, l = n.length; i < l; i++) {
o = o[n[i]];
if (!o)
break;
}
return o;
},
addUnload : function(f, s) {
var t = this, unload;
unload = function() {
var li = t.unloads, o, n;
if (li) {
// Call unload handlers
for (n in li) {
o = li[n];
if (o && o.func)
o.func.call(o.scope, 1); // Send in one arg to distinct unload and user destroy
}
// Detach unload function
if (win.detachEvent) {
win.detachEvent('onbeforeunload', fakeUnload);
win.detachEvent('onunload', unload);
} else if (win.removeEventListener)
win.removeEventListener('unload', unload, false);
// Destroy references
t.unloads = o = li = w = unload = 0;
// Run garbarge collector on IE
if (win.CollectGarbage)
CollectGarbage();
}
};
function fakeUnload() {
var d = document;
function stop() {
// Prevent memory leak
d.detachEvent('onstop', stop);
// Call unload handler
if (unload)
unload();
d = 0;
};
// Is there things still loading, then do some magic
if (d.readyState == 'interactive') {
// Fire unload when the currently loading page is stopped
if (d)
d.attachEvent('onstop', stop);
// Remove onstop listener after a while to prevent the unload function
// to execute if the user presses cancel in an onbeforeunload
// confirm dialog and then presses the browser stop button
win.setTimeout(function() {
if (d)
d.detachEvent('onstop', stop);
}, 0);
}
};
f = {func : f, scope : s || this};
if (!t.unloads) {
// Attach unload handler
if (win.attachEvent) {
win.attachEvent('onunload', unload);
win.attachEvent('onbeforeunload', fakeUnload);
} else if (win.addEventListener)
win.addEventListener('unload', unload, false);
// Setup initial unload handler array
t.unloads = [f];
} else
t.unloads.push(f);
return f;
},
removeUnload : function(f) {
var u = this.unloads, r = null;
tinymce.each(u, function(o, i) {
if (o && o.func == f) {
u.splice(i, 1);
r = f;
return false;
}
});
return r;
},
explode : function(s, d) {
if (!s || tinymce.is(s, 'array')) {
return s;
}
return tinymce.map(s.split(d || ','), tinymce.trim);
},
_addVer : function(u) {
var v;
if (!this.query)
return u;
v = (u.indexOf('?') == -1 ? '?' : '&') + this.query;
if (u.indexOf('#') == -1)
return u + v;
return u.replace('#', v + '#');
},
// Fix function for IE 9 where regexps isn't working correctly
// Todo: remove me once MS fixes the bug
_replace : function(find, replace, str) {
// On IE9 we have to fake $x replacement
if (isRegExpBroken) {
return str.replace(find, function() {
var val = replace, args = arguments, i;
for (i = 0; i < args.length - 2; i++) {
if (args[i] === undef) {
val = val.replace(new RegExp('\\$' + i, 'g'), '');
} else {
val = val.replace(new RegExp('\\$' + i, 'g'), args[i]);
}
}
return val;
});
}
return str.replace(find, replace);
}
};
// Initialize the API
tinymce._init();
// Expose tinymce namespace to the global namespace (window)
win.tinymce = win.tinyMCE = tinymce;
// Describe the different namespaces
})(window);
tinymce.create('tinymce.util.Dispatcher', {
scope : null,
listeners : null,
inDispatch: false,
Dispatcher : function(scope) {
this.scope = scope || this;
this.listeners = [];
},
add : function(callback, scope) {
this.listeners.push({cb : callback, scope : scope || this.scope});
return callback;
},
addToTop : function(callback, scope) {
var self = this, listener = {cb : callback, scope : scope || self.scope};
// Create new listeners if addToTop is executed in a dispatch loop
if (self.inDispatch) {
self.listeners = [listener].concat(self.listeners);
} else {
self.listeners.unshift(listener);
}
return callback;
},
remove : function(callback) {
var listeners = this.listeners, output = null;
tinymce.each(listeners, function(listener, i) {
if (callback == listener.cb) {
output = listener;
listeners.splice(i, 1);
return false;
}
});
return output;
},
dispatch : function() {
var self = this, returnValue, args = arguments, i, listeners = self.listeners, listener;
self.inDispatch = true;
// Needs to be a real loop since the listener count might change while looping
// And this is also more efficient
for (i = 0; i < listeners.length; i++) {
listener = listeners[i];
returnValue = listener.cb.apply(listener.scope, args.length > 0 ? args : [listener.scope]);
if (returnValue === false)
break;
}
self.inDispatch = false;
return returnValue;
}
});
(function() {
var each = tinymce.each;
tinymce.create('tinymce.util.URI', {
URI : function(u, s) {
var t = this, o, a, b, base_url;
// Trim whitespace
u = tinymce.trim(u);
// Default settings
s = t.settings = s || {};
// Strange app protocol that isn't http/https or local anchor
// For example: mailto,skype,tel etc.
if (/^([\w\-]+):([^\/]{2})/i.test(u) || /^\s*#/.test(u)) {
t.source = u;
return;
}
// Absolute path with no host, fake host and protocol
if (u.indexOf('/') === 0 && u.indexOf('//') !== 0)
u = (s.base_uri ? s.base_uri.protocol || 'http' : 'http') + '://mce_host' + u;
// Relative path http:// or protocol relative //path
if (!/^[\w\-]*:?\/\//.test(u)) {
base_url = s.base_uri ? s.base_uri.path : new tinymce.util.URI(location.href).directory;
u = ((s.base_uri && s.base_uri.protocol) || 'http') + '://mce_host' + t.toAbsPath(base_url, u);
}
// Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)
u = u.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something
u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u);
each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) {
var s = u[i];
// Zope 3 workaround, they use @@something
if (s)
s = s.replace(/\(mce_at\)/g, '@@');
t[v] = s;
});
b = s.base_uri;
if (b) {
if (!t.protocol)
t.protocol = b.protocol;
if (!t.userInfo)
t.userInfo = b.userInfo;
if (!t.port && t.host === 'mce_host')
t.port = b.port;
if (!t.host || t.host === 'mce_host')
t.host = b.host;
t.source = '';
}
//t.path = t.path || '/';
},
setPath : function(p) {
var t = this;
p = /^(.*?)\/?(\w+)?$/.exec(p);
// Update path parts
t.path = p[0];
t.directory = p[1];
t.file = p[2];
// Rebuild source
t.source = '';
t.getURI();
},
toRelative : function(u) {
var t = this, o;
if (u === "./")
return u;
u = new tinymce.util.URI(u, {base_uri : t});
// Not on same domain/port or protocol
if ((u.host != 'mce_host' && t.host != u.host && u.host) || t.port != u.port || t.protocol != u.protocol)
return u.getURI();
var tu = t.getURI(), uu = u.getURI();
// Allow usage of the base_uri when relative_urls = true
if(tu == uu || (tu.charAt(tu.length - 1) == "/" && tu.substr(0, tu.length - 1) == uu))
return tu;
o = t.toRelPath(t.path, u.path);
// Add query
if (u.query)
o += '?' + u.query;
// Add anchor
if (u.anchor)
o += '#' + u.anchor;
return o;
},
toAbsolute : function(u, nh) {
u = new tinymce.util.URI(u, {base_uri : this});
return u.getURI(this.host == u.host && this.protocol == u.protocol ? nh : 0);
},
toRelPath : function(base, path) {
var items, bp = 0, out = '', i, l;
// Split the paths
base = base.substring(0, base.lastIndexOf('/'));
base = base.split('/');
items = path.split('/');
if (base.length >= items.length) {
for (i = 0, l = base.length; i < l; i++) {
if (i >= items.length || base[i] != items[i]) {
bp = i + 1;
break;
}
}
}
if (base.length < items.length) {
for (i = 0, l = items.length; i < l; i++) {
if (i >= base.length || base[i] != items[i]) {
bp = i + 1;
break;
}
}
}
if (bp === 1)
return path;
for (i = 0, l = base.length - (bp - 1); i < l; i++)
out += "../";
for (i = bp - 1, l = items.length; i < l; i++) {
if (i != bp - 1)
out += "/" + items[i];
else
out += items[i];
}
return out;
},
toAbsPath : function(base, path) {
var i, nb = 0, o = [], tr, outPath;
// Split paths
tr = /\/$/.test(path) ? '/' : '';
base = base.split('/');
path = path.split('/');
// Remove empty chunks
each(base, function(k) {
if (k)
o.push(k);
});
base = o;
// Merge relURLParts chunks
for (i = path.length - 1, o = []; i >= 0; i--) {
// Ignore empty or .
if (path[i].length === 0 || path[i] === ".")
continue;
// Is parent
if (path[i] === '..') {
nb++;
continue;
}
// Move up
if (nb > 0) {
nb--;
continue;
}
o.push(path[i]);
}
i = base.length - nb;
// If /a/b/c or /
if (i <= 0)
outPath = o.reverse().join('/');
else
outPath = base.slice(0, i).join('/') + '/' + o.reverse().join('/');
// Add front / if it's needed
if (outPath.indexOf('/') !== 0)
outPath = '/' + outPath;
// Add traling / if it's needed
if (tr && outPath.lastIndexOf('/') !== outPath.length - 1)
outPath += tr;
return outPath;
},
getURI : function(nh) {
var s, t = this;
// Rebuild source
if (!t.source || nh) {
s = '';
if (!nh) {
if (t.protocol)
s += t.protocol + '://';
if (t.userInfo)
s += t.userInfo + '@';
if (t.host)
s += t.host;
if (t.port)
s += ':' + t.port;
}
if (t.path)
s += t.path;
if (t.query)
s += '?' + t.query;
if (t.anchor)
s += '#' + t.anchor;
t.source = s;
}
return t.source;
}
});
})();
(function() {
var each = tinymce.each;
tinymce.create('static tinymce.util.Cookie', {
getHash : function(n) {
var v = this.get(n), h;
if (v) {
each(v.split('&'), function(v) {
v = v.split('=');
h = h || {};
h[unescape(v[0])] = unescape(v[1]);
});
}
return h;
},
setHash : function(n, v, e, p, d, s) {
var o = '';
each(v, function(v, k) {
o += (!o ? '' : '&') + escape(k) + '=' + escape(v);
});
this.set(n, o, e, p, d, s);
},
get : function(n) {
var c = document.cookie, e, p = n + "=", b;
// Strict mode
if (!c)
return;
b = c.indexOf("; " + p);
if (b == -1) {
b = c.indexOf(p);
if (b !== 0)
return null;
} else
b += 2;
e = c.indexOf(";", b);
if (e == -1)
e = c.length;
return unescape(c.substring(b + p.length, e));
},
set : function(n, v, e, p, d, s) {
document.cookie = n + "=" + escape(v) +
((e) ? "; expires=" + e.toGMTString() : "") +
((p) ? "; path=" + escape(p) : "") +
((d) ? "; domain=" + d : "") +
((s) ? "; secure" : "");
},
remove : function(name, path, domain) {
var date = new Date();
date.setTime(date.getTime() - 1000);
this.set(name, '', date, path, domain);
}
});
})();
(function() {
function serialize(o, quote) {
var i, v, t, name;
quote = quote || '"';
if (o == null)
return 'null';
t = typeof o;
if (t == 'string') {
v = '\bb\tt\nn\ff\rr\""\'\'\\\\';
return quote + o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g, function(a, b) {
// Make sure single quotes never get encoded inside double quotes for JSON compatibility
if (quote === '"' && a === "'")
return a;
i = v.indexOf(b);
if (i + 1)
return '\\' + v.charAt(i + 1);
a = b.charCodeAt().toString(16);
return '\\u' + '0000'.substring(a.length) + a;
}) + quote;
}
if (t == 'object') {
if (o.hasOwnProperty && Object.prototype.toString.call(o) === '[object Array]') {
for (i=0, v = '['; i<o.length; i++)
v += (i > 0 ? ',' : '') + serialize(o[i], quote);
return v + ']';
}
v = '{';
for (name in o) {
if (o.hasOwnProperty(name)) {
v += typeof o[name] != 'function' ? (v.length > 1 ? ',' + quote : quote) + name + quote +':' + serialize(o[name], quote) : '';
}
}
return v + '}';
}
return '' + o;
};
tinymce.util.JSON = {
serialize: serialize,
parse: function(s) {
try {
return eval('(' + s + ')');
} catch (ex) {
// Ignore
}
}
};
})();
tinymce.create('static tinymce.util.XHR', {
send : function(o) {
var x, t, w = window, c = 0;
function ready() {
if (!o.async || x.readyState == 4 || c++ > 10000) {
if (o.success && c < 10000 && x.status == 200)
o.success.call(o.success_scope, '' + x.responseText, x, o);
else if (o.error)
o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o);
x = null;
} else
w.setTimeout(ready, 10);
};
// Default settings
o.scope = o.scope || this;
o.success_scope = o.success_scope || o.scope;
o.error_scope = o.error_scope || o.scope;
o.async = o.async === false ? false : true;
o.data = o.data || '';
function get(s) {
x = 0;
try {
x = new ActiveXObject(s);
} catch (ex) {
}
return x;
};
x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Microsoft.XMLHTTP') || get('Msxml2.XMLHTTP');
if (x) {
if (x.overrideMimeType)
x.overrideMimeType(o.content_type);
x.open(o.type || (o.data ? 'POST' : 'GET'), o.url, o.async);
if (o.content_type)
x.setRequestHeader('Content-Type', o.content_type);
x.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
x.send(o.data);
// Syncronous request
if (!o.async)
return ready();
// Wait for response, onReadyStateChange can not be used since it leaks memory in IE
t = w.setTimeout(ready, 10);
}
}
});
(function() {
var extend = tinymce.extend, JSON = tinymce.util.JSON, XHR = tinymce.util.XHR;
tinymce.create('tinymce.util.JSONRequest', {
JSONRequest : function(s) {
this.settings = extend({
}, s);
this.count = 0;
},
send : function(o) {
var ecb = o.error, scb = o.success;
o = extend(this.settings, o);
o.success = function(c, x) {
c = JSON.parse(c);
if (typeof(c) == 'undefined') {
c = {
error : 'JSON Parse error.'
};
}
if (c.error)
ecb.call(o.error_scope || o.scope, c.error, x);
else
scb.call(o.success_scope || o.scope, c.result);
};
o.error = function(ty, x) {
if (ecb)
ecb.call(o.error_scope || o.scope, ty, x);
};
o.data = JSON.serialize({
id : o.id || 'c' + (this.count++),
method : o.method,
params : o.params
});
// JSON content type for Ruby on rails. Bug: #1883287
o.content_type = 'application/json';
XHR.send(o);
},
'static' : {
sendRPC : function(o) {
return new tinymce.util.JSONRequest().send(o);
}
}
});
}());
(function(tinymce){
tinymce.VK = {
BACKSPACE: 8,
DELETE: 46,
DOWN: 40,
ENTER: 13,
LEFT: 37,
RIGHT: 39,
SPACEBAR: 32,
TAB: 9,
UP: 38,
modifierPressed: function (e) {
return e.shiftKey || e.ctrlKey || e.altKey;
},
metaKeyPressed: function(e) {
// Check if ctrl or meta key is pressed also check if alt is false for Polish users
return tinymce.isMac ? e.metaKey : e.ctrlKey && !e.altKey;
}
};
})(tinymce);
tinymce.util.Quirks = function(editor) {
var VK = tinymce.VK, BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection,
settings = editor.settings, parser = editor.parser, serializer = editor.serializer;
function setEditorCommandState(cmd, state) {
try {
editor.getDoc().execCommand(cmd, false, state);
} catch (ex) {
// Ignore
}
}
function getDocumentMode() {
var documentMode = editor.getDoc().documentMode;
return documentMode ? documentMode : 6;
};
function isDefaultPrevented(e) {
return e.isDefaultPrevented();
};
function cleanupStylesWhenDeleting() {
function removeMergedFormatSpans(isDelete) {
var rng, blockElm, node, clonedSpan;
rng = selection.getRng();
// Find root block
blockElm = dom.getParent(rng.startContainer, dom.isBlock);
// On delete clone the root span of the next block element
if (isDelete)
blockElm = dom.getNext(blockElm, dom.isBlock);
// Locate root span element and clone it since it would otherwise get merged by the "apple-style-span" on delete/backspace
if (blockElm) {
node = blockElm.firstChild;
// Ignore empty text nodes
while (node && node.nodeType == 3 && node.nodeValue.length === 0)
node = node.nextSibling;
if (node && node.nodeName === 'SPAN') {
clonedSpan = node.cloneNode(false);
}
}
// Do the backspace/delete action
editor.getDoc().execCommand(isDelete ? 'ForwardDelete' : 'Delete', false, null);
// Find all odd apple-style-spans
blockElm = dom.getParent(rng.startContainer, dom.isBlock);
tinymce.each(dom.select('span.Apple-style-span,font.Apple-style-span', blockElm), function(span) {
var bm = selection.getBookmark();
if (clonedSpan) {
dom.replace(clonedSpan.cloneNode(false), span, true);
} else {
dom.remove(span, true);
}
// Restore the selection
selection.moveToBookmark(bm);
});
};
editor.onKeyDown.add(function(editor, e) {
var isDelete;
isDelete = e.keyCode == DELETE;
if (!isDefaultPrevented(e) && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
e.preventDefault();
removeMergedFormatSpans(isDelete);
}
});
editor.addCommand('Delete', function() {removeMergedFormatSpans();});
};
function emptyEditorWhenDeleting() {
function serializeRng(rng) {
var body = dom.create("body");
var contents = rng.cloneContents();
body.appendChild(contents);
return selection.serializer.serialize(body, {format: 'html'});
}
function allContentsSelected(rng) {
var selection = serializeRng(rng);
var allRng = dom.createRng();
allRng.selectNode(editor.getBody());
var allSelection = serializeRng(allRng);
return selection === allSelection;
}
editor.onKeyDown.add(function(editor, e) {
var keyCode = e.keyCode, isCollapsed;
// Empty the editor if it's needed for example backspace at <p><b>|</b></p>
if (!isDefaultPrevented(e) && (keyCode == DELETE || keyCode == BACKSPACE)) {
isCollapsed = editor.selection.isCollapsed();
// Selection is collapsed but the editor isn't empty
if (isCollapsed && !dom.isEmpty(editor.getBody())) {
return;
}
// IE deletes all contents correctly when everything is selected
if (tinymce.isIE && !isCollapsed) {
return;
}
// Selection isn't collapsed but not all the contents is selected
if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) {
return;
}
// Manually empty the editor
editor.setContent('');
editor.selection.setCursorLocation(editor.getBody(), 0);
editor.nodeChanged();
}
});
};
function selectAll() {
editor.onKeyDown.add(function(editor, e) {
if (!isDefaultPrevented(e) && e.keyCode == 65 && VK.metaKeyPressed(e)) {
e.preventDefault();
editor.execCommand('SelectAll');
}
});
};
function inputMethodFocus() {
if (!editor.settings.content_editable) {
// Case 1 IME doesn't initialize if you focus the document
dom.bind(editor.getDoc(), 'focusin', function(e) {
selection.setRng(selection.getRng());
});
// Case 2 IME doesn't initialize if you click the documentElement it also doesn't properly fire the focusin event
dom.bind(editor.getDoc(), 'mousedown', function(e) {
if (e.target == editor.getDoc().documentElement) {
editor.getWin().focus();
selection.setRng(selection.getRng());
}
});
}
};
function removeHrOnBackspace() {
editor.onKeyDown.add(function(editor, e) {
if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {
var node = selection.getNode();
var previousSibling = node.previousSibling;
if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "hr") {
dom.remove(previousSibling);
tinymce.dom.Event.cancel(e);
}
}
}
})
}
function focusBody() {
// Fix for a focus bug in FF 3.x where the body element
// wouldn't get proper focus if the user clicked on the HTML element
if (!Range.prototype.getClientRects) { // Detect getClientRects got introduced in FF 4
editor.onMouseDown.add(function(editor, e) {
if (!isDefaultPrevented(e) && e.target.nodeName === "HTML") {
var body = editor.getBody();
// Blur the body it's focused but not correctly focused
body.blur();
// Refocus the body after a little while
setTimeout(function() {
body.focus();
}, 0);
}
});
}
};
function selectControlElements() {
editor.onClick.add(function(editor, e) {
e = e.target;
// Workaround for bug, http://bugs.webkit.org/show_bug.cgi?id=12250
// WebKit can't even do simple things like selecting an image
// Needs tobe the setBaseAndExtend or it will fail to select floated images
if (/^(IMG|HR)$/.test(e.nodeName)) {
selection.getSel().setBaseAndExtent(e, 0, e, 1);
}
if (e.nodeName == 'A' && dom.hasClass(e, 'mceItemAnchor')) {
selection.select(e);
}
editor.nodeChanged();
});
};
function removeStylesWhenDeletingAccrossBlockElements() {
function getAttributeApplyFunction() {
var template = dom.getAttribs(selection.getStart().cloneNode(false));
return function() {
var target = selection.getStart();
if (target !== editor.getBody()) {
dom.setAttrib(target, "style", null);
tinymce.each(template, function(attr) {
target.setAttributeNode(attr.cloneNode(true));
});
}
};
}
function isSelectionAcrossElements() {
return !selection.isCollapsed() && dom.getParent(selection.getStart(), dom.isBlock) != dom.getParent(selection.getEnd(), dom.isBlock);
}
function blockEvent(editor, e) {
e.preventDefault();
return false;
}
editor.onKeyPress.add(function(editor, e) {
var applyAttributes;
if (!isDefaultPrevented(e) && (e.keyCode == 8 || e.keyCode == 46) && isSelectionAcrossElements()) {
applyAttributes = getAttributeApplyFunction();
editor.getDoc().execCommand('delete', false, null);
applyAttributes();
e.preventDefault();
return false;
}
});
dom.bind(editor.getDoc(), 'cut', function(e) {
var applyAttributes;
if (!isDefaultPrevented(e) && isSelectionAcrossElements()) {
applyAttributes = getAttributeApplyFunction();
editor.onKeyUp.addToTop(blockEvent);
setTimeout(function() {
applyAttributes();
editor.onKeyUp.remove(blockEvent);
}, 0);
}
});
}
function selectionChangeNodeChanged() {
var lastRng, selectionTimer;
dom.bind(editor.getDoc(), 'selectionchange', function() {
if (selectionTimer) {
clearTimeout(selectionTimer);
selectionTimer = 0;
}
selectionTimer = window.setTimeout(function() {
var rng = selection.getRng();
// Compare the ranges to see if it was a real change or not
if (!lastRng || !tinymce.dom.RangeUtils.compareRanges(rng, lastRng)) {
editor.nodeChanged();
lastRng = rng;
}
}, 50);
});
}
function ensureBodyHasRoleApplication() {
document.body.setAttribute("role", "application");
}
function disableBackspaceIntoATable() {
editor.onKeyDown.add(function(editor, e) {
if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {
var previousSibling = selection.getNode().previousSibling;
if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "table") {
return tinymce.dom.Event.cancel(e);
}
}
}
})
}
function addNewLinesBeforeBrInPre() {
// IE8+ rendering mode does the right thing with BR in PRE
if (getDocumentMode() > 7) {
return;
}
// Enable display: none in area and add a specific class that hides all BR elements in PRE to
// avoid the caret from getting stuck at the BR elements while pressing the right arrow key
setEditorCommandState('RespectVisibilityInDesign', true);
editor.contentStyles.push('.mceHideBrInPre pre br {display: none}');
dom.addClass(editor.getBody(), 'mceHideBrInPre');
// Adds a \n before all BR elements in PRE to get them visual
parser.addNodeFilter('pre', function(nodes, name) {
var i = nodes.length, brNodes, j, brElm, sibling;
while (i--) {
brNodes = nodes[i].getAll('br');
j = brNodes.length;
while (j--) {
brElm = brNodes[j];
// Add \n before BR in PRE elements on older IE:s so the new lines get rendered
sibling = brElm.prev;
if (sibling && sibling.type === 3 && sibling.value.charAt(sibling.value - 1) != '\n') {
sibling.value += '\n';
} else {
brElm.parent.insert(new tinymce.html.Node('#text', 3), brElm, true).value = '\n';
}
}
}
});
// Removes any \n before BR elements in PRE since other browsers and in contentEditable=false mode they will be visible
serializer.addNodeFilter('pre', function(nodes, name) {
var i = nodes.length, brNodes, j, brElm, sibling;
while (i--) {
brNodes = nodes[i].getAll('br');
j = brNodes.length;
while (j--) {
brElm = brNodes[j];
sibling = brElm.prev;
if (sibling && sibling.type == 3) {
sibling.value = sibling.value.replace(/\r?\n$/, '');
}
}
}
});
}
function removePreSerializedStylesWhenSelectingControls() {
dom.bind(editor.getBody(), 'mouseup', function(e) {
var value, node = selection.getNode();
// Moved styles to attributes on IMG eements
if (node.nodeName == 'IMG') {
// Convert style width to width attribute
if (value = dom.getStyle(node, 'width')) {
dom.setAttrib(node, 'width', value.replace(/[^0-9%]+/g, ''));
dom.setStyle(node, 'width', '');
}
// Convert style height to height attribute
if (value = dom.getStyle(node, 'height')) {
dom.setAttrib(node, 'height', value.replace(/[^0-9%]+/g, ''));
dom.setStyle(node, 'height', '');
}
}
});
}
function keepInlineElementOnDeleteBackspace() {
editor.onKeyDown.add(function(editor, e) {
var isDelete, rng, container, offset, brElm, sibling, collapsed;
isDelete = e.keyCode == DELETE;
if (!isDefaultPrevented(e) && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
rng = selection.getRng();
container = rng.startContainer;
offset = rng.startOffset;
collapsed = rng.collapsed;
// Override delete if the start container is a text node and is at the beginning of text or
// just before/after the last character to be deleted in collapsed mode
if (container.nodeType == 3 && container.nodeValue.length > 0 && ((offset === 0 && !collapsed) || (collapsed && offset === (isDelete ? 0 : 1)))) {
nonEmptyElements = editor.schema.getNonEmptyElements();
// Prevent default logic since it's broken
e.preventDefault();
// Insert a BR before the text node this will prevent the containing element from being deleted/converted
brElm = dom.create('br', {id: '__tmp'});
container.parentNode.insertBefore(brElm, container);
// Do the browser delete
editor.getDoc().execCommand(isDelete ? 'ForwardDelete' : 'Delete', false, null);
// Check if the previous sibling is empty after deleting for example: <p><b></b>|</p>
container = selection.getRng().startContainer;
sibling = container.previousSibling;
if (sibling && sibling.nodeType == 1 && !dom.isBlock(sibling) && dom.isEmpty(sibling) && !nonEmptyElements[sibling.nodeName.toLowerCase()]) {
dom.remove(sibling);
}
// Remove the temp element we inserted
dom.remove('__tmp');
}
}
});
}
function removeBlockQuoteOnBackSpace() {
// Add block quote deletion handler
editor.onKeyDown.add(function(editor, e) {
var rng, container, offset, root, parent;
if (isDefaultPrevented(e) || e.keyCode != VK.BACKSPACE) {
return;
}
rng = selection.getRng();
container = rng.startContainer;
offset = rng.startOffset;
root = dom.getRoot();
parent = container;
if (!rng.collapsed || offset !== 0) {
return;
}
while (parent && parent.parentNode && parent.parentNode.firstChild == parent && parent.parentNode != root) {
parent = parent.parentNode;
}
// Is the cursor at the beginning of a blockquote?
if (parent.tagName === 'BLOCKQUOTE') {
// Remove the blockquote
editor.formatter.toggle('blockquote', null, parent);
// Move the caret to the beginning of container
rng = dom.createRng();
rng.setStart(container, 0);
rng.setEnd(container, 0);
selection.setRng(rng);
}
});
};
function setGeckoEditingOptions() {
function setOpts() {
editor._refreshContentEditable();
setEditorCommandState("StyleWithCSS", false);
setEditorCommandState("enableInlineTableEditing", false);
if (!settings.object_resizing) {
setEditorCommandState("enableObjectResizing", false);
}
};
if (!settings.readonly) {
editor.onBeforeExecCommand.add(setOpts);
editor.onMouseDown.add(setOpts);
}
};
function addBrAfterLastLinks() {
function fixLinks(editor, o) {
tinymce.each(dom.select('a'), function(node) {
var parentNode = node.parentNode, root = dom.getRoot();
if (parentNode.lastChild === node) {
while (parentNode && !dom.isBlock(parentNode)) {
if (parentNode.parentNode.lastChild !== parentNode || parentNode === root) {
return;
}
parentNode = parentNode.parentNode;
}
dom.add(parentNode, 'br', {'data-mce-bogus' : 1});
}
});
};
editor.onExecCommand.add(function(editor, cmd) {
if (cmd === 'CreateLink') {
fixLinks(editor);
}
});
editor.onSetContent.add(selection.onSetContent.add(fixLinks));
};
function setDefaultBlockType() {
if (settings.forced_root_block) {
editor.onInit.add(function() {
setEditorCommandState('DefaultParagraphSeparator', settings.forced_root_block);
});
}
}
function removeGhostSelection() {
function repaint(sender, args) {
if (!sender || !args.initial) {
editor.execCommand('mceRepaint');
}
};
editor.onUndo.add(repaint);
editor.onRedo.add(repaint);
editor.onSetContent.add(repaint);
};
function deleteControlItemOnBackSpace() {
editor.onKeyDown.add(function(editor, e) {
var rng;
if (!isDefaultPrevented(e) && e.keyCode == BACKSPACE) {
rng = editor.getDoc().selection.createRange();
if (rng && rng.item) {
e.preventDefault();
editor.undoManager.beforeChange();
dom.remove(rng.item(0));
editor.undoManager.add();
}
}
});
};
function renderEmptyBlocksFix() {
var emptyBlocksCSS;
// IE10+
if (getDocumentMode() >= 10) {
emptyBlocksCSS = '';
tinymce.each('p div h1 h2 h3 h4 h5 h6'.split(' '), function(name, i) {
emptyBlocksCSS += (i > 0 ? ',' : '') + name + ':empty';
});
editor.contentStyles.push(emptyBlocksCSS + '{padding-right: 1px !important}');
}
};
function fakeImageResize() {
var selectedElmX, selectedElmY, selectedElm, selectedElmGhost, selectedHandle, startX, startY, startW, startH, ratio,
resizeHandles, width, height, rootDocument = document, editableDoc = editor.getDoc();
if (!settings.object_resizing || settings.webkit_fake_resize === false) {
return;
}
// Try disabling object resizing if WebKit implements resizing in the future
setEditorCommandState("enableObjectResizing", false);
// Details about each resize handle how to scale etc
resizeHandles = {
// Name: x multiplier, y multiplier, delta size x, delta size y
n: [.5, 0, 0, -1],
e: [1, .5, 1, 0],
s: [.5, 1, 0, 1],
w: [0, .5, -1, 0],
nw: [0, 0, -1, -1],
ne: [1, 0, 1, -1],
se: [1, 1, 1, 1],
sw : [0, 1, -1, 1]
};
function resizeElement(e) {
var deltaX, deltaY;
// Calc new width/height
deltaX = e.screenX - startX;
deltaY = e.screenY - startY;
// Calc new size
width = deltaX * selectedHandle[2] + startW;
height = deltaY * selectedHandle[3] + startH;
// Never scale down lower than 5 pixels
width = width < 5 ? 5 : width;
height = height < 5 ? 5 : height;
// Constrain proportions when modifier key is pressed or if the nw, ne, sw, se corners are moved on an image
if (VK.modifierPressed(e) || (selectedElm.nodeName == "IMG" && selectedHandle[2] * selectedHandle[3] !== 0)) {
width = Math.round(height / ratio);
height = Math.round(width * ratio);
}
// Update ghost size
dom.setStyles(selectedElmGhost, {
width: width,
height: height
});
// Update ghost X position if needed
if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) {
dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width));
}
// Update ghost Y position if needed
if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) {
dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height));
}
}
function endResize() {
function setSizeProp(name, value) {
if (value) {
// Resize by using style or attribute
if (selectedElm.style[name] || !editor.schema.isValid(selectedElm.nodeName.toLowerCase(), name)) {
dom.setStyle(selectedElm, name, value);
} else {
dom.setAttrib(selectedElm, name, value);
}
}
}
// Set width/height properties
setSizeProp('width', width);
setSizeProp('height', height);
dom.unbind(editableDoc, 'mousemove', resizeElement);
dom.unbind(editableDoc, 'mouseup', endResize);
if (rootDocument != editableDoc) {
dom.unbind(rootDocument, 'mousemove', resizeElement);
dom.unbind(rootDocument, 'mouseup', endResize);
}
// Remove ghost and update resize handle positions
dom.remove(selectedElmGhost);
showResizeRect(selectedElm);
}
function showResizeRect(targetElm) {
var position, targetWidth, targetHeight;
hideResizeRect();
// Get position and size of target
position = dom.getPos(targetElm);
selectedElmX = position.x;
selectedElmY = position.y;
targetWidth = targetElm.offsetWidth;
targetHeight = targetElm.offsetHeight;
// Reset width/height if user selects a new image/table
if (selectedElm != targetElm) {
selectedElm = targetElm;
width = height = 0;
}
tinymce.each(resizeHandles, function(handle, name) {
var handleElm;
// Get existing or render resize handle
handleElm = dom.get('mceResizeHandle' + name);
if (!handleElm) {
handleElm = dom.add(editableDoc.documentElement, 'div', {
id: 'mceResizeHandle' + name,
'class': 'mceResizeHandle',
style: 'cursor:' + name + '-resize; margin:0; padding:0'
});
dom.bind(handleElm, 'mousedown', function(e) {
e.preventDefault();
endResize();
startX = e.screenX;
startY = e.screenY;
startW = selectedElm.clientWidth;
startH = selectedElm.clientHeight;
ratio = startH / startW;
selectedHandle = handle;
selectedElmGhost = selectedElm.cloneNode(true);
dom.addClass(selectedElmGhost, 'mceClonedResizable');
dom.setStyles(selectedElmGhost, {
left: selectedElmX,
top: selectedElmY,
margin: 0
});
editableDoc.documentElement.appendChild(selectedElmGhost);
dom.bind(editableDoc, 'mousemove', resizeElement);
dom.bind(editableDoc, 'mouseup', endResize);
if (rootDocument != editableDoc) {
dom.bind(rootDocument, 'mousemove', resizeElement);
dom.bind(rootDocument, 'mouseup', endResize);
}
});
} else {
dom.show(handleElm);
}
// Position element
dom.setStyles(handleElm, {
left: (targetWidth * handle[0] + selectedElmX) - (handleElm.offsetWidth / 2),
top: (targetHeight * handle[1] + selectedElmY) - (handleElm.offsetHeight / 2)
});
});
// Only add resize rectangle on WebKit and only on images
if (!tinymce.isOpera && selectedElm.nodeName == "IMG") {
selectedElm.setAttribute('data-mce-selected', '1');
}
}
function hideResizeRect() {
if (selectedElm) {
selectedElm.removeAttribute('data-mce-selected');
}
for (var name in resizeHandles) {
dom.hide('mceResizeHandle' + name);
}
}
// Add CSS for resize handles, cloned element and selected
editor.contentStyles.push(
'.mceResizeHandle {' +
'position: absolute;' +
'border: 1px solid black;' +
'background: #FFF;' +
'width: 5px;' +
'height: 5px;' +
'z-index: 10000' +
'}' +
'.mceResizeHandle:hover {' +
'background: #000' +
'}' +
'img[data-mce-selected] {' +
'outline: 1px solid black' +
'}' +
'img.mceClonedResizable, table.mceClonedResizable {' +
'position: absolute;' +
'outline: 1px dashed black;' +
'opacity: .5;' +
'z-index: 10000' +
'}'
);
function updateResizeRect() {
var controlElm = dom.getParent(selection.getNode(), 'table,img');
// Remove data-mce-selected from all elements since they might have been copied using Ctrl+c/v
tinymce.each(dom.select('img[data-mce-selected]'), function(img) {
img.removeAttribute('data-mce-selected');
});
if (controlElm) {
showResizeRect(controlElm);
} else {
hideResizeRect();
}
}
// Show/hide resize rect when image is selected
editor.onNodeChange.add(updateResizeRect);
// Fixes WebKit quirk where it returns IMG on getNode if caret is after last image in container
dom.bind(editableDoc, 'selectionchange', updateResizeRect);
// Remove the internal attribute when serializing the DOM
editor.serializer.addAttributeFilter('data-mce-selected', function(nodes, name) {
var i = nodes.length;
while (i--) {
nodes[i].attr(name, null);
}
});
}
function keepNoScriptContents() {
if (getDocumentMode() < 9) {
parser.addNodeFilter('noscript', function(nodes) {
var i = nodes.length, node, textNode;
while (i--) {
node = nodes[i];
textNode = node.firstChild;
if (textNode) {
node.attr('data-mce-innertext', textNode.value);
}
}
});
serializer.addNodeFilter('noscript', function(nodes) {
var i = nodes.length, node, textNode, value;
while (i--) {
node = nodes[i];
textNode = nodes[i].firstChild;
if (textNode) {
textNode.value = tinymce.html.Entities.decode(textNode.value);
} else {
// Old IE can't retain noscript value so an attribute is used to store it
value = node.attributes.map['data-mce-innertext'];
if (value) {
node.attr('data-mce-innertext', null);
textNode = new tinymce.html.Node('#text', 3);
textNode.value = value;
textNode.raw = true;
node.append(textNode);
}
}
}
});
}
}
// All browsers
disableBackspaceIntoATable();
removeBlockQuoteOnBackSpace();
emptyEditorWhenDeleting();
// WebKit
if (tinymce.isWebKit) {
keepInlineElementOnDeleteBackspace();
cleanupStylesWhenDeleting();
inputMethodFocus();
selectControlElements();
setDefaultBlockType();
// iOS
if (tinymce.isIDevice) {
selectionChangeNodeChanged();
} else {
fakeImageResize();
selectAll();
}
}
// IE
if (tinymce.isIE) {
removeHrOnBackspace();
ensureBodyHasRoleApplication();
addNewLinesBeforeBrInPre();
removePreSerializedStylesWhenSelectingControls();
deleteControlItemOnBackSpace();
renderEmptyBlocksFix();
keepNoScriptContents();
}
// Gecko
if (tinymce.isGecko) {
removeHrOnBackspace();
focusBody();
removeStylesWhenDeletingAccrossBlockElements();
setGeckoEditingOptions();
addBrAfterLastLinks();
removeGhostSelection();
}
// Opera
if (tinymce.isOpera) {
fakeImageResize();
}
};
(function(tinymce) {
var namedEntities, baseEntities, reverseEntities,
attrsCharsRegExp = /[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
textCharsRegExp = /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
rawCharsRegExp = /[<>&\"\']/g,
entityRegExp = /&(#x|#)?([\w]+);/g,
asciiMap = {
128 : "\u20AC", 130 : "\u201A", 131 : "\u0192", 132 : "\u201E", 133 : "\u2026", 134 : "\u2020",
135 : "\u2021", 136 : "\u02C6", 137 : "\u2030", 138 : "\u0160", 139 : "\u2039", 140 : "\u0152",
142 : "\u017D", 145 : "\u2018", 146 : "\u2019", 147 : "\u201C", 148 : "\u201D", 149 : "\u2022",
150 : "\u2013", 151 : "\u2014", 152 : "\u02DC", 153 : "\u2122", 154 : "\u0161", 155 : "\u203A",
156 : "\u0153", 158 : "\u017E", 159