/*
Charting tool 
    (c) RusIndex, RUSTOCKS.com
    Author V. Dmitriev
*/
//ChartAssoc 
//utils
Array.prototype.indexOf=function(el){
    for(var i=0;i<this.length;i++){
        if(this[i]==el) return i;
    }
    return -1;
}
Array.prototype.closestUp=function(value){
    for(var i=0; i<this.length; i++){
        if(value<=this[i]){
            return i;
        }
    }
    return i;   
}
Array.prototype.closestDown=function(value){
    for(var i=0; i<this.length; i++){
        if(value==this[i]){
            return i;
        }
        if(value<this[i]){
            return i-1;
        }
    }
    return i;
}
function ChartAssoc(){
    this.keys=new Array();
    this.vals=new Array();
    //this.hash=new Array();
    
    this.add=function(key,val){
        var ix=this.keys.length;
        var i=-1;
        if(
            (i=this.keys.indexOf(key))!=-1
        )ix=i;
        this.keys[ix]=key;
        this.vals[ix]=val;
        //this.hash[key]=val;
    }
    this.get=function(key){
/* */
        var ix=this.keys.indexOf(key);
        if(ix==-1) return null;
        return this.vals[ix];
//*/
/* почему мозилла виснет? *
        if(this.hash[key]+''=='undefined') return null;
        return this.hash[key];
// */
    }
    this.indexOf=function(value, array){
        return array.indexOf(value);
    }
    this.closestUp=function(value,array){
        return array.closestUp(value);
    }
    this.closestDown=function(value,array){
        return array.closestDown(value);
    }
}
//controls
function ChartSeria(input){
    this.input;
    this.id;
    this.code;
    this.name;
    this.target=new Array();
    this.params=new ChartAssoc();
    
    this.setInput=function(input){
        this.input=input;
        this.id=input.id;
    
        var val=input.value.split('|');
        this.code=val[0];
        if(val[2]+''!='undefined')this.name=val[2];
        if(val.length>1){
            this.target=val[1].split(',');
        }
    }
    if(input+''!='undefined') this.setInput(input);
    
    this.hasTarget=function(needle){
        for(var i=0;i<this.target.length;i++){
            if(this.target[i]==needle){
                return true;
            }
        }
        return false;
    }
    
    this.setParameter=function(input){
        var id=input.id.split('.');
        if(id[3]+''=='undefined') return;
        this.params.add(id[3],input);
    }
}
function ChartTypeSel(container){

    this.container=container;
    this.prefix=this.container.prefix;
    this.input=document.getElementById(this.prefix+'.type');
    
    this.getValue=function(){
        if(this.input==null) return 0;
        return this.input.value;
    }
    this.disable=function(){
        if(this.input!=null) this.input.disabled=true;
    }
    this.enable=function(){
        if(this.input!=null) this.input.disabled=false;
    }
}

function ChartVolSel(container){
    this.container=container;
    this.prefix=this.container.prefix;
    this.input=document.getElementById(this.prefix+'.volume');
    this.ok=true;
    if(this.input.nodeName!='SELECT') this.ok=false;
    
    this.add=function(code,name){
        var option=document.createElement('OPTION');
        option.value=code;
        option.text=name;

        this.input.options.add(option);
    }
    
    this.clear=function(){
        this.input.innerHTML='';
    }
    
    this.change=function(ix){
        if(this.input.options.length<=0 || ix<0 ) this.input.selectedIndex=0;
        this.input.selectedIndex=ix%this.input.options.length;
    }
    
    this.getValue=function(){
        if(this.input.options.length<1) return '';
        if(this.input.selectedIndex<0 || this.input.selectedIndex>this.input.options.length){
            this.input.selectedIndex=0;
        }
        return this.input.options[this.input.selectedIndex].value;
    }
}

/////calendar control
function ChartCalendar(container){
    this.prefix=container.prefix;
    var prefix=container.prefix;
    //controls
    this.start= new Array();
    this.end  = new Array();
    this.selector=null;
    //data
    this.dStart=new Date();
    this.dEnd=new Date();
    
    //methods
    this.init=function(){
        this.readForm();
        this.chngPeriod();
    };
    this.readForm=function(){
        var inputs=document.getElementsByTagName('input');
        for(var i=0;i<inputs.length;i++){
            var input=inputs[i];
            if(input.id.indexOf(prefix+'.d.')==0 && input.type=='text'){
                var id=input.id.split('.');
                var trgt=null;
                if(id[2]=='start'){
                    trgt=this.start;
                }else if(id[2]=='end'){
                    trgt=this.end;
                }else{continue;}
                ///
                if(id[3]=='year'){
                    trgt[0]=input;
                }else if(id[3]=='month'){
                    trgt[1]=input;
                }else if(id[3]=='day'){
                    trgt[2]=input;
                }else {continue;}
            }
        }
        var selector=document.getElementById(prefix+'.period');
        this.selector=selector;
    };
    this.dateAdd=function(date,years,months,days){
        
        var year=(date.getYear()<1900?date.getYear()+1900:date.getYear())+years;
        var month=date.getMonth()+months;
        
        var yearShift = parseInt(month/12);
        
        yearShift+=month<0?-1:0;
        year=year+yearShift;
        
        month = ((month)%12+12)%12;
        
        var day=date.getDate()+days;

        var result=new Date(year,month,day);
        
        return result;
    };
    this.getDateStart=function(){
        this.dStart=new Date(
            parseInt(this.start[0].value),
            parseInt(this.start[1].value)-1,
            parseInt(this.start[2].value)
        );
        return this.dStart;
    };
    this.getDateEnd=function(){
        this.dEnd=new Date(
            parseInt(this.end[0].value),
            parseInt(this.end[1].value)-1,
            parseInt(this.end[2].value)
        );
        return this.dEnd;
    };
    this.chngPeriod=function(){
        this.dEnd=new Date();
        var period=this.selector.value.split(',');
        for(var i=0;i<3;i++){
            if(period[i]+''=='undefined') period[i]=0;
        }
        this.dStart=this.dateAdd(this.dEnd,-period[0],-period[1],-period[2]);
        
        this.end[0].value=(this.dEnd.getYear()<1900)?
            (this.dEnd.getYear()+1900):
                this.dEnd.getYear();
        this.end[1].value=this.dEnd.getMonth()+1;
        this.end[2].value=this.dEnd.getDate();
        
        this.start[0].value=(this.dStart.getYear()<1900)?
            (this.dStart.getYear()+1900):
                this.dStart.getYear();
        this.start[1].value=this.dStart.getMonth()+1;
        this.start[2].value=this.dStart.getDate();
        
    };
    this.formatDate=function(date){
        var year=date.getYear();
            if(year<1900) year+=1900;
        var month=date.getMonth()+1;
            month=month<10?'0'+month:''+month
        var day=date.getDate();
            day=day<10?'0'+day:''+day;
        var res=year+"-"+month+"-"+day;

        return res;
    };
    
    this.parseDate=function(sDate,handler){
        var dp=sDate.split('-');
        for(var i=1;i<3;i++){
            if(dp[i].substr(0,1)=='0') {dp[i]=dp[i].substr(1,2);}
        }
        handler[0].value=parseInt(dp[0]);
        handler[1].value=parseInt(dp[1]);
        handler[2].value=parseInt(dp[2]);
    };

    this.setMargin=function(date1, date2){
        if(date1==date2) {
            this.chngPeriod();
            return;
        }
        this.parseDate(date1,this.start);
        this.parseDate(date2,this.end);
    };
    
    this.getMargin=function(){
        var d1=this.formatDate(this.getDateStart());
        var d2=this.formatDate(this.getDateEnd());
        
        return "d1="+d1+"&d2="+d2;
    };

    /////end of declarations
    this.init();

}
//presentations
function ChartDraw(img,container,isVolumes){
    this.img=img;
    this.container=container;
    this.container.images.add(img.id,this);
    
    this.series=new Array();
    this.instrums=new Array();
    
    this.isVolumes=isVolumes;
    
    this.addSeria=function(seria){
        this.series[this.series.length]=seria;
    }
    
    this.addInstrum=function(inst){
        this.instrums[this.instrums.length]=inst;
    }
    this.checkedSeries=new Array();    
    this.redraw=function(index){
        if(index+''=='undefined') index=0;
        this.img.style.display='';
        var uriArray=new Array();
        //config
        if(this.container.conf!=null){
            uriArray[uriArray.length]="conf="+this.container.conf;
        }
        //image size
        uriArray[uriArray.length]="w="+this.img.width;
        uriArray[uriArray.length]="h="+this.img.height;
        //referer
        uriArray[uriArray.length]="referer="+this.container.referer;
        //time margins
        uriArray[uriArray.length]=this.container.calendar.getMargin();
        //go by series
        var ns=new Array(); var nsn=new Array();
        for(var i=0;i<this.series.length;i++){
            var s=this.series[i];
            var led=document.getElementById(this.container.prefix+'.led.'+s.code);
            led.src=this.container.uriBase+"led";
            if(s.input.checked){
                ns[ns.length]=s.code;
                nsn[nsn.length]=s.name;
                led.src=
                this.container.uriBase+
                "led?referer="+this.container.referer+
                "&conf="+this.container.conf+
                "&seria="+s.code;
            }
        }
        this.checkedSeries=ns;
        //go by instrums
        var ni=new Array();
        for(var i=0;i<this.instrums.length;i++){
            var ii=this.instrums[i];
            var led = document.getElementById(this.container.prefix+'.led.'+ii.code);
            led.src=this.container.uriBase+"led";
            if(ii.input.checked){
                ni[ni.length]=ii.code;
                var ips=ii.params.keys;
                for(var j=0;j<ips.length;j++){
                    uriArray[uriArray.length]=('ip.'+ii.code+'.'+ips[j]+'='+ii.params.vals[j].value);
                }
                led.src=
                this.container.uriBase+
                "led?referer="+this.container.referer+
                "&conf="+this.container.conf+
                "&instrument="+ii.code;
            }
        }
        //if(ns.length<1)return;
        //select the type of drawing
        var volSel=this.container.volSel;
//          volSel.clear();
//          volSel.change(index);
        if(this.isVolumes){
            uriArray[uriArray.length] = "type=2";
            volSel.clear();
            for(var i=0;i<ns.length;i++){
                volSel.add(ns[i],nsn[i]);
            }
            //here we should choose the seria
            volSel.change(index);
            if(volSel.getValue()!=''){
                uriArray[uriArray.length]="series="+volSel.getValue();
            }
            else {
                this.img.style.display='none';              
            }
        }
        else if (ns.length>1){
            uriArray[uriArray.length] = "type=1";
            container.typeSel.disable();
        }
        else {
            uriArray[uriArray.length]="type="+container.typeSel.getValue();
            container.typeSel.enable();
        }
        //when type is not 2, create list of series
        if(!this.isVolumes){
            if(ns.length>0) uriArray[uriArray.length]="series="+ns.join(',');

        }
        //anyway list of instruments
        if(ni.length>0) uriArray[uriArray.length]="instruments="+ni.join(',');
        if(volSel.getValue()!='') uriArray[uriArray.length]="main="+volSel.getValue();
        //output the same for all types
        this.img.src=this.container.uriBase+'?'+uriArray.join('&');
        this.loadHighLow(
            this.container.uriBase+'highLow?'
            +uriArray.join('&')+
            '&target='+this.container.myName+
            '&id='+this.img.id
        );
    }
    
    this.high=null;
    this.low=null;
    this.measure='';
    this.ready=false;
    this.sc=null;
    
    this.loadHighLow=function(uri){

        this.ready=false;
        if(this.sc!=null){
            document.body.removeChild(this.sc);
            this.sc=null;
        }
        this.sc=document.createElement('SCRIPT');
        this.sc.setAttribute('language','javascript');
        this.sc.setAttribute('src',uri);
        document.body.appendChild(this.sc);
    };
    
    this.getHigh=function(){
        if(this.ready) return this.high;
    };
    this.getLow=function(){
        if(this.ready) return this.low;
    };
    this.getMeasure=function(){
        if(this.ready) return this.measure;
    };
    
}

function ChartTable(target, container){
    
    this.container=container;
    this.target=target;
    this.series=new Array();
    
    this.sc=null;
    
    this.addSeria=function(seria){
        this.series[this.series.length]=seria;
    }
    this.redraw=function(){
        var uriArray=new Array();
        //target
        uriArray[uriArray.length]="target="+this.target;
        //config
        if(this.container.conf!=null){
            uriArray[uriArray.length]="conf="+this.container.conf;
        }
        //referer
        uriArray[uriArray.length]="referer="+this.container.referer;
        //time margins
        uriArray[uriArray.length]=this.container.calendar.getMargin();
        //series
        var ns=new Array();
        for(var i=0;i<this.series.length;i++){
            var s=this.series[i];
            if(s.input.checked){
                ns[ns.length]=s.code;
            }
        }
        uriArray[uriArray.length]="series="+ns.join(',');
        //get uri
        var uri=this.container.uriBase+"table?"+uriArray.join('&');
        //do
        if (this.sc!=null){
            document.body.removeChild(this.sc);
        }
        this.sc=document.createElement("script");
        this.sc.setAttribute("language", "javascript");
        this.sc.setAttribute("src",uri);
        document.body.appendChild(this.sc);
    }
}
//data seria
function ChartDataSeria(container, seria, fields, fnames){
    
    this.ready=100;
    
    this.container=container;
    this.seria=seria;
    this.sfields=fields;
    this.fields=fields.split(',');
    this.fnames=fnames.split(',');

    this.data=new ChartAssoc();
    
    this.setData=function(field,data){
        this.data.add(field,data);
        this.ready--;

    }
    this.getFname=function(field){
        var i=this.fields.indexOf(field);
        return this.fnames[i];
    }
    this.sc=null;
    this.loadData=function(){
        if(this.sc!=null && !(this.ready > 0)){
            document.body.removeChild(this.sc);
            this.sc=null;
        }
        this.ready=this.fields.length;
        var uri=this.container.uriBase+"data?"
        var uriArray=new Array();
        //target
        uriArray[uriArray.length]="target="+this.container.myName;
        //config
        if(this.container.conf!=null){
            uriArray[uriArray.length]="conf="+this.container.conf;
        }
        //referer
        uriArray[uriArray.length]="referer="+this.container.referer;
        uriArray[uriArray.length]="series="+this.seria;
        uriArray[uriArray.length]="fields="+this.sfields;
        //go
        uri+=uriArray.join('&');
        this.sc=document.createElement('script');
        this.sc.setAttribute('language','javascript');
        this.sc.setAttribute("src",uri);

        document.body.appendChild(this.sc);
        
    }
    this.showData=function(i){
        if(i<0) return null;
        var s=0;
        var res=null;
        
        res=
            "<table class='chart_hint'><tr><td class=chart_hint><b>"+container.seriaInputs.get(this.seria).name+"</b></td><td class='chart_hint' nowrap>"
            +container.mouseCursor.dateList[i]+"</td></tr>";
            
                for(var j=0;j<this.fields.length;j++){
                    
                    var v=this.data.get(this.fields[j]);
                    if(v==null) continue;
                    v=v[i];
                    if(v!=0){
                        res+="<tr><td class='chart_hint'>";
                        res+=this.fnames[j];
                        res+="</td><td class='chart_hint'>";
                        res+=v;
                        res+="</td></tr>";
                        s++;
                    } 
                }       
        res+="</table>";
        return s>0?res:null;
    }
}
//map dates to x
function ChartMouseCursor(container){
    this.container=container;
    //data
    this.dateList=new Array();
    this.series=new ChartAssoc();
    
    this.lm=10; 
    this.rm=10; 
    this.tm=10; 
    this.bm=10;
    //script handler
    this.sc=null;
    //cursor view
    this.cursor=null;
    this.cursor1=null;
    //cursor data view
    this.hint=null;
    //ready or not?
    this.ready=false;
    
    //color for the hints bg
    this.hBG="#ffffcc";
    
    //call server for seria
    this.loadSeria=function(seria,fields,fnames){
        var sd=new ChartDataSeria(this.container,seria,fields,fnames);
        this.series.add(seria,sd);
        sd.loadData();
    }
    this.seriaSetData=function(seria,field,data){
        var sd=this.series.get(seria);
        if(sd==null) return;
        sd.setData(field,data);
    }
    //call server for dates
    this.loadDates=function(){
        this.ready=false;
        /////form URI
        var uri=this.container.uriBase+"dates?";
        var uriArray=new Array();
        //target
        uriArray[uriArray.length]="target="+this.container.myName;
        //config
        if(this.container.conf!=null){
            uriArray[uriArray.length]="conf="+this.container.conf;
        }
        //referer
        uriArray[uriArray.length]="referer="+this.container.referer;
        //time margins
        uriArray[uriArray.length]=this.container.calendar.getMargin();
        uri+=uriArray.join('&');
        /////update dates
        if(this.sc!=null){
            document.body.removeChild(this.sc);     
        }       
        this.sc=document.createElement('script');
        this.sc.setAttribute('language','javascript');
        this.sc.setAttribute("src",uri);
        document.body.appendChild(this.sc);

    };
    
    this.d1ix=0;
    this.d2ix=this.dateList.length-1;
    
    this.update=function(){
        if(this.dateList.length==0) {
            this.loadDates(); 
            return;
        }
        var clndr=this.container.calendar;
        var d1=clndr.formatDate(clndr.getDateStart());
        var d2=clndr.formatDate(clndr.getDateEnd());

        if(d1>d2){
            var dtmp=d1;
            d1=d2;
            d2=dtmp;
        }


        this.d1ix=this.dateList.closestUp(d1);
        this.d2ix=this.dateList.closestDown(d2);


    };
  
    this.targetX=function(event){
        return this.outerMouseX(event)-this.innerMouseX(event);
    }
    this.targetY=function(event){
        return this.outerMouseY(event)-this.innerMouseY(event);
    }
    
    this.innerMouseX=function(event){
        if(event.offsetX+''!='undefined'){
            //ie
            return event.offsetX;
        }
        else{
            //standart (mozilla)
            return event.pageX-event.target.x;
        }
    };
    this.innerMouseY=function(event){       
        if(event.offsetY+''!='undefined'){
            //ie
            return event.offsetY;
        }
        else{
            //standart (mozilla)
            return event.pageY-event.target.y;
        }
    };
    this.outerMouseX=function(event){
        return this.container.outerMouseX(event);
    }
    this.outerMouseY=function(event){
        return this.container.outerMouseY(event);
    }
    
    this.plotCursor=function(event){
        if(!this.ready) {
            this.hideCursor();
            return null;
        }
        var absX=this.innerMouseX(event);
        var x, w, y, h;
        var trgt=null;
        //right and bottom exception
        if(event.srcElement){
            trgt=event.srcElement;
        }
        else{
            trgt=event.target;
        }

        y=this.innerMouseY(event);
                
        w=trgt.width; h=trgt.height;
        if(absX-5>w-this.rm || y-5>h-this.bm) {
            this.hideCursor();
            return null
        };
        //left and top exception
        x=absX-this.lm;
        y=y-this.tm;
        w=w-this.lm-this.rm;
        if(x<5 || y<5 || w<0){
            this.hideCursor();
            return null;
        }
        ////////////////////////draw cursor
        var cursorHeight=(trgt.height-this.tm-this.bm);

        var cursorTop=this.targetY(event)+this.tm;

        var cursorLeft=this.outerMouseX(event)-5;

        var vc=new Array(this.cursor, this.cursor1);
        if(this.cursor1==null){
            this.cursor=document.createElement('div');
            this.cursor1=document.createElement('div');
            vc=new Array(this.cursor, this.cursor1);
            for(var i=0;i<vc.length;i++){ 
                with(vc[i]){
                    style.display='none';
                    style.backgroundColor='#000000';
                    style.width='1px';
                    style.position='absolute';
                }
                document.body.appendChild(vc[i]);
            }
        }
        with(this.cursor){
            var img=this.container.price.img;
            style.height=img.height-this.tm-this.bm+'px';
            style.left=cursorLeft+'px';
            style.top=this.container.getImgXY(img)[1]+this.tm+'px';
            style.display=img.style.display;
        }
        with(this.cursor1){
            var img=this.container.volume.img;
            style.height=img.height-this.tm-this.bm+'px';
            style.left=cursorLeft+'px';
            style.top=this.container.getImgXY(img)[1]+this.tm+'px';
            style.display=img.style.display;
        }
        
        /* */
        var result=this.findDateByX(x-5,w);
        
        this.dataHint(event);
        this.plotHCursor(event);
        this.hint.style.top=(cursorTop+cursorHeight+5)+'px';
        this.hint.innerHTML=result;
        ////////////////////////return date
        return result;
    };
    
    this.dataHint=function(event){
        if(this.hint==null){
            this.hint=document.createElement('div');
            this.hint.style.display='none';
            this.hint.style.backgroundColor=this.hBG;
            this.hint.style.border='1px outset #cccccc';
            this.hint.style.position='absolute';
            this.hint.className='chart_hint';
            document.body.appendChild(this.hint);
        }
        
        var mouseX, mouseY;
        var shift = -this.hint.offsetWidth/2;
        
        mouseY=this.outerMouseY(event);
        mouseX=this.outerMouseX(event);
        
        this.hint.style.left=(mouseX + shift-5)+'px';
        this.hint.style.display='';
    };
    
    this.box=null;
    this.boxStarts=0;
    
    this.drawBox=function(event){
        if(this.box==null){
            this.box=document.createElement('div');
            this.box.style.display='none';
            this.box.style.backgroundColor='#cccccc';
            this.box.style.filter='alpha(opacity=40)';
            this.box.style.opacity=0.4;
            this.box.style.border='1px solid #999999';
            this.box.style.position='absolute';
            this.box.style.height=this.cursor.style.height;
//            this.box.className='chart_hint';
            
            document.body.appendChild(this.box);
            if(this.hint!=null) this.hint.style.zIndex++;
        }
        this.box.style.top=this.cursor.style.top;

        var mouseX = this.outerMouseX(event)-5;
        if(this.boxStarts==0) this.boxStarts=mouseX;
        
        if(mouseX>this.boxStarts){
            this.box.style.left=this.boxStarts+'px';//-2;
            this.box.style.width=mouseX-this.boxStarts+'px';
    
            this.box.style.display='';
        }
        else if(mouseX<this.boxStarts){
            
            this.box.style.left=(mouseX+5+2)+'px';
            this.box.style.width=(this.boxStarts-mouseX-5-2)+'px';
    
            this.box.style.display='';
        }else{
            this.box.style.left=0+'px';
            this.box.style.width=1+'px';
            this.box.style.display='none';
        }

        
    };  
    
    this.hCursor=null;
    this.vHint=null;
    
    this.plotHCursor=function(event){
        var x, w;//, y, h;
        var trgt=null;
    
        if(event.srcElement){
            trgt=event.srcElement;
        }
        else{
            trgt=event.target;
        }
        var mouseX=this.outerMouseX(event)-5;
        var mouseY=this.outerMouseY(event)-5;
        
        w=trgt.width-this.lm-this.rm;
/*        
        x=trgt.x?
            trgt.x+this.lm:
            event.clientX-event.offsetX+this.lm+document.body.scrollLeft-document.body.clientLeft;
*/
        x=this.targetX(event)+this.lm;
            
        if(this.hCursor==null){
            this.hCursor=document.createElement('div');
            this.hCursor.style.display='none';
            this.hCursor.style.backgroundColor='#000000';
            this.hCursor.innerHTML='';
            this.hCursor.style.padding=0;
            this.hCursor.style.fontSize=0; 
            this.hCursor.style.position='absolute';
            this.hCursor.style.height=1+'px';
            this.hCursor.height=1;
            
//          this.hCursor.style.
            document.body.appendChild(this.hCursor);
        }
        
        this.hCursor.style.width=w+'px';     //mouseX-x-15;
        this.hCursor.style.top=mouseY+'px';
        this.hCursor.style.left=x+'px';
        this.hCursor.style.display='';
        
        this.valueHint(event);
    };

    this.fHint=null;
    this.fieldsHint=function(event){
        var x=this.innerMouseX(event);
        var trgt=null;
        if(event.srcElement){
            trgt=event.srcElement;

        }
        else{
            trgt=event.target;

        }
        if(this.fHint==null){
            this.fHint=document.createElement('div');
            this.fHint.style.display='none';
            this.fHint.style.backgroundColor=this.hBG;
            this.fHint.style.filter='alpha(opacity=80)';
            this.fHint.style.opacity=0.8;
            this.fHint.style.border='1px outset #cccccc';
            this.fHint.style.zIndex=100;
            this.fHint.style.position='absolute';
            this.fHint.className='chart_hint';
            document.body.appendChild(this.fHint);      
        }
        //find needed seria first!
        var seria=this.container.volSel.input.value;
        var show=this.findSeriaRowByX(seria, x-5-this.lm,trgt.width-this.lm-this.rm);
        if(show==null) {
            this.fHint.style.display='none';
            return;
        }
        this.fHint.innerHTML=show;
        var xShift=30;
        if(x-5>trgt.width/2){
            xShift=-(this.fHint.offsetWidth+30);
        }
        var yShift=-(this.fHint.offsetHeight+20);
        
        this.fHint.style.left=(this.outerMouseX(event)+xShift)+'px';
        this.fHint.style.top=(this.outerMouseY(event)+yShift)+'px';
        this.fHint.style.display='';
    }

    this.valueHint=function(event){
        if(!this.ready) return;
        var y;
        var trgt;
        var x=this.innerMouseX(event)-5;
        if(event.srcElement){
            trgt=event.srcElement;
            y=event.offsetY-5;
        }
        else{
            trgt=event.target;
            y=event.pageY-trgt.y-5;
        }
        
        y=this.innerMouseY(event)-5;
        
        if(this.vHint==null){
            this.vHint=document.createElement('div');
            this.vHint.style.display='none';
            this.vHint.style.backgroundColor=this.hBG;
            this.vHint.style.border='1px outset #cccccc';
            this.vHint.style.position='absolute';
            this.vHint.className="chart_hint";
            document.body.appendChild(this.vHint);
        }
        
        var valuez=this.findValueByY(this.innerMouseY(event)-5,trgt);
        this.vHint.innerHTML=valuez;
        
        var mouseX, mouseY;
        var tShift = -this.vHint.offsetHeight/2;
        var vShift=(x > trgt.width/2)?(-20-this.vHint.offsetWidth):20;
        
        mouseX=this.outerMouseX(event)-5;
        mouseY=this.outerMouseY(event)-5;
        
        this.vHint.style.top=(mouseY + tShift)+'px';
        this.vHint.style.left=(parseInt(this.hCursor.style.left)-this.vHint.offsetWidth-5)+'px';
        this.vHint.style.display=(valuez==''?'none':'');
        
        this.fieldsHint(event);
    }
    
    this.hideCursor=function(){
        if(this.cursor!=null) 
            this.cursor.style.display='none';
        if(this.cursor1!=null) 
            this.cursor1.style.display='none';
        if(this.hint!=null)
            this.hint.style.display='none';
        if(this.vHint!=null)
            this.vHint.style.display='none';
        if(this.hCursor!=null)
            this.hCursor.style.display='none';
        if(this.box!=null){
            this.box.style.display='none';
            this.container.mousePressed=false;
            this.boxStarts=0;
        }
        if(this.fHint!=null) this.fHint.style.display='none';
    };
    this.findYbyValue=function(val,target){
        var tt=this.container.getDrawing(target.id);
        var h=target.height-this.tm-this.bm;
        var high=tt.getHigh();
        var low=tt.getLow();

        var y=h-(val-low)/(high-low)*h+this.tm;

        return y;
        
    }
    this.findValueByY=function(y,target){
        var tt=this.container.getDrawing(target.id);
        if(tt==null) return;
        var h=target.height-this.tm-this.bm;
        var high=tt.getHigh();
        var low=tt.getLow();
        var meas=tt.getMeasure();
        y=h-(y-this.tm);
        var val=(high-low)/h*y+low;
        
        if(meas+''=='undefined'){
            return '';
        }
        
        return this.fmt(val);//+" "+y+" "+this.findYbyValue(val,target);//+' '+meas;
    };
    
    this.fmt=function(num){
        if(isNaN(num)) return 0;
        if(num==0) return 0;

        var prec=(3-Math.floor(Math.log(num>0?num:-num)/Math.log(10)));
        
        if(prec>20) return num;

        if(prec<0){
            return Math.round(num);
        }

        if(num.toFixed){
            return num.toFixed(prec); 
        }

        return num;
    };

    this.findIndexByX=function(x,width){
        return this.d1ix+Math.round(x/(width/(this.d2ix-this.d1ix)));
    }
    
    this.findDateByX=function(x,width){
//      return this.dateList[Math.round(x/(width/(this.dateList.length-1)))];
//return this.findSeriaRowByX('eesr',x,width);
        return this.dateList[this.findIndexByX(x,width)];
    };
    this.findSeriaRowByX=function(seria,x,width){
        var sd=this.series.get(seria);
        if(sd!=null) return sd.showData(this.findIndexByX(x,width));
        return null;
    }
    
}
//infoHeaders
function ChartInfo(container){

    this.container=container;//ChartingTool obj 
    this.headers=new ChartAssoc();//keys is comp's
    this.index=new Array();
    this.bodies=new Array();
    this.sc=new ChartAssoc();
    
    this.links=new ChartAssoc();
    this.loading=0;
    
    this.addHeader=function(comp,id,date,header){
        var coHeaders=this.headers.get(comp);
        if(coHeaders==null){
            coHeaders=new Array();
            this.headers.add(comp,coHeaders);
        }
        var index=parseInt(date.split('-').join(''));
        var hdrs=coHeaders[index];
        if(hdrs+''=='undefined' || hdrs==null){
            hdrs=new Array();
            coHeaders[index]=hdrs;
        }
        var head=new Array(comp,id,date,header);
        hdrs[hdrs.length]=head;
        this.index[parseInt(id)]=head;
    }
    this.loadHeaders=function(comp,types){
//      this.loading++;
        var sc=this.sc.get(comp);
        if(sc!=null){
            document.body.removeChild(cs);
            this.sc.add(comp,null);
        }
        sc=document.createElement('script');
        sc.setAttribute('language','javascript');
        
        //src:  
        var src=this.container.uriBase+"headers?"
        
        var qp=new Array();
        qp[qp.length]="conf="+this.container.conf;
        qp[qp.length]="target="+this.container.myName;
        qp[qp.length]="referer="+this.container.referer;
        qp[qp.length]="comp="+comp;
        qp[qp.length]="types="+types;
        
        src=src+qp.join('&');
        sc.setAttribute('src',src);
        
        document.body.appendChild(sc);  
        this.sc.add(comp,sc);
    }
    this.addHeadersComplete=function(comp){
//      this.loading--;
        this.container.showHeaders();
    }
    //link comp's to series
    this.linkComp=function(seria,comp){
        var link=this.links.get(seria);
        if(link==null) {
            link=new Array(); this.links.add(seria,link);
        }
        link[link.length]=comp;
    }
    
    this.menuItems=new Array();
    this.menuDrops=new Array();

    this.borderColor="#6666FF";
    this.bgColor="#EEEEEE";
    
    this.showHeaders=function(series,start,end,x,y,width,height){
        this.clear();
        if(this.loading>0) return;
        //find companies
        var comps=new Array();
        for(var i=0;i<series.length;i++){
            var link=this.links.get(series[i]);
            if(link==null) continue;
            for(var j=0;j<link.length;j++){
                if(this.links.indexOf(link[j],comps)<0){
                    comps[comps.length]=link[j];
                }
            }
        }
        if(comps.length==0){return;}
        //narezat width na priemlimye kuski
        var L=width/(end-start);
        var n=Math.floor(width/(L<10?10:L));
        //chislo dney v kuske (drobnoe!)
        var daysLen=(end-start)/n;
        var imgPos=this.container.getImgXY(this.container.price.img);
        for(var i=0;i<n+1;i++){

            var dayIxS=Math.round(daysLen*i);
            var dayIxE=Math.round(daysLen*(i+1));
            var dateS=this.container.mouseCursor.dateList[start+dayIxS];
            
            var ei=((start+dayIxE)>end+1)?end+1:start+dayIxE;
            var dateE=this.container.mouseCursor.dateList[ei];

            var xx=Math.round(dayIxS*L-L/2);
            //if(xx<0) xx=0;
            var xx1=Math.round(dayIxE*L-L/2);
            var w=xx1-xx;
            var x1=imgPos[0]+this.container.price.img.width;
            this.createMenuItem(comps,dateS,dateE,x+xx,y,w,height,x1);
        }
    }
    this.createMenuItem=function(comps,dateS,dateE,x,y,w,h,x1){
        if(dateS+''=='undefined' || dateE+''=='undefined') return;

        //select headers
        dateS=parseInt(dateS.split('-').join(''));
        dateE=parseInt(dateE.split('-').join(''));

        var i=this.menuItems.length;
        var size=250;       
        var result=new Array();
        var drop="<table class='chart_hint' width=100% >";
        for(var ii=0;ii<comps.length;ii++){
            var coHeaders=this.headers.get(comps[ii]);
            if(coHeaders==null) continue;
            for(var ix=dateS;ix<dateE;ix++){
                var hdrs=coHeaders[ix];
                if(hdrs+''=='undefined' || hdrs==null) continue;
                for(var j=0;j<hdrs.length;j++){
                    result[result.length]=hdrs[j];
                    drop+=  "<tr><td class='chart_hint' style='"+
                                "background-color:"+this.bgColor+
                                (j>100?";border-top:1px solid #999999;":";")+
                                "cursor:pointer;"+
                            "' onclick='"+
                            this.container.myName+".showInfoBody("+hdrs[j][1]+");"+
                            this.container.myName+".hideInfoDrop("+i+");"+
                            "'>"+
                                hdrs[j][2]+"<br>"+hdrs[j][3]+
                            "</td></tr>";
                }
            }
        }
        drop+="</table>";
        
        //if headers found
        if(result.length<1) return;
        //draw menuItem, register it

        var mI=document.createElement('DIV');
        
        this.menuItems[i]=mI;
        mI.innerHTML="<img src='"+
            this.container.uriBase+"../images/info.gif'>";
        mI.style.position='absolute';
        mI.style.top=(y+h-10)+'px';
        mI.style.left=x+w/2-4+'px';
        mI.style.width='10px';//w+'px';
        mI.style.padding=0;
        mI.style.fontSize=0; 
        mI.style.zIndex=95;
        mI.style.cursor='pointer';
//      mI.style.height=h+3+'px';
//      mI.style.backgroundColor=this.container.mouseCursor.hBG;//"#FFFFFF";//"#6666FF";//
//      mI.style.border='1px solid #000000';//'#CCCCCC';

        document.body.appendChild(mI);
        
        //draw dropDown, register it

        var dD=document.createElement('DIV');
        this.menuDrops[i]=dD;
        dD.innerHTML=drop;
        dD.style.position='absolute';
        dD.style.width=size+'px';
        dD.style.top=y+h+'px';
        dD.style.left=((x1>(x+w/2-5+size))?x+w/2-5:x1-size)+'px';
        dD.style.padding=0;
        dD.style.backgroundColor=this.borderColor;
        dD.style.border='1px outset #000000';
        dD.style.display='none';
        dD.style.zIndex=90;
        document.body.appendChild(dD);
        dD.style.display='';
        if(dD.offsetHeight>size*1.5) {
            dD.style.height=size*1.5+'px';
            dD.style.overflow='auto';
        }
        dD.style.display='none';
        
        var show=new Function(this.container.myName+'.showInfoDrop('+i+');return false;');
        var hide=new Function(this.container.myName+'.hideInfoDrop('+i+');return false;');
        
        this.container.addEvent(mI,"onmouseover",show);
        this.container.addEvent(mI,"onmouseout",hide);
        this.container.addEvent(dD,"onmouseover",show);
        this.container.addEvent(dD,"onmouseout",hide);

    }
    this.showDrop=function(i){
        this.menuDrops[i].style.display='';
    }
    this.hideDrop=function(i){
        this.menuDrops[i].style.display='none';
    }
    //clear menu
    this.clear=function(){
        for(var i=0;i<this.menuItems.length;i++){
            document.body.removeChild(this.menuItems[i]);
        }
        this.menuItems=new Array();
        for(var i=0;i<this.menuDrops.length;i++){
            document.body.removeChild(this.menuDrops[i]);
        }
        this.menuDrops=new Array();
    }
//body ops
    this.popup=null;
    
    this.showBody=function(id){
        var ix=parseInt(id);
        var body="Loading ...";
        var head=null;

        head=this.index[ix];
        //try to get loaded
        if(this.bodies[ix]+''!='undefined' && this.bodies[ix]!=null){
            body=this.bodies[ix];
        } 

        //show
        this.hideBody();

        this.popup=document.createElement('div');
        this.popup.style.backgroundColor=this.borderColor;
        this.popup.style.border="1px outset #000000";
        this.popup.style.position='absolute';
        this.popup.style.display='none';
        this.popup.style.zIndex=110;
        document.body.appendChild(this.popup);


        var img=this.container.price.img;
        var xy=this.container.getImgXY(img);
        
        var scrollLeft=document.documentElement?document.documentElement.scrollLeft:document.body.scrollLeft;
        var scrollTop=document.documentElement?document.documentElement.scrollTop:document.body.scrollTop;

        var winWH=this.getWindowSize();
                
        var clientWidth=winWH[0];
        var clientHeight=winWH[1];

        var w=img.width*.9;//clientWidth/4*3;
                
        var h=img.height+this.container.volume.img.height/2;
        
        var x=xy[0]+w/18;//scrollLeft+clientWidth/8;
            
        var y=scrollTop+clientHeight/8;
        
        var content="<table id='chart.info.tab'>"+
        "<tr><td align=right style='background-color:"+this.borderColor+";' "+
            "onmousedown='"+this.container.myName+".infos.dragBody(event,0);return false;'"+
            ">"+
            "<a style='cursor:pointer;' onclick='"+
            this.container.myName+".infos.hideBody()'><img src='"+
            this.container.uriBase+"../images/close.gif'></a></td></tr>"+
            "<tr><td valign=top colspan=2 style='width:"+w+
                                                "px;background-color:"+this.bgColor+
                                                ";border-top:1px solid #CCCCCC;padding:0px;'>"+
            "<div id='chart.info.head.pane' style='padding:10px;'>"+
            head[2]+"<br><b>"+
            head[3]+"</b>"+
            "</div>"+
            "<div id='chart.info.body.pane' style='padding:10px;width:"+w+"px;height:"+h+
                "px;overflow:auto;background-color:"+this.bgColor+
                ";border-top:1px solid #CCCCCC'>"+
            body+
            "</div></td></tr>"+
            "<tr><td style='text-align:right;' align=right>"+
            "<img style='cursor:se-resize;' src='"+this.container.uriBase+"../images/resize.gif' onmousedown='"+
            this.container.myName+".infos.resizeBody(event,0);return false;'></td></tr>"+
        "</table>";
            
        this.popup.innerHTML=content;
        this.popup.style.padding=0;
        
        var top=y;
        if(top<xy[1])top=xy[1];
        this.popup.style.left=x+'px';
        this.popup.style.top=top+'px';
        this.popup.style.display='';
        
        if(this.bodies[ix]+''=='undefined' || this.bodies[ix]==null) {
        //load if not loaded
            this.loadBody(id);
        }
    }
    
    //body move
    this.moving=false;
    this.movX=null; this.movY=null;
    
    this.moveF=new Function("event",this.container.myName+".infos.dragBody(event,1);return false;");
    this.upF=new Function("event",this.container.myName+".infos.dragBody(event,2);return false;");
    
    this.dragBody=function(event, what){
    //what: 0 - down
    //      1 - move
    //      2 - up
        var size=500;
        var handler=document.documentElement?document.documentElement:document.body;
        if(what==0){//down handling
            this.moving=true;
            this.movX=event.screenX;
            this.movY=event.screenY;
            this.container.addEvent(handler,"onmousemove",this.moveF);
            this.container.addEvent(handler,"onmouseup",this.upF);
            return;
        }
        if(what==2){//up handling
            this.moving=false;
            this.movX=null;
            this.movY=null;
            this.container.remEvent(handler,"onmousemove",this.moveF);
            this.container.remEvent(handler,"onmouseup",this.upF);
            return;
        }

        if(!this.moving){return;}

        if(what==3){//out handling
            this.dragBody(event,1);
            
            return;
        }

        var x=event.screenX;
        var y=event.screenY;

        if(this.movX==null)this.movX=x;
        if(this.movY==null)this.movY=y;

        var shiftX=this.movX-x;
        var shiftY=this.movY-y;
        
        var nX=parseInt(this.popup.style.left)-shiftX;
        var nY=parseInt(this.popup.style.top)-shiftY;
        
        nX=nX<0?0:nX; nY=nY<0?0:nY;
        
        this.popup.style.left=nX+'px';
        this.popup.style.top=nY+'px';
        this.movX=x;
        this.movY=y;
        
    }
    ////////////////////resize body
    var sizStart=false;
    var sizX=null;
    var sizY=null;

//  var resDn=new Function('event',this.container.myName+".infos.resizeBody(event,0);return false;");
    var resMv=new Function('event',this.container.myName+".infos.resizeBody(event,1);return false;");
    var resUp=new Function('event',this.container.myName+".infos.resizeBody(event,2);return false;");

    this.resizeBody=function(event, what){
    //what: 0 - down
    //      1 - move
    //      2 - up
    //      3 - over
            var handler=document.body;
            var sizHandler=document.getElementById('chart.info.body.pane');
            var sizHead=document.getElementById('chart.info.head.pane');
            var sizTab=document.getElementById('chart.info.tab');
            
            if(what==0){//down handling
                sizStart=true;
                sizX=event.screenX;
                sizY=event.screenY;
                sizHead.style.width=sizHandler.style.width;
                sizTab.style.width=sizHandler.offsetWidth+'px';
                //sizHead.style.height=sizHandler.offsetHeight+'px';
                this.container.addEvent(handler,"onmousemove",resMv);
                this.container.addEvent(handler,"onmouseup",resUp);
                return;
            }
            if(what==2){//up handling
                sizStart=false;
                sizX=null;
                sizY=null;
                this.container.remEvent(handler,"onmousemove",resMv);
                this.container.remEvent(handler,"onmouseup",resUp);
                return;
            }
            if(!sizStart) return;
            
            var x=event.screenX;
            var y=event.screenY;
            
            if(sizX==null)sizX=x;
            if(sizY==null)sizY=y;
            
            var shiftX=(sizX-x);
            var shiftY=(sizY-y);


            var nW=parseInt(sizHandler.style.width)-shiftX;
            var nH=parseInt(sizHandler.style.height)-shiftY;

            nW=nW<=100?100:nW;
            nH=nH<=50?50:nH;

            sizHandler.style.width=nW+'px';
            sizHandler.style.height=nH+'px';
            
            var headHeight=sizHead.offsetHeight+0;
            
            sizHead.style.width=sizHandler.style.width;
            sizTab.style.width=sizHandler.offsetWidth+'px';         
            this.popup.style.width=sizTab.offsetWidth+'px';
            
            nH=parseInt(sizHandler.style.height)-
                    (sizHead.offsetHeight-headHeight);
            
            sizHandler.style.height=(nH<=0?0:nH)+'px';
            
            sizX=x; sizY=y;
    }
    ///////////////////////////////
    this.getWindowSize=function(){
        return this.container.getWindowSize();
    }

    this.hideBody=function(){
        if(this.popup==null) return;
        document.body.removeChild(this.popup);
        this.popup=null;
    }
    
    //load body
    this.uloads=new ChartAssoc();
    this.bodyLoads=new Array();//scripts by id
        
    this.loadBody=function(id){

        var ix=parseInt(id);
        //check for loads
        //clear all completed
        for(var i=0;0<this.bodyLoads.length;i++){
            var rem=this.bodyLoads.shift();
            document.body.removeChild(rem);
        }
        
        var sc=document.createElement('script');
        sc.setAttribute('language', 'javascript');
        
        var src=this.container.uriBase+"infoBody?";
        
        var qp=new Array();
        qp[qp.length]="conf="+this.container.conf;
        qp[qp.length]="target="+this.container.myName;
        qp[qp.length]="referer="+this.container.referer;
        qp[qp.length]="id="+id;
        
        src=src+qp.join('&');
        sc.setAttribute('src',src);
        document.body.appendChild(sc);  
        this.uloads.add(id,sc);
    }
    //set body
    this.setBody=function(id,body){
        var ix=parseInt(id);
        this.bodies[ix]=body;
        //this.hideBody();
        this.showBody(id);
        var sc=this.uloads.get(id);
        if(sc!=null){
            this.bodyLoads.push(sc);
            this.uloads.add(id,null);
        }
    }
}
//container
function ChartingTool(prefix,myName){
/* */
    this.uriBase='http://tools.rsf.ru/superchart/chart/';
/* *
    this.uriBase='http://localhost/superchart/chart/';
/* */
    this.prefix=prefix;
    this.myName=myName;

    this.conf=null;
    this.referer=document.location.href.split('?')[0];
    this.calendar=null;//ChartCalendar
    this.volSel=null;//ChartVolSel
    this.typeSel=null;//ChartTypeSel
    this.mouseCursor=null;//ChartDateMap
    this.instruments=new ChartAssoc();
    ///presentations
    this.price;// ChartDraw
    this.volume;// ChartDraw
    this.table;// ChartTable
    this.seriaInputs=new ChartAssoc();
    this.infos=new ChartInfo(this);
    
    //registry
    this.images=new ChartAssoc();
    ///read form, register controls and create presentations
    this.readForm=function(){
        //presentations
        this.price=new ChartDraw(
            document.getElementById(this.prefix+'.PriceImg'),
            this
        );
        //set the events??
        /////////////////////////////
        this.volume=new ChartDraw(
            document.getElementById(this.prefix+'.VolumeImg'),
            this, true
        );
        this.table=new ChartTable(
            this.prefix+'.Table',
            this
        );
        this.mouseCursor = new ChartMouseCursor(
            this
        );
        //read form and register controls
        var inputs=document.getElementsByTagName('input');
        
        for(var i=0; i<inputs.length; i++){
            var input=inputs[i];
            if(input.id.indexOf(this.prefix+'.')==0){
                var id=input.id.split('.');
                if(id.length<2) continue;
                
                var obj;
                if(id[1]=='seria'){
                    obj=new ChartSeria(input);
                    this.seriaInputs.add(obj.code,obj);
                    if(obj.hasTarget('price'))
                        this.price.addSeria(obj);
                    if(obj.hasTarget('volume'))
                        this.volume.addSeria(obj);
                    if(obj.hasTarget('table'))
                        this.table.addSeria(obj);
                    
                } else if(id[1]=='instrument'){
                    var instr=this.instruments.get(id[2]);
                    if (instr==null) {
                        instr=new ChartSeria();
                        this.instruments.add(id[2],instr);
                    }
                    instr.setInput(input);
                    if(instr.hasTarget('price'))
                        this.price.addInstrum(instr);
                    if(instr.hasTarget('volume'))
                        this.volume.addInstrum(instr);
                } else if(id[1]=='ip'){
                    var instr=this.instruments.get(id[2]);
                    if (instr==null) {
                        instr=new ChartSeria();
                        this.instruments.add(id[2],instr);
                    }
                    instr.setParameter(input);                  
                } else if(id[1]=='volume'){
                    //this.volume = input;
                } else if(id[1]=='conf'){
                    this.conf=input.value;
                }// else {continue;}
            }
        }
        this.volSel=new ChartVolSel(this);
        this.calendar= new ChartCalendar(this);
        this.typeSel=new ChartTypeSel(this);
    };

    this.redraw=function(){
        this.mouseCursor.hideCursor();
        var index=this.volSel.input.selectedIndex;
        this.volume.redraw(index);
        this.table.redraw();
        this.price.redraw();
        this.mouseCursor.update();
        this.showHeaders();
    };
    
    this.nextVol=function(){
        this.volSel.change(this.volSel.input.selectedIndex+1);
        this.redraw();
    };
    
    this.getDrawing=function(id){
        return this.images.get(id);
    };
    
    ////facade for ChartMouseCursor
    this.setCalendar=function(calendarArray){
        if(calendarArray.length==0) return;
        this.mouseCursor.dateList=calendarArray;
        this.mouseCursor.update();
    };
    
    this.setMargins=function(l,r,t,b){
        this.mouseCursor.lm=l;
        this.mouseCursor.rm=r;
        this.mouseCursor.tm=t;
        this.mouseCursor.bm=b;
    };
    
    this.imReady=function(){
        this.mouseCursor.ready=true;
    };
    
    this.mousePressed=false;
    this.zoomStart;
    this.zoomEnd;


    
    this.mouseDown=function(event){

        if(event.button==2) return false;

        var date=this.mouseCursor.plotCursor(event);
        document.body.style.cursor='e-resize';
        this.mousePressed=true;
        this.mouseCursor.hint.innerHTML=date;
        this.mouseCursor.hCursor.style.display='none';
        this.mouseCursor.vHint.style.display='none';
        this.mouseCursor.fHint.style.display='none';
        this.zoomStart=date;
        
        return false;
    };

    this.mouseUp=function(event){

        if(event.button==2 || !this.mousePressed) return false;

        var date=this.mouseCursor.plotCursor(event);

        this.zoomEnd=date;
        
        this.mousePressed=false;
        this.calendar.setMargin(this.zoomStart,this.zoomEnd);
        document.body.style.cursor='auto';
        this.mouseCursor.hideCursor();
        this.redraw();
        return false;
    };

    this.hideCursor=function(){
        document.body.style.cursor='auto';
        this.mouseCursor.hideCursor();
    };
    this.mouseOut=function(event){
        var call=this.myName+'.hideCursor()';
        setTimeout(call,100);
        return false;
    };
    this.mouseMove=function(event){
        var date=this.mouseCursor.plotCursor(event);
        this.zoomEnd=date;
        
        if(this.mousePressed){
            document.body.style.cursor='e-resize';
            if(this.mouseCursor.hCursor){
                this.mouseCursor.hCursor.style.display='none';
                this.mouseCursor.vHint.style.display='none';
                this.mouseCursor.fHint.style.display='none';
            }
            if(this.mouseCursor.hint){
                this.mouseCursor.hint.innerHTML=date;
                this.mouseCursor.drawBox(event);
            }
            
        }
        else{
            document.body.style.cursor='pointer';
            this.getValues(event);
        }
        return false;
    };

    this.setHintsColor=function(color){
        this.mouseCursor.hBG=color;
    }

    this.setInfoColor=function(border,bg){
        this.infos.borderColor=border;
        this.infos.bgColor=bg;
    }
    
    this.getValues=function(event){
        var date=this.mouseCursor.plotCursor(event);
    };
    
    this.setHighLow=function(id, high, low, measure){
        var img=this.images.get(id);
        img.high=high;
        img.low=low;
        img.measure=measure;
        img.ready=true;
    };
    //setSeria
    this.loadSeria=function(seria,fields,fnames){
        this.mouseCursor.loadSeria(seria,fields,fnames);
    }
    this.setSeria=function(seria,field,data){
        this.mouseCursor.seriaSetData(seria,field,data);
    }
    //loadHeaders
    this.loadHeaders=function(comp,types){
        this.infos.loadHeaders(comp,types);
    }
    //addHeader 
    this.addHeader=function(comp,id,date,header){
        this.infos.addHeader(comp,id,date,header);
    }
    this.addHeaderReady=function(comp){
        this.infos.addHeadersComplete(comp);
    }
    this.linkComp=function(series,comps){
        var seria=series.split(',');
        var comp=comps.split(',');
        for(var i=0;i<seria.length;i++){
            for(var j=0;j<comp.length;j++){
                this.infos.linkComp(seria[i],comp[j]);
            }
        }
    }
    this.showHeaders=function(){
        var start=this.mouseCursor.d1ix;
        var end=this.mouseCursor.d2ix;
        var xy=this.getImgXY(this.price.img);
        var x=xy[0]+this.mouseCursor.lm;
        var y=xy[1];
        var w=this.price.img.width-this.mouseCursor.lm-this.mouseCursor.rm;
        var h=this.mouseCursor.tm;

        this.infos.showHeaders(this.price.checkedSeries,start,end,x,y,w,h);
    }
    
    this.showInfoDrop=function(i){
        this.infos.showDrop(i);
    }
    this.hideInfoDrop=function(i){
        this.infos.hideDrop(i);
    }
    this.showInfoBody=function(id){
        this.infos.showBody(id);
    }
    this.setBody=function(id,body){
        this.infos.setBody(id,body);
    }
    //end of declarations
    this.init=function(){
        this.readForm();
        this.setEventHandling();
        this.redraw();
    }
    //common utils
    this.getImgXY=function(img){
        var res=new Array();
        if(img.x+''!='undefined'){
            res[0]=img.x;
            res[1]=img.y;
            return res;
        }
        var x,y;

        x=img.offsetLeft; 
        y=img.offsetTop;
        
        var cEl=img.offsetParent;
        while(cEl!=null){
            x+=cEl.offsetLeft;  
            y+=cEl.offsetTop;
            cEl=cEl.offsetParent;
        }
        res[0]=x;res[1]=y;
        return res;
    }
    this.getWindowSize=function(){
        var sizer=document.createElement('div');
        sizer.style.width='100%';
        sizer.style.height='100%';
        document.body.appendChild(sizer);
        
        var w=sizer.offsetWidth;
        var h=sizer.offsetHeight;
        document.body.removeChild(sizer);   
        
        return new Array(w, h);
    }
    this.outerMouseX=function(event){
        if(event.pageX){
            return event.pageX;
        }
        if(document.documentElement.scrollLeft || document.documentElement.clientLeft){
            return event.clientX+document.documentElement.scrollLeft-document.documentElement.clientLeft;
        }
        else{
            return (event.clientX+document.body.scrollLeft-document.body.clientLeft);
        }
    }
    this.outerMouseY=function(event){
        if(event.pageY){
            return event.pageY;
        }
        if(document.documentElement.scrollTop || document.documentElement.clientTop){
            return (event.clientY+document.documentElement.scrollTop-document.documentElement.clientTop);
        }
        else{
            return (event.clientY+document.body.scrollTop-document.body.clientTop);
        }
    }
    this.addEvent=function(handler,ev,func){
        if(handler.attachEvent){
            handler.attachEvent(ev,func);
        } else if(handler.addEventListener){
            handler.addEventListener(ev.substr(2),func,false);
        }
    }
    this.remEvent=function(handler,ev,func){
        if(handler.detachEvent){
            handler.detachEvent(ev,func);
        } else if(handler.removeEventListener){
            handler.removeEventListener(ev.substr(2),func,false);
        }
    }
    //set events handling
    this.setEventHandling=function(){
    //document.body.onresize
    //this.price.img.onmousemove
        if(!this.price.img.onmousemove){
            this.price.img.onmouseon=new Function("return false;");
            this.addEvent(this.price.img,'onmousemove',
                new Function('event','return '+this.myName+'.mouseMove(event);'));
        }
    //               onmousedown
        if(!this.price.img.onmousedown){
            this.price.img.onmousedown=new Function("return false;");
            this.addEvent(this.price.img,'onmousedown',
                new Function('event','return '+this.myName+'.mouseDown(event);'));
        }   
    //               onmouseup
        if(!this.price.img.onmouseup){
            this.addEvent(this.price.img,'onmouseup',
                new Function('event','return '+this.myName+'.mouseUp(event);'));
        }   
    //               onmouseout
        if(!this.price.img.onmouseout){
            this.addEvent(this.price.img,'onmouseout',
                new Function('event','return '+this.myName+'.mouseOut(event);'));
        }   
    //this.volume.img.onmousemove
        if(!this.volume.img.onmousemove){
            this.addEvent(this.volume.img,'onmousemove',
                new Function('event','return '+this.myName+'.mouseMove(event)'));
        }
    //                onmousedown
        if(!this.volume.img.onmousedown){
            this.volume.img.onmousedown=new Function("return false;");
        }   
    //                onmouseout
        if(!this.volume.img.onmouseout){
            this.addEvent(this.volume.img,'onmouseout',
                new Function('event','return '+this.myName+'.mouseOut(event);'));
        }   
    //                onclick
        if(!this.volume.img.onclick){
            this.addEvent(this.volume.img,'onclick',
                new Function('event','return '+this.myName+'.nextVol();'));
        }
    }
}
/* *
if(window.chartInit){
    window.chartInit();
}/* */