Function.prototype.inheritsFrom = function( superClass ) {
	if( !superClass ) return false;
	var Inheritance = function(){};
	Inheritance.prototype = superClass.prototype;
	this.prototype = new Inheritance();
	this.prototype.constructor = this;
	this.superClass = superClass;
}

/* ---------------------------------------------------------------------- */

Glyph = function() {
	this.element = null;
	this.Observers = new Array();
}

/* ---------------------------------------------------------------------- */

Glyph.prototype.getEl = function( id ) {
	if( !id ) return false;
	return document.getElementById( id ) || false;
}

/* ---------------------------------------------------------------------- */

Glyph.prototype.attachObserver = function( sEv, Action, Context ) {
	Context = Context || this;

	if( !( Action instanceof Object ) || !( Context instanceof Object ) || ( !this.Observers ) ) return;
	if( !this.Observers[ sEv ] ) this.Observers[ sEv ] = new Array();
	Action = {
		Context: Context,
		Action: Action
	};
	this.Observers[ sEv ].push( Action );
}

/* ----------------------- Detach Observer ------------------------------ */

Glyph.prototype.detachObserver = function( sEv, Action, Context ) {
	Context = Context || this;
	if( !( Action instanceof Object ) || !( Context instanceof Object ) ) return;
	if( this.Observers[ sEv ] ) {
		for( var c in this.Observers[ sEv ] ) {
			var cA = this.Observers[ sEv ][c];
			if( cA.Action == Action && cA.Context == Context ) break;
		}
		this.Observers[ sEv ].splice( c, 1 );
	}
}

/* ---------------------------- Notify ---------------------------------- */

Glyph.prototype.notify = function( sEv, params ) {
	if( !this.Observers[ sEv ] ) return;

	for( var c in this.Observers[ sEv ] ) {
		var cA = this.Observers[ sEv ][c];
		if( cA.Action ) cA.Action.call( cA.Context, params, this );
	}
}

/* -------------------------- Set Class Name -------------------------------- */

Glyph.prototype.setClassName = function( c, f, el ) {
	el = el || this.element;
	if( !el ) return false;
	if( c === false ) { el.className = ''; return; }
	if( typeof( c ) != 'string' ) return false;
	var pt = new RegExp( c, 'gi' );
	if( f === true ) {
		if( !pt.test( el.className ) ) el.className += ' ' + c;
	} else { el.className = el.className.replace( pt, '' ); }
}

/* -------------------------- Add Handler ------------------------------- */

Glyph.prototype.addHandler = function( el, ev, handler, params, capture ) {
	if( !el ) return false;
	if( !el.handlers ) el.handlers = new Array();
	if( !el.handlers[ ev ] ) {
		el.handlers[ ev ] = new Array();
	} else {
		for( var c in el.handlers[ ev ] ) {
			var cH = el.handlers[ ev ][ c ];
			if( cH.handler == handler && cH.context == this ) {
				return false;
			}
		}
	}

	capture = capture || false;
	el.handlers[ ev ][ el.handlers[ ev ].length ] = {
		handler: handler,
		arguments: params,
		capture: capture,
		context: this
	}

	if( !el.handle ) {
		el.handle = function( ev ) {
			return Glyph.commonHandler( ev, el );
		}
	}
	
	if( document.addEventListener ) {
	    if( el.addEventListener )
		    el.addEventListener( ev, el.handle, capture );
	} else {
		if( capture ) el.releaseCapture();
		el.attachEvent( 'on' + ev, el.handle );
	}
}

/* ------------------------- Remove Handler ----------------------------- */

Glyph.prototype.removeHandler = function( el, ev, handler, params, capture ) {
	if( !el ) return false;
	if( !el.handlers || !el.handlers[ ev ] ) return false;

	for( var c in el.handlers[ ev ] ) {
		var cH = el.handlers[ ev ][ c ];
		if( cH.handler == handler && cH.context == this ) break;
	}

	if( cH ) {
		if( document.removeEventListener ) {
			el.removeEventListener( ev, el.handle, cH.capture );
		} else {
			if( cH.capture ) el.releaseCapture();
			el.detachEvent( 'on' + ev, el.handle );
		}

		cH.handler = null;
		cH.arguments = null;
		cH.capture = null;
		el.handlers[ ev ][ c ] = null;
		el.handlers[ ev ].splice( c, 1 );
	}

	if( el.handlers[ ev ] && el.handlers[ ev ].length == 0 ) delete el.handlers[ ev ];
	for( var any in el.handlers ) return;
	el.handlers = false;
	el.handle = false;
}

/* ------------------------- Common Handler ----------------------------- */

Glyph.commonHandler = function( ev, el ) {
	var eventHandlers = el.handlers[ ev.type ];
	for( var c in eventHandlers ) {
		var cH = eventHandlers[ c ];
		if( cH.handler ) cH.handler.call( cH.context, cH.arguments, ev );
	}
}

/* ----------------------- Prevent Default ------------------------------ */

Glyph.prototype.preventDefault = function( ev ) {
	if( !ev ) return false;
	ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
}

/* ----------------------- Stop Propagaion ------------------------------ */

Glyph.prototype.stopPropagation = function( ev ) {
	if( !ev ) return false;
	ev.stopPropagation ? ev.stopPropagation() : ev.cancelBubble = true;
}

/* -------------------------- Create Node ------------------------------- */

Glyph.prototype.createNode = function( n, t, p, h ) {
	if( !n || typeof n != 'string' ) return false;
	var node = document.createElement( n );
	if( !node ) return false;
	
	if( p != undefined ) this.setProperty( p, node );
	if( t != undefined ) this.append( t, node );
	if( h != undefined ) this.setContent( h, node );

	return node;
}

/* ---------------------------- Append ---------------------------------- */

Glyph.prototype.append = function( t, el ) {
	var el = el || this.element;
	if( !el || !t || !t.appendChild ) return false;
	return t.appendChild( el );
}

/* ------------------------ Set Properties ------------------------------ */

Glyph.prototype.setProperty = function( p, el ) {
	el = el || this.element;
	if( !el ) return false;
	for( var c in p ) if( c != 'class' ) el.setAttribute( c, p[c] );
	if( p['class'] ) this.setClassName( p['class'], true, el );
}

/* -------------------------- Set Style -------------------------------- */

Glyph.prototype.setStyle = function( p, el ) {
	el = el || this.element;
	if( !el ) return false;
	for( var c in p ) {
		el.style[ c ] = p[ c ];
	}
}

/* -------------------------- Set Content ------------------------------- */

Glyph.prototype.setContent = function( c, el ) {
	el = el || this.element;
	if( !el ) return false;
	if( c !== undefined ) {
		if( c.element && c.append ) c.append( el );
		else if( c.nodeType ) el.appendChild( c );
		else el.innerHTML = c + '';
	}
}

/* ---------------------------- Offset ---------------------------------- */

Glyph.prototype.offset = function ( el ) {
	var el = el || this.element;
	if( !el ) return false;
	var result = { top: 0, left: 0, width: el.offsetWidth, height: el.offsetHeight };
		
	try {
        while( el ) {
            result.top += el.offsetTop;
            result.left += el.offsetLeft;
            el = el.offsetParent;
        }
    }
    catch(ex) {}
  
	return result;
}

/* -------------------------- isParentOf ------------------------------- */

Glyph.prototype.isParentOf = function( target ) {
	if( !target ) return false;

	while(
		target &&
		target.nodeName &&
		target.nodeName != 'BODY'
	) {
		if( this.element == target ) return true;
		target = target.parentNode;
	}

	return false;
}

/* ------------------------------------------------------------------------------------------------------------ */

Currency = function( id, code, name ) {
	this.id = id;
	this.code = code;
	this.name = name;
}

/* ------------------------------------------------------------------------------------------------------------ */

Currency.prototype.getId = function() {
	return this.id;
}

/* ------------------------------------------------------------------------------------------------------------ */

Currency.prototype.getCode = function() {
	return this.code;
}

/* ------------------------------------------------------------------------------------------------------------ */

Currency.prototype.getName = function() {
	return this.name;
}



/* ------------------------------------- Popup ------------------------------------------------------------- */
/* Class Popup provides methods for later achievement
** 
*/

Popup = function( target ) {
	Popup.superClass.apply( this, arguments );
	this.popup = this.createNode( 'span', document.body );
	if( target ) {
		this.target = target;
		this.setPosition();
	}
	this.hide();
	this.setStyle({ 'position' : 'absolute' }, this.popup );

	while(
		target &&
		target.nodeName &&
		target.nodeName != 'BODY'
	) {
		//if( target.style.position == 'fixed') {
		if( window.$ ) {
			if( $(target).css( 'position' ) == 'fixed' ) {
				this.setStyle({ 'position': 'fixed' }, this.popup );
				break;
			}
		}
		target = target.parentNode;
	}
}
Popup.inheritsFrom( Glyph );


/* ----------------------------------------------------------------------- */

Popup.prototype.show = function( ev ) {
	this.stopPropagation( ev );
	this.setStyle({ 'display': 'block' }, this.popup );
}

/* ----------------------------------------------------------------------- */

Popup.prototype.hide = function( ev ) {
	this.stopPropagation( ev );
	this.setStyle({ 'display' : 'none' }, this.popup );
}

/* ----------------------------------------------------------------------- */

Popup.prototype.setPosition = function( ) {
	var offset = this.offset( this.target );

	this.setStyle({
		'top': offset['top'] - offset['height'] + 'px',
		'left': offset['left'] + 'px'
	}, this.popup );
}
