/*

    fss (Free Software Signature)
    version 1.0 Copyright (C) 2006-2007 Tagata Akira

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.

    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.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
    02110-1301 USA

*/

_fss.prototype._fss = _fss;

_fss.prototype._fss('fss','Free Software Signature','1.0r','2006-2007 Tagata Akira','http://www.tagata.org/software/');

// update history
// 1.0g: 2006-11-26 bug fix
// 1.0h: 2006-12-07 wild card for searchClass()
// 1.0i: 2006-12-07 parseClass()
// 1.0j: 2007-02-04 setStyleSheetData(), makeAnimated()
// 1.0k: 2007-02-05 concatenateTextNode(), concatenateTextNodeById(), removeTextNode()
// 1.0k2: 2007-03-07 Safari requires \s for spaces
// 1.0k3: 2007-03-14 Bug fix
// 1.0l: 2007-02-18 innerSize(),scrollSize
// 1.0m: 2007-02-25 _fss.prototype.makeAnimated has been moved into _vadi.js
// 1.0m: 2007-02-25 findContainingBlockInInlineStyle(),elementXY()
// 1.0n: 2007-03-02 _fss.prototype.xxxxx -> _fss.xxxxx
// 1.0o: 2007-03-18 _fss.prototype..*Cookie -> _fss..*Cookie
// 1.0p: 2007-04-08 _fss.prototype.elementIdentified -> _fss.elementIdentified
// 1.0q: 2007-04-08 added some functions
// 1.0r: 2007-04-09 element search functions

function _fss(name,desc,ver,copy,web,contact) {

	_fssObj.prototype = {
		name:	'n/a',
		desc:	'n/a',
		ver:	'n/a',
		copy:	'n/a',
		web:	'n/a',
		contact:'n/a'
	}
	function _fssObj() { }

	this._fssObj = new _fssObj;
	if (name)
		this._fssObj.name = name;
	if (desc)
		this._fssObj.desc = desc;
	if (ver)
		this._fssObj.ver = ver;
	if (copy)
		this._fssObj.copy = copy;
	if (web)
		this._fssObj.web = web;
	if (contact)
		this._fssObj.contact = contact;

}

_fss.prototype._fssName = function () { return this._fssObj.name }
_fss.prototype._fssDesc = function () { return this._fssObj.desc }
_fss.prototype._fssVer = function () { return this._fssObj.ver }
_fss.prototype._fssCopy = function () { return this._fssObj.copy }
_fss.prototype._fssWeb = function () { return this._fssObj.web }
_fss.prototype._fssContact = function () { return this._fssObj.contact }

_fss.prototype._fssHtml = '_fss.html';
_fss.prototype._fssUrlStyle = 'padding-left: 1ex; font-size: smaller;';
_fss.prototype._fssUrlMargin = '0 0 0 1ex';
_fss.prototype._fssUrlFont = 'smaller serif';
_fss.prototype._fssElementIdToBeInserted = 'fss-siglink-box';
_fss.prototype._fssTagNameToBeInserted = 'div';
_fss.prototype._fssInsertedSig = {};
_fss.prototype._fssInsertUrl = function (eltId) {
	if ('name' in this._fssObj) {
		var elementId = this._fssElementIdToBeInserted;
		if (eltId) {
			elementId = eltId;
		}
		var elementToBeInserted = this.elementIdentified(elementId,this._fssTagNameToBeInserted);
// 1.0k3: 2007-03-14 Bug fix
		if (elementToBeInserted._fssGenerated && !elementToBeInserted._fssGeneratedEver) {
			document.body.appendChild(elementToBeInserted);
		}

		if (this._fssObj['name'] in _fss.prototype._fssInsertedSig)
			return;
		_fss.prototype._fssInsertedSig[this._fssObj['name']] = true;

		// insert signature of myself only the first ime
		_fss.prototype._fssInsertUrl();

		var url = this._fssUriElement(this._fssObj);
//		url.setAttribute('style',this._fssUrlStyle);
		url.style.margin = this._fssUrlMargin;
		url.style.font = this._fssUrlFont;
		elementToBeInserted.appendChild(url);
	}
}
_fss.prototype._fssUriElement = function (fssObj) {
	ret = document.createElement('a');
	ret.appendChild(document.createTextNode(fssObj.name));
	function objectToQuery(o) {
		var query = '';
		for (var p in o) {
			if (query != '')
				query += '&amp;';
			query += p+'='+o[p];
		}
		return query;
	}
	var href = encodeURI(this._prependInstallDirectory(this._fssHtml)+'?'+objectToQuery(fssObj));
	var title = 'what is '+fssObj.name+'?';
	ret.setAttribute('href',href);
	ret.setAttribute('title',title);
	return ret;
}

_fss.prototype._log = function () { }; // dummy

// common use method for inferitanced objects
// 1.0p: 2007-04-08 _fss.prototype.elementIdentified -> _fss.elementIdentified

_fss.prototype.elementIdentified =
	 function (id,tagName) { return _fss.elementIdentified(id,tagName); };

_fss.elementIdentified = function (id,tagName) {
	var elt = id? document.getElementById(id): null;
	if (elt) {
		if (elt._fssGenerated) // check generated ever
			elt._fssGeneratedEver = true;
		else
			elt._fssPredefined = true;
	}
	else {
		elt = document.createElement(tagName);
		elt.id = id;
		elt._fssGenerated = true;
	}
	return elt;
};

// 1.0g
//_fss.prototype._isLocal = window.location.protocol == 'file:';
_fss.prototype._isLocal = /^file:/i.test(document.URL);

// 1.0i
_fss.prototype.parseClass = function (elt,classNames,f) {
	if (!(elt && elt.className))
		return;
	var className = elt.className;

	// HTML4.01 white space
	//  * ASCII space (&#x0020;)
	//  * ASCII tab (&#x0009;)
	//  * ASCII form feed (&#x000C;)
	//  * Zero-width space (&#x200B;)
//  1.0k2: Safari requires \s for spaces
//	var classNamesSplit = className.split(/[\u0020\u0009\u000C\u200B]+/);
	var classNamesSplit = className.split(/\s+/);
	for (j = 0; j < classNamesSplit.length; j++) {
		for (k = 0; k < classNames.length; k++) {
// 1.0h
//			if (classNamesSplit[j] == classNames[k]) {
			if (classNames[k] == '*' || classNamesSplit[j] == classNames[k]) {
//				f.call(this,all[i],classNames[k]);
				f.call(this,elt,classNamesSplit[j],j,classNames[k],k); // (elt,className,classNameIndex,classNameArg,classNameArgIndex)
				this._log('parseClass(): class found:'+classNames[k],0);
			}
		}
	}
}

_fss.prototype.searchClass = function (classNames,f,tagName,top) {
	if (!top) var top = document;
	if (!tagName) var tagName = '*';
	this._log('searchClass(): top:'+top+', tagName:'+tagName,0);
	var all = top.getElementsByTagName(tagName);
	this._log('searchClass(): all.length:'+all.length,0);
	for (var i = 0; i < all.length; i++) {
		all[i].className && this.parseClass(all[i],classNames,f);
//		if (all[i].className) {
//
//			// HTML4.01 white space
//			//  * ASCII space (&#x0020;)
//			//  * ASCII tab (&#x0009;)
//			//  * ASCII form feed (&#x000C;)
//			//  * Zero-width space (&#x200B;)
//			var classNamesSplit = all[i].className.split(/[\u0020\u0009\u000C\u200B]+/);
//			for (j = 0; j < classNamesSplit.length; j++) {
//				for (k = 0; k < classNames.length; k++) {
//// 1.0h
////					if (classNamesSplit[j] == classNames[k]) {
//					if (classNames[k] == '*' || classNamesSplit[j] == classNames[k]) {
////						f.call(this,all[i],classNames[k]);
//						f.call(this,all[i],classNamesSplit[j],j,classNames[k],k); // (elt,className,classNameIndex,classNameArg,classNameArgIndex)
//
//						this._log('searchClass(): class found:'+classNames[k],0);
//					}
//				}
//			}
//		}
	}
}

////////////////////////////////////////////////////////////////
// xxxCookie from http://www.quirksmode.org/
////////////////////////////////////////////////////////////////
// 1.0o: 2007-03-18 _fss.prototype..*Cookie -> _fss..*Cookie
//_fss.prototype.createCookie = function (name,value,days)
_fss.createCookie = function (name,value,days)
{
	if (days)
	{
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
//		var expires = "; expires="+date.toGMTString();
		var expires = "; expires="+date.toUTCString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

//_fss.prototype.readCookie = function (name)
_fss.readCookie = function (name)
{
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++)
	{
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

//_fss.prototype.eraseCookie = function (name)
_fss.eraseCookie = function (name)
{
//	this.createCookie(name,"",-1);
	_fss.createCookie(name,"",-1);
}

_fss.prototype.createCookie = function (name,value,days) { _fss.createCookie(name,value,days); };
_fss.prototype.readCookie = function (name) { return _fss.readCookie(name); };
_fss.prototype.eraseCookie = function (name) { _fss.eraseCookie(name); };

////////////////////////////////////////////////////////////////

_fss.prototype._jlOffStartup	= false;
_fss.prototype._jlHideJlogButtonOnStartup = false;
_fss.prototype._jlogSetUp = function (ini,obj,opId,
		offStartup,hideJlogButtonOnStartup) {
	if (typeof _jlog != 'undefined') {
		if (offStartup) {
			this._jlOffStartup = offStartup;
		}
		if (hideJlogButtonOnStartup) {
			this._jlHideJlogButtonOnStartup = hideJlogButtonOnStartup;
		}
		this.jl = new _jlog(function () { ini.call(obj); },opId);
		this._log =
			function (s,level) { this.jl._jlPuts(s,level); };
	}
}

_fss.prototype._installDirectory = null;
_fss.prototype._prependInstallDirectory = function (path) {
	if (this._installDirectory && this._installDirectory.length && this._installDirectory.charAt(this._installDirectory.length - 1) == '/') {
		return this._installDirectory + path;
	}
	return path;
}


// 1.0j
// 1.0m: 2007-02-25 _fss.prototype.setStyleSheetData -> _fss.setStyleSheetData
_fss.setStyleSheetData = function (elt, style) {
	if (typeof style == 'object') {
		for (var p in style) elt.style[p] = style[p];
	}
	else if (typeof style == 'string') {
		elt.className = style;
	}
};
_fss.prototype.setStyleSheetData =
	function (elt, style) { _fss.setStyleSheetData(elt, style); };



// 1.0n: 2007-03-02 _fss.prototype.xxxxx -> _fss.xxxxx
_fss.prototype.concatenateTextNode =
	function (elt) { return _fss.concatenateTextNode(elt); };
_fss.prototype.concatenateTextNodeById =
	function (id) { return _fss.concatenateTextNodeById(id); };
_fss.prototype.removeTextNode =
	function (elt) { return _fss.removeTextNode(elt); };
_fss.prototype.innerSize =
	function () { return _fss.innerSize(); };
_fss.prototype.scrollSize =
	function () { return _fss.scrollSize(); };
_fss.prototype.findContainingBlockInInlineStyle =
	function (elt) { return _fss.findContainingBlockInInlineStyle(elt); };
_fss.prototype.elementXY =
	function (elt) { return _fss.elementXY(elt); };


// 1.0m: 2007-02-25 _fss.prototype.makeAnimated has been moved into _vaid.js


// 1.0k
_fss.concatenateTextNode = function (element) {
	var text = '';
	if (element.hasChildNodes()) {
		for  (var x = element.firstChild; x; x = x.nextSibling) {
			if (x.nodeName == '#text') {
				text += x.nodeValue;
			}
		}
	}
	return text;
}
_fss.concatenateTextNodeById = function (id) {
	var element = document.getElementById(id);
	if (element) {
		return _fss.concatenateTextNode(element);
	}
	return null;
}
_fss.removeTextNode = function (element) {
	var text = '';
	if (element.hasChildNodes()) {
		for  (var x = element.firstChild; x; x = x.nextSibling) {
			if (x.nodeName == '#text') {
				text += x.nodeValue;
				element.removeChild(x);
			}
		}
	}
	return text;
}

// 1.0l: 2007-02-18 innerSize(),scrollSize


// from <http://www.quirksmode.org/viewport/compatibility.html> 2007-02-17
_fss.innerSize = function () {
	var x,y;
	if (self.innerHeight) // all except Explorer
	{
		x = self.innerWidth;
		y = self.innerHeight;
	}
	else if (document.documentElement && document.documentElement.clientHeight)
		// Explorer 6 Strict Mode
	{
		x = document.documentElement.clientWidth;
		y = document.documentElement.clientHeight;
	}
	else if (document.body) // other Explorers
	{
		x = document.body.clientWidth;
		y = document.body.clientHeight;
	}
	return { x: x, y: y };
}

_fss.scrollSize = function () {
	var x,y;
	if (self.pageYOffset) // all except Explorer
	{
		x = self.pageXOffset;
		y = self.pageYOffset;
	}
	else if (document.documentElement && document.documentElement.scrollTop)
		// Explorer 6 Strict
	{
		x = document.documentElement.scrollLeft;
		y = document.documentElement.scrollTop;
	}
	else if (document.body) // all other Explorers
	{
		x = document.body.scrollLeft;
		y = document.body.scrollTop;
	}
	return { x: x, y: y };
}

// 1.0m: 2007-02-25 findContainingBlockInInlineStyle(),elementXY()

_fss.findContainingBlockInInlineStyle = function (elt) {
	var x = elt.parentNode;
	while (x) {
//		this._log('x.style.position:'+x.style.position);
		if (x.style && (x.style.position == 'absolute' || x.style.position == 'relative' || x.style.position == 'fixed'))
			break;
		x = x.parentNode;
	}
	return x;
}

_fss.elementXY = function (element) {
	var curleft = 0, curtop = 0;
	if (element.offsetParent) {
		while (element.offsetParent) {
			curtop += element.offsetTop
			curleft += element.offsetLeft
			element = element.offsetParent;
		}
	}
	else {
		if (element.x)
			curleft += element.x;
		if (element.y)
			curtop += element.y;
	}
	return { x: curleft, y: curtop } ;
}


// 1.0q: 2007-04-08 added some functions
// _fss.pageSize
// _fss.copyObject
// _fss.mergeObject
// _fss.styleSilhouette
// _fss.styleBody
// _fss.elementObject
// _fss.prototype.changeClass
// _fss.opacity

////////////////////////////////////////////////////////////////
// _fss.pageSize
////////////////////////////////////////////////////////////////

// from <http://www.quirksmode.org/viewport/compatibility.html> 2007-04-01
_fss.pageSize = function () {
	var x,y;
	var test1 = document.body.scrollHeight;
	var test2 = document.body.offsetHeight
	if (test1 > test2) // all but Explorer Mac
	{
		x = document.body.scrollWidth;
		y = document.body.scrollHeight;
	}
	else // Explorer Mac;
	     //would also work in Explorer 6 Strict, Mozilla and Safari
	{
		x = document.body.offsetWidth;
		y = document.body.offsetHeight;
	}
	return { x: x, y: y };
}

_fss.copyObject = function (from,to) {
	for (var prop in from)
		to[prop] = from[prop];
	return to;
};

_fss.mergeObject = function (obj1,obj2) {
	return _fss.copyObject(obj2,_fss.copyObject(obj1, new Object));
};

_fss.styleSilhouette = {
	margin:			'1em',	// height
	backgroundColor:	'#999',
	opacity:		'0.5',
	filter:			'alpha(opacity=50)'
};


_fss.styleBody = {
	width: '10em',
	textAlign: 'center',
	padding: '1ex 1em',
	border: '1px solid #000',
	backgroundColor: '#fff',
	color: '#000'
};

_fss.elementObject = function (object) {
	var element = null;
	if (object) {
		if (object.elt) {
			element = object.elt;
		}
		else if (object.id || object.tagName) {
			element = _fss.elementIdentified(object.id,object.tagName);
		}
		if (element) {
			if (object.title) {
				element.title = object.title;
			}
			if (typeof object.label == 'string') {
				element.appendChild(document.createTextNode(object.label));
			}
			else if (typeof object.label == 'object') {
				element.appendChild(object.label);
			}
			_fss.setStyleSheetData(element,object.style);
		}
	}
	return element;
};

////////////////////////////////////////////////////////////////
// changeClass
////////////////////////////////////////////////////////////////

_fss.prototype.changeClass = function (from,to,tagName,top) {
	var changeObject = new Object;
	var toArray = (to instanceof Array)? to: [to];
	this.searchClass((from instanceof Array)? from: [from],
		function(elt,className,classNameIndex,classNameArg,classNameArgIndex) {
			if (!(className in changeObject)) {
				changeObject[className] = new Object;
				changeObject[className].elts = new Array;
				changeObject[className].to = toArray[classNameArgIndex];
			}
			changeObject[className].elts.push(elt);
			
		},tagName,top);
	for (var className in changeObject) {
		for (var i = 0; i < changeObject[className].elts.length; i++) {
			var elt = changeObject[className].elts[i];
			var toClassName = changeObject[className].to? changeObject[className].to: '';
			var changedClassNameList = elt.className.replace(new RegExp('\\b'+className+'\\b'),toClassName);
			elt.className = changedClassNameList;
		}
	}
};

_fss.opacity = function (elt,v) {
	elt.style.opacity = v;
	elt.style.filter = 'alpha(opacity='+(v*100)+')';
};


// 1.0r: 2007-04-09 element search functions

_fss.searchForward = function (x,reference) {
	while (reference = reference.nextSibling) {
		if (x == reference) return true;
	}
	return false;
}

_fss.searchBackward = function (x,reference) {
	while (reference = reference.previousSibling) {
		if (x == reference) return true;
	}
	return false;
}

_fss.searchSibling = function (x,reference) {
	return _fss.searchBackward(x,reference) || _fss.searchForward(x,reference);
}

_fss.searchUpward = function (x,reference) {
	while (reference = reference.parentNode) {
		if (x == reference) return true;
	}
	return false;
}

_fss.searchDownward = function (x,reference) {
	for (var y = reference.firstChild; y; y = y.nextSibling) {
		if (x == y) return true;
		if (y.firstChild) {
			if (_fss.searchDownward(x,y)) return true;
		}
	}
	return false;
}

_fss.searchInside = function (x,reference) {
	return x == reference || _fss.searchDownward(x,reference);
}

