﻿ 

/**
    The component_common file containers common javascript objects that manage 
    component creation and registration
**/

/**
    common methods
**/

var PT_DEBUG_ON = false;

var debug_win= null;

/// <summary>
///  Debug Out allows the creation of a client side display an error
///  or state of an object used for debugging purposes
/// </summary>
/// <param name="exception"> The exception which occured</param>
/// <param name="object">The object needing to be inspected on error</param>


function Debug_Out(exception,object,funcName)
{
    if(!PT_DEBUG_ON)return;
    if(debug_win == null)
    {
        debug_win = document.createElement("div");
        debug_win.style.position = "absolute";
        debug_win.style.top = "0px";
        debug_win.style.left="800px";
        debug_win.style.width= "400px";
        debug_win.style.height="800px";
        debug_win.style.overflow= "auto";
        debug_win.style.backgroundColor = "white";
        document.body.appendChild(debug_win);
    }
    var stemp="";
    if(funcName!=null){
         stemp += "<strong>"+funcName +"</strong><br/>"
    }
    else
    {
        stemp += "<strong>error</strong><br/>";
    }
    
    for (s in exception)
    {
        stemp += s + " : " + exception[s]+"<br/>";
    }
    stemp+="<br/><br/>";
    stemp +="<strong>object</strong><br/>";
    for(s in object)
    {
       stemp += s + " : "; 
       if(typeof(object[s]) != "function")
       {
            stemp += object[s];
       }
       else{
           stemp +="function";
       }
       stemp +="<br/>";
    }
    stemp+="<br/><br/>";
    debug_win.innerHTML = debug_win.innerHTML + stemp;    
}


///#region  PT_Registered_Component method Implementation
///
/// <summary>
/// Implementation of the  register method of the  PT_Registered_Component class  
///  An instance of newObject can now register it self in the system by calling 
///     this.register("A_NMTOKEN_DEFINED_FOR_NEWOBJECT");        
///  If the object has no parent and
///       this.register("A_NMTOKEN_DEFINED_FOR_NEWOBJECT",parent);        
/// If it does.
/// </summary>
/// <param name="Control_Prefix">A NMTOKEN to define the Control (does not need to be unique except it helps with debugging if it is)</param>
/// <param name="Parent"> A Parent Object that is derived from  PT_Registered_Container</param>

function PT_Registered_ComponentRegister(Control_Prefix,Parent)
{
    if(!window.PTCOMPONENT_REGISTRY)
    {
       new PTComponent_Register();
    }
    this._refIndex =  Control_Prefix+ PT_Registered_Component.count++;  
    if(Parent != null && Parent._Components!= null)
    {
        this._ref= Parent._ref +"._Components['"+this._refIndex+"']";
        Parent._Components[this._refIndex]=this;
        this._PT_Is_Registered = true;
    }
    else if(window.PTCOMPONENT_REGISTRY!=null)
    {
        this._ref="window.PTCOMPONENT_REGISTRY._Components['"+this._refIndex+"']";
        window.PTCOMPONENT_REGISTRY._Components[this._refIndex]= this;
        this._PT_Is_Registered = true;
    }
}
//global count used to name components uniquely
PT_Registered_Component.count = 0;

// <summary>
/// Copies all properties and methods form another object to the object that extends registered component
/// </summary>
///<param name="object">The javascript object </param>
function PT_RegisteredCopyProperties(object){
    for(var prop in object){ 
        this[prop]=object[prop]
    }
}

///#endregion


///#region  PT_Registered_Component Interface


/// <summary>
/// Base Abstract class to derive new Registered Classes from
/// </summary>


function PT_Registered_Component(){

}

PT_Registered_Component.prototype.register          = PT_Registered_ComponentRegister;
PT_Registered_Component.prototype.OnLoad            = function(){};
PT_Registered_Component.prototype.OnUnload          = function(){};
PT_Registered_Component.prototype.OnResize          = function(){};
PT_Registered_Component.prototype.copyProperties    = PT_RegisteredCopyProperties;


///#endregion 


///#region  PT_Registered_Container Implementation

/// <summary>
///  Unloads all the child components of a parent component
/// </summary>

function PT_Registered_ContainerUnloadChildren()
{
    for(var s in this._Components)
    {
        try
        {
            this._Components[s].OnUnload();
            this._Components[s]= null;
        }
        catch(exception)
        {
            Debug_Out(exception,this._Components[s],"Unload")
        }     
    } 
    this._Components = new Object();   
}

/// <summary>
///  Loads all the child components of a parent component
/// </summary>
function PT_Registered_ContainerLoadChildren()
{
    for(var s in this._Components)
    {
        try
        {
            this._Components[s].OnLoad();
        }
        catch(exception)
        {
            Debug_Out(exception,this._Components[s],"Load")
          // standard exception handler here 
        }        
     }    
}

/// <summary>
///  resizes all the child components of a parent component
/// </summary>

function PT_Registered_ContainerResizeChildren()
{
    for(var s in this._Components)
    {
        try
        {
            this._Components[s].OnResize();
        }
        catch(exception)
        {
            Debug_Out(exception,this._Components[s],"resize")
        }     
    } 
}

/// <summary>
///  Calls a named Method on each Child passing in the specified args
/// </summary>
/// <param name="Method"> the name of the method to be called on the children </param>
/// <param name="args"> an array of arguments to pass to the method </param>

function PT_Registered_ContainerCallChildren(Method,args){
    for(var s in this._Components)
    {
        try
        {
            if(typeof this._Components[s][Method] == 'function'){
               this._Components[s][Method](args);             
            }
        }
        catch(exception)
        {
            Debug_Out(exception,this._Components[s],"call " + Method )
        }     
    } 
}

///#endregion 
///#region  PT_Registered_Component Interface
/// <summary>
/// Base Abstract class to derive new parent elements from  from
/// </summary>

function PT_Registered_Container(){
    PT_Registered_Component.call(this);
    this._Components = new Object();
}


PT_Registered_Container.prototype                   = new PT_Registered_Component();
PT_Registered_Container.prototype.ResizeChildren    = PT_Registered_ContainerResizeChildren;
PT_Registered_Container.prototype.UnloadChildren    = PT_Registered_ContainerUnloadChildren;
PT_Registered_Container.prototype.LoadChildren      = PT_Registered_ContainerLoadChildren;
PT_Registered_Container.prototype.CallChildren      = PT_Registered_ContainerCallChildren;




///#endregion

///#region PTComponent_Register

/// the master Component Register
/// <summary>
///
///  A master parent that serves as the default parent for all components register
///  If a components is registered without a parent it registers itself with Component registery
///  This object always creates a single object that is attached to the window object;
/// </summary>

function PTComponent_Register()
{
    if(window.PTCOMPONENT_REGISTRY!=null)
    {
        return;
    }
    PT_Registered_Container.call(this);
    window.PTCOMPONENT_REGISTRY= this;
/** define the loader**/
   	var _loader = function(){
						window.PTCOMPONENT_REGISTRY.LoadChildren();
					};
/** define the resizer**/
					
	var _resizer = function(){
		window.PTCOMPONENT_REGISTRY.ResizeChildren();
					};
/** define the unloader**/
	var _unloader = function(){
		window.PTCOMPONENT_REGISTRY.UnloadChildren();
					};
	if(window.PT_RegisterOnLoad)
	{
		PT_RegisterOnLoad(_loader);
	}
	else{
		window.onload= _loader;
	}
					
	window.onunload = _unloader;
	window.onresize = _resizer;
	

}

PTComponent_Register.prototype = new PT_Registered_Container();

//just removed this to prove a point according to some this code should not work now
//var PTREG = new PTComponent_Register();
// I guess it still works : TTA #1


///#endregion



//Event Object




///#region PT_Event method implementation


/// <summary>
///    Cancel the bubble on an event
/// </summary>



function PT_EventStopPropogation()
{
    if(this._event.stopPropagation)
    {
        this._event.stopPropagation();
        this._event.preventDefault();
    }
    else if(this._event.cancelBubble)
    {
        this._event.cancelBubble=true;
        this._event.returnValue = false;
    }
}



/// <summary>
///     Static methods of the PT_Event object
/// </summary>


/// <summary>
///   static method 
///       Add a crossbrowser event listener to an element
/// </summary>

function PT_EventAddEventListener(Elem,type,listener,useCapture)
{
    if(document.addEventListener!=null)
    {
        Elem.addEventListener(type,listener,useCapture);
    }
    else if(document.attachEvent)
    {
        Elem.attachEvent("on" + type,listener,useCapture);
    }
    else{
        Elem["on"+type]=listener;
    }
}

/// <summary>
///   static method 
///      Remove a crossbrowser event listener to an element
/// </summary>


function PT_EventRemoveEventListener(Elem,type,listener,useCapture)
{
    if(document.removeEventListener!=null)
    {
        Elem.removeEventListener(type,listener,useCapture);
    }
    else if(document.detachEvent)
    {
        Elem.detachEvent("on" + type,listener,useCapture);
    }
    else{
        Elem["on"+type]=null;
    }
}


///#endregion




//#region PT_Event Interface
/// <summary>
///    A Crossbrowser event object used to inspect events with in event listeners
/// </summary>

function PT_Event(evt)
{
    if(evt==null)
    {
        evt = window.event;
    }
    this._event = evt;
    if(this._event!=null)
    {
       this._source = this._event.target; 
    }
    else
    {
        this._source = this._event.srcElement;        
    }
    if(this._event.pageX != null )
    {
        this._x= this._event.pageX;
        this._y = this._event.pageY;
    }
    else
    {
        this._x= this._event.clientX;
        this._y = this._event.clientY;      
    }
}


 PT_Event.prototype.StopPropogation =  PT_EventStopPropogation;
 //Static Methods
 PT_Event.addEventListener          =  PT_EventAddEventListener;
 PT_Event.removeEventListener       =  PT_EventRemoveEventListener;

///#endregion

//#region PT_ElementCoordinates method implementation
/// <summary>
/// PT Element Coordinates provide crossbrowser position and size detection
/// </summary>
// Element Coordinate 

function PT_ElementCoordinatesGetCoords()
{
    var current =this._element;
    while(current != null)
    {
        this.top+=current.offsetTop-current.scrollTop;
        this.left+=current.offsetLeft -current.scrollLeft;
        current= current.offsetParent;
    }
    //Safari special case
    if (navigator.userAgent.indexOf("Mac") != -1 && navigator.userAgent.indexOf("Safari") == -1 && typeof document.body.leftMargin != "undefined") 
    {
        this.left += document.body.leftMargin;
        this.top += document.body.topMargin;
    }
    this.width= this._element.offsetWidth;
    this.height= this._element.offsetHeight;
}


function PT_ElementCoordinatesContain(x,y){
    var does = false;
    if((x >= this.left && x <= (this.left + this.width)) && (y >= this.top && y <= (this.top + this.height))){
        does = true;
    }
    return does;
}

function PT_ElementColliding(left,top,height,width){
    var collide =false;
    var deltaTop= this.top - top;
    var xcheck = ((left + width) >this.left ) && (left < (this.left + this.width));
    var ycheck = ((top + height) > this.top) && (top < (this.top + this.height));
    collide = xcheck && ycheck;
    return collide;
}
///#endregion



//#region PT_Event Interface


function PT_ElementCoordinates(Elm)
{
    this._element = Elm;
    this.top=0;
    this.left= 0;
    this.width=0;
    this.height=0;
    this.getCoords();
}

PT_ElementCoordinates.prototype.getCoords   = PT_ElementCoordinatesGetCoords;
PT_ElementCoordinates.prototype.Contains    = PT_ElementCoordinatesContain;
PT_ElementCoordinates.prototype.Colliding   = PT_ElementColliding;

///#endregion




///#region Utility methods

///cross browsers function to insure the previous element is selected as oppose to text attribute or comment nodes

function getPreviousSibling(Element){
    var temp = Element.previousSibling;
    if(temp==null)return
    if(temp.nodeType==1)
    {
        return(temp);
    }
    else
    {
        return getPreviousSibling(temp);
    }    
}

/// Basic dummy function to avoid dublication

function PT_Dummy_Function(){
    return false;
}

///#endregion


//#region PT_BUTTON method implementation

/// <summary>
/// Button OnLoad event handler
/// </summary>

function PT_BUTTON_OnLoad(){
	if(this._loaded)return;
	this._loaded=true;
    if(this._ButtonLoaded)
    {
        return;
    }
    this._ButtonLoaded=true;
    if(typeof this._Pointer =="string")
    {
        this._canvas= document.getElementById(this._Pointer);
    }
    else
    { 
        this._canvas= this._Pointer;
    }
    if(this._canvas!=null)
    {
        //get the default Class for the element
        this._defaultClassName= this._canvas.className;
        this._elementName=this._canvas.nodeName;
		
		
		var _self = this;
		/**define the click handler**/	
		this._clickHandler	=	function(evt)
										{
											_self.Click(evt);
										};
		this._outHandler	= 	function(evt)
										{
											_self.Out(evt);
										};
		this._overHandler	= 	function(evt)
										{
											_self.Over(evt);
										}
		this._downHandler	= 	function(evt)
										{
											_self.Down(evt);
										}
		this._upHandler	= 	function(evt)
										{
											_self.Up(evt);
										};
													
        this._canvas.onclick =this._clickHandler;
        this._canvas.onmouseover = this._overHandler ;   
        this._canvas.onmouseout = this._outHandler;
        this._canvas.onmousedown = this._downHandler;    
        this._canvas.onmouseup = this._upHandler; 
        if(typeof this._Action== "string"){
            this.onClick= new Function( this._Action );
        }
        else  if(typeof this._Action =="function"){
            this.onClick = this._Action;
        }
    }   
}
/// <summary>
/// Button OnUnload event handler
/// </summary>

function PT_BUTTON_OnUnLoad(){
	   this._canvas.onclick =function(){};
        this._canvas.onmouseover = function(){};  
        this._canvas.onmouseout = function(){};
        this._canvas.onmousedown = function(){};
        this._canvas.onmouseup = function(){};
}    

/// <summary>
/// Button OnClick event handler
/// </summary>

function PT_ButtonClick(evt){
    try
    {
        this.onClick();
    }
    catch(e)
    {
        Debug_Out(e,this,"click");
    }
}

/// <summary>
/// Button OnMouseOut event handler
/// </summary>

function PT_ButtonOut(evt){
    if(this._disabled)return;
    if(this._canvas)
    {
        if(!this._active)
        {
            this._canvas.className=this._defaultClassName;
        }
        else
        {
               this._canvas.className=this._defaultClassName+"-Active";
        }    
    }
    try
    {
        if(this.onMouseOut != null)
        {
            if(typeof this.onMouseOut == "string")
            {
            
                this.onMouseOut = new Function("evt",this.onMouseOut);
            }
            if(typeof this.onMouseOut=="function")
            {
                this.onMouseOut(evt);
            }        
        }
    }
    catch(exception)
    {
    
    }
}


/// <summary>
/// Button OnMouseDown event handler
/// </summary>

function  PT_ButtonDown(evt){
    if(this._disabled)return;
    if(this._canvas){
        this._canvas.className=this._defaultClassName +"-Down";
        try
        {
            if(this.onMouseDown != null)
            {
                if(typeof this.onMouseDown == "string")
                {
                    this.onMouseDown = new Function("evt",this.onMouseDown);
                }
                if(typeof this.onMouseDown=="function")
                {
                    this.onMouseDown(evt);
                }        
            }
        }
        catch(exception)
        {
        
        }
    }
}


/// <summary>
/// Button OnMouseUp event handler
/// </summary>

function PT_ButtonUp(evt){
    if(this._disabled)return;
    if(this._canvas){
        if(!this._active)
        {
            this._canvas.className=this._defaultClassName;
        }
        else
        {
               this._canvas.className=this._defaultClassName+"-Active";
        }    
        try
        {
            if(this.onMouseUp != null)
            {
                if(typeof this.onMouseUp == "string")
                {
                    this.onMouseUp = new Function("evt",this.onMouseUp);
                }
                if(typeof this.onMouseUp=="function")
                {
                    this.onMouseUp(evt);
                }        
            }
        }
        catch(exception)
        {
        
        }
    }
}

/// <summary>
/// Button OnMouseOver event handler
/// </summary>

function PT_ButtonOver(evt){
    if(this._disabled)return;
    if(this._canvas){
        this._canvas.className=this._defaultClassName+"-Hover";
        try
        {
            if(this.onMouseOver != null)
            {
                if(typeof this.onMouseOver == "string")
                {
                    this.onMouseOver = new Function("evt",this.onMouseOver);
                }
                if(typeof this.onMouseOver=="function")
                {
                    this.onMouseOver(evt);
                }        
            }
        }
        catch(exception)
        {
        
        }
        
        
        
    }
}

/// <summary>
/// Disable the Button
/// </summary>


function PT_ButtonDisable(){
    this._disabled= true;
    if(this._canvas){
        this._canvas.className=this._defaultClassName+"-Disabled";
        try
        {
            if(this.onDisable != null)
            {
                if(typeof this.onDisable == "string")
                {
                    this.onDisable = new Function(this.onDisable);
                }
                if(typeof this.onDisable=="function")
                {
                    this.onDisable();
                }        
            }
        }
        catch(exception)
        {
        
        }
        
    }
}

/// <summary>
/// Enable the Button
/// </summary>

function PT_ButtonEnable(){
    this._disabled= false;
    if(this._canvas){
        this._canvas.className=this._defaultClassName;
        try
        {
            if(this.onEnable != null)
            {
                if(typeof this.onEnable == "string")
                {
                    this.onEnable = new Function(this.onEnable);
                }
                if(typeof this.onEnable=="function")
                {
                    this.onEnable();
                }        
            }
        }
        catch(exception)
        {
        }
    }
}

/// <summary>
/// Set the Button as Active
/// </summary>

  function PT_ButtonSetActive()
  {
    this._active= true;
    if(this._canvas){
        this._canvas.className=this._defaultClassName+"-Active";
    }    
  }

/// <summary>
/// Set the Button Inacative
/// </summary>
  
   
   function PT_ButtonSetInActive()
   {
    this._active= false;
    if(this._canvas){
        this._canvas.className=this._defaultClassName;
    }    
   }
  
  
 ///#endregion
 
 
 //#region PT_Event Interface
 
 //Basic Button Object used to bind any html element to be actionable
// Assumes the button has five class states
// normal:      the base {classname}
// hover:       {classname}-Hover
// down:        {classname}-Down
// active:      {classname}-Active
// disabled:    {classname}-Disabled

function PT_Button(Button_Ptr,Action,Parent){
    PT_Registered_Component.call(this);
    this._Pointer = Button_Ptr;
    this._Action= Action;
    this._canvas= null;
    this.register("BUTTON",Parent);    
    this._defaultClassName = "";
    this._elementName="";
    this._disabled= false;
    this._active= false;
    this._ButtonLoaded=false;
    //these are events handlers specific to the 
    //instance object so they arer not defined on the class 
    this.onClick = function(){};    
    this.onMouseOver = function(){};
    this.onMouseOut = function(){};
    this.onMouseDown = function(){};
    this.onMouseUp = function(){};
    this.onDisable = function(){};
    this.onEnable= function(){};
}

PT_Button.prototype             = new PT_Registered_Component();
PT_Button.prototype.OnLoad      = PT_BUTTON_OnLoad;
PT_Button.prototype.OnUnload    = PT_BUTTON_OnUnLoad;    
PT_Button.prototype.Click       = PT_ButtonClick;
PT_Button.prototype.Out         = PT_ButtonOut;
PT_Button.prototype.Down        = PT_ButtonDown;
PT_Button.prototype.Up          = PT_ButtonUp;
PT_Button.prototype.Over        = PT_ButtonOver;
PT_Button.prototype.Disable     = PT_ButtonDisable;
PT_Button.prototype.Enable      = PT_ButtonEnable;
PT_Button.prototype.SetActive   = PT_ButtonSetActive;
PT_Button.prototype.SetInActive = PT_ButtonSetInActive;

//a common class to control dynamic script referencing

/// <summary>
/// PT_ScriptRegistry handles the insertion of scripts into the Head element 
///of an html page dynamically
/// </summary>



/// <summary>
/// PT_ScriptRegistry Onload event handler
/// </summary>

function PT_ScriptRegistryOnLoad()
{
  // get the head tag 
  
  	if(this._loaded)return;
	this._loaded=true;
  this._Head = document.getElementsByTagName("head").item(0);
  if(this._Head != null)
  {
    //get a refreence to all scripts already in the head element
    var scripts = this._Head.getElementsByTagName("SCRIPT");
    var len = scripts.length;
    currentIndex = 0;
    //iterate through each script already inserted in the head
    for(var scriptIndex = 0; scriptIndex < len; scriptIndex++){
        var script= scripts[scriptIndex];
        if(script.src != ""){
            //if the script has a source attribute create a new script refrence for it
            var scriptRef = new  PT_Script_Reference(script.src);
            //insert it into the scripts collection
            this._scripts[currentIndex]    = scriptRef;
            //increment the script count
            currentIndex++;
        }
    }    
  }  
}

/// <summary>
/// Add a new script reference to the registry
/// </summary>
/// <param name="ScriptRef">PT_Script_Reference object containing the script Src</param>
function PT_ScriptRegistryAddScript(ScriptRef){
    var len = this._scripts.length;
    var bFound = false;
    for(var scriptIndex=0 ; scriptIndex<len; scriptIndex++){
        //iterate through each already inserted script 
        if(this._scripts[scriptIndex]._Src==ScriptRef._Src){
            bFound = true;
            // set a flag if found and drop out of loop
            break;
        }    
    }  
    if(!bFound){
        // if the script was not found then add it
        this._scripts[len] = ScriptRef;
        // insert the script into the head by resolving it
        this.ResolveScript(ScriptRef);
    }
}

/// <summary>
/// Resolve the script reference
/// </summary>
/// <param name="ScriptRef">PT_Script_Reference object containing the script Src</param>

function PT_ScriptRegistryResolveScript(ScriptRef, Frame){
    if(Frame!= null)
    {
        var framedoc = Frame.document;
        if(framedoc != null)
        {
            var frameHead = framedoc.getElementsByTagName("head").item(0);
            if(frameHead != null)
            {
                newScript = framedoc.createElement("script");    
                newScript.setAttribute("src",ScriptRef._Src);
	            frameHead.appendChild(newScript);
            }
        }
    }
    else if(this._Head != null){
        //create
        newScript = document.createElement("script");
        newScript.setAttribute("src",ScriptRef._Src);
	    this._Head.appendChild(newScript);
    }
}


/// <summary>
///  Copies all registered Scripts to a contained frame
/// </summary>
/// <param name="Frame">A pointer to a frame which need all the scripts</param>


function PT_ScriptRegistryCopyScripts(Frame){
    var len = this._scripts.length;
    for(var scriptIndex=0 ; scriptIndex<len; scriptIndex++){
        //iterate through each script and resolve it the frame
        this.ResolveScript(this._scripts[scriptIndex],Frame);
    } 
   
   
}


/// <summary>
/// OnUnload ebvent handler
/// </summary>


function PT_ScriptRegistryOnUnload()
{
    this._scripts= null;
}

/// <summary>
/// 'tor for PT_ScriptRegistry
/// </summary>

function PT_ScriptRegistry()
{
    //if it already exists then exit
   if(window.PT_SCRIPTREGISTRY != null)
   {
        return;
   } 
   //set Global singleton reference to the script registry
   PT_Registered_Component.call(this); 
   window.PT_SCRIPTREGISTRY= this; 
   this.register("ScriptReg");
   //create an array to hold the script references
   this._scripts= new Array();
   // a pointer to the head element
   this._Head = null; 
}
// register the component with the registry

PT_ScriptRegistry.prototype                 = new PT_Registered_Component(); 
PT_ScriptRegistry.prototype.OnLoad          = PT_ScriptRegistryOnLoad;
PT_ScriptRegistry.prototype.OnUnload        = PT_ScriptRegistryOnUnload;
PT_ScriptRegistry.prototype.AddScript       = PT_ScriptRegistryAddScript;
PT_ScriptRegistry.prototype.ResolveScript   = PT_ScriptRegistryResolveScript;
PT_ScriptRegistry.prototype .CopyScripts    = PT_ScriptRegistryCopyScripts;

/// <summary>
/// An Object used to store a script source use to store a registerered script
/// </summary>
/// <param name="Scr">the Url use to resolve the script</param>

function PT_Script_Reference(src)
{
    this._Src= src;
}


//Create the Globale Scriptregistry
new PT_ScriptRegistry();


var DIALOG_MIN_HEIGHT= 100;
var DIALOG_MIN_WIDTH= 200;
var DIALOG_DEFAULT_URL= "/dir-app/blank.htm";


function PT_Modal_DialogOnLoad(){
	if(this._loaded)return;
	this._loaded=true;
    this._canvas = document.createElement("DIV");
    this._canvas.style.position="absolute"	;
    this._canvas.style.display="none"; 		
    document.body.appendChild(this._canvas);
    this._frameCanvas= document.createElement("IFRAME");
    this._frameCanvas.frameBorder=0;
    //name the frame uniquely using the refIndex
    this._frameCanvas.name=this._refIndex;
    this._frameCanvas.id=this._refIndex;
    this._frameCanvas.src = DIALOG_DEFAULT_URL;
    this._canvas.appendChild(this._frameCanvas);
    this._frame= window.frames[this._refIndex];
    this.OnResize();
    if(parent)
    {
        if(parent.PTMODALDIALOG)
        {
            parent.PTMODALDIALOG.OnResize();
        }
    }
}

function PT_Modal_DialogOpen(url,width,height,resizable)
{
	if(!this._visable)
	{ 
        if(width == null)
        {
           this._minWidth = DIALOG_MIN_WIDTH;
        }
        else
        {
            this._minWidth=width;
        }
        if(height==null)
        {
            this._minHeight = DIALOG_MIN_HEIGHT;
        }
        else
        {
            this._minHeight = height;
        }
        if(resizable!= null){
           this._resizable= resizable;
        }
        else
        {
            this._resizable= true;
        }   
        if(this._canvas==null)
        {
            return;
        }
        this._frame.location= url;
        this._canvas.style.display="block";
        this._canvas.style.zIndex=999;
        this._visable = true;
    }
}

function PT_Modal_DialogClose(refresh){
    this._visable = false;
    this._canvas.style.display="none";
    this._frame.location= DIALOG_DEFAULT_URL;
    if(refresh){
        window.location.href = window.location.href;    
    }
}

function PT_ModalDialogSetDimensions(){
    if(this._canvas != null){
        this._canvas.style.top = (document.body.scrollTop + this._top) + "px";
        this._canvas.style.left = (document.body.scrollLeft + this._left) + "px";
        this._canvas.style.width = (this._width) + "px";
        this._canvas.style.height= (this._height) + "px";
    }
    if(this._frameCanvas != null){
      this._frameCanvas.style.width = (this._width) + "px";
      this._frameCanvas.style.height= (this._height) + "px";
    }
}

function PT_ModalDialogResize()
{
    
    this.CalculateDimensions();
    var winH = document.body.clientHeight;
    var winW = document.body.clientWidth;
    var padT = Math.floor(winH /5);
    if(!this._resizable)
    {
        this._height = this._minHeight;
        this._width = this._minWidth;                           
    }
    else
    {
        this._height =winH - 2*(padT);
        if(this._height < this._minHeight )	{
	        this._height = this._minHeight;
        }
        this._width = winW - 200;
        if(this._width < this._minWidth )	{
	        this._width = this._minWidth;
        }
    }
    this._left = Math.floor((winW-this._width)/2);
    this._top = Math.floor((winH-this._height)/5);
    this.SetDimensions();
}


function PT_ModalDialogCloseModal(target){
    if(target != null)
    {
        if(target["PTMODALDIALOG"] != null){
            target["PTMODALDIALOG"].Close();            
        }
    }
}

function PT_ModalDialogCalculateDimensions()
{
    var winH = document.body.clientHeight;
    var winW = document.body.clientWidth;
    if(this._frame)
    {
        if(this._frame.document)
        {
            if(this._frame.document.body){
                this._minHeight=this._frame.document.body.scrollHeight;
                this._minWidth=this._frame.document.body.scrollWidth;
            }
        }
    }
    if(this._minHeight > winH )
    {
        this._minHeight= winH;
    }   
    if(this._minWidth > winW )
    {
        this._minWidth= winW;
    }   
}


function PT_Modal_Dialog(){
    if(window.PTMODALDIALOG != null)
    {
        //create a single instance of the Dialog;
        return;
    }
    window.PTMODALDIALOG=this;
    PT_Registered_Component.call(this);
    this.register("ModelDialog");
    this._frame = null;
	this._frameCanvas = null;
	this._canvas= null;
	this._visable = false;
	this._width= 0;
	this._height= 0;
	this._left= 0;
	this._top= 0;	
    this._body = null;
    this._minHeight= DIALOG_MIN_HEIGHT;
    this._minWidth = DIALOG_MIN_WIDTH;
    this._resizable = true;
}


PT_Modal_Dialog.prototype                       = new PT_Registered_Component();
PT_Modal_Dialog.prototype.OnLoad                = PT_Modal_DialogOnLoad;
PT_Modal_Dialog.prototype.Open                  = PT_Modal_DialogOpen;
PT_Modal_Dialog.prototype.Close                 = PT_Modal_DialogClose;
PT_Modal_Dialog.prototype.SetDimensions         = PT_ModalDialogSetDimensions;
PT_Modal_Dialog.prototype.OnResize              = PT_ModalDialogResize;

PT_Modal_Dialog.prototype.CalculateDimensions   = PT_ModalDialogCalculateDimensions;
PT_Modal_Dialog.prototype.closeModal            = PT_ModalDialogCloseModal;

new PT_Modal_Dialog();


/// <summary>
///Tools for handling Opacity setting
/// </summary>


/// <summary>
/// First initialization of the opacity tools 
/// </summary>

function OpacityToolsInit(oNode)
{
	this.isSupported = true;
	if(typeof oNode.style.MozOpacity != "undefined")
	{
		this._property = "MozOpacity";
	}
	else if(typeof oNode.style.opacity != "undefined")
	{
		this._property = "opacity";
	}
	else if(typeof oNode.style.KhtmlOpacity != "undefined")
	{
		this._property = "KhtmlOpacity";
	}
	else if(typeof oNode.style.filter != "undefined")
	{
		this._property = "filter";
		this._isIE = true;
		this._regExpGet = /.*opacity=([0-9]+).*/; // IE doesn't seem to understand \d
		this._regExpSet = /(.*opacity=)[0-9]+(.*)/;
	}
	else
	{
		this.isSupported = false;
	}
	this.isInitiated = true;
}


/// <summary>
///     Set opacity on an element
/// </summary>

function OpacityToolsSet(oNode,nValue,skey)
{
	if(skey && !oNode)
	{
		oNode=document.getElementById(skey);
	}
	if(!this.isInitiated)
	{
	    this.initiate(oNode);
    }
	if(!this.isSupported)
	{
	    return null;
	}	
	nValue = Math.round(nValue);
	if(!this._isIE)
	{
		oNode.style[this._property] = nValue / 100;
		return nValue;
	}
	else if(this.get(oNode) != null)
	{ 
		oNode.style[this._property] = (oNode.currentStyle ? oNode.currentStyle[this._property] : oNode.style[this._property]).replace(this._regExpSet, "$1" + nValue + "$2");
		return nValue;
	}
	else
	{
		oNode.style[this._property] +=  "alpha(opacity=" + nValue + ")";
		return nValue;
	}
	return null;
}


/// <summary>
/// Inspect the opacity of an element
/// </summary>

function OpacityToolsGet(oNode)
{
	var sStyle;
	if(!this.isInitiated)
	{
	    this.initiate(oNode); 
    }
	if(!this.isSupported)
	{
	    return null; 
	}
	sStyle = document.defaultView ? document.defaultView.getComputedStyle(oNode, null)[this._property] : oNode.currentStyle ? oNode.currentStyle[this._property] : oNode.style[this._property];
	if(!this._isIE){
		return isNaN(sStyle) ? null : sStyle * 100;
	} else {
		return sStyle.match(this._regExpGet) ? sStyle.replace(this._regExpGet, "$1") : null;
	}
	return null;
}

/// <summary>
/// The OpacityTools Object
/// </summary>

OpacityTools = new Object();
OpacityTools.isSupported =null;
OpacityTools.isInitiated = false;
OpacityTools._IE=false;
OpacityTools._property= null;
OpacityTools._regexpGet= null;
OpacityTools._regexpSet= null;
OpacityTools.initiate = OpacityToolsInit;
OpacityTools.set = OpacityToolsSet;
OpacityTools.get = OpacityToolsGet;


/// <summary>
///     The Library Object used to access utility methods and provide some namespace scoping
/// </summary>

function PTLibrary(){
    if(window.PTLib != null){
        return;
    }
    window.PTLib = this;
    this.Utility = new PTUtility();
}


/// <summary>
///    The Utilty Object used to access utility methods 
/// </summary>


function PTUtility(){
    this.RemoveElement = PTUtilityRemoveElement;
    this.GetElement =PTUtilityGetElement;
}

/// <summary>
///   Remove an element with an Id from the document
/// </summary>
/// <param name="elemId">The Id to be removed</param>

function PTUtilityRemoveElement(elemId){
    var elmToRemove = document.getElementById(elemId);
	if (elmToRemove)
	{
		elmToRemove.parentNode.removeChild(elmToRemove);
	}
}


/// <summary>
///   Gain reference to an element by its ID or script reference 
/// </summary>
/// <param name="elm">either an string containing the elements id or the element itself </param>
function PTUtilityGetElement(elm)
{
	// if the elm is a string, use it as an ID
	if (typeof elm == "string")
	{
		var theElm = document.getElementById(elm);
		return theElm;
	}
	return elm; // otherwise (for now) assume it's an element
}

// Contsruct the common Libary object

var lib = new PTLibrary();




//#region PT_DataCollection Interface

/// <summary>
///   PT_DataCollection provides a generic double linked list collection of data items used a a generic data model
///   The data collection can be linked to a controller to allow the registrations of views 
/// </summary>


/// <summary>
///   Implementation of the Add method
/// </summary>
/// <param name="item">the item to add to the collection</param>
function PT_DataCollectionAdd(item)
{
    // if item does not exist then drop out
    if(!item) return;
    // Coerce the item into a DataCollectionItem
    item = this.coerce(item);
	var thisId=item._refIndex;
	//use the unique _refIndex property of a registered component as a key
	if (thisId)
	{
	    //iff it has an id
		if (this.Items[thisId])
		{
			//an with this key exists,replace it
			item.next = this.Items[thisId].next;
			item.prev = this.Items[thisId].prev;
            if(this.Loaded){
                //it the page is already load use 
            
                item._dataElement =this.Items[thisId]._dataElement
                item._dataElement._boundItem= item;
            }
			this.Items[thisId] = item;
			this.select(thisId); // added item is always made current
			return item; // already here, just return it
		}
		else
		{
            this.length++;
		}
		if (this.firstItem !== null)
		{	
			var tmpObj = this.Items[this.lastItem];
			item.prev = this.lastItem;
			item.next = tmpObj.next;
			tmpObj.next = thisId;
			tmpObj = this.Items[item.next];
			tmpObj.prev = thisId;
			tmpObj = null;
		}
		else
		{
		    //if there is no firstItem this must be the first item
			this.firstItem = thisId;
			this.CurItem = thisId;
			item.prev = thisId;
			item.next = thisId;
		}
		//refrence the item by it's ref index and by an integer index by pushing it onto the array
		this.Items[thisId] = item;
		this.Items.push(item);
		//since its the last item placed in the collection set the lastid
		this.lastItem = thisId;
        if(this.Loaded){	
           //if the collection has already has had its onload method invoke then add an element
           //to represent this item in the html element used as a data island for the collection
            this.addElement(item);       
            this._resetFromElms();
        }
        // return the item
		this.select(thisId);
		return item;
	}
	// error - 
	return null;
}


/// <summary>
///   Implementation of the InsertBefore method
/// </summary>
/// <param name="newitem">the item to be added to the collection</param>
/// <param name="refitem">the pre-existing(or its key) item in the collection to insert the new item before</param>

function PT_DataCollectionInsertBefore(newItem, refItem)
{
  // exit if there is nothing to insert  
  if(!newItem) return;
  
  //coerce the newitem
  newItem = this.coerce(newItem);
  var refKey = PT_DataCollection.GetItemKey(refItem);  
  if(this.containsKey(refKey)){
    refItem = this.Items[refKey];
  }
  else
  {
    refItem = this.Items[this.firstItem];
  }  
  if(refItem != null && refItem._dataElement != null)
  {
      if(newItem._dataElement!=null)
      {
        // the new item already exists in the collection - remove its dataflement first
        this.element.removeChild(newItem._dataElement);      
      }  
    this.element.insertBefore(newItem._dataElement ,refItem._dataElement );      
    this._resetFromElms();
  }
}


function PT_DataCollectionItem(ref)
{
    return this.Items[ref];
}


function PT_DataCollectionAddElement(item){
   var childElem = document.createElement("div");
   childElem.setAttribute("id", item._refIndex);
   childElem.innerHTML = item._refIndex;
   this.element.appendChild(childElem);
   item._dataElement =childElem;
   childElem._boundItem= item; 
}



function PT_DataCollectionCoerce(item){
     if(!item)
     {
        return null; 
     }  
     if(item.collection != this)
     {
         return new PT_DataCollectionItem(this,item)
     }    
     else
     {
        return item;
     }
 }   

function PT_DataCollectionRemove(ItemRef)
{
   var theKey = "";
   if(typeof ItemRef =='string')
   {
        theKey = ItemRef;
   }
   else if(typeof ItemRef =='object')
   {
        theKey = ItemRef._refIndex;
   }
   if(this.containsKey(theKey)){
        var objtemp = this.Items[theKey];
        this.Items[objtemp.prev].next = objtemp.next;
        this.Items[objtemp.next].prev = objtemp.prev;
        if(this.firstItem==theKey){
            this.firstItem = objtemp.next;
        }        

        if(this.lastItem==theKey){
            this.lastItem = objtemp.prev;
        }        

        if((objtemp.prev==theKey)&&(objtemp.next==theKey)){
        	this.firstItem = null;
	        this.lastItem = null;
	        this.curItem = null;
        }
        if(this.Loaded){
           this.element.removeChild(this.Items[theKey]._dataElement);
           this._resetFromElms();   
        }
        else
        {
           this.Items[theKey]= null;        
        }
        return objtemp;
   }
}


function PT_DataCollectionContains(Item)
{
    var found = false;
    if(Item._refIndex)
    {
        found = this.containsKey(Item._refIndex); 
    }
    return found;
}

function PT_DataCollectionContainKey(Key)
{
    var found = false;
    if(this.Items[Key]){
        found = true;
    }
    return found;    
}

function PT_DataCollectionSelect(Key)
{
    if(this.Item){
        this.Item._selected = false;    
    }
	var item = this.Items[Key];
	if (item)
	{
		this.curItem = Key;
		this.Item =item;

	}
    if(this.Item){
        this.Item._selected = true;    
    }
	return this.Item;
}

function PT_DataCollectionOnload()
{
	if(this._loaded)return;
	this._loaded=true;
    this.element = document.createElement("div");
    this.element.setAttribute("id", this._refIndex);
    this.element.style.display = 'none';
//    document.body.appendChild(this.element);

    var len = this.Items.length;
    for(var i = 0; i< len;i++)
    {
        this.addElement(this.Items[i]);
    }
    this._AJAXHOLDER = document.createElement("div");
    this._AJAXHOLDER.style.display = 'none';
   // document.body.appendChild(this._AJAXHOLDER);
    this.Loaded= true;
}

function PT_DataCollectionResetFromElms()
{
    var count = 0;
    if(!this.Loaded){
        return;
    }
    this.Items = new Array();
    var length = this.element.childNodes.length;
    
    
    this.firstItem = null;
    this.lastItem = null;
    for(var index = 0; index< length; index ++)
    {
        var item = this.element.childNodes[index]._boundItem
        if(item !=null){
            var thisId = item._refIndex;
            if(!this.firstItem)
            {
                this.firstItem = thisId;
    		    this.lastItem = thisId;
	    		item.prev = thisId;
		    	item.next = thisId;
            }
            else
            {
              	var tmpObj = this.Items[this.lastItem];
	    		item.prev = this.lastItem;
		    	item.next = tmpObj.next;
			    tmpObj.next = thisId;
			    tmpObj = this.Items[item.next];
			    tmpObj.prev = thisId;
			    tmpObj = null;
            }
            this.Items[thisId]= item; 
            this.lastItem = thisId;
            this.Items.push(item);
            count++;       
        }
    }    
    this.length = this.Items.length;
    this.DataSetChange();
}

function  PT_DataCollectionMoveUp(ItemRef){
    if(!ItemRef)
    {
        return;
    }
    var thisId = "";
    if(typeof ItemRef == 'string')
    {
        thisId = ItemRef;    
    }
    else
    {
        if(ItemRef._refIndex){
            thisId = ItemRef._refIndex;    
        }
    }
    if(thisId == this.firstItem)
    {
        //already at top
        return;
    }
    if(this.containsKey(thisId)){
       	var tmpObj = this.Items[thisId];
        var previousObj = this.Items[tmpObj.prev];
        if(previousObj._dataElement && tmpObj._dataElement)
        {
            this.element.insertBefore(tmpObj._dataElement,previousObj._dataElement);
            this._resetFromElms();
        }
    }
}


function PT_DataCollectionMoveDown(ItemRef){
    if(!ItemRef)
    {
        return;
    }
    var thisId = "";
    if(typeof ItemRef == 'string')
    {
        thisId = ItemRef;    
    }
    else
    {
        if(ItemRef._refIndex){
            thisId = ItemRef._refIndex;    
        }
    }
    if(thisId == this.lastItem)
    {
        //already at bottom
        return;
    }
    if(this.containsKey(thisId)){
       	var tmpObj = this.Items[thisId];
        var nextObj = this.Items[tmpObj.next];
        if(nextObj._refIndex == this.lastItem){
            //the next item is the last in the list so 
            //just remove the element and append it
            this.element.removeChild(tmpObj._dataElement);
            this.element.appendChild(tmpObj._dataElement);
        } 
        else
        {
           nextObj = this.Items[nextObj.next];
           if(nextObj._dataElement && tmpObj._dataElement)
           {
                this.element.insertBefore(tmpObj._dataElement,nextObj._dataElement);
                
           }  
        }
        this._resetFromElms();
    }
}




function PT_DataCollectionMoveToBottom(ItemRef){
    if(!ItemRef)
    {
        return;
    }
    var thisId = "";
    if(typeof ItemRef == 'string')
    {
        thisId = ItemRef;    
    }
    else
    {
        if(ItemRef._refIndex){
            thisId = ItemRef._refIndex;    
        }
    }
    if(thisId == this.lastItem)
    {
        //already at bottom
        return;
    }
    if(this.containsKey(thisId))
    {
       	var tmpObj = this.Items[thisId];
        this.element.removeChild(tmpObj._dataElement);
        this.element.appendChild(tmpObj._dataElement);
        this._resetFromElms();
    }
}



function  PT_DataCollectionMoveToTop(ItemRef){
    if(!ItemRef)
    {
        return;
    }
    var thisId = "";
    if(typeof ItemRef == 'string')
    {
        thisId = ItemRef;    
    }
    else
    {
        if(ItemRef._refIndex){
            thisId = ItemRef._refIndex;    
        }
    }
    if(thisId == this.firstItem)
    {
        //already at top
        return;
    }
    if(this.containsKey(thisId)){
       	var tmpObj = this.Items[thisId];
        var firstObj = this.Items[this.firstItem];
        if(firstObj._dataElement && tmpObj._dataElement)
        {
            this.element.insertBefore(tmpObj._dataElement,firstObj._dataElement);
            this._resetFromElms();
        }
    }
}


function PT_DataCollectionAjaxReply(xhr,status){
    if(this._AJAXHOLDER){
        this._AJAXHOLDER.innerHTML = xhr.responseText;
        var divs = this._AJAXHOLDER.getElementsByTagName("DIV");
        var length = divs.length;
		var bScriptFound = false;
        for(var divIndex=0;divIndex < length; divIndex++)		
		{
            if(divs[divIndex].className="JSONRESPONSE")
            {
                try
                {
                    this._jsonEval = new Function(divs[divIndex].innerHTML);
                    this._jsonEval();
                    this.DataSetChange();
                    break;
                }
                catch(exception)
                {
                }
            }		
		}
    }
    
}

function PT_DataCollectionMakeAjaxRequest(command){
    PTButtonCmdAjax(this._AjaxDataSource, "", new Function("xhr,status" ,this._ref+ ".OnAjaxReply(xhr,status)") ,command , "");
}


function PT_DataCollectionGetIterator(){
    return new PT_Collection_Iterator(this);
}

function PT_DataCollectionRefreshViews(){
    this._resetFromElms();
}

function PT_DataCollectionAddListener(Listener){
    if(Listener)
    {
        if(typeof Listener.OnDataSetChange =='function')
        {
           Listener.Data = this; 
           this._Listeners.push(Listener); 
        }
    }
}

function PT_DataCollectiOnDataSetChange(){
    var length = this._Listeners.length;
    for(var index = 0; index <length;index++)
    {
        try
        {
          this._Listeners[index].OnDataSetChange(this);
        }
        catch(exception)
        {
            Debug_Out(exception, this._Listeners[index],"datasetchange");
        }
    }
}


function PT_DataCollectionGetItemKey(RefItem)
{
    if(RefItem==null)
    {
        return "";
    }
    if(typeof RefItem =="string")
    {
        return RefItem;
    }
    else if(RefItem._refIndex)
    {
        return RefItem._refIndex;
    }
    else
    {
        return "";
    }
}


function PT_DataCollection(AjaxDataSource)
{
    PT_Registered_Container.call(this);
	this.firstItem = null; // set only once, when first item is added
	this.lastItem = null;
	this.curItem= null;
	this.Items = new Array();
    this.length = 0;
    this.register("DATACOLLECTION");
    this.Item = null;
    this.element = null;
    this._AjaxDataSource = AjaxDataSource;
    this._AJAXHOLDER= null;
    this._Listeners = new Array();
}

PT_DataCollection.prototype                 = new PT_Registered_Container(); 
PT_DataCollection.prototype.add             = PT_DataCollectionAdd;
PT_DataCollection.prototype.insertBefore    = PT_DataCollectionInsertBefore;
PT_DataCollection.prototype.Item            = PT_DataCollectionItem;
PT_DataCollection.prototype.addElement      = PT_DataCollectionAddElement;
PT_DataCollection.prototype.select          = PT_DataCollectionSelect;
PT_DataCollection.prototype.remove          = PT_DataCollectionRemove;
PT_DataCollection.prototype.contains        = PT_DataCollectionContains;
PT_DataCollection.prototype.containsKey     = PT_DataCollectionContainKey;
PT_DataCollection.prototype.coerce          = PT_DataCollectionCoerce;  
PT_DataCollection.prototype._resetFromElms  = PT_DataCollectionResetFromElms;  
PT_DataCollection.prototype.moveUp          = PT_DataCollectionMoveUp;
PT_DataCollection.prototype.moveDown        = PT_DataCollectionMoveDown;
PT_DataCollection.prototype.moveToBottom    = PT_DataCollectionMoveToBottom;
PT_DataCollection.prototype.moveToTop       = PT_DataCollectionMoveToTop;
PT_DataCollection.prototype.OnLoad          = PT_DataCollectionOnload;
PT_DataCollection.prototype.addListener     = PT_DataCollectionAddListener;
PT_DataCollection.prototype.DataSetChange   = PT_DataCollectiOnDataSetChange;
PT_DataCollection.prototype.OnAjaxReply     = PT_DataCollectionAjaxReply;
PT_DataCollection.prototype.MakeAjaxRequest = PT_DataCollectionMakeAjaxRequest;
PT_DataCollection.prototype.Iterator        = PT_DataCollectionGetIterator;

PT_DataCollection.prototype.RefreshViews    = PT_DataCollectionRefreshViews;
//static methods
PT_DataCollection.GetItemKey                = PT_DataCollectionGetItemKey;

function PT_DataCollectionItemMoveUp(){
    if(this.collection)
    {
        this.collection.moveUp(this);
    }
}

function PT_DataCollectionItemMoveDown(){
    if(this.collection)
    {
        this.collection.moveDown(this);
    }
}


function PT_DataCollectionItemToTop()
{
    if(this.collection)
    {
        this.collection.moveToTop(this);
    }

}

function  PT_DataCollectionItemToBottom()
{
    if(this.collection)
    {
        this.collection.moveToBottom(this);
    }
}


function PT_DataCollectionItemSelect(){
    if(this.collection)
    {
        this.collection.select(this._refIndex);
    }
    this.RefreshViews();
}


function PT_DataCollectionItemRefreshViews(){
    if(this.collection)
    {
        this.collection.RefreshViews();
    }
}

function PT_DataCollectionItem(collection,object){
   PT_Registered_Component.call(this);   
   this.copyProperties(object); 
   this.register("Item",collection);
   this.collection = collection;
}





PT_DataCollectionItem.prototype             =  new PT_Registered_Component();
PT_DataCollectionItem.prototype.moveUp      =  PT_DataCollectionItemMoveUp;
PT_DataCollectionItem.prototype.moveDown    =  PT_DataCollectionItemMoveDown;
PT_DataCollectionItem.prototype.toTop       =  PT_DataCollectionItemToTop;
PT_DataCollectionItem.prototype.toBottom    =  PT_DataCollectionItemToBottom;

PT_DataCollectionItem.prototype.Select    =  PT_DataCollectionItemSelect;

PT_DataCollectionItem.prototype.RefreshViews    =  PT_DataCollectionItemRefreshViews;


function PT_ControllerOnDataSetChange()
{
    for(var s in  this._views)
    {
        try
        {
          this._views[s].OnDataSetChange(this.Data);              
        }
        catch(exception)
        {
             Debug_Out(exception,  this._views[s],"dataSetChange");
        }
    }
}


function PT_ControllerOnSelectionChange()
{
    for(var s in  this._views)
    {
        try
        {
          this._views[s].OnSelectionChange(this._CurrentItem);              
        }
        catch(exception)
        {
             Debug_Out(exception,    this._CurrentItem,"selection change");
        }
    }
}


function PT_ControllerSelectItem(key)
{
    this._CurrentItem=this.Data.select(key);
    this.OnSelectionChange(this._CurrentItem);
}

function PT_ControllerAddView(View)
{
    

    if(View != null)
    {
        //insure the View implements the inteface with methos OnDataSetChange
        if((typeof View.OnDataSetChange=='function') && typeof View._refIndex =='string')
        {
           this._views[View._refIndex] =View;  
           this._views[View._refIndex].Controller = this;      
        }
    }
}



function PT_ControllerFirst()
{
    this.SelectItem(0);
}



function PT_ControllerNext()
{
    var next = this._CurrentItem.next;
    this.SelectItem(next);
}

function PT_ControllerPrev()
{
    var prev = this._CurrentItem.prev;
    this.SelectItem(prev);
}


function PT_ControllerOnLoad()
{
	if(this._loaded)return;
	this._loaded=true;
  this.SelectItem(0);
  this.LoadChildren();
  this.OnDataSetChange(); 
}

function PT_ControllerRaiseEvent(EventName, args){
    for(var s in  this._views)
    {
        try
        {
            var handlerName = "on" + EventName;
            if(typeof this._views[s][handlerName] == 'function')
            {
               this._views[s][handlerName](args);             
            }
        }
        catch(exception)
        {
            Debug_Out(exception,this._views[s],"calling handler for " + EventName )
        }     
    }
}


function PT_ControllerAddItem(Item)
{
    if(!this.Data){
        return null;
    }
    var newItem = this.Data.add(Item);    
    var EventArgs=[this.Data,newItem];
    this.RaiseEvent("AddItem",EventArgs);
    return newItem;    
}

function PT_Controller(Data)
{
    if(!Data)return;
    this.register("Controller");
    this.Data = Data;
    this.Data.addListener(this);
    this._views = new Object();
    this._CurrentItem = null;
}

PT_Controller.prototype                     = new PT_Registered_Container(); 
PT_Controller.prototype.OnDataSetChange     = PT_ControllerOnDataSetChange;
PT_Controller.prototype.OnSelectionChange   = PT_ControllerOnSelectionChange;
PT_Controller.prototype.RaiseEvent          = PT_ControllerRaiseEvent;
PT_Controller.prototype.SelectItem          = PT_ControllerSelectItem;
PT_Controller.prototype.First               = PT_ControllerFirst;
PT_Controller.prototype.Next                = PT_ControllerNext;
PT_Controller.prototype.Prev                = PT_ControllerPrev;
PT_Controller.prototype.AddView             = PT_ControllerAddView;
PT_Controller.prototype.OnLoad              = PT_ControllerOnLoad;

PT_Controller.prototype.AddItem              = PT_ControllerAddItem;





function PT_Collection_IteratorHasNext()
{
    return((this._currentItem +1 ) <  this._items.length);
}

function PT_Collection_IteratorNext(){
    this._currentItem++;
    if(this._currentItem < this._items.length){
        this.Item = this._items[this._currentItem];
    }
    else
    {
        this.Item = null;
    }
    return this.Item;
}

function PT_Collection_Iterator(Collection){
    this._currentItem = -1;
    this._items = Collection.Items;
    this.Item = null;
} 

PT_Collection_Iterator.prototype.hasNext= PT_Collection_IteratorHasNext;
PT_Collection_Iterator.prototype.next= PT_Collection_IteratorNext;



function PT_HBOXOnLoad(){
	if(this._loaded)return;
	this._loaded=true;
    // get a reference to the Container and the content
    if(this.Loaded)return;
    this.containerElm = PTLib.Utility.GetElement(this._key + "_container");
    this.setButtons();
    this.Loaded=true;
    this.LoadChildren();
    this.calculateDimensions();
}


/// <summary>
/// OnUnLoad Event Handler 
/// </summary>

function PT_HBOXOnUnload(){
    //unLoad The Children
    this.UnLoadChildren();
}



/// <summary>
/// Innitialize scrolling 
/// </summary>

function PT_HBOXStartScroll(direction){
	var startit = (this.scrolling === "");
	this.scrolling = direction;
	if (startit)
    {
		this.testScroll();
    }
}

/// <summary>
/// Increment or decrement the the scroll Increment based on direction 
/// </summary>

function PT_HBOXTestScroll(){
	if (this.scrolling == "left")
	{
		this.scroll(this.scrollIncrement);
	}
	else if (this.scrolling == "right")
	{
		this.scroll(-this.scrollIncrement);
	}
	this.setButtonStates();
}




/// <summary>
/// Stop Scrolling
/// </summary>

function PT_HBOXStopScroll(direction){
    if (this.scrolling == direction)
    {
	    this.scrolling = "";
    }
}



/// <summary>
/// cancel Animation 
/// </summary>

function PT_HBOXCancelAnimation(){
   	if (this.animation)
	{
		this.animation.stop();
		this.animation = null;
	}
}



/// <summary>
/// Scroll by amount
/// </summary>

function PT_HBOXScroll(amt){
    if (amt === 0)
    {
        return; 
    }
	var newLeftPos = this.curPos + amt;
	
	if (newLeftPos < this.minLeft)
    {
	    newLeftPos = this.minLeft;
    }
	if (newLeftPos > 0)
    {
		newLeftPos = 0;
    }
	if (newLeftPos != this.curPos)
	{
		// movement is possible
		Spry.Debug.trace("Hbox scrolling from " + this.curPos + " to " + newLeftPos);
		this.curPos = newLeftPos;
		this.cancelAnimation();
		var self = this;
		this.animation = new Spry.Effects.Move(this.contentElm, this.curPos, 0, {duration:400,steps:10,onComplete:function(b){self.animation = null; self.testScroll();}});
	}
	else
	{
		//Spry.Debug.trace("HScroller not moving ... cur: " + this.curPos + "; amt: " + amt + "; minLeft: " + this.minLeft);
	}
	this.setButtonStates();
}


/// <summary>
/// Innitialize All Buttons
/// </summary>

function PT_HBOXSetButtons(){
    var LeftScrollButton =   PTLib.Utility.GetElement(this._key + "_left"); 
    var RightScrollButton =  PTLib.Utility.GetElement(this._key + "_right"); 
    this.LeftScrollButton =new PT_Button(LeftScrollButton,PT_Dummy_Function,this);
    
    
    
    this.LeftScrollButton.onMouseOut= new Function("evt", this._ref+".stopScroll('left')");
    this.LeftScrollButton.onMouseDown= new Function("evt", this._ref+".startScroll('left')");
    this.LeftScrollButton.onMouseUp= new Function("evt", this._ref+".stopScroll('left')");
    this.RightScrollButton =new PT_Button(RightScrollButton,PT_Dummy_Function, this);
    this.RightScrollButton.onMouseOut= new Function("evt", this._ref+".stopScroll('right')");
    this.RightScrollButton.onMouseDown= new Function("evt", this._ref+".startScroll('right')");
    this.RightScrollButton.onMouseUp= new Function("evt", this._ref+".stopScroll('right')");
    this.setButtonStates();
}



/// <summary>
/// Set The Buttons state
/// </summary>


function PT_HBOXSetButtonStates(){
	if (this.curPos > this.minLeft)
    {
		this.RightScrollButton.Enable();
    }
	else
    {
		this.RightScrollButton.Disable();
    }
	if (this.curPos < 0)
    {
		this.LeftScrollButton.Enable();
    }
	else
    {
		this.LeftScrollButton.Disable();
    }
}



/// <summary>
///  Scroll Object into view
/// </summary>



function PT_HBOXScrollObjIntoView(obj){
    thisobj = PTLib.Utility.GetElement(obj);
    Spry.Debug.trace("HScroller scrollObjIntoView " + thisObj.id);
    if(thisobj != null)
    {
		var thisObjPos = PTD_getElementPosition(thisObj);
		var containerPos = PTD_getElementPosition(this.containerElm);
		Spry.Debug.trace("HScroller objPos=" + thisObjPos.left + "; container: " + containerPos.left);
		// TODO - figure out borders, etc.
		if ((thisObjPos.left) < containerPos.left)
		{
			this.scroll(containerPos.left - thisObjPos.left); 
		}
		else
		{
			// see if we're to the right
			var objWidth = PTD_getObjectWidth(thisObj);
			var objRight = thisObjPos.left + objWidth;
			var containerRight = containerPos.left + this.containerWidth;
			Spry.Debug.trace("HScroller objRight: " + objRight + "; containerRight: " + containerRight);
			if (objRight > containerRight)
			{
				this.scroll(containerRight - objRight);
			}
			// otherwise, it's in the window
		}
    }
}



/// <summary>
/// Calculate the scrolling dimenesions of the scroller by inspecting the size of the 
/// the container and the content. All calculate the scroll increment
/// </summary>

function PT_HBOXCalcDimensions(){
   if(this.containerElm != null)
   {
        this.contentElm =   this.containerElm.firstChild; 
        this.containerWidth = this.containerElm.offsetWidth;
    }    
    // get the contents width
    if(this.contentElm != null){
        this.contentWidth = this.contentElm.offsetWidth;
    }
    // calculated the minLeft coordinated
    this.minLeft = this.containerWidth - this.contentWidth;
    this.scrollIncrement = parseInt(this.containerWidth / 4,10);
    this.setButtonStates(); 
}

function PT_HBOXOnDataSetChange(Data)
{
    if(this.DataRenderer != null){
        this.DataRenderer.Render(this.containerElm,Data,this);
    }
    this.calculateDimensions();
}


function PT_HBOXOnDataSetRenderer(renderer){
   this.DataRenderer= renderer;
}

function PT_HBOXOnDataSelectionChange(Item){
   this._CurrentItem=Item;
}




function PT_HBOXSetSelected(key)
{
    if(this.Controller != null)
    {
        this.Controller.SelectItem(key);
    }
}





function PT_HBOX(key,controller){
    PT_Registered_Container.call(this);
    this._key = key;
    this.register("HBOX",controller);
    if(controller){
        controller.AddView(this);
    }
	this.containerElm = null;
	this.contentElm = null;
	this.leftScrollButton = null;
	this.rightScrollButton = null;
	this.contentWidth = 0;
	this.containerWidth = 0;
	this.minLeft = 0;
	this.curPos = 0;  // goes from here down to minLeft (all the way right)
	this.scrolling = "";
	this.scrollIncrement =0;
	this.animation = null;
    this.Loaded= false;
    this.DataRenderer=null;
    this._currentItem = null;    
}

// inherited from Registered components to allow subcomponents

PT_HBOX.prototype                       = new PT_Registered_Container();
PT_HBOX.prototype.OnLoad                = PT_HBOXOnLoad;
PT_HBOX.prototype.OnUnload              = PT_HBOXOnUnload;
PT_HBOX.prototype.startScroll           = PT_HBOXStartScroll;
PT_HBOX.prototype.testScroll            = PT_HBOXTestScroll;
PT_HBOX.prototype.stopScroll            = PT_HBOXStopScroll;
PT_HBOX.prototype.cancelAnimation       = PT_HBOXCancelAnimation;
PT_HBOX.prototype.scroll                = PT_HBOXScroll;
PT_HBOX.prototype.setButtons            = PT_HBOXSetButtons; 
PT_HBOX.prototype.setButtonStates       = PT_HBOXSetButtonStates; 
PT_HBOX.prototype.calculateDimensions   = PT_HBOXCalcDimensions;
PT_HBOX.prototype.OnDataSetChange       = PT_HBOXOnDataSetChange;
PT_HBOX.prototype.OnSelectionChange     = PT_HBOXOnDataSelectionChange;
PT_HBOX.prototype.SetRenderer           = PT_HBOXOnDataSetRenderer;


PT_HBOX.prototype.SetSelected           = PT_HBOXSetSelected;


 