/*
 * (c) actSoft
 *
 * name: package.js
 *
 * description: description
 *
 * written by: Christof Donat
 * 
 * changes:
 *    08.06.06 (Christof Donat): created this file
 *    05.09.06 (Christof Donat): added License Notice
 *    25.11.06 (Christof Donat): use window.execScript instead of timeout,
 *                               reduced codesize a bit
 *    29.11.06 (Christof Donat): now Works with IE 7 as well
 *    21.01.09 (Christof Donat): threw out problematic fallback of fallback
 *                               of fallback; replaced with a slow implementation
 *                               of getElementsByTagName().
 *    21.01.09 (Christof Donat): added comments
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

/* create an object for a loaded package. Use this after your package has been fully initialized */
$package = function(p,o) {
  var ps = p.split('.');
  var co = window; 
  for( i = 0; i < ps.length; i++ ) {
	if( ! co[ps[i]] ) co[ps[i]] = {};
	co = co[ps[i]];
  }
  for(ob in o) co[ob] = o[ob];
};

/* this is the base URL where the packages are located. overwrite this value to fit your installation */
$package.packageBase = '/';

/* internally used test functions */
$package.testSubobj = function(o,co) {
  var ps = o.split('.');
  for( i = 0; i < ps.length; i++ )
	if( ! co[ps[i]] ) return false;
	else co = co[ps[i]];
  return true;
};

$package.testforobject = function(o) { return $package.testSubobj(o,$package); };
$package.packageCreated = function(o) { return $package.testSubobj(o,window); };

$package.havepackage = function(p) { return $package.testforobject(p) };
$package.packagefinished = function(p) { return $package.testforobject(p+'.loaded')&&$package.packageCreated(p) };

/* fallback for browsers that don't support document.getElementByTagName(). this is slow! */
if( !document.getElementsByTagName )
document.getElementsByTagName = function(n,o) {
  var r = [];
  if( !o ) o = this;
  var c = o.childNodes;
  for( i = 0; i < c.length; i++ ) if( c.nodeType == 1 ) {
	if( c.nodeName.toLowerCase() == n ) r.push(c);
	r.concat(document.getElementsByTagName(n,c));
  }
  return r;
};

/* fallback for browsers without XMLHttpRequest; adds a script tag to the head */
$package.loadscript = function(scriptURI,evalme) {
  var h = document.getElementsByTagName("head")[0];
  var e = document.createElement("script");
  e.src = scriptURI;
  e.type="text/javascript";
  h.appendChild(e);
  e = document.createElement("script");
  e.type="text/javascript";
  e.appendChild(document.createTextNode(evalme));
  h.appendChild(e);
};

/* window.execScript is an IE function. We emulate it for all other browsers because that is easier than the other way round. */
if( ! window.execScript ) window.execScript = function(src) { eval.call(window,src) };

/* overwrite $package.loadscript() for Browsers with XMLHttpRequest. */
if( window.XMLHttpRequest || window.ActiveXObject ) {
  var isIE = false;
  /* emulate window.XMLHttpRequest for IE */
  if( window.ActiveXObject ) {
	isIE = true; // yes, IE needs special treatment alter again :-(
	var lib = /MSIE 5/.test(navigator.userAgent) ? "Microsoft" : "Msxml2";
  	window.XMLHttpRequest = function() {
  	  return new ActiveXObject(lib + ".XMLHTTP");
	};
  };
  /* keep the fallback in case something goes wrong at runtime */
  $package._loadscript = $package.loadscript;
  /* load script */
  $package.loadscript = function(scriptURI,evalme) {
	try {
  	  var x = new XMLHttpRequest();
  	  x.open('GET',scriptURI);
  	  
	  var f2 =  function() { 
		window.execScript(x.responseText+'\n'+evalme);
	  }; 
	  if(isIE) x.onreadystatechange = function() { if(x.readystate == 4) f2() };
	  else x.onload = f2;
	  
	  x.send(''); 
	} catch(e) { // use the fallback if something has gone wrong.
	  $package._loadscript(scriptURI,evalme);
	}
  };
};

/* require a package; call the callback as soon as it is available */
$package.require = function(p,f) {
  if($package.packagefinished(p)) f(); // package is already loaded an initialized
  else if( !$package.havepackage(p) ) { // package has not yet been requested
	$package('$package.'+p,{'onload':function() { $package('$package.'+p+'.loaded',true);$package.require(p,f) }});
	$package.loadscript($package.packageBase+(p.split('.').join('/')+'.js'),'$package.'+p+'.onload()');
  } else { // package has been requested but has not finished initialization - try again later.
	setTimeout(function(){$package.require(p,f)},10);
  }
};

/* 
 * This is the core function for clients using packages.
 * You can provide one or multiple names of packages and a callback function that will be
 * called as soon as all required packages are loaded and initialized.
 */
$using = function(ps,f) {
  if( !(ps instanceof Array) ) ps = [ps];
  var count = 0;
  for(p in ps) $package.require(ps[p],function() {
	count++;
	if( count == ps.length ) f();
  });
};

/* end package.js */


