Benutzer:Revvar/KH/configHelper.js

aus Wikipedia, der freien Enzyklopädie
Zur Navigation springen Zur Suche springen

Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.

  • Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
  • Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
  • Internet Explorer/Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
  • Opera: Strg+F5
/**
* Project:  Config Helper, Version: 0.8beta, Date: 2010-03-14
* Copyright (C) 2010 Frank Rechenberger
* Released under the GPL license version 2
* http://www.gnu.org/copyleft/gpl.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE.
* See the GNU General Public License for more details.
*/

// Gadget: Config Helper (Konfigurationshelfer)
var $__c = new Object();
$__c.a_namespace = "";
$__c.a_namespaces = new Object();

var is_khtml = navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled );
var is_ie = !(is_gecko || is_opera || is_safari || is_khtml);

$__c.namespace = function(ns, from_saved_config_file) {
	if (typeof($__c.a_namespaces[ns]) == "undefined") throw("ConfigHelper.namespace : Unknown namespace:"+ns);
	$__c.a_namespace = ns;
	if (typeof(from_saved_config_file) != "undefined" && from_saved_config_file == true) {
		$__c.a_namespaces[ns].is_configured = true;
	}
};

$__c.set = function(id, val) {
	if ($__c.a_namespace == "") throw("ConfigHelper.set: No namespace selected.");
	if (typeof($__c.a_namespaces[$__c.a_namespace].config[id]) == "undefined") throw("ConfigHelper.set : Unknown attribute:"+id);
	$__c.a_namespaces[$__c.a_namespace].config[id].value = val;
	setVar(id, $__c.a_namespaces[$__c.a_namespace].config[id].type, val);
}

$__c.get = function(id) {
	if ($__c.a_namespace == "") throw("ConfigHelper.get: No namespace selected.");
	if (typeof($__c.a_namespaces[$__c.a_namespace].config[id]) == "undefined") throw("ConfigHelper.get : Unknown attribute:"+id);
	return $__c.a_namespaces[$__c.a_namespace].config[id].value;
}

$__c.getDefault = function(id) {
	if ($__c.a_namespace == "") throw("ConfigHelper.get: No namespace selected.");
	if (typeof($__c.a_namespaces[$__c.a_namespace].config[id]) == "undefined") throw("ConfigHelper.getDefault : Unknown attribute:"+id);
	return $__c.a_namespaces[$__c.a_namespace].config[id].v_default;
}

$__c.getB = function(id) {
	return ($__c.get(id) == "true");
}

$__c.getN = function(id) {
	return parseInt($__c.get(id));
}

$__c.getF = function(id) {
	return parseFloat($__c.get(id));
}

$__c.getM = function(id) {
	if (typeof($__c.a_namespaces[$__c.a_namespace].config[id].type) != "object") throw("ConfigHelper.getM : Type of attribute "+id+" is not an object.");
	var gui_id = $__c.get(id);
	return $__c.a_namespaces[$__c.a_namespace].config[id].type[gui_id];
}


$__c.register = new Object();
$__c.register.namespace = function(ns, name, description) {
	if (typeof($__c.a_namespaces[ns]) != "undefined") throw("ConfigHelper.register.namespace : Namespace already registered:"+ns);
	if (ns != escape(ns)) throw("ConfigHelper.register.namespace : Namespace identifier contains invalid chars.");
	$__c.a_namespaces[ns] = new Object();
	$__c.a_namespaces[ns].name = name;
	$__c.a_namespaces[ns].description = description;
	$__c.a_namespaces[ns].config = new Object();
	$__c.a_namespaces[ns].groups = new Object();
	$__c.a_namespaces[ns].is_configured = false; // the user saved a configuration for this ns 
}

$__c.register.group = function(ns, group, description, parent) {
	if (typeof($__c.a_namespaces[ns]) == "undefined") throw("ConfigHelper.attribute : Unknown namespace:"+ns);
	if (typeof($__c.a_namespaces[ns].groups[group]) != "undefined") throw("ConfigHelper.attribute : Group already registered:"+group);
	$__c.a_namespaces[ns].groups[group] = new Object();
	$__c.a_namespaces[ns].groups[group].name = group;
	$__c.a_namespaces[ns].groups[group].description = description;
	$__c.a_namespaces[ns].groups[group].parent = (typeof(parent) == "undefined" ? null : parent);
}

$__c.register.attribute = function(ns, group, id, name, type, v_default, description) {
	if (typeof($__c.a_namespaces[ns]) == "undefined") throw("ConfigHelper.attribute : Unknown namespace:"+ns);
	if (typeof($__c.a_namespaces[ns].groups[group]) == "undefined") throw("ConfigHelper.attribute : Unknown group:"+group);
	if (typeof($__c.a_namespaces[ns].config[id]) != "undefined") throw("ConfigHelper.register.attribute : Attribute already registered:"+id);
	if (id != escape(id)) throw("ConfigHelper.register.attribute : Attribute identifier contains invalid chars.");
	$__c.a_namespaces[ns].config[id] = new Object();
	$__c.a_namespaces[ns].config[id].name = name;
	$__c.a_namespaces[ns].config[id].group = group;
	$__c.a_namespaces[ns].config[id].type = type;
	$__c.a_namespaces[ns].config[id].description = description;
	$__c.a_namespaces[ns].config[id].v_default = v_default;
	$__c.a_namespaces[ns].config[id].value = v_default;
	setVar(id, type, v_default);
}

function setVar(name, type, value)
{
	if (type == "number") window[name] = parseInt(value);
	else if (type == "float") window[name] = parseFloat(value);
	else if (type == "bool") window[name] = (value == "true");
	else if (typeof(type) == "function") window[name] = type("get");
	else if (type instanceof Object) window[name] = type[value];
	else window[name] = value;

}


var oldMainGroup = null;
function showMainGroup(id)
{
	if (oldMainGroup != null) $(oldMainGroup).style.display = "none";
	oldMainGroup = "__c_grp_" + id;
	$(oldMainGroup).style.display = "";
}

function getGroupHTML(ns, grp)
{
	var html = '<FIELDSET id="__c_grp_' + grp.name + '"';
	if (grp.name != "default") {
		html += (grp.parent == null) ? ' style="display:none">' : '';
		html += '<LEGEND>' + grp.description + '</LEGEND';
	}
	html += '><TABLE>';
	for (var att in $__c.a_namespaces[ns].config) with($__c.a_namespaces[ns].config[att]) {
		if (group == grp.name) {
			html += '<TR><TD>' + name + ':</TD><TD>';
			if (type instanceof Array) {
				for (var m = 0; m < type.length; ++m) {
					if (m > 0) html += ' ';
					html += '<input type="radio" name="__c_' + ns + '_' + att + '" value="' + escapeValue(type[m]) + '"';
					if (type[m] == $__c.get(att)) html += ' checked ';
					html += '>' + escapeValue(type[m]);
				}
			} else if ((typeof(type) != "function") && (type instanceof Object)) {
				for (var oid in type) {
					html += '<input type="radio" name="__c_' + ns + '_' + att + '" value="' + escapeValue(oid) + '"';
					if (oid == $__c.get(att)) html += ' checked ';
					html += '> ' + escapeValue(oid);
				}
			} else {
				if (type == "bool") {
					html += '<INPUT id="__c_' + ns + '_' + att + '" type="checkbox" value="' + escapeValue($__c.get(att)) + '" ' + ($__c.getB(att) ? 'checked' : '') + '/>';
				} else {
					html += '<INPUT id="__c_' + ns + '_' + att + '" type="text" value="' + escapeValue($__c.get(att)) + '"/>';
				}
			}
			html += '</TD><TD class="htmlform-tip">(' + description + ')</TD></TR>';
		}
	}
	html += '</TABLE>';
	if (grp.parent == null) html += '$$$__c_3$$$';
	html += '</FIELDSET>';
	return html;
}

function showConfig(oldConfig)
{
	var notice = null;
	try {
		notice = $("jump-to-nav").nextSibling.nextSibling.nextSibling.nextSibling;
		if (notice.nodeName != "P") notice = null;
	} catch(e) {}
	$_DEL("content");
	$_DEL("p-cactions");
	var content = cNode($("column-content"), "DIV", null, {"id":"content"});
	var html = '<H1 id="firstHeading" class="firstHeading">Tool-Einstellungen</H1>'
		+ '<DIV id="bodyContent">$$$__c_1$$$';
	if (areUnconfiguredNs()) {
		html += '<br /><br /><div style="border:2px solid red;padding:4px;">Die gelb unterlegten Tools sind neu und wurden noch nicht konfiguriert. Nach dem ersten Speichern der Konfiguration verschwindet diese Aufforderung.';
		if (typeof(oldConfig) == "undefined") {
			html += '<br />Das Programm kann versuchen eine alte Konfiguration aus deiner ' + skin + '.js zu extrahieren. Folge dazu bitte diesem <b><a href="' + mw.config.get('wgServer') + mw.config.get('wgScript') + '?title=Benutzer:' + wgUserName + '/' + skin + '.js#Prehistoric">Link</a>.</b>';
		} else {
			html += '<br /><b>Deine alte Konfiguration wurde wiederhergestellt.</b> Bitte kontrolliere die vorgenommen Einstellungen. Diese werden erst nach dem Speichern umgesetzt.';
		}
		html += "</div><br /><br />";
	}

	var head_nav = '';

	for (var ns in $__c.a_namespaces) {
		var ns_nav = '';
		$__c.namespace(ns);
		if (head_nav != "") head_nav += " | ";
		head_nav += '<A ' + ($__c.a_namespaces[ns].is_configured ? '' : 'style="background-color:yellow" ') + 'HREF="#__c_ns_' + ns + '">' + $__c.a_namespaces[ns].name + '</A> ';
		html += '<H2 id="__c_ns_' + ns + '" ' + ($__c.a_namespaces[ns].is_configured ? '' : ' style="background-color:yellow" ') + '>' + $__c.a_namespaces[ns].name + '</H2>' + $__c.a_namespaces[ns].description + '<br />$$$__c_2$$$';
		for (var grp_id in $__c.a_namespaces[ns].groups) {
			var grp = $__c.a_namespaces[ns].groups[grp_id];
			if (grp.parent == null) {
				html += getGroupHTML(ns, grp);
				if (grp.name != "default") ns_nav += '<INPUT onclick="showMainGroup(\'' + grp_id + '\');" type="button" id="__c_grp_sel_' + grp_id + '" value="' + grp.description + '"/> ';

				var subhtml = "";
				for (var subgrp_id in $__c.a_namespaces[ns].groups) {
					var subgrp = $__c.a_namespaces[ns].groups[subgrp_id];
					if (subgrp.parent == grp_id) {
						subhtml += getGroupHTML(ns, subgrp);
					}
				}
				html = html.replace('$$$__c_3$$$', subhtml);

			}
		}
		html = html.replace('$$$__c_2$$$', ns_nav);
	}
	html = html.replace('$$$__c_1$$$', head_nav);
	html += '<hr /><INPUT type="button" id="__c_save_config" value="Speichern" /> <INPUT type="button" id="__c_save_default" value="Standardwerte" /></DIV>';

	content.innerHTML = html;
	if (notice != null) content.appendChild(notice);

	f_addEventListener($("__c_save_config"), "click", function() {saveConfig(false);}, true);
	f_addEventListener($("__c_save_default"), "click", function() {saveConfig(true);}, true);

}

function saveConfig(use_defaults) {
	$("__c_save_config").disabled = true;
	$("__c_save_default").disabled = true;
	var title = "User:" + wgUserName + "/" + skin + ".js";
	loadPage(title, function(state, token, content) {
		var new_content = "";
		if (state) {
			content += "";
			var conf_start = content.search("// ##[$]__CONFIG_START##");
			var conf_end = content.search("// ##[$]__CONFIG_END##");
			if (conf_end > -1) {
				var next_new_line = content.substring(conf_end).search("\n");
				if (next_new_line > -1) {
					conf_end += next_new_line;
				} else {
					conf_end = content.length;
				}
			}
			if (conf_start == -1 && conf_end == -1) new_content = getJSConfig(use_defaults) + '\n' + content;
			else if (conf_start == -1 || conf_end == -1) {
				alert("Can't modify javascript.");
				return;
			} else {
				new_content = content.substring(0, conf_start) + getJSConfig(use_defaults) + content.substring(conf_end);
			}
		} else {
			new_content = getJSConfig(use_defaults);
		}
		savePage(title, token, "config changed", new_content, function(state, msg) {
			if (state == false) {
				if (use_defaults) $("__c_save_default").style["backgroundColor"] = "#ff6666";
				else $("__c_save_config").style["backgroundColor"] = "#ff6666";
				alert(msg);
			} else {
				if (use_defaults) $("__c_save_default").style["backgroundColor"] = "#66ff66";
				else $("__c_save_config").style["backgroundColor"] = "#66ff66";
			}
			$("__c_save_config").disabled = false;
			$("__c_save_default").disabled = false;
		});
	});
}

function getJSConfig(use_defaults)
{
	var js = '// ##' + '$__CONFIG_START##\n// ACHTUNG: Dieser Abschnitt wurde und wird automatisch generiert!\n';
 
	for (var ns in $__c.a_namespaces) {
		$__c.namespace(ns);
		js += '$__c.namespace("' + ns + '", true);\n';
 
		if (!(typeof(use_defaults) != "undefined" && use_defaults == true)) {
			for (var att in $__c.a_namespaces[ns].config) with($__c.a_namespaces[ns].config[att]) {
				var elem = getConfigElement('__c_' + ns + '_' + att);
				if (elem != $__c.getDefault(att)) js += '$__c.set("' + att + '", "' + elem + '");\n';
			}
		}
	}
	js += '// ##' + '$__CONFIG_END##';
	return js;
}

function areUnconfiguredNs()
{
	var res = true;
	for (var ns in $__c.a_namespaces) res = res && $__c.a_namespaces[ns].is_configured;
	return !res;
}

function restorePrehistoricConfig(fCallback)
{
	GM_xmlhttpRequest({
		'method'	: 'GET',
		'url'		: mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?action=query&prop=revisions&titles=Benutzer:' + encodeURIComponent(wgUserName) + '/' + skin + '.js&rvprop=content&rvlimit=10&format=json',
		'headers'	: {'User-agent': 'Skript:ConfigHelper(wp_de_user_Revvar)'},
		'onload'	: function(req) {
			try {
				var rT = req.responseText;
				var ts = JSON.parse(rT);
				if (typeof(ts.error) != "undefined") {
					alert("Error: " + rT);
					return;
				} else {
					var pages = ts.query.pages;
					for (var page_id in pages) {
						var page = pages[page_id];
						if (typeof(page.revisions)!='undefined') {
							for (var rev_id in page.revisions) {
								var content = page.revisions[rev_id]["*"];
								var found = 0;
								for (var ns in $__c.a_namespaces) if (!($__c.a_namespaces[ns].is_configured)) {
									$__c.namespace(ns);
 
									for (var att in $__c.a_namespaces[ns].config) with($__c.a_namespaces[ns].config[att]) {
										var xatt = new RegExp('(^|[\\s])' + att + '[\\s]*=([\\s]*)([^"\'\\s;]*)[\\s]*;','i');
										var xsatt = new RegExp('(^|[\\s])' + att + '[\\s]*=[\\s]*([\'"])([^\'"]*)\\1[\\s]*;','i');
										var res = xsatt.exec(content);
										if (res == null) res = xatt.exec(content);
										if (res != null) {
											found++;
											var type = $__c.a_namespaces[$__c.a_namespace].config[att].type;
											if (typeof(type) == "function") { 
												$__c.set(att, type("set", res[3]));
											} else if (type instanceof Object && !(type instanceof Array)) {
												for (var oid in type) if (res[3] == type[oid]) $__c.set(att, oid);
											} else {
												$__c.set(att, res[3]);
											}
										} else found--;
									}
								}

								if (found>0) {
									fCallback();
									return;
								}
							}
						}
					}
				}
			} catch (e) {
				alert(e.message);
			}
			fCallback();
		}
	});
}

function getConfigElement(id)
{
	var elem = $(id);
	if (elem != null && elem.type != "radio") {
		if (elem.type == "checkbox") return (elem.checked ? "true" : "false");
		else return elem.value;
	}

	var all_radios = document.getElementsByName(id);
	for (var i = 0; i < all_radios.length; ++i) if (all_radios[i].checked) {
		return all_radios[i].value;
	}

	return "";
}

function loadPage(title, fCallback) {
	GM_xmlhttpRequest({
		'method'	: 'GET',
		'url'		: mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?action=query&prop=info|revisions&rvprop=content&rvlimit=1&titles=' + encodeURIComponent(title) + '&intoken=edit&format=json',
		'headers'	: {'User-agent': 'Skript:ConfigHelper(wp_de_user_Revvar)'},
		'onload'	: function(req) {
			try {
				var rT = req.responseText;
				var ts = JSON.parse(rT);
				if (typeof(ts.error) != "undefined") {
					fCallback(false, ts.error, null);
				} else {
					var pages = ts.query.pages;
					for (var page_id in pages) {
						var page = pages[page_id];
						if (typeof(page.edittoken)!='undefined') {
							if (typeof(page.missing)!='undefined') {
								fCallback(false, page.edittoken, null);
								return;
							} else {
								for (var rev_id in page.revisions) {
									fCallback(true, page.edittoken, page.revisions[rev_id]["*"]);
									return;
								}
							}
						}
					}
				}
				fCallback(false, null, null);
			} catch (e) {
				fCallback(false, e.message, null);
			}
		}
	});
}

function savePage(title, token, summary, content, fCallback) {
	var data =  'title=' + encodeURIComponent(title) +
	'&summary=' + encodeURIComponent(summary) +
	'&watchlist=nochange' +
	'&minor&format=json&action=edit' +
	'&text=' + encodeURIComponent(content) +
	'&token=' + encodeURIComponent(token);

	GM_xmlhttpRequest({
		method	: 'POST',
		url	: mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?minor',
		data	: data,
		headers	: {'Content-Type':'application/x-www-form-urlencoded', 'User-agent': 'Skript:ConfigHelper(wp_de_user_Revvar)'},
		onload	: function(req) {
			try {
				var rT = req.responseText;
				var ts = JSON.parse(rT);
				try {
					if (typeof(ts.error) != "undefined") {
						fCallback(false, rT);
					} else {
						fCallback(true);
					}
				} catch (e) {
					alert("[Error] save config: " + e.message);
				}
			} catch (e) {
				fCallback(false, e.message);
			}
		}
	});
}

function GM_xmlhttpRequest(req)
{
	var xmlHttp = sajax_init_object();// gets the XMLHttpRequest object (depends on ajax.js)

	xmlHttp.open(req.method, req.url, true);
	xmlHttp.onreadystatechange = function () {
		if (xmlHttp.readyState == 4) {
			req.onload(xmlHttp);
		}
	};
	for (var name in req.headers) {
		xmlHttp.setRequestHeader(name, req.headers[name]);
	}
	xmlHttp.send(req.data);
}

function $(id) {return document.getElementById(id);}
function $_DEL(id) {
	var elem = $(id);
	if (elem != null && elem.parentNode != null) {
		elem.parentNode.removeChild(elem);
	}
}

/**
  Creates a new GUI node.
 
 @author [[de:Benutzer:Revvar]]
 @param nRoot null or reference to the prefered root node object
 @param nType HTML type string ("div" for example)
 @param nText null or string with the text for the text child node
 @param nAttr null or object with attribute attributes, ({style:"...",width:"100%"} for example)
 @return the new node object
*/
function cNode(nRoot,nType,nText,nAttr)
{
	var elem=document.createElement(nType);
	if (nAttr) for (var aid in nAttr) {
		if (aid == "style") {
			var style_attr = nAttr[aid].split(";");
			var style_obj = new Object();
			for (var i = 0; i < style_attr.length; i++) {
				var style_id = style_attr[i].replace(/^\s*([^:]+):.*$/,"$1");
				var style_value = style_attr[i].replace(/^\s*[^:]+:\s*([^\s;]+)[\s;]*$/,"$1");
				if (style_id.length > 0) style_obj[style_id] = style_value;
			}
		  setStyleAttribute(elem, style_obj);
		} else {
			if (aid == "class") elem.className = nAttr[aid];
			else elem.setAttribute(aid, nAttr[aid]);
		}
	}
	if (nText) elem.appendChild(document.createTextNode(nText));
	if (nRoot) nRoot.appendChild(elem);
	return elem;
}
 
 
function setStyleAttribute(Node, Attribute)
{
	if ((Node) && (Attribute)) {
		 for (var aid in Attribute) {
			 Node.style[aid] = Attribute[aid];
		 }
	}
}

function escapeValue(value) { return value.replace(/([~'"])/g, '\\$1');}

// replacement for the FF 3.5 JSON object
if (typeof(JSON) == "undefined") {
	JSON = new Object();
	JSON.parse = function(txt) {
		return eval('(' + txt + ')');
	}
}

function f_addEventListener(Node, event, callback)
{
	if (is_ie) {
		if (typeof(Node.attachEvent) != "undefined") Node.attachEvent("on"+event, callback);
	} else {
		if (typeof(Node.addEventListener) != "undefined") Node.addEventListener(event, callback, false);
	}
}

// XXX: Chrome doesn't fires the on DomContentLoaded event on dynamicaly loaded scripts, if it restores a page from the cache
//      Solution: Bind the function to the Load event too, and let them only call once.
ch_atMostOnce = new Object();
callKey = 0;
function callMeAtMostOnce(p_func, key)
{
	if (typeof(ch_atMostOnce[key]) != "undefined") return;
	ch_atMostOnce[key] = true;
	p_func();
}

function f_addOnDomContentLoaded(f_event)
{
	var l_callKey = callKey;
	callKey++;

	if (typeof(document.addEventListener) == "function") {
		document.addEventListener("DOMContentLoaded", function() {callMeAtMostOnce(f_event, l_callKey);}, false);
	} else {
		document.onreadystatechange = function() {
			if ((document.readyState == "interactive") || (document.readyState == "complete")) callMeAtMostOnce(f_event, l_callKey);
		}
	}
	addOnloadHook(function() {callMeAtMostOnce(f_event, l_callKey);});
}

function ch_show_gui() {
	// show GUI
	var blink_state = 0;
	if (document.location.toString().search(".js#ConfigHelper") > 0) {
		showConfig();
	} else if (document.location.toString().search(".js#Prehistoric") > 0) {
		restorePrehistoricConfig(function() {showConfig(true);});
	} else {
		var config_link = $("pt-preferences");
		if (config_link != null) {
			var tool_prefs = cNode(null, "LI", null, {"id":"c__configLink"});
			var tool_prefs_link = cNode(tool_prefs, "A", "Tool-" + config_link.firstChild.firstChild.nodeValue, {"href":mw.config.get('wgServer') + mw.config.get('wgArticlePath').replace("$1", "Benutzer:" + wgUserName + "/" + skin + ".js#ConfigHelper")});
			config_link.parentNode.insertBefore(tool_prefs, config_link);

			if (areUnconfiguredNs()) setTimeout(fBlink, 1000);
		}
	}
	return;

	function fBlink() {
		if (blink_state == 0) 	$("c__configLink").style.backgroundColor = null;
		else $("c__configLink").style.backgroundColor = "#ffff55";
		blink_state = 1 - blink_state;
		setTimeout(fBlink, 1000);
	}

}

if (typeof($__callstack) == "undefined") throw("No callstack defined.");

// helper object for the imported scripts, to execute their code in the defined order
$__oCallstack = {
	exec : function(name) {
		// alert("callback : " + name);
		for (var i = 0; i < $__callstack.length - 1; ++i) {
			if ($__callstack[i].name == name) {
				i++;
				while ((i < $__callstack.length) && (typeof($__callstack[i].path) == "undefined")) {
					// alert("call : " + $__callstack[i].name);
					window[$__callstack[i].name]();
					i++;
				}
				if (i < $__callstack.length) if (typeof($__callstack[i].path) != "undefined") {
					// alert("import : " + $__callstack[i].name);
					importScript($__callstack[i].path);
				}
				break;
			}
		}
	}
};

// import first external scripts
for (var i = 0; i < $__callstack.length; ++i) if (typeof($__callstack[i].path) != "undefined") {
  importScript($__callstack[i].path);
  break;
}