/**
* $Id$
*
* @author Moxiecode
* @copyright Copyright � 2004-2007, Moxiecode Systems AB, All rights reserved.
*
* The contents of this file will be wrapped in a class later on.
*/
/**#@+
* @member TinyMCE_Engine
* @method
*/
tinyMCE.add(TinyMCE_Engine, {
/**
* Parses a URL in to its diffrent components.
*
* @param {string} url_str URL string to parse into a URL object.
* @return URL object based on input string.
* @type TinyMCE_URL_Item
*/
parseURL : function(url_str) {
var urlParts = [], i, pos, lastPos, chr;
if (url_str) {
// Parse protocol part
pos = url_str.indexOf('://');
if (pos != -1) {
urlParts.protocol = url_str.substring(0, pos);
lastPos = pos + 3;
}
// Find port or path start
for (i=lastPos; i<url_str.length; i++) {
chr = url_str.charAt(i);
if (chr == ':')
break;
if (chr == '/')
break;
}
pos = i;
// Get host
urlParts.host = url_str.substring(lastPos, pos);
// Get port
urlParts.port = "";
lastPos = pos;
if (url_str.charAt(pos) == ':') {
pos = url_str.indexOf('/', lastPos);
urlParts.port = url_str.substring(lastPos+1, pos);
}
// Get path
lastPos = pos;
pos = url_str.indexOf('?', lastPos);
if (pos == -1)
pos = url_str.indexOf('#', lastPos);
if (pos == -1)
pos = url_str.length;
urlParts.path = url_str.substring(lastPos, pos);
// Get query
lastPos = pos;
if (url_str.charAt(pos) == '?') {
pos = url_str.indexOf('#');
pos = (pos == -1) ? url_str.length : pos;
urlParts.query = url_str.substring(lastPos+1, pos);
}
// Get anchor
lastPos = pos;
if (url_str.charAt(pos) == '#') {
pos = url_str.length;
urlParts.anchor = url_str.substring(lastPos+1, pos);
}
}
return urlParts;
},
/**
* Serializes the specified URL object into a string.
*
* @param {TinyMCE_URL_Item} up URL object to serialize.
* @return Serialized URL object.
* @type string
*/
serializeURL : function(up) {
var o = "";
if (up.protocol)
o += up.protocol + "://";
if (up.host)
o += up.host;
if (up.port)
o += ":" + up.port;
if (up.path)
o += up.path;
if (up.query)
o += "?" + up.query;
if (up.anchor)
o += "#" + up.anchor;
return o;
},
/**
* Converts an absolute path to relative path.
*
* @param {string} base_url URL to make as a base path, URLs will be converted relative from this point.
* @param {string} url_to_relative URL to convert into a relative URL.
* @return Relative URL based in input.
* @type string
*/
convertAbsoluteURLToRelativeURL : function(base_url, url_to_relative) {
var baseURL = this.parseURL(base_url), targetURL = this.parseURL(url_to_relative);
var i, strTok1, strTok2, breakPoint = 0, outPath = "", forceSlash = false;
var fileName, pos;
if (targetURL.path == '')
targetURL.path = "/";
else
forceSlash = true;
// Crop away last path part
base_url = baseURL.path.substring(0, baseURL.path.lastIndexOf('/'));
strTok1 = base_url.split('/');
strTok2 = targetURL.path.split('/');
if (strTok1.length >= strTok2.length) {
for (i=0; i<strTok1.length; i++) {
if (i >= strTok2.length || strTok1[i] != strTok2[i]) {
breakPoint = i + 1;
break;
}
}
}
if (strTok1.length < strTok2.length) {
for (i=0; i<strTok2.length; i++) {
if (i >= strTok1.length || strTok1[i] != strTok2[i]) {
breakPoint = i + 1;
break;
}
}
}
if (breakPoint == 1)
return targetURL.path;
for (i=0; i<(strTok1.length-(breakPoint-1)); i++)
outPath += "../";
for (i=breakPoint-1; i<strTok2.length; i++) {
if (i != (breakPoint-1))
outPath += "/" + strTok2[i];
else
outPath += strTok2[i];
}
targetURL.protocol = null;
targetURL.host = null;
targetURL.port = null;
targetURL.path = outPath == '' && forceSlash ? "/" : outPath;
// Remove document prefix from local anchors
fileName = baseURL.path;
if ((pos = fileName.lastIndexOf('/')) != -1)
fileName = fileName.substring(pos + 1);
// Is local anchor
if (fileName == targetURL.path && targetURL.anchor !== '')
targetURL.path = "";
// If empty and not local anchor force filename or slash
if (targetURL.path == '' && !targetURL.anchor)
targetURL.path = fileName !== '' ? fileName : "/";
return this.serializeURL(targetURL);
},
/**
* Converts an relative path to absolute path.
*
* @param {string} base_url URL to make as a base path, URLs will be converted absolute from this point.
* @param {string} relative_url URL to convert into a absolute URL.
* @return Absolute URL based in input.
* @type string
*/
convertRelativeToAbsoluteURL : function(base_url, relative_url) {
var baseURL = this.parseURL(base_url), baseURLParts, relURLParts, newRelURLParts, numBack, relURL = this.parseURL(relative_url), i;
var len, absPath, start, end, newBaseURLParts;
if (relative_url == '' || relative_url.indexOf('://') != -1 || /^(mailto:|javascript:|#|\/)/.test(relative_url))
return relative_url;
// Split parts
baseURLParts = baseURL.path.split('/');
relURLParts = relURL.path.split('/');
// Remove empty chunks
newBaseURLParts = [];
for (i=baseURLParts.length-1; i>=0; i--) {
if (baseURLParts[i].length == 0)
continue;
newBaseURLParts[newBaseURLParts.length] = baseURLParts[i];
}
baseURLParts = newBaseURLParts.reverse();
// Merge relURLParts chunks
newRelURLParts = [];
numBack = 0;
for (i=relURLParts.length-1; i>=0; i--) {
if (relURLParts[i].length == 0 || relURLParts[i] == ".")
continue;
if (relURLParts[i] == '..') {
numBack++;
continue;
}
if (numBack > 0) {
numBack--;
continue;
}
newRelURLParts[newRelURLParts.length] = relURLParts[i];
}
relURLParts = newRelURLParts.reverse();
// Remove end from absolute path
len = baseURLParts.length-numBack;
absPath = (len <= 0 ? "" : "/") + baseURLParts.slice(0, len).join('/') + "/" + relURLParts.join('/');
start = "";
end = "";
// Build output URL
relURL.protocol = baseURL.protocol;
relURL.host = baseURL.host;
relURL.port = baseURL.port;
// Re-add trailing slash if it's removed
if (relURL.path.charAt(relURL.path.length-1) == "/")
absPath += "/";
relURL.path = absPath;
return this.serializeURL(relURL);
},
/**
* Converts the specified URL based in TinyMCE configuration settings.
*
* @param {string} url URL to convert based on config.
* @param {HTMLElement} node HTML element that holds the URL.
* @param {boolean} on_save Is this convertion the final output URL.
* @return Converted URL string.
* @type string
*/
convertURL : function(url, node, on_save) {
var dl = document.location, start, portPart, urlParts, baseUrlParts, tmpUrlParts, curl;
var prot = dl.protocol, host = dl.hostname, port = dl.port;
// Pass through file protocol
if (prot == "file:")
return url;
// Something is wrong, remove weirdness
url = tinyMCE.regexpReplace(url, '(http|https):///', '/');
// Mailto link or anchor (Pass through)
if (url.indexOf('mailto:') != -1 || url.indexOf('javascript:') != -1 || /^[ \t\r\n\+]*[#\?]/.test(url))
return url;
// Fix relative/Mozilla
if (!tinyMCE.isIE && !on_save && url.indexOf("://") == -1 && url.charAt(0) != '/')
return tinyMCE.settings.base_href + url;
// Handle relative URLs
if (on_save && tinyMCE.getParam('relative_urls')) {
curl = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, url);
if (curl.charAt(0) == '/')
curl = tinyMCE.settings.document_base_prefix + curl;
urlParts = tinyMCE.parseURL(curl);
tmpUrlParts = tinyMCE.parseURL(tinyMCE.settings.document_base_url);
// Force relative
if (urlParts.host == tmpUrlParts.host && (urlParts.port == tmpUrlParts.port))
return tinyMCE.convertAbsoluteURLToRelativeURL(tinyMCE.settings.document_base_url, curl);
}
// Handle absolute URLs
if (!tinyMCE.getParam('relative_urls')) {
urlParts = tinyMCE.parseURL(url);
baseUrlParts = tinyMCE.parseURL(tinyMCE.settings.base_href);
// Force absolute URLs from relative URLs
url = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, url);
// If anchor and path is the same page
if (urlParts.anchor && urlParts.path == baseUrlParts.path)
return "#" + urlParts.anchor;
}
// Remove current domain
if (tinyMCE.getParam('remove_script_host')) {
start = "";
portPart = "";
if (port !== '')
portPart = ":" + port;
start = prot + "//" + host + portPart + "/";
if (url.indexOf(start) == 0)
url = url.substring(start.length-1);
}
return url;
},
/**
* Converts all img and a element URLs to absolute URLs. This will use the mce_src or mce_href attribute values
* if they are provided. This function is used when the editor is initialized.
*
* @param {HTMLElement} body HTML element to convert all URLs in.
*/
convertAllRelativeURLs : function(body) {
var i, elms, src, href, mhref, msrc;
// Convert all image URL:s to absolute URL
elms = body.getElementsByTagName("img");
for (i=0; i<elms.length; i++) {
src = tinyMCE.getAttrib(elms[i], 'src');
msrc = tinyMCE.getAttrib(elms[i], 'mce_src');
if (msrc !== '')
src = msrc;
if (src !== '') {
src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, src);
elms[i].setAttribute("src", src);
}
}
// Convert all link URL:s to absolute URL
elms = body.getElementsByTagName("a");
for (i=0; i<elms.length; i++) {
href = tinyMCE.getAttrib(elms[i], 'href');
mhref = tinyMCE.getAttrib(elms[i], 'mce_href');
if (mhref !== '')
href = mhref;
if (href && href !== '') {
href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, href);
elms[i].setAttribute("href", href);
}
}
}
/**#@-*/
});