﻿/// AJAX CLASS ///
//© 2008 SeatQuest LLC.

//http://www.hunlock.com/blogs/Snippets:_Synchronous_AJAX
function AJAX(url,callback,post_params)
{
    post_params = post_params || null;

    //ELI PRIVATE DECLERATIONS
    //-------------------------
    this.type=this.get_type();
    var request=this.get_request();
    
    //ELI PUBLIC DECLERATIONS
    //-------------------------
    this.get = function(url,callback,post_params)
    {
         var async=false;
         if(callback){async=true;}
         if(post_params!=null)
         {
            request.open("POST", url, async);
            request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            request.setRequestHeader("Content-length", post_params.length);
            request.setRequestHeader("Connection", "close");
            request.setRequestHeader("User-agent", navigator.userAgent);
            request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
         }
         else
         {
            request.open("GET", url, async);
            request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
         }
         if (callback)
         {
            //ELI this is a good example of closure since we are passing the request objec into the anonymous function.
            var ajax_loaded = function ()
            {
                if (request.readyState==4 || request.readyState=="complete") 
                {
                    if(callback){callback(request,url);}
                }
            };
            if (framework.browser.id === "firefox" && framework.browser.version === 3.5) {
              // Firefox 3.5 has some weird readystatechange bug, so use the W3C Progress Events instead
              // see: http://www.nczonline.net/blog/2009/07/09/firefox-35firebug-xmlhttprequest-and-readystatechange-bug/
              request.onload = request.onerror = request.onabort = ajax_loaded;
            } else {
              request.onreadystatechange = ajax_loaded;
            }
         }
         request.send(post_params);
         if(!async){this.response = request;return request;}else{this.response =null;return null;}
    }
    
    //ELI trigger a get if values are in the contructor.
    if(url){this.get(url,callback,post_params);}

};

//ELI get the browser type
AJAX.prototype.get_type=function()
{
    if (window.XMLHttpRequest){return "GECKO";} else {return "IE";}
};

//ELI AJAX Reuqest.
AJAX.prototype.get_request = function() 
{
    //if(type=="IE"){return new ActiveXObject("Microsoft.XMLHTTP");}
    if (this.type == "IE") { return new ActiveXObject('MSXML2.XMLHTTP.3.0'); }
    if (this.type == "GECKO") { return new XMLHttpRequest(); }
    return null;
};﻿// CSS CLASS
//© 2008 SeatQuest LLC.
//TODO FUTURE CLASS.

//ELI for future ease of page manipulation I would like to create a CSS class that will be able to provide the folowing tools:
//1. replace a whole CSS file with URL or a whole string.
//2. change/add/remove properties in a class (.id) or element (#id) in a CSS file.


////ELI filter and sort to the current configuration.
//XSLT.prototype.apply_filter_css=function (args)
//{
//    if(!args.xsl){return;}
//    if(!this) return;
//    var dom=this.merge(null,args.xsl,args.params);
//    this.replace_css(args.href,dom);
//};

////ELI get a style sheet by href
//XSLT.prototype.get_css=function (href) {
//    var css=-1;
//    for (var s = 0; s < document.styleSheets.length; s++){
//        if(document.styleSheets[s].href.indexOf(href)>0){css=s;break;}
//    }
//    if (css<0){return null;}
//    return document.styleSheets[s];
//};


//XSLT.prototype.create_css=function (href,style_body)
//{
//        //ELI Replace
//        var link=document.createElement('link');
//        link.href=href;
//        link.type='text/css';
//        link.rel='Stylesheet';
//        if(style_body)
//        {
//            var style=document.createElement('style');
//            var div=document.createElement('div');
//            div.appendChild(style_body);
//            //alert(div.innerHTML);
//            var tn=document.createTextNode(div.innerHTML);
//            style.appendChild(tn);
//            link.appendChild(style);
//        }
//        
//        var head = document.getElementsByTagName('head')[0];
//        head.appendChild(link);
//        return link;
//};

////ELI replace the document style sheet
//XSLT.prototype.replace_css=function (href,style_body)
//{
//    this.debug.time("Replace_CSS");
//    var css=this.get_css(href);

//    //ELI TODO
//    //css=null;
//    if(!css){css=this.create_css(href,null);css=this.get_css(href)}//return;}

//    if(document.all)//ELI IE only
//    {
//        var end_xml=style_body.indexOf('?>');
//        if(end_xml>0){style_body = style_body.substring(end_xml+2);}
//        
//        //ELI IE6 
//        if(!window.XMLHttpRequest){ style_body=style_body.replace(/table-row/g,'block');}
//        css.cssText=style_body;//'.switch{display:none !important;}#cls_523629796{display:block  !important;}';
//    }else{ //ELI other browsers

//        //ELI Remove css
//        var head=css.ownerNode.parentNode;
//        head.removeChild(css.ownerNode);
//        this.create_css(href,style_body);
//    }
//    this.debug.time("Replace_CSS",true);
//    return;

//};


﻿/// DEBUG CLASS ///
//© 2008 SeatQuest LLC.
function DEBUG(args)
{
    this.args=args;
    if(!this.args){this.args={};}
    
    this.queue={};
    this.timers={};
    this.elapsed={};
    this.errors={};
    this.output={};
    this.time_stamp={};
    
    
    //BOGDAN 
    var _this = this;
    if(this.args.key_hook)
    {
        framework.observe(window, 'load', function(e){_this.create_window(e);}, false);
        //framework.observe(document, 'keydown', function(e){_this.key_down_handler(e);}, false);
        //framework.observe(document, 'keyup', function(e){_this.key_up_handler(e);}, false);
        //framework.observe(document, 'keypress', function(e){_this.key_press_handler(e);}, false);
    }        
};


DEBUG.prototype.args={
    active:null,
    add_categories:null,
    key_hook:null
};
//DEBUG.prototype.errors=null;
//DEBUG.prototype.output=null;
//DEBUG.prototype.timers={};
//DEBUG.prototype.elapsed={};
//DEBUG.prototype.time_stamp={};
DEBUG.prototype.changes={};
DEBUG.prototype.shiftPressed=0;
//DEBUG.prototype.queue={
//    apply_to:null
//};

DEBUG.prototype.start=function(s){this.changes[s]=s;this.timers[s]= new Date().getTime(); };
DEBUG.prototype.stop=function(s){if(this.timers[s]){this.elapsed[s]=(new Date().getTime()-this.timers[s]);} return this.elapsed[s];};
DEBUG.prototype.time=function(id,exec)
{
    if(typeof exec=='function')
    {
        this.start(id);
        exec();
        this.stop(id);
    }else{
        if(!exec){
            this.start(id);
        }else{
            this.stop(id);
        }
    }
};

DEBUG.prototype.window_id='div_framework_debug';
DEBUG.prototype.window_created=null;
DEBUG.prototype.create_window=function()
{
    var _this=this;
    var e=document.createElement('div');
    try
    {
        e.style.position='absolute';
        e.style.left='0px';
        e.style.bottom='0px';
        e.style.zIndex='1999';
        e.style.width='300px';
        e.style.display='none';
        e.style.padding='3px';
        
        e.style.fontSize='10px';
        e.style.fontFamily='MS Sans Serif';
        e.style.backgroundColor='White';
        e.style.borderRight='1px solid gray';
        e.style.borderTop='1px solid gray';

        e.id=this.window_id;
        var body = document.getElementsByTagName('body')[0];
        if(body)
        {
            body.appendChild(e);
            this.window_created=true;
            if(this.queue.apply_to){this.queue.apply_to();}
        }
    }catch(err){
        this.debug.error("DEBUG->create_window",err);
    }    
};

DEBUG.prototype.hide=function()
{
    //if(!id){id=this.args.id;}
    var id=this.window_id;
    var e =document.getElementById(id);
    if(e)
    {
        e.style.display='none';
    }
};

DEBUG.prototype.post=function()
{
    //CHRIS
    var operations=new StringBuilder(), times=new StringBuilder();
    for(var s in this.elapsed)
    {
        operations.append(";"+s);
        times.append(";"+this.elapsed[s]);
    }
    //ELI initiate an asynchronious ajax call.
    new AJAX("../profile.aspx",function(){},"operation="+operations.toString().substr(1)+"&pid="+query("pid")+"&elapsed="+times.toString().substr(1));
};

DEBUG.prototype.clear=function()
{   
    this.timers={};
    this.elapsed={};
    this.time_stamp={};
    this.changes={};
    this.output=null;
};

DEBUG.prototype.apply_to=function()
{  
    var _this=this;
    if(!this.args.active){return;}
    if(!this.window_created){this.queue.apply_to=function(){_this.apply_to();};}else{this.queue.apply_to=null;}
    
    var id=this.window_id;
    var e=document.getElementById(id);
    if(e)
    {
        e.style.display='';
        e.innerHTML=this.toString(true);
    }
};

DEBUG.prototype.add_categories=function(obj)
{
    for(var s in obj)
    {
        var e= obj[s];
        this.add_category(s,e);
    }
};

DEBUG.prototype.add_category=function(name,obj)
{
    if(!this.args.categories){this.args.categories={};}
    this.args.categories[name]=obj;
};

DEBUG.prototype.parse_category=function(name,obj,sb,sb_html,element,limit)
{

    if(obj){
        if(name)
        {
            sb.append( name + '\t->\t' +"\r\n");
            sb_html.append('<div style="float:left"><b>' + name + '</b></div><div style="float:right"></div><br/>');
        }
        for(var s in obj){

            if(s=='no_total') continue;
            var c=this.changes[s] ? 'color:red;':'';
            var value=obj[s];
            if(element){value=value[element];}
            if(!value){value=obj[s];}
            if(limit){value=value.toString().substring(0,limit);}
            sb.append(s + "\t->\t" + value + "\r\n");
            sb_html.append('<div style="float:left;border:0px solid black;'+c+'">' + s + '</div><div style="float:right;border:0px solid gray;'+c+'">' + value + "</div><br/>");
        }
    }
};

DEBUG.prototype.calcualte_totals=function(obj,element)
{
    var total=0;
    for(var s in obj)
    {
        if(s=='no_total')continue;
        var value=obj[s];
        if(element){value=value[element];}
        if(!value){value=obj[s];}
        total+=parseInt(value);
    }
    return total;
};

DEBUG.prototype.toString=function(args)
{   

    var sb=new StringBuilder();
    var sb_html=new StringBuilder();

    this.parse_category("Timers",this.elapsed,sb,sb_html);
    this.parse_category(null,{Total:this.calcualte_totals(this.elapsed)},sb,sb_html);

    //ELI collect debug categories fro other objeects.
    if(this.args.add_categories)
    {
        var categories=null;
        if(typeof this.args.add_categories =='object'){categories=this.args.add_categories;}
        if(typeof this.args.add_categories =='function'){categories=this.args.add_categories();}
        this.add_categories(categories);
    }
    
    //ELI add categories
    for(var s in this.args.categories)
    {
        sb.append("\r\n");
        sb_html.append('<br/>'); 
        var obj=this.args.categories[s];
        this.parse_category(s,obj,sb,sb_html);
        if(!obj.no_total) {this.parse_category(null,{Total:this.calcualte_totals(obj)},sb,sb_html);}
    }

    if(this.errors)
    {
        sb.append("\r\n");
        sb_html.append('<br/>');
        this.parse_category("Errors",this.errors,sb,sb_html,'message')
    }
    
    if(this.output)
    {
        sb.append("\r\n");
        sb_html.append('<br/>');    
        this.parse_category("Messages",this.output,sb,sb_html)    
    }
     
    //ELI clear the changes list
    this.changes={}; 

    if(!args){return sb.toString();}else{return sb_html.toString();}
    
};

DEBUG.prototype.print=function(name,value)
{
    if(!this.output){this.output={};}
    this.changes[name]=name;
    this.output[name]=value;

};

DEBUG.prototype.key_down_handler=function(event)
{
    if(event.shiftKey) this.shiftPressed = 1;
};


DEBUG.prototype.key_up_handler=function(event)
{
    /* there's no event.shiftKey onkeyup response
    so this detects it */
    if (event.keyCode == 18 || event.charCode == 18) 
    {
        this.shiftPressed = 0;
    }
};

DEBUG.prototype.key_press_handler=function(event) 
{
    if (this.shiftPressed == 1) {
        if(event.keyCode == 84 || event.charCode == 84)
        {
            this.args.active=true;
            this.apply_to();
        }
        if(event.keyCode == 82 || event.charCode == 82)
        {
            this.args.active=false;
            this.hide();
        }        
    }
};


DEBUG.prototype.trap=function(name,fn)
{
    try
    {
        fn();
    }catch(err){
        this.error(name,err);
    }

};

DEBUG.prototype.error=function(name,value)
{
    if(!this.errors){this.errors={};}
    this.changes['err_'+name]=name;
    this.errors[name]=value;
};/// FILTER CLASS ///
//© 2008 SeatQuest LLC.

/// <reference path="framework.js" />
/// <reference path="zoomer.js" />
/// <reference path="debug.js" />
/// <reference path="xsl.js" />
function FILTER(args)
{
    this.actual_sections_ready=false;
    var _this=this;
    if(args){this.args=args;}
    
    //ELI will provide debug information.
    this.debug=this.args.debug;
    if(!this.debug){this.debug=new DEBUG();}
    this.zoomer=this.args.zoomer;
    this.price_ranges=this.args.price_ranges;
    
    //ELI will help manipulate XSL.
    this.xslt = new XSLT({debug:this.debug});
    
    //ELI set default args
    this.set_default_args();

    //ELI start looking for the ticket list DIV element.
    this.flags.load=true;
    framework.observe(this.args.id,'onload',function(){_this.load();});
    
    //ELI if we have XML and XSL urls we can start he download.
    if(this.args.xsl_url)
    {
        this.download();
        this.apply();
    }
    //initialize section selections
    this.reset_selected_sections();

};

//ELI default parameters
FILTER.prototype.args={
    id:null,
    xml_url:null,
    xsl_url:null,
    pre_render:null,
    post_render:null,
    pre_filter:null,
    post_filter:null,
    get_values:null,
    set_values:null,
    quantity_filter:null,
    sort_options:null,
    filter_options:null,
    delay_default:null, 
    debug:null,
    zoomer:null,
    sq_contains_coordinates:null,
    convert_from_tb:null,
    show_all:null,
    parking_tab:null,
    no_filtering_for_parking:null,
    wait_for_zoomer:null
}

FILTER.prototype.debug=null;
FILTER.prototype.xslt=null;
FILTER.prototype.xml=null;
FILTER.prototype.xsl=null;
FILTER.prototype.xsl_base=null;
FILTER.prototype.xsl_base_url=null;
FILTER.prototype.complete_xsl=null;
FILTER.prototype.xsl_for_conversion_url=null;



FILTER.prototype.flags={
    load:null,          //ELI FLAG which indicates that we are waiting for the ticket list DIV to load.
    download:null,      //ELI FLAG which indicates that we started a download.
    xml_ready:null      //ELI FLAG when xml_ready starts
};

FILTER.prototype.queue={
    apply:null,      //ELI apply() request was made but XSL & XML havent arrived yet.
    reset:null      //ELI reset() it is possible that a reset operation is requested before we downloaded the XML.
};

FILTER.prototype.load=function()
{
    this.flags.load=null;
    if(this.queue.apply){this.queue.apply();}
}

FILTER.prototype.set_default_args=function()
{
    //ELI quantity filter.
    if(!this.args.quantity_filter)
    {
        //ELI load default quantity filter.
        this.args.quantity_filter=[];
        this.args.quantity_filter[1]=[1,3,5,7,9,11,13];
        this.args.quantity_filter[2]=[2,4,5];
        this.args.quantity_filter[3]=[3,5,7,9,11,13];
        this.args.quantity_filter[4]=[4,6];
        this.args.quantity_filter[5]=[5,7,9,11];
        this.args.quantity_filter[6]=[6,8,10];
        this.args.quantity_filter[7]=[7,9,11];
        this.args.quantity_filter[8]=[8,10];
        this.args.quantity_filter[9]=[9,11];
        this.args.quantity_filter[10]=[10];
    };
    
    if(!this.args.sort_options)
    {
        //ELI load default sort_option values.
        this.args.sort_options={
            'default':{id:'price',field:'SGPriceWithFees',order:'ascending',type:'number'},
            'price':{field:'SGPriceWithFees',order:'ascending',type:'number'},
            'available':{field:'Available',order:'ascending',type:'number'},
            'section':{field:'SeatSection',order:'ascending',type:'text'},
            'row':{field:'SeatRow',order:'ascending',type:'text'}
        };
    };

    if(!this.args.filter_options)
    {
        //ELI load default filter option values.
        this.args.filter_options={
            'default':{id:'tickets',min:0,max:99999,quantity:'',ticket_type:'',fees:false,ga: 0},
            'tickets':{min:0,max:99999,quantity:'',ticket_type:'',fees:false,ga: 0},
            'parking':{min:0,max:99999,quantity:'',ticket_type:'',fees:false,ga: 2}
        };
    };
    
    if(!this.args.delay_default)
    {
        this.args.delay_default=100;
    };
    
    if(this.args.xsl_base_url)
    {
        this.xsl_base_url=this.args.xsl_base_url;  
    };
    
    if(this.args.xsl_for_conversion_url)
    {
        this.xsl_for_conversion_url=this.args.xsl_for_conversion_url;  
    };
    
    //ELI wait for zoomer loop in apply function
    if(this.args.wait_for_zoomer==undefined){
        this.args.wait_for_zoomer=true;
    }
    
    //ELI creates a queue for ticket id's that wil show in the list alone. 
    this.reset_selected();
  
}

//ELI in charge of firing the appropriate callbacks + mergin and rendering the XHTML to the document.
FILTER.prototype.inner_callback=function(ajax,url)
{
    var _this=this;
    //if(this.args.xml_ready){ setTimeout(function(){_this.args.xml_ready(_this);},1); }
    //if(this.args.xsl_ready){ setTimeout(function(){_this.args.xsl_ready(_this);},1);}
    if(url==this.args.xml_url && this.xml==null){this.xml=ajax; this.debug.time("Download XML",true); if(!this.args.convert_from_tb) {this.xml_ready();}; }  
    if(url==this.args.xsl_url && this.xsl==null){this.xsl=ajax; this.debug.time("Download XSL",true); }
    
    
    //ELI check for xsl base
    var ready=this.xml && this.xsl;
    if(this.xsl_base_url)
    {
        if(url==this.xsl_base_url && this.xsl_base==null ){this.xsl_base=ajax; this.debug.time("Download XSL_BASE",true); }
        ready=ready && this.xsl_base;
    }
    //BOGDAN check for xsl for conversion
    if(this.args.convert_from_tb)
    {
        if(url==this.xsl_for_conversion_url && this.xsl_for_conversion==null){this.xsl_for_conversion=ajax; this.debug.time("Download XSL for conversion",true); }
        ready=ready && this.xsl_for_conversion;
    }
    
    //ELI return the parsed result with the ajax objects.
    if(ready)
    {
        var status=this.xml.status!=200 || this.xsl.status!=200;
        if(this.xsl_base_url){ status=status || this.xsl_base.status!=200; };
        if(this.args.convert_from_tb){ status=status || this.xsl_for_conversion.status!=200; };
        
        //ELI make sure that we have valid xml, xsl before we proceed.
        if(status) { if(this.args.post_render){setTimeout(function(){_this.args.post_render(_this);},1);} return;}
        
        //BOGDAN convert xml to our format
        if(this.args.convert_from_tb)
        {
            var converted_xml = this.xslt.merge(this.xml,this.xsl_for_conversion.responseText);   
            if(framework.browser != 'explorer')
            {
                this.debug.time("Convert XML");
                var xmlDoc;
                if(framework.browser == 'firefox' || framework.browser == 'opera')
                {                   
                    var xmlDoc=document.implementation.createDocument("","",null);
                    xmlDoc.async="false";
                    xmlDoc.appendChild(converted_xml);              
                }
                else
                {
                    var xmlParser = new DOMParser();
                    xmlDoc = xmlParser.parseFromString(converted_xml.firstChild.innerHTML, "text/xml");
                }
                 converted_xml = xmlDoc;
                 this.debug.time("Convert XML", true);
            }
            this.xml = {responseXML:converted_xml};
            this.xml_ready();
        }    
        //ELI build the complete XSL from XSL_BASE and client XSL.
        if(this.xsl_base_url)
        {
            var tr=this.xsl.responseText.split('<xsl:stylesheet')[1];
            var client_xsl=tr.substring(tr.indexOf('>')+1,tr.indexOf('</xsl:stylesheet'));
            this.complete_xsl=this.xsl_base.responseText.replace('js_client_xsl',client_xsl);
        }else{
            this.complete_xsl =this.xsl.responseText;
        };
        
        //ELI execute this.apply if it is in the queue.
        this.flags.download=null;
        try{
        if(_this.queue.apply){setTimeout(function(){try{_this.queue.apply();}catch(ee){};},1);}
        }catch(e){}
    }
};

//ELI initiate the xml,xsl download.
FILTER.prototype.download= function (args)
{
    //this.args=args;
    this.dom=null;
    this.xml=null;
    this.xsl=null;
    this.queue.apply=null;
    this.flags.download=true;
    this.flags.xml_ready=true;
    
    //ELI without this closure we would not be able to pass "this"
    // as a parameter in the this.args.callback
    this.debug.time("Download XML");
    this.debug.time("Download XSL");
    if(this.xsl_base_url){this.debug.time("Download XSL_BASE");};
    
    var _this=this;
    var cb=function(ajax,url){_this.inner_callback(ajax,url);};
    if(this.args.convert_from_tb) new AJAX(this.xsl_for_conversion_url,cb);
    new AJAX(this.args.xml_url,cb);
    new AJAX(this.args.xsl_url,cb);
    if(this.xsl_base_url){new AJAX(this.xsl_base_url,cb);};

};


//ELI send the h elements to the zoomer.   
FILTER.prototype.xml_ready=function()
{
    var _this=this;
    this.actual_sections = {};
    var filter_option=this.args.filter_options['default'];
    if(!filter_option){return null;}
    if(filter_option.min)filter_option.min=0;
    if(filter_option.max)filter_option.max=99999;
    
    this.debug.time("Calculate Tickets and Rows");
    var xml = this.xml.responseXML;
    if(xml)
    {
        //BOGDAN set sq_contains_coordinates flag
        if(!this.args.sq_contains_coordinates)
        {
            var data = xml.getElementsByTagName('DATA')[0];
            if(data)
            {
                var sq_contains_coordinates = data.getAttribute('sq_contains_coordinates');
                if(sq_contains_coordinates && sq_contains_coordinates.search(/true/i) != -1)
                    this.args.sq_contains_coordinates = true;
                else
                    this.args.sq_contains_coordinates = false;
                
//                if(framework.browser=='firefox')
//                {
//                    var e= data.getAttribute('sq_debug');
//                    if(e)
//                    {
//                        eval(e);
//                        if(xml_debug_information) {this.debug.add_categories(xml_debug_information);}
//                    }
//                }
            }
        }

        //ELI get the times
        try{
            var e= data.getAttribute('sq_debug');
            if(e)
            {
                eval(e);
                if(xml_debug_information) {this.debug.add_categories(xml_debug_information);}
            }
        }catch(err){
            this.debug.error("FILTER->xml_ready",err );
        }
                    
        var rows=xml.getElementsByTagName('row');
        var tickets=0;
        var sq_tickets = 0;
        var sh_tickets = 0;
        var tn_tickets = 0;
        var ei_tickets = 0;
        var rg_tickets = 0;
        var tm_tickets = 0;
        var min=999999,max=0;
        if(rows)
        {
            for(i=0;i<rows.length;i++)
            {
                this.actual_sections[rows[i].getAttribute('SeatSection')] = true;
                var op=parseInt(rows[i].getAttribute('SGPriceWithFees'));
                var p=parseInt(rows[i].getAttribute('TicketPrice'));
                var available = parseInt(rows[i].getAttribute('Available'));
                tickets+=parseInt(rows[i].getAttribute('Available'));
                //BOGDAN count # of tickets for each board
                var tb = rows[i].getAttribute('TB');
                switch(tb){
                    case '1': ei_tickets+=available;
                    break;
                    case '2': tn_tickets+=available;
                    break;
                    case '5': rg_tickets+=available;
                    break;                    
                    case '6': sh_tickets+=available;
                    break;
                    case '7': sq_tickets+=available;
                    break;
                    case '255': tm_tickets+=available;
                    break;

                }
                 
                
                //ELI it is possible that 'op' will not exist in the XML.
                //BOGDAN if no op
                if(!op) op = p;
                if(op<min){min=op;}
                if(p>max){max=p;}
            }
            filter_option.min=min;//data.getAttribute('sq_min_op');
            filter_option.max=max;//data.getAttribute('sq_max_op');
        }
        
        //ELI add times to the debug class.    
        this.debug.time("Calculate Tickets and Rows",true);
        this.debug.print("Rows",rows.length);
        this.debug.print("Tickets Total",tickets); 
        this.debug.print("Event Inventory",ei_tickets);   
        this.debug.print("Ticket Network",tn_tickets);   
        this.debug.print("StubHub",sh_tickets);   
        this.debug.print("RazorGator",rg_tickets); 
        this.debug.print("Ticketmaster",tm_tickets);
        this.debug.print("SeatQuest",sq_tickets);          
    }

    //ELI execute reset in case it is in the queue.
    this.flags.xml_ready=null;
    if(this.queue.reset){setTimeout(function(){_this.queue.reset();},1);}
    
    this.actual_sections_ready = true;
    //ELI load tickets to zoomer
    if(this.zoomer) this.zoomer.load_tickets(xml);
}

// FILTER OPERATIONS
//-----------------------------------------------
//ELI get the values from the client's page.
FILTER.prototype.get_values = function()
{
    //ELI use try catch to silently surpress the user function error.
    if(!this.args || typeof this.args.get_values!='function'){return null;}
    try{
        return this.args.get_values();
    }catch(err){
        this.debug.error("FILTER->get_values",err);
        //ELI return the default filter parameters
        return this.args.filter_options[this.args.filter_options['default'].id];
    }
}

//ELI filter and sort to the current configuration.
FILTER.prototype.apply_htimer = null;
FILTER.prototype.apply = function (args)
{   
    //ELI  the structure of args.
    //    var args={
    //        delay:null,
    //        params:null,
    //    }
    
    //ELI this pre filter function will hold execution until done.
    if(this.args.pre_filter){this.debug.trap("FILTER->pre_filter",this.args.pre_filter);}    

        
    //ELI queue filter operation if necessary.
    //ELI set of checks before we can apply the filter:
    //1. did the XML & XSL download finish?
    //2. is the target DIV element ready yet? 
    var _this=this;
    
    //ELI remove this function from the queue.
    this.queue.apply=null;

    //ELI if download is still going on then queue this call.
    //ELI if ticket list DIV is not ready then queue this call.
    if(this.flags.download || this.flags.load)
    {
        this.queue.apply=function(){_this.apply(args);};
        return;
    }


    //ELI apply filter with delay.
    if(!args){args={};}
    if(!args.delay){args.delay=this.args.delay_default;}
    if(args.delay || ((!this.zoomer || !this.zoomer.ready) && this.args.wait_for_zoomer))
    {
        if(this.apply_htimer){clearTimeout(this.apply_htimer);this.apply_htimer=null;}    
        if((!this.apply_htimer && !args.timer_done) || ((!this.zoomer || !this.zoomer.ready) && this.args.wait_for_zoomer))
        {
            this.apply_htimer=setTimeout(function(){args.timer_done=true;_this.apply(args);},args.delay);
            return;
        }
    }
    
    //ELI no we are ready.
    this.ready_to_apply(args);
 
};

FILTER.prototype.last_params=null;
FILTER.prototype.ready_to_apply = function(args) {
    ///<summary>filter and sort to the current client page.</summary>
    ///<parm name="args.params">parameters to override.</param>
    var _this = this;

    //ELI get values from client
    var params = this.get_values();

    //ELI minimum parameters
    if (!params) { params = {}; }

    //ELI parameter override logic.
    if (args.params) {
        //TODO override other paramteres than sort.
        if (args.params.sort) params.sort = args.params.sort;
        if (args.params.ga) params.ga = args.params.ga;
        //if (args.params.sections) params.sections = args.params.sections;
        //else params.sections = null;
        if (args.params.color) params.color = args.params.color;
        else params.color = null;
    }

    //BOGDAN if no sort option is passed restore last or assign default
    if (!args.params || !args.params.sort) {
        if (!this.last_params || !this.last_params.sort) {
            params.sort = this.args.sort_options['default'].id;
        } else {
            params.sort = this.last_params.sort;
        }
    }


    //ELI final filter parameters.  
    var filter_option = params;

    //ELI if no parameteres exist then return immidiatly.
    while (filter_option) {

        //ELI arrange the sorting options.
        var sort_option = this.args.sort_options[filter_option.sort];
        //BOGDAN flip order only when sort is passed explicitly in args.params
        
		//ERIC we don't want this toggle functionality
		if (args.params) sort_option.order = args.params.order;
		//if (args.params && args.params.sort && filter_option.sort) { sort_option.order = sort_option.order == 'ascending' ? 'descending' : 'ascending'; }
		
		filter_option.order = sort_option.order;
        filter_option.sort_option = sort_option;

        //ELI remember the last parameter and exits if the same.
        if(!this.args.force)
        {
            if (!framework.object_comparison(filter_option, this.last_params)) {
                this.last_params = filter_option;
            } else {
                break;
            }
        }else{
            this.args.force =false;
        }

        //ELI start the filter according to the parameters.
        this.debug.print("XSL Sort", sort_option.field + ", " + sort_option.order + ", " + sort_option.type );

        //ELI start the filter according to the parameters.
        var select = this.query_builder(filter_option);
        this.debug.print("XSL Query", select);

        //ELI build the string params.
        var string_params =
        {
            'js_select': select,
            'js_sort_field': sort_option.field,
            'js_sort_order': sort_option.order,
            'js_sort_type': sort_option.type,
            //'js_queue_applied': this.ids.length,
            //'js_show_ids': this.ids_onhold.join(';') + ';',
            'js_fees': filter_option.fees,
            'js_fav_ids': this.ids_onhold.join(";")
        };
        //ELI add string parmeters to args.string_params
        framework.object_overwrite(string_params, this.args.string_params);

        //ELI merge xml and xsl.
        //alert(this.xml.responseXML.firstChild.tagName);
        var dom = this.xslt.merge(this.xml, this.complete_xsl, string_params);

        //alert(dom.firstChild.innerHTML)
        //BOGDAN extract stats object 
        var xsl_stats = this.extract_xsl_stats(dom);
        //alert(xsl_stats.ids)
        filter_option.xsl = xsl_stats;

        //ELI 
        if (dom) {
        
            
            //ELI higlight/switch off tickets in the zoomer
            //setTimeout(function(){_this.apply_to_zoomer(dom);},1);
            //ELI 3.0.0 - if no zoomer info then dont apply to zoomer.
            if (xsl_stats) { 
                if(this.price_ranges != null) this.price_ranges.init_price_ranges(xsl_stats.prices, xsl_stats.sections, filter_option.min, filter_option.max);
                this.apply_to_zoomer(xsl_stats.ids, xsl_stats.sections, filter_option.color); 
            }

            //ELI apply to div
            this.apply_to(this.args.id, dom);
        }
        break;
    }

    //ELI show debug info.
    this.debug.apply_to();

    //ELI execute client's post_filter function.
    //args.params.sort_option=this.args.sort_options[args.params.sort];
    //args.params.sort_option = this.args.sort_options[args.params.sort ? args.params.sort : this.args.sort_options['default'].id ];
    if (this.args.post_filter) { this.debug.trap("FILTER->post_filter", function() { _this.args.post_filter(filter_option); }); }

}

FILTER.prototype.apply_to_zoomer = function(s, sections, color)
{
    try
    {
//        this.debug.time("Array 1st");
//        var table = null;
//        if(dom.firstChild.nodeName.toLowerCase()=='xml'){table=dom;}else{table=dom.firstChild;};
//        var trs =table.getElementsByTagName('tr');
//        if(!trs){return;}

//        var ids=[];
//        for(i=0;i<trs.length;i++)
//        {
//            var tr=trs[i];
//            ids.push(tr.getAttribute('id').replace(/ /g,'').replace(/tg_/g,''));
//        }
//        this.debug.time("Array 1st",true);

//        this.debug.time("Array 2nd");
//        var s=ids.join('$,');
//        this.debug.time("Array 2nd",true);

        this.debug.time("Zoomer Bridge");
        if(this.zoomer){
            if(this.price_ranges == null) {
                this.zoomer.show_seats(s);
            } else {
                this.price_ranges.show_sections(sections, color);
            }
        }
        
        this.debug.time("Zoomer Bridge",true);
    }catch(err){
        this.debug.error("FILTER->apply_to_zoomer",err);
    }
}

//ELI apply the dom tree to an element.
FILTER.prototype.apply_to = function(id,dom,encode)
{
    this.debug.time("HTML Render");
    
    //if(this.args.pre_render){this.args.pre_render(this);}    
    var s=null;
    if(dom)
    {
        if(document.all)
        {
            s=this.toString(dom);
        }else{
            s=this.toString(dom);
            s=this.apply_firefox_fix(s);
        }
        if(encode){s=this.html_encode(s);}
    }      

    var e=null;
    if(typeof id=='string'){e=document.getElementById(id);}
    if(typeof id=='object'){e=id;}

    if(e)
    {
        if(typeof s=='string')
        {
            e.innerHTML=s;
        }
        if(typeof s=='object')
        {
            e.appendChild(s);
        }
        
    }
    
    this.debug.time("HTML Render",true);
};

FILTER.prototype.toString = function(dom,encode)
{
    if(typeof dom=='string'){return dom;};
    if(typeof dom=='object')
    {
       if(framework.browser=='explorer'){return dom.xml;}
       return (new XMLSerializer()).serializeToString(dom);
    }
}

//ELI apply the dumb FF fix.
FILTER.prototype.apply_firefox_fix = function(s)
{
    if(framework.browser=='firefox')
    {   
            //this.replaceHTML(e,this.html_decode(e.innerHTML));
            s=this.html_decode(s);
    }    
    return s;
};

//ELI decodes HTML entities.
FILTER.prototype.html_decode=function(value)
{
        return !value ? value : String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");
};

//ELI encodes HTML entities.
FILTER.prototype.html_encode=function(value)
{
        return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/""/g, '&quot;').replace(/[<]/g, "&lt;");
};

//ELI Reset the filter
FILTER.prototype.reset=function()
{
    var _this=this;
    
    //ELI remove ourselves from the queue
    if(this.queue.reset){this.queue.reset=null;}
    
    //ELI queue ourselves in case XML is not ready yet.
    if(this.flags.xml_ready){this.queue.reset=function(){_this.reset();};return;}

    //ELI reset to default options in filter and sorting.
    var filter_option = this.args.filter_options[this.args.filter_options['default'].id];
    framework.object_assign(filter_option,this.args.filter_options['default']);
    var sort_option = this.args.sort_options[this.args.sort_options['default'].id];
    framework.object_assign(sort_option,this.args.sort_options['default']);
    filter_option.sort=sort_option;
    
    //BOGDAN reset last params
    this.last_params = null;

    //ELI reset the queue of last ids.
    this.reset_selected();
    this.reset_selected_sections();
    
    //ELI section highlight support
    if(framework.section_logic)
    { 
        framework.section_logic.reset_highlights();
    }
    
    this.args.set_values(filter_option);    
    
    //if(this.zoomer)this.zoomer.zoom(1);
}


FILTER.prototype.apply_selected = function()
{
    ///<summary>apply the queue of last ids.</summary>
    this.ids = this.ids_onhold;     //ELI activate the IDs
    this.last_params = null;        //ELI this will force a filter operation.
    this.apply();
}

FILTER.prototype.apply_all = function()
{
    ///<summary>apply the queue of last ids.</summary>
    this.ids = [];     //Bogdan deactivate the IDs
    this.last_params = null;        //ELI this will force a filter operation.
    this.apply();
}

FILTER.prototype.reset_selected = function()
{
    ///<summary>reset the queue of last ids.</summary>
    this.ids = [];
    this.ids_onhold = [];
}


FILTER.prototype.apply_selected_sections = function()
{
    ///<summary>apply the queue of last selected sections.</summary>
    this.sections = this.sections_onhold;     
    this.last_params = null;        //ELI this will force a filter operation.
    this.apply();
}

FILTER.prototype.reset_selected_sections = function()
{
    ///<summary>reset the queue of last sections.</summary>
    this.sections = [];
    this.sections_onhold = [];
}


FILTER.prototype.queue_selected_section = function(section)
{
    ///<summary>add the ticket id to a queue that will show only them in the next apply.</summary>
    var ra = this.sections_onhold;
    
    //ELI first remove the id from the queue
    for(var i=0;i<ra.length;i++)
    {
        if(ra[i]==section){ra.splice(i,1); return;}
    }
    
    //ELI if the id DNE in the queue then add it.
    this.sections_onhold.push(section);
}


FILTER.prototype.queue_selected = function(id)
{
    ///<summary>add the ticket id to a queue that will show only them in the next apply.</summary>
    var ra = this.ids_onhold;
    
    //ELI first remove the id from the queue
    for(var i=0;i<ra.length;i++)
    {
        if(ra[i]==id){ra.splice(i,1); return;}
    }
    
    //ELI if the id DNE in the queue then add it.
    this.ids_onhold.push(id);
}

FILTER.prototype.query_builder = function (params)
{
    ///<sumary>buld a string for filter query in the XSL_BASE document.</sumary>    
    ///<return></return>
    ///
    //ELI ticket price filter
    var ticket_type=(params.ticket_type=='exact') ? '' : params.ticket_type;
    var ticket_price=(params.fees ? '@TicketPrice':'@SGPriceWithFees');
    var exact= (params.ticket_type=='exact') ? {name:' and @sq_exact',op:"=", value:'1',prefix:"'",suffix:"'"} : null;
  
    //ELI ga filter - [0-all tickets except ga types, 1-ga (ga type), 2-parking (ga type)]
    // the ")" before the end is very important to generate this kind of query at the end:
    //
    var ga = params.ga>0 ? {name:' and (@sq_ga',op:"=", value:params.ga, glue:"",suffix:")"} : {name:' and (not(@sq_ga) or @sq_ga',op:" &lt; ", value:"2", glue:"",suffix:")"};
    
    //ELI sq_coords
    var sq_coords = params.ga==0 ? {name:' and @sq_coords',op:"!=", value:"''",bypass_wildcard:true}:null;
    //var sq_coords = null; //ELI we want to show all the tickets.
    
    //ELI ticket board filter
    var tb = {name:' and @TB',op:"=", value:ticket_type,prefix:"'",suffix:"'"};
    
    if(!this.args.sq_contains_coordinates)
    {
        sq_coords=null;
    }

    //ELI show all the tickets ga+ parking +anything possible and do not filter ticketboards
    if(this.args.show_all)
    {
        sq_coords=null;
        //BOGDAN parking_tab
        if(!this.args.parking_tab)
        {
            ga=null;//tb=null;
        }
    }
    

    var quantity_select=this.args.quantity_filter;
    var quantity = params.quantity;
    var qs=quantity_select[parseInt(quantity)];
    if(qs){quantity=qs.join(" or @Available = ") +  " or @Available &gt; " + qs[qs.length-1];}

    //ELI setup the query to show only certain ticekts.
    var show_ids=null;
    if(this.ids.length>0)
    {
       show_ids={name:" and (@TicketID" ,op:"=", value:this.ids.join(" or @TicketID=")+")"};
    }
    
    //bogdan show sections
    var show_sections=null;
    if(typeof this.sections != "undefined" && this.sections.length>0)
    {
       show_sections={name:" and (@SeatSection" ,op:"='", value:this.sections.join("' or @SeatSection='")+"')"};
       ga = null;
    }
    

    //ELI the extra "(" at the beginning is very important to generate this kind of query at the end:
    //
	var available, min_price, max_price;
    if(params.ga == 2 && this.args.no_filtering_for_parking)
    {
        available = {name:'(@Available',op:"=", value:0, glue:")"};
        min_price = {name:' and ' + ticket_price ,op:" &gt;= ", value:"0"};
        max_price = {name:' and ' + ticket_price ,op:" &lt;= ", value:"999999"};    
    }
    else
    {
        available = {name:'(@Available',op:"=", value:quantity, glue:")"};
        min_price = {name:' and ' + ticket_price ,op:" &gt;= ", value:params.min};
        max_price = {name:' and ' + ticket_price ,op:" &lt;= ", value:params.max};    
    }
    
    //ELI make sure to add the appropriate parenthasis.
    if(ga!=null)
    {
        available.name = "(" + available.name;
        tb.name = ")" + tb.name;
    }
	
    var args=[
    available,
    show_sections,
    show_ids,
    min_price,
    max_price,
    exact,
    sq_coords,
    ga,
    tb
    ];
    
//    //BOGDAN if there are specific ids to show don't apply other filters 
//    if(show_ids)
//    {
//        args=[show_ids];
//    }
    
    //ELI {name,value,op,glue}
    var query=this.query_parse(args);
    
    //alert(query);
    return query;
}

//ELI parse the string_params in orer to create a dynamic XSL.
FILTER.prototype.query_parse=function (args)
{
    //ELI we are expecting set of {name,value,op,glue}
    if(!args) return null;
    var output= new StringBuilder();
    for(s in args)
    {
        var obj=args[s];
        if(!obj || typeof obj!='object'){continue;}
        var select=obj.name;
        if(obj.value!='' && obj.value!="''" || obj.bypass_wildcard){select+= obj.op + (obj.prefix ? obj.prefix: '') + (obj.value ? obj.value: '') + (obj.suffix ? obj.suffix: '');}
        select+=(obj.glue ? obj.glue: '');
        output.append(select);
    }
    return output.toString();
}

FILTER.prototype.params_builder=function()
{
    var params=get_filter_params();
    if(params.sort){params.order=params.order[params.sort];} //ELI we cant pass arrays so we must reduce this parameter.
    return params;    
}

FILTER.prototype.extract_xsl_stats=function(dom)
{
    if(!dom) {return null;}

    var xmldom = null;
    if(dom.firstChild.nodeName.toLowerCase()=='xml')
    {
        xmldom=dom;
    }else{
        xmldom=dom.firstChild;
    };
    
    var stats = xmldom.getElementsByTagName('stats');
    
    if(!stats || stats.length<1){return null;}else{stats=stats[0];}

    var text=null;
    if(stats.text){text=stats.text;};
    if(stats.innerHTML){text=stats.innerHTML;};
    window.eval('var filter_stats_obj =' + text + ';');
    stats.parentNode.removeChild(stats);     
    return filter_stats_obj;
}

FILTER.prototype.load_xml=function(text)
{
    ///<param name="text"/>
    
    if(!text){return;}
    var xml =null;
    if(framework.browser!='explorer' )
    {
       xml = new DOMParser().parseFromString(text, "text/xml");
     }else {
       //ELI create the XSL object.
       xml = XMLDOMObject();
       xml.loadXML(text);
     }
     
     if(!xml) {return;}
     var ajax = {responseXML:xml,status:200};
     this.args.xml_url="artificial_xml";
     this.inner_callback(ajax,this.args.xml_url);   
}

//FILTER.prototype.build_js_fav_test=function(ids, ticketIdName)
//{
//    var result = "";
//    for(var i = 0; i < ids.length(); i++)
//    {
//        result += ticketIdName + "=" + ids[i] + "||";
//    }
//    
//}

//var element='';
//var html='';
//var hTimer=null;
//var index=0;
//XSLT.prototype.fragment_html = function()
//{
//    if(hTimer){clearTimeout(hTimer);}
//    if (index>html.length) {return;}
//    element.innerHTML+=html[index] + "</table>";
//    index++;
//    hTimer=setTimeout(this.fragment_html(),100);    
//};


  
//    //ELI trigger the xsl filtering.
//    function filter_xsl(args)
//    {
//        if(!args){args={};}
//        if(!args.async){
//            if(!args.msg){args.msg="Filtering ...";}
//            show_message(args.msg);
//            
//            //ELI fire yourself back again.
//            var p=function(){filter_xsl({async:true})}
//            setTimeout(p,100);
//            return;
//        }

//        
//        if(xslt)
//        {
//            //ELI filter table
//            xslt.apply_filter();

//            //ELI filter zoomer on another thread
//            //setTimeout(filter_zoomer,1);
//            filter_zoomer();
//                        
//            //xslt.debug.post('div_h');
//        }
//        
//        hide_message();
//        return;
//    }

//        
//    //ELI sort the list.
//    function filter_sort(column)
//    {
//        //ELI start XSL sorting.
//        var params=get_filter_params();
//        var sort='SGPriceWithFees';
//        var type="number";
//        if(column==7 || column==6){sort=params.fees ? 'TicketPrice':'SGPriceWithFees';type="number";}
//        if(column==5){sort="Available";type="number";}
//        if(column==3){sort="SeatRow";type="text";}
//        if(column==2){sort="SeatSection";type="text";}

//        if(!params.order){params.order=new Array();}
//        if(params.order[sort]=="ascending" || params.order[sort]=="" || params.order[sort]==null){params.order[sort]="descending";}else{params.order[sort]="ascending";}
//        params.sort=sort;
//        params.type=type;
//        set_filter_params(params);
//        
//        filter_xsl({msg:"Sorting " + params.sort + " (" + params.order[sort] + ") ..."});    
//    }

﻿/// FRAMEWORK CLASS ///
//© 2008 SeatQuest LLC.
/// <reference path="ajax.js"/>


function FRAMEWORK()
{
    ///<summary>Initializes all the classes neccessary for this framework.</summary>
    this.detect_browser();
};

FRAMEWORK.version = "6.0.0"
FRAMEWORK.prototype.args = {
    filter:null,
    zoomer:null,
    debug:null
};

FRAMEWORK.prototype.debug = null;
FRAMEWORK.prototype.filter = null; // {base,version,full}
FRAMEWORK.prototype.zoomer = null; // {base,version,full}
FRAMEWORK.prototype.path = null; // {base,version,full}


FRAMEWORK.prototype.load=function(args)
{
    if(args){this.args=args;}

    var debug=this.args.debug ? this.args.debug :null;   
    //ELI debug comes first since it needs to be passed to all the other classes.
    if(!debug){debug={key_hook:true};}
    this.debug = new DEBUG(debug);
    
    this.load_with_debug();
       
};

FRAMEWORK.prototype.load_with_debug = function(){

    var google_map=this.args.google_map ? this.args.google_map :null;
    var show_google_map=this.args.show_google_map ? this.args.show_google_map :null;
 
    if(google_map){
        google_map.debug = this.debug;
        this.google_map=new GOOGLE_MAP(google_map);
    }   
    
    if(show_google_map == 1){
        this.google_map.load();
    }else{
        this.load_interactive_map_with_debug();
    }
    
    this.load_filter_with_debug();
}



FRAMEWORK.prototype.load_interactive_map_with_debug = function(){

    var zoomer=this.args.zoomer ? this.args.zoomer :null;
    var price_ranges=this.args.price_ranges ? this.args.price_ranges :null;
    var section_logic=this.args.section_logic ? this.args.section_logic :null;
    //var seat_logic=this.args.seat_logic ? this.args.seat_logic :null;
    var section_tanslation=this.args.section_tanslation ? this.args.section_tanslation :null;
    
    if(zoomer){
        zoomer.debug=this.debug;
        if(section_logic) {
            zoomer.enable_section_highlights = true;
        }else{
            zoomer.enable_section_highlights = false;
        }
        this.zoomer=new ZOOMER(zoomer);
    }
    
    if(section_tanslation){
        section_tanslation.debug = this.debug;
        section_tanslation.zoomer = this.zoomer;
        this.section_tanslation=new SECTION_TRANSLATION(section_tanslation);
    }
    
//    if(seat_logic){
//        seat_logic.debug = this.debug;
//        this.seat_logic=new SEAT_LOGIC(seat_logic);
//    }
    
    if(section_logic){
        section_logic.debug = this.debug;
        section_logic.zoomer = this.zoomer;
        section_logic.section_translation = this.section_tanslation;
        this.section_logic=new SECTION_LOGIC(section_logic);
        //resolve cross dependency
        this.zoomer.set_section_logic(this.section_logic);
    }
    
    if(price_ranges){
        price_ranges.debug=this.debug;
        this.price_ranges=new PRICE_RANGES(price_ranges);
    }
}

FRAMEWORK.prototype.load_filter_with_debug = function(){
    var filter=this.args.filter ? this.args.filter :null;
    //ELI load the filter class.
    if(filter)
    {
        filter.debug=this.debug;
        filter.zoomer=this.zoomer;
        if(this.price_ranges) {
            filter.price_ranges = this.price_ranges;
        } else {
             filter.price_ranges = null;
        }
        //ERIC don't do anything tricky with these urls
        filter.xsl_base_url=this.args.filter.xsl_base_url;
        //BOGDAN set the url for convertion xsl
        if(filter.convert_from_tb)
        {
            filter.xsl_for_conversion_url=this.path.current.xsl + filter.convert_from_tb +'.xsl';
        } 
        this.filter=new FILTER(filter); 
    }
}

FRAMEWORK.prototype.included = {};
FRAMEWORK.prototype.include = function (url) 
{
    //ELI this function is disabled until we solve the SAFARI issue.
    if(!this.included[url])
    {
        this.included[url]=url;
        
        //ELI url of script to download.
        var src=this.path.current.scripts + url;

        if(this.browser=='firefox' )
        {
            var head = document.getElementsByTagName('head')[0];
            var script=document.createElement('script');
            script.src=src;
            script.type='text/javascript';
            script.defer=false;
            //ELI this will help us debug the code in firebug.
            // document.write() does not allow any browser to debug the code.
            head.appendChild(script);
            return;
        }        

        //ELI write a script to the document.
        var ajax=this.get_url(src);
        var script=ajax.responseText;

//        if(this.browser=='chrome' )
//        {
//            eval.call(window,script);
//            return;
//        }
        
        //ELI protects our code from being debuged or looked at by any debugger of browser.
        this.write_script(script);
    }
};

FRAMEWORK.prototype.get_url=function(url)
{
    var ajax=null;
    if (window.XMLHttpRequest){ajax=new XMLHttpRequest();}else{ajax=new ActiveXObject('MSXML2.XMLHTTP.3.0');}
    if(ajax)
    {
        ajax.open("GET", url,false);
        ajax.send(null);
    }
    return ajax;
};


FRAMEWORK.prototype.write_script=function(script)
{
    if (!script){    return;}
    script='<script type="text/javascript">' + script+ '</script>';
    document.write(script);
};

//ELI get the framework path
FRAMEWORK.prototype.get_script = function (name)
{
    var head = document.getElementsByTagName('head')[0];
    if(!head){return null;}
    var scripts=head.getElementsByTagName('script');
    if(!scripts){return null;}
    for(i=0;i<scripts.length;i++)
    {
        var uri=parse_url(scripts[i].src);
        var f=uri.filename;
        var file=f.substring(0,f.indexOf('.'))
        f=file=='' ? f: file;
        if(f.toLowerCase()!=name){continue;};    
        return scripts[i];
    }
    return null;
};

//ELI get the framework path
FRAMEWORK.prototype.get_path = function ()
{
    var script = this.get_script("framework");
    if(!script){return null;}
    var uri=parse_url(script.src);
    var c= uri.source.split('/');
    var pos=-1;
    for(i=c.length;i>=0;i--)
    {   
        if(c[i]=='framework'){pos=i; break;}
    }
    if (pos==-1){return;}
    pos++;
    var base =c.slice(0,pos).join('/')+ '/';
    var version=c[pos] ;
    var path={
        base: base ,
        version: version,
        current: {
            base: base + version + '/',
            scripts: base + version + '/scripts/',
            xsl:  base + version + '/xsl/'}
    }
    return path;
};

FRAMEWORK.prototype.observe=function (element, event_name, handler) 
{
      var name = event_name;
      
      //ELI watch for an element on load.
      if((name=='onload' || name=='load') && typeof element=='string'){this.element_onload(element,handler);return;}

      if (element.addEventListener) {
        element.addEventListener(name, handler, false);
      } else {
        element.attachEvent("on" + name, handler);
      }
      return element;
};

FRAMEWORK.prototype.elements=[];
FRAMEWORK.prototype.elements_htimer=null;
FRAMEWORK.prototype.element_onload=function (id,callback) 
{
    this.elements.push({id:id,callback:callback});
    var _this=this;
    if(!this.elements_htimer)
    {
        this.elements_htimer=setInterval(function(){_this.element_search();},100);
    }
};

FRAMEWORK.prototype.element_search=function()
{
    for(i=this.elements.length-1;i>=0;i--)
    {
        var search=this.elements[i];
        var e = document.getElementById(search.id);
        if(e) {this.elements.splice(i,1);setTimeout(search.callback,1);}
    }
    if(this.elements.length<1) {clearInterval(this.elements_htimer);}
};

FRAMEWORK.prototype.browser=null;
FRAMEWORK.prototype.detect_browser=function()
{
    var version_search_string='';
	var search_string= function (data) 
	{
		for (var i=0;i<data.length;i++)	
		{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			version_search_string = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	};

	var search_version= function (dataString) 
	{
		var index = dataString.indexOf(version_search_string);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+version_search_string.length+1));
	};
	
	var browsers= [
	    {
		    string: navigator.userAgent,
		    subString: "Chrome",
		    identity: "Chrome"
	    },

	    { 	string: navigator.userAgent,
		    subString: "OmniWeb",
		    versionSearch: "OmniWeb/",
		    identity: "OmniWeb"
	    },
	    {
		    string: navigator.vendor,
		    subString: "Apple",
		    identity: "Safari"
	    },
	    {
		    prop: window.opera,
		    identity: "Opera"
	    },
	    {
		    string: navigator.vendor,
		    subString: "iCab",
		    identity: "iCab"
	    },
	    {
		    string: navigator.vendor,
		    subString: "KDE",
		    identity: "Konqueror"
	    },
	    {
		    string: navigator.userAgent,
		    subString: "Firefox",
		    identity: "Firefox"
	    },
	    {
		    string: navigator.vendor,
		    subString: "Camino",
		    identity: "Camino"
	    },
	    {		// for newer Netscapes (6+)
		    string: navigator.userAgent,
		    subString: "Netscape",
		    identity: "Netscape"
	    },
	    {
		    string: navigator.userAgent,
		    subString: "MSIE",
		    identity: "Explorer",
		    versionSearch: "MSIE"
	    },
	    {
		    string: navigator.userAgent,
		    subString: "Gecko",
		    identity: "Mozilla",
		    versionSearch: "rv"
	    },
	    { 		// for older Netscapes (4-)
		    string: navigator.userAgent,
		    subString: "Mozilla",
		    identity: "Netscape",
		    versionSearch: "Mozilla"
	    }
	];

    var oses = [
	    {
		    string: navigator.platform,
		    subString: "Win",
		    identity: "Windows"
	    },
	    {
		    string: navigator.platform,
		    subString: "Mac",
		    identity: "Mac"
	    },
	    {
		    string: navigator.platform,
		    subString: "Linux",
		    identity: "Linux"
	    }
    ];

    this.browser={
        id: search_string(browsers).toLowerCase() || null,
        version: search_version(navigator.userAgent) || search_version(navigator.appVersion) || null,
        os: search_string(oses) || null,
        toString:function(){return this.id;}
    }

};



//ELI assigns any matching properties from object on the right to the left.
FRAMEWORK.prototype.object_assign=function(a,b)
{
    for(var i in a)
    {   
        if(b[i])
        {
            a[i]=b[i];
        }
    }
}

//ELI copy any object properties from right to left.
FRAMEWORK.prototype.object_overwrite=function(a,b)
{
    for(var i in b)
    {   
        a[i]=b[i];
    }
}

//ELI compares the contents of common values in both objects, if one common value is different we fail the comparison.
FRAMEWORK.prototype.object_comparison=function(a,b)
{   
    if(a==null && b==null ){return true;}
    if(a==null || b==null ){return false;}
    for(var i in a)
    {   
        if(a[i]!=b[i])
        {
           return false;
        }
    }
    for(var i in b)
    {   
        if(b[i]!=a[i])
        {
           return false;
        }
    }
    
    return true;
}

//ELI this line is the most important line!!! do not remove.
var framework = new FRAMEWORK();

///////////////////////////////////////////////////////
//  GLOBAL FUNCTIONALITY
///////////////////////////////////////////////////////

//ELI generate an XML parser for gecko or XMLDOM for IE.
function XMLDOMObject()
{
    if (framework.browser.id != "explorer")
    {
        //ELI apply string parsed xsl
        return new DOMParser();
    } else  {
        xml = new ActiveXObject("Microsoft.XMLDOM");
        xml.async = false;
        return xml;
    }       
};

//ELI parse a URL.
function parse_url(sourceUri)
{
    var uriPartNames = ["source","protocol","authority","domain","port","path","directory_path","filename","query","anchor"];
    var uriParts = new RegExp("^(?:([^:/?#.]+):)?(?://)?(([^:/?#]*)(?::(\\d*))?)?((/(?:[^?#](?![^?#/]*\\.[^?#/.]+(?:[\\?#]|$)))*/?)?([^?#/]*))?(?:\\?([^#]*))?(?:#(.*))?").exec(sourceUri);
    var uri = {};
    
    for(var i = 0; i < 10; i++){
        uri[uriPartNames[i]] = (uriParts[i] ? uriParts[i] : "");
    }
    
    // Always end directoryPath with a trailing backslash if a path was present in the source URI
    // Note that a trailing backslash is NOT automatically inserted within or appended to the "path" key
    if(uri.directory_path.length > 0){
        uri.directory_path = uri.directory_path.replace(/\/?$/, "/");
    }
    
    return uri;
};

//ELI high-speed string manipulation.
function StringBuilder() {this.buffer = [];} 
StringBuilder.prototype.append = function append(s) {this.buffer.push(s); return this; }; 
StringBuilder.prototype.toString = function toString() {return this.buffer.join("");}; 

//ELI get a query parameter from the URL
function query(ji) 
{
    hu = window.location.search.substring(1);
    gy = hu.split("&");
    for (i=0;i<gy.length;i++) {
        ft = gy[i].split("=");
        if (ft[0] == ji) {
            return ft[1];
        }
    }
}


function array_unique(array){
    var r = new Array();
	o:for(var i = 0, n = array.length; i < n; i++)
	{
		for(var x = 0, y = r.length; x < y; x++)
		{
			if(r[x]==array[i])
			{
				continue o;
			}
		}
		r[r.length] = array[i];
	}
	return r;
}

function array_search(array, elem){
	for(var i = 0; i < array.length; i++)
	{
        if(array[i] == elem) return i;
	}
	return -1;
}



function PRICE_RANGES(args)
{
    if(args){this.args=args;}
    this.set_default_args();
}

PRICE_RANGES.prototype.init_complete = false;
PRICE_RANGES.prototype.price_section_pairs = [];
PRICE_RANGES.prototype.range_to_sections_map = [];
PRICE_RANGES.prototype.sections_colors_map = new Object();

//ELI default parameters
PRICE_RANGES.prototype.args={
    id:null,
    colors:[0xffAC64DB, 0xff9C38DB, 0xff7002B6, 0xff612389, 0xff490176],
    grey_color:0xff868686
}

PRICE_RANGES.prototype.set_default_args=function()
{       
    if(!this.args.colors) {
        this.args.colors=[0xffAC64DB, 0xff9C38DB, 0xff7002B6, 0xff612389, 0xff490176]; 
    }
    if(!this.args.grey_color) {
        this.args.grey_color=0xff868686; 
    }
};


PRICE_RANGES.prototype.init_price_ranges=function(prices, sections, min, max)
{
    //set price ranges
    if(!this.init_complete)
    {
        var split_prices_results = prices.split(';');
        split_prices_results.pop(); //empty string
        var split_sections_results = sections.split(';');
        split_sections_results.pop(); //empty string
        //var price_section_pairs = [];
        for(var i = 0; i < split_prices_results.length; i++)
        {
            this.price_section_pairs.push(new KeyValuePair(split_prices_results[i], split_sections_results[i]));
            this.sections_colors_map[split_sections_results[i]] = this.args.grey_color;
        }
        this.apply_price_ranges(this.price_section_pairs, min, max, this.args.id);
        this.init_complete = true;
    }
}
    
    
PRICE_RANGES.prototype.compute_num_of_points=function(data_length)
{
    if(data_length > 30) {
        return 4;
    }
    else if(data_length > 15) {
        return 3;
    }    
    else if(data_length > 10) {
        return 2;
    }    
    else
        return 1;        
}
    
PRICE_RANGES.prototype.apply_price_ranges=function(price_section_pairs, min, max, id)
{
    var points = this.get_dividing_points(price_section_pairs, this.compute_num_of_points(price_section_pairs.length), min, max); 
    var html = "";
    //var html = createButtonHTML("Under $" + points[0]);
    for(var i = 0; i < points.length - 1; i++)
    {
        html += this.createRangeButtonHTML("$" + points[i] + " - $" + points[i+1], points[i], points[i+1], i, i + 1);
    }
    //html += createButtonHTML("Above $" + points[points.length - 1]);
    if(points.length == 2) html = ""; //special case only one price range
    html += this.createRangeButtonHTML("All", points[0], points[points.length - 1], 0, points.length - 1);
    $(id).innerHTML = html + $(id).innerHTML; 
}
    
PRICE_RANGES.prototype.createRangeButtonHTML=function(label, min, max, range_start, range_end)
{
    //return '<a class="button" href="javascript:void(0);" onclick="priceRangeButtonClick(' + min + ',' + max + ')"><span>' + label + '</span></a>';
    var color = null;
    if(range_end - range_start != 1) {
        color = "000000";
    } else {
        color = this.args.colors[range_start].toString(16).substr(2);
    }       
    return '<input class="button_pr" style="background-color:#' + color + '" type="submit" onclick="framework.price_ranges.priceRangeButtonClick(' + min + ',' + max + ',' + range_start + ',' + range_end + ')" value="' + label + '"/>';
}
    
    
    
    
PRICE_RANGES.prototype.priceRangeButtonClick=function(min,max,range_start,range_end)
{
    $('input_min').value = min;
    $('input_max').value = max;
    //framework.zoomer.reset_section_highlights();
    //TODO: disable apply_to_zoomer
    framework.filter.reset_selected_sections();
    if(range_end - range_start == 1) {
         framework.filter.apply({params:{color:this.args.colors[range_start]}});
    }
    else {
        framework.filter.apply();
    }    
}
    
function sortNumber(a,b)
{
    return a._strKey - b._strKey;
}

PRICE_RANGES.prototype.get_dividing_points=function(price_section_pairs, num_of_points, min, max)
{
    var result = [];
    price_section_pairs.sort(sortNumber);
    result.push(min);
    
    var index = 0;
    var old_index = 0;
    for(var i = 1; i < num_of_points; i++)
    {
        index = Math.round((price_section_pairs.length * i)/num_of_points);
        result.push(price_section_pairs[index]._strKey);
        this.add_range(price_section_pairs, this.range_to_sections_map, old_index, index);
        old_index = index;
    }
    result.push(max);
    this.add_range(price_section_pairs, this.range_to_sections_map, old_index, price_section_pairs.length); 
    return result;   
}

PRICE_RANGES.prototype.add_range=function(price_section_pairs, range_to_sections_map, old_index, index)
{
    var map = new Object();
    for(var i = old_index; i < index; i++)
    {
        map[price_section_pairs[i]._strValue] = price_section_pairs[i]._strValue;
    }
    this.range_to_sections_map[this.range_to_sections_map.length] = map;
}

PRICE_RANGES.prototype.get_section_color=function(sec_name)
{
    for(var i = 0; i < this.range_to_sections_map.length; i++)
    {
        if(this.range_to_sections_map[i][sec_name]) return this.args.colors[i];
    }
    return null;
}


//PRICE_RANGES.prototype.show_sections=function(sections, color)
//{
//    if(this.args.debug!=null) this.args.debug.time("show_sections");
//     framework.zoomer.reset_section_highlights();   
//     //remove duplicates
//     var split_sections_results = sections.split(';');
//     if(split_sections_results[split_sections_results.length - 1] == "") {
//        split_sections_results.pop(); //empty string
//     }   
//     split_sections_results = split_sections_results.unique();

//     var gray_sections = new Array();
//     var tmp_color = color;
//     for(var i = 0; i < this.range_to_sections_map.length; i++) {
//        var colored_sections = new Array();          
//        if(color == null) {
//            tmp_color = this.args.colors[i];
//        } else {
//            tmp_color = color;
//        }  
//                     
//        for (var j in this.range_to_sections_map[i]) {
//            if(split_sections_results.search(j) != -1) {
//               var j_corrected = j; 
//               if(j == "BL") j_corrected = "GA";
//               colored_sections.push(j_corrected);           
//            } else {
//               var j_corrected = j;  
//               if(j == "BL") 
//                    j_corrected = "GA";
//                    
//               if(gray_sections.search(j_corrected) == -1)     
//                    gray_sections.push(j_corrected); 
//            }
//        }
//        if(colored_sections.length > 0) framework.zoomer.highlight_sections(colored_sections.join("$,"), tmp_color);
//     }
//     framework.zoomer.highlight_sections(gray_sections.join("$,"), this.args.grey_color);
//     if(this.args.debug!=null) this.args.debug.time("show_sections",true);
//}


PRICE_RANGES.prototype.show_sections=function(sections, color)
{   
    if(this.args.debug!=null) this.args.debug.time("show_sections");
    //remove duplicates
    var split_sections_results = sections.split(';');
    if(split_sections_results[split_sections_results.length - 1] == "") {
    split_sections_results.pop(); //empty string
    } 
    
    var diff = new Object();  
    for(var section in this.sections_colors_map) {
        var tmp_color = color;
        //find color
        if(array_search(split_sections_results, section) != -1) {
            if(color == null) {
                tmp_color = this.get_section_color(section);
            } else {
                tmp_color = color;
            }  
        } else {
            tmp_color = this.args.grey_color;
        }
        
        if(this.sections_colors_map[section] != tmp_color) {
            this.sections_colors_map[section] = tmp_color;
            //handle GA and BL separatly
            if(section == "BL" || section == "GA") {
                if(tmp_color == this.args.grey_color)
                    framework.zoomer.reset_section_highlight("GA");
                else
                    framework.zoomer.highlight_section("GA", tmp_color); //zoomer know only about GA
            }

            if(diff[tmp_color])
                diff[tmp_color] += "$," + section;
            else
                diff[tmp_color] = section;    
        }
    }
    //apply new colors
    for(var tmp_color in diff) {
        framework.zoomer.highlight_sections(diff[tmp_color], tmp_color);
    }
    
    if(this.args.debug!=null) this.args.debug.time("show_sections", true);
}




//KeyValuePair function
function KeyValuePair()
{

  //Assigning the Key from the arguments
  this._strKey = (arguments.length == 2) ? arguments[0]: null;
  //Assigning the Key from the arguments
  this._strValue = (arguments.length == 2) ? arguments[1]: null;
 
  // if parameter is defined, the key is set.
  // if parameter is not defined, the key is retrieved.
  this.Key = function()
  {
    if (arguments.length == 1)
      this._strKey = arguments[0];
    else
      return this._strKey;
  }
  // if parameter is defined, the value is set.
  // if parameter is not defined, the value is retrieved.
  this.Value = function()
  {
    if (arguments.length == 1)
      this._strValue = arguments[0];
    else
      return this._strValue;
  }
  // Params: (KeyValuePair objkvp)
  // Return: boolean
  this.Equals = function(oKV)
  {
    try
    {
      if (oKV.GetType() == this.GetType())
      {
        if (this._strKey == oKV.Key() && this._strValue == oKV.Value())
        {
          return true;
        }
      }
    }
    catch (e)
    {
      throw "(Exception: kvp_e0) Invalid parameter type";
    }
    return false;
  }
  // Return: string
  this.GetType = function()
  {
    return "Library.KeyValuePair";
  }
  // Return: string (delimits the key and value if provided)
  this.ToString = function()
  {
    var strDelimiter = (arguments.length == 1) ? arguments[0]: "";
    return this._strKey + strDelimiter + this._strValue;
  }
}// Used to track if a visitor uses SQ
var track_sq_interaction = (function () {
  var sq_interaction = false;
  return function () {
    if (!sq_interaction) {
      pageTracker._trackPageview("/track/sq_interact");
      sq_interaction = true;
    }
  };
})();


document.observe("dom:loaded", function () {
  pageTracker._trackPageview('/track/event_with_forecast?forecast=' + event_info.forecast);
  
  $("ticket_list_loading").show();
  $("ticket_list_loading").clonePosition("ticket_list", {
    offsetLeft: 2
  }).setStyle({
    width: ($("ticket_list_loading").getWidth() - 4) + "px",
    height: ($("ticket_list_loading").getHeight() - 2) + "px"
  }).setOpacity(0.9);
});

document.observe("sq:loaded", function (e) {
  
  framework.filter.reset();
  
  // Register clicks on "select" buttons
  document.observe("click", function(e, btn) {
    if (btn = e.findElement(".ticket .select")) {
      e.stop();
      document.fire("sg:click", {ticket: e.findElement(".ticket"), src: "table"});
    }
  });

  // Setup callback for clicks in the zoomer
  window.buyNow = function (tID, exact, tb, amount) {
    // These razorgator IDs are a disaster, when they come back from flash
    // they're unescaped, so now we're looking for non-alphanumeric chars
    var safeID = tID.replace(/[^0-9a-z]/ig, "");
    document.fire("sg:click", {ticket: $("id_" + safeID), src: "flash"});
  }
  
  // track google analytics sq_loaded
  pageTracker._trackPageview("/track/sq_loaded");
});

document.observe("sq:loaded", function (e) {
  var median_price = Math.floor($("id_seatquest_table").getAttribute("median_price")),
      median_pr = Math.floor($("id_seatquest_table").getAttribute("median_price_ratio"));
  
  $("median_price").update(median_price > 0 ? "$" + median_price : "--");
  
  if (median_pr) {
    $("avgPr").show();
    $("median_price_ratio").update(median_pr + "%");
  }
});


var sq = (function () {
    
  // Handle showing bubble on zoomer/highlighting ticket
  var highlighted;
  var highlight = function (ticket) {
    if (highlighted) {
      highlighted.removeClassName("hover");
    }
    ticket.addClassName("hover");
    highlighted = ticket;
    
    // someone hovered over or clicked on a ticket listing
    track_sq_interaction();
  };
  Event.observe(window, "click", function (e) {
    if (!Event.findElement(e, "#flashcontent") && !Event.findElement(e, ".ticket")) {
      if (highlighted) {
        highlighted.removeClassName("hover");
      }
      framework.zoomer.reset_highlights();
    }
  });
  
  // Used to improvise a sq:loaded event
  var sq_loaded = false;
  
  var slider_loaded = false,
      slider = null;
  var setup_slider = function (max) {
    slider = new Control.Slider([$('min_handle'), $('max_handle')], 'price_slider', {
      range:$R(0, max),
      values:$R(0, max),
      sliderValue: [0, max],
      alignX: -4,
      restricted:true,
      onChange: function (vals) {
        $("sq_min_price").value = vals[0];
        $("sq_max_price").value = vals[1] >= 2000 ? "2000+" : vals[1];
        filter_tickets();
      },
      onSlide: function (vals) {
        $("sq_min_price").value = vals[0];
        $("sq_max_price").value = vals[1] >= 2000 ? "2000+" : vals[1];
      }
    });
    $("sq_min_price").stopObserving("change");
    $("sq_min_price").observe("change", function () {
      slider.setValue($("sq_min_price").value, 0);
    });
    $("sq_max_price").stopObserving("change");
    $("sq_max_price").observe("change", function () {
      slider.setValue($("sq_max_price").value, 1);
    });
  };
  
  // remember the default sort since html select doesn't support defaultValue
  var sq_sort_default;
  document.observe("dom:loaded", function (e) {
    sq_sort_default = $("sq_sort").value;
  });
  
  return {
    seat_selected: function (id) {
      // replacing hex escape codes in razorgator ids
      var safeID = id.replace(/%[0-9a-f]{2}/ig, ""),
          ticket = $("id_"+safeID);
      
      highlight(ticket);
      $("ticket_list").scrollTop = ticket.up("table").offsetTop;
    },
    pre_filter: function () {
      $("ticket_list_loading").show();
    },
    post_filter: function (stats) {
      // The framework will call this function immediately after the xml has
      // been processed so we can use it to improvise a sq:loaded event
      
      if (!sq_loaded) {
        sq_loaded = true;
        document.fire("sq:loaded");
      }
      
      $$(".ticket").each(function (ticket) {
        Event.observe(ticket, "mouseover", function (e) {
          highlight(this);
          framework.zoomer.highlight_ticket(this.getAttribute("rel"));
        });
      });
      
      if ($("id_seatquest_table").readAttribute("ticket_count") <= 0) {
        $("id_seatquest_table").innerHTML = "<div class='no-tickets-message'>We're sorry, there are currently no tickets available for this event</div>";
      } else if ($$(".ticket").length <= 0) {
        $("id_seatquest_table").innerHTML = "<div class='no-tickets-message'>We're sorry, there are currently no tickets available for your filter settings</div>";
      }
      
      $("ticket_list_loading").hide();
    },
    set_values: function (params) {
      ///<sumary>fires when you call framework.filter.reset().</sumarry>
      
      var actual_max = params.max;
      try {
        actual_max = Math.floor($("id_seatquest_table").getAttribute("max_price"));
      } catch (e) {}
      
      function set_if_exists(input, quantity) {
        if (quantity !== null && input) {
          $(input).value = quantity;
        }
      }
      
      //ELI zero everything out.
      set_if_exists($('sq_min_price'), 0);
      set_if_exists($('sq_max_price'), actual_max > 2000 ? "2000+" : actual_max);
      set_if_exists($('sq_sort'), sq_sort_default);
      set_if_exists($('sq_available'), params.quantity);
      
      // Setup the slider
      if (!slider_loaded) {
        slider_loaded = true;
        setup_slider(Math.min(actual_max, 2000));
      } else {
        slider.setValue(0, 0);
        slider.setValue(Math.min(actual_max, 2000), 1);
      }
    },
    get_values: function () {
      ///<sumary>this function will be called by the filter class to collect
      ///the values for the filter operation. fitres everytime framework.filter.apply() is executed.</sumarry>
      ///<return name="params">you must return a params object with all the values listed below.</return>      
      var params = {
        min:            $("sq_min_price").value || 0,   //ELI minimum price, range (0-999999)            
        max:            parseInt($("sq_max_price").value) >= 2000 ? 999999 : $("sq_max_price").value,  //ELI maximum price, range (0-999999)
        quantity:       $("sq_available").value || "",   //ELI quantity of ticket sets to show, range (''-all,1-999999) 
        ticket_type:    "",   //ELI ticket board to show, range (''-all,1-TicketsNow,2-TicketNetwork,3-
        fees:           false,   //ELI show seller fees, range(true,false)
        
        // sort options must be provided directly to framework.filter.apply()
        sort:           "price"  //ELI column to sort, range ('price','available','row','section')
      };
      return params;
    }
  }
})();

function filter_tickets () {
  var pair  = $("sq_sort").value.split(":"),
      sort  = pair[0],
      order = pair[1];
  
  framework.filter.apply({
    params: {
      sort: sort,
      order: order
    }
  });
  
  $("ticket_list").scrollTop = 0; // scroll to the top
  
  // someone interacted with the filter
  track_sq_interaction();
}

$(document).observe("dom:loaded", function () {
    $w("sq_min_price sq_max_price sq_available sq_sort").each(function (id) {
      $(id).observe("change", filter_tickets);
    });
    
    // the object seatquest_data must be written into the page by php
    framework.load({
      filter: {
        id: 'ticket_list',                 //ELI id of the DIV that will contain the ticket list.
        xml_url: seatquest_data.tickets_xml,  //ELI link to the ticket XML
        xsl_base_url: "/js/seatquest/xsl/listings-table.xsl?v=1", // Link to the framework's XSL, I added this
        xsl_url: "/js/seatquest/xsl/single-listing.xsl?v=1",    //ELI link to the table template XSL.
        get_values:sq.get_values,                //ELI callback to your get_values function.
        set_values:sq.set_values,                //ELI callback to your set_values function.
        pre_filter:sq.pre_filter,                //ELI callback to your pre_filter function.
        post_filter:sq.post_filter,              //ELI callback to your post_filter function.
        sort_options:{
          'default':    seatquest_data.has_fv ? 
                          {id:'priceratioasc',field:'SGPRUp',order:'ascending',type:'number'} :
                          {id:'price',field:'SGPriceWithFees',order:'ascending',type:'number'},
          'price':      {field:'SGPriceWithFees',order:'ascending',type:'number'},
          'available':  {field:'Available',order:'ascending',type:'number'},
          'section':    {field:'SeatSection',order:'ascending',type:'text'},
          'row':        {field:'SeatRow',order:'ascending',type:'text'},
          'priceratioasc': {field:'SGPRUp',order:'ascending',type:'number'},
          'priceratiodesc': {field:'SGPRDown',order:'descending',type:'number'}
        }
      },
      zoomer: {
        id:'flashcontent',                    //ELI id of the DIV that will contain the zoomer object.
        seat_selected:sq.seat_selected,          //ELI callback to your seat_selected function.
        help:0,                               //ELI add/remove the help message when the zoomer loads.
        zoom_ratio:1.5,                       //ELI control the zoom ratio of the zoom_in(), zoom_out() operations.
        swf_url: "/js/seatquest/zoomer-dot-coloring.swf", // zoomer version that shows map unavailable on a generate_l_venue 500
        map_xml: seatquest_data.map_xml, //ELI URL to the zoomer configuration XML.
        theme: "",    //ELI specify color for dialogs in the zoomer
        stmap: seatquest_data.static_map //ELI URL to static map to show in the zoomer instead of SeatQuest's venue map.
      }
    });
});

function SECTION_LOGIC(args){
    this.args = args;
    this.section_translation = args.section_translation;
    this.zoomer = args.zoomer;
    this.init();
}

SECTION_LOGIC.prototype.args = null;
SECTION_LOGIC.prototype.section_translation = null;
SECTION_LOGIC.prototype.zoomer = null;
SECTION_LOGIC.prototype.sections_onhold = [];
SECTION_LOGIC.prototype.ready = false;
SECTION_LOGIC.prototype.translated_actual_sections = [];

SECTION_LOGIC.prototype.highlight_color = 0xff490176;
SECTION_LOGIC.prototype.color_gray = 0xff868686;

SECTION_LOGIC.prototype.first_click_on_zoomer = true;

//SECTION_LOGIC.prototype.reset_selected_sections = function()
//{
//    this.args.debug.time("reset_selected_sections");
//    if(this.ga_selected){
//        this.recover_from_last_ga_selected();
//    }else{
//        var translated_sections_onhold = {};
//        for(var i = 0; i < this.sections_onhold.length; i++){
//            var translations = this.section_translation.trans_from_list_to_zoomer(this.sections_onhold[i]);
//            for(var j = 0; j < translations.length; j++)    
//                translated_sections_onhold[translations[j]] = true;
//        } 
//        
//        var translated_sections_onhold_array = [];
//        for(var section in translated_sections_onhold){
//            translated_sections_onhold_array.push(section);
//        }
//        
//        //hide highlighted sections

//        //ELI bogdan logic means that all sections are highlighted light gray and ections with tickets are highlighted dark gray.
//        if(this.args.bogdan_logic){
//            framework.zoomer.highlight_sections(translated_sections_onhold_array, this.color_gray);
//        }else{
//            framework.zoomer.highlight_other_sections(translated_sections_onhold_array, this.color_gray);
//        }
//                
//        this.sections_onhold = [];
//    }
//    this.args.debug.time("reset_selected_sections",true);
//}

SECTION_LOGIC.prototype.reset_highlights = function(){
    this.args.debug.time("SECTION_LOGIC.reset_highlights");
    try{
    //if(this.ready){
        this.sections_onhold = [];
        if(this.args.bogdan_logic){
            framework.zoomer.highlight_sections(this.translated_actual_sections, this.color_gray);
        }else{
            framework.zoomer.highlight_other_sections(this.translated_actual_sections, this.color_gray);
        }        
    //}
    }catch(err){}
    this.args.debug.time("SECTION_LOGIC.reset_highlights", true);
}

SECTION_LOGIC.prototype.init = function(){
    if(this.zoomer && this.zoomer.ready){
        //framework.zoomer.highlight_sections(section_name, this.color_gray);
        this.translated_actual_sections = [];
        var translated_actual_sections_map = {};
        for(var i = 0; i < this.zoomer.actual_sections.length; i++){
            var translations = this.section_translation.trans_from_list_to_zoomer(this.zoomer.actual_sections[i]);
            for(var j = 0; j < translations.length; j++){
                translated_actual_sections_map[translations[j]] = true;
            }
        }     
        for(var section in translated_actual_sections_map){
            this.translated_actual_sections.push(section);
        } 
        this.ready = true;
        this.reset_highlights();
    }else{
        var _this = this;
        setTimeout(function() {_this.init()}, 500);
    }
}



SECTION_LOGIC.prototype.queue_selected_sections = function(sections)
{
    for(var j = 0; j < sections.length; j++){
        var ra = this.sections_onhold;    
        var not_found = true;
        //ELI first remove the ids from the queue
        for(var i=0;i<ra.length;i++)
        {
            if(ra[i]==sections[j]){
                ra.splice(i,1); 
                not_found = false;
            }
        }
        //ELI if the id DNE in the queue then add it.
        if(not_found) this.sections_onhold.push(sections[j]);
    }
    return not_found;
}


SECTION_LOGIC.prototype.list_section_selected = function (section)
{   
    this.args.debug.time("list_section_selected");
    try{
    //if(this.ready){
        this.first_click_on_zoomer = true;
        //ELI bogdan logic
        //this.reset_selected_sections();
        this.queue_selected_sections([section]);
        var translations = this.section_translation.trans_from_list_to_zoomer(section);
        if(this.contains_ga(translations)){
            this.ga_selected = true; 
            framework.zoomer.highlight_section("GA", this.highlight_color);
            //this.reset_highlights(); 
        }else{
            framework.zoomer.highlight_sections(translations, this.highlight_color);
        }
    //}
    }catch(err){}
    this.args.debug.time("list_section_selected", true);
}

SECTION_LOGIC.prototype.contains_ga = function(array){
    for(var i = 0; i < array.length; i++){
        if(array[i] == "GA") return true;
    }
    return false;
} 

 SECTION_LOGIC.prototype.in_translated_actual_sections = function(section_name){
    for(var i = 0; i < this.translated_actual_sections.length; i++){
        if(this.translated_actual_sections[i] == section_name) return true;
    }
    return false;
 }
 
 SECTION_LOGIC.prototype.zoomer_section_selected = function(section_name) {
        this.args.debug.time("zoomer_section_selected");
        try{
        //if(this.ready){
            //if section doesn't have tickets, do nothing
            if(!this.in_translated_actual_sections(section_name)){
                return;
            }
//            //ELI bogdan logic     
//            if(this.first_click_on_zoomer){
//                this.reset_selected_sections();
//                this.first_click_on_zoomer = false;
//            }
            if(section_name == "GA") {
                this.zoomer_section_selected_ga();
            } else {
                this.zoomer_section_selected_non_ga(section_name);
            } 
        //}
        }catch(err){} 
        this.args.debug.time("zoomer_section_selected", true);
 }
 
SECTION_LOGIC.prototype.zoomer_section_selected_ga = function(){
//    //ELI bogdan logic     
//    this.reset_selected_sections(); 
    //this.queue_selected_sections(this.section_translation.trans_from_zoomer_to_list("GA"));
    //this.queue_selected_sections(this.section_translation.trans_from_zoomer_to_list("BL"));
    //framework.filter.apply({params:{ga:1}});
    this.args.selected_sections_change(this.sections_onhold, true);
    this.ga_selected = true; 
}

SECTION_LOGIC.prototype.recover_from_last_ga_selected = function(){
    this.args.debug.time("recover_from_last_ga_selected");
    //framework.zoomer.reset_highlights();
    //this.reset_highlights();
    this.sections_onhold = [];
    this.zoomer.toggle_ga(false);
    this.ga_selected = false;
    this.args.debug.time("recover_from_last_ga_selected", true);
}

SECTION_LOGIC.prototype.zoomer_section_selected_non_ga = function(section_name){
    if(this.ga_selected){
        this.recover_from_last_ga_selected();
    }
    if(this.queue_selected_sections(this.section_translation.trans_from_zoomer_to_list(section_name))) {
        framework.zoomer.highlight_sections([section_name], this.highlight_color);
    }else{
        
        if(this.args.bogdan_logic){
            framework.zoomer.highlight_sections([section_name], this.color_gray);
        }else{
            framework.zoomer.reset_section_highlight(section_name);
        }
        
    }
    this.args.selected_sections_change(this.sections_onhold, false);
}
 function SECTION_TRANSLATION(args){
    this.args = args;
    this.zoomer = args.zoomer;
    this.init_section_translation();
}

SECTION_TRANSLATION.prototype.args = null;
SECTION_TRANSLATION.prototype.zoomer = null;
SECTION_TRANSLATION.prototype.ready = false;

SECTION_TRANSLATION.prototype.translations = null;

SECTION_TRANSLATION.prototype.init_section_translation = function(){
    //create one-to-one match
    if(this.zoomer && this.zoomer.ready) {
        var all_translations = this.zoomer.get_section_translations();
        this.add_ga_tanslations(all_translations, this.zoomer.actual_sections, "GA");
        this.translations = all_translations;
        this.ready = true;
    } else {
        var _this = this;
        setTimeout(function() {_this.init_section_translation()}, 500);
    }
}

//SECTION_TRANSLATION.prototype.find_ga(section_list){
//    var ga_sections_list = [];
//    for(var i = 0; i < section_list.length; i++){
//        if(this.isGA(section_list[i]) || this.isLawn(section_list[i])){
//            ga_sections_list.push(section_list[i]);
//        }  
//    }
//    return ga_sections_list;
//}

SECTION_TRANSLATION.prototype.add_ga_tanslations = function(translations, section_list, ga_name){
    for(var i = 0; i < section_list.length; i++){
        if(this.isGA(section_list[i]) || this.isLawn(section_list[i])){
            translations[0].push(section_list[i]);
            translations[1].push(ga_name);
        }  
    }
}


SECTION_TRANSLATION.prototype.GA_DEF = ["GA", "G.A", "G.A.", "Gen Adm", "G/A", "GENERAL ADM", "GEN ADM", "GENADMN", "SRO", "General Admission"];
SECTION_TRANSLATION.prototype.GA_EXCLUDE_DEF = [ "GARDEN", "GARDEN BOX", "GATORS", "UGA" ];


SECTION_TRANSLATION.prototype.isGA = function(name){
    return array_indexOf(this.GA_DEF, name) != -1 && array_indexOf(this.GA_EXCLUDE_DEF, name) == -1
}

function array_indexOf(lst, name){
    for(var i = 0; i < lst.length; i++){
        if(name.toLowerCase().indexOf(lst[i].toLowerCase()) != -1) return i;
    }
    return -1;
}

SECTION_TRANSLATION.prototype.LAWN_DEF = ["LAWN", "GRASS"];
SECTION_TRANSLATION.prototype.isLawn = function(name){
    return array_indexOf(this.LAWN_DEF, name) != -1 
}

SECTION_TRANSLATION.prototype.trans_from_list_to_zoomer = function(name){
    var result = new Array();
    for(var i = 0; i < this.translations[0].length; i++){
        if(this.translations[0][i] == name) {
            result.push(this.translations[1][i]);
        }
    }
    if(result.length == 0) result.push(name);
    return result;
}

SECTION_TRANSLATION.prototype.trans_from_zoomer_to_list = function(name){
    var result = new Array();
    for(var i = 0; i < this.translations[0].length; i++){
        if(this.translations[1][i] == name) {
            result.push(this.translations[0][i]);
        }
    }
    if(result.length == 0) result.push(name);    
    return result;
}
/**
 * SWFObject v1.4.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
 *
 * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * **SWFObject is the SWF embed script formerly known as FlashObject. The name was changed for
 *   legal reasons.
 */
if(typeof deconcept == "undefined") var deconcept = new Object();
if(typeof deconcept.util == "undefined") deconcept.util = new Object();
if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
	if (!document.getElementById) { return; }
	this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
	this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
	this.params = new Object();
	this.variables = new Object();
	this.attributes = new Array();
	if(swf) { this.setAttribute('swf', swf); }
	if(id) { this.setAttribute('id', id); }
	if(w) { this.setAttribute('width', w); }
	if(h) { this.setAttribute('height', h); }
	if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
	this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion();
	if(c) { this.addParam('bgcolor', c); }
	var q = quality ? quality : 'high';
	this.addParam('quality', q);
	this.setAttribute('useExpressInstall', useExpressInstall);
	this.setAttribute('doExpressInstall', false);
	var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
	this.setAttribute('xiRedirectUrl', xir);
	this.setAttribute('redirectUrl', '');
	if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
}
deconcept.SWFObject.prototype = {
	setAttribute: function(name, value){
		this.attributes[name] = value;
	},
	getAttribute: function(name){
		return this.attributes[name];
	},
	addParam: function(name, value){
		this.params[name] = value;
	},
	getParams: function(){
		return this.params;
	},
	addVariable: function(name, value){
		this.variables[name] = value;
	},
	getVariable: function(name){
		return this.variables[name];
	},
	getVariables: function(){
		return this.variables;
	},
	getVariablePairs: function(){
		var variablePairs = new Array();
		var key;
		var variables = this.getVariables();
		for(key in variables){
			variablePairs.push(key +"="+ variables[key]);
		}
		return variablePairs;
	},
	getSWFHTML: function() {
		var swfNode = "";
		if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
			if (this.getAttribute("doExpressInstall")) { this.addVariable("MMplayerType", "PlugIn"); }
			swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
			swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
			var params = this.getParams();
			 for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
			var pairs = this.getVariablePairs().join("&");
			 if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
			swfNode += '/>';
		} else { // PC IE
			if (this.getAttribute("doExpressInstall")) { this.addVariable("MMplayerType", "ActiveX"); }
			swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
			swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
			var params = this.getParams();
			for(var key in params) {
			 swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
			}
			var pairs = this.getVariablePairs().join("&");
			if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
			swfNode += "</object>";
		}
		return swfNode;
	},
	write: function(elementId){
		if(this.getAttribute('useExpressInstall')) {
			// check to see if we need to do an express install
			var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
			if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
				this.setAttribute('doExpressInstall', true);
				this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
				document.title = document.title.slice(0, 47) + " - Flash Player Installation";
				this.addVariable("MMdoctitle", document.title);
			}
		}
		if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
			var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
			n.innerHTML = this.getSWFHTML();
			return true;
		}else{
			if(this.getAttribute('redirectUrl') != "") {
				document.location.replace(this.getAttribute('redirectUrl'));
			}
		}
		return false;
	}
}

/* ---- detection functions ---- */
deconcept.SWFObjectUtil.getPlayerVersion = function(){
	var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
	if(navigator.plugins && navigator.mimeTypes.length){
		var x = navigator.plugins["Shockwave Flash"];
		if(x && x.description) {
			PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
		}
	}else{
		// do minor version lookup in IE, but avoid fp6 crashing issues
		// see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
		try{
			var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
		}catch(e){
			try {
				var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
				PlayerVersion = new deconcept.PlayerVersion([6,0,21]);
				axo.AllowScriptAccess = "always"; // throws if player version < 6.0.47 (thanks to Michael Williams @ Adobe for this code)
			} catch(e) {
				if (PlayerVersion.major == 6) {
					return PlayerVersion;
				}
			}
			try {
				axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
			} catch(e) {}
		}
		if (axo != null) {
			PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
		}
	}
	return PlayerVersion;
}
deconcept.PlayerVersion = function(arrVersion){
	this.major = arrVersion[0] != null ? parseInt(arrVersion[0]) : 0;
	this.minor = arrVersion[1] != null ? parseInt(arrVersion[1]) : 0;
	this.rev = arrVersion[2] != null ? parseInt(arrVersion[2]) : 0;
}
deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
	if(this.major < fv.major) return false;
	if(this.major > fv.major) return true;
	if(this.minor < fv.minor) return false;
	if(this.minor > fv.minor) return true;
	if(this.rev < fv.rev) return false;
	return true;
}
/* ---- get value of query string param ---- */
deconcept.util = {
	getRequestParameter: function(param) {
		var q = document.location.search || document.location.hash;
		if(q) {
			var pairs = q.substring(1).split("&");
			for (var i=0; i < pairs.length; i++) {
				if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
					return pairs[i].substring((pairs[i].indexOf("=")+1));
				}
			}
		}
		return "";
	}
}
/* fix for video streaming bug */
deconcept.SWFObjectUtil.cleanupSWFs = function() {
	if (window.opera || !document.all) return;
	var objects = document.getElementsByTagName("OBJECT");
	for (var i=0; i < objects.length; i++) {
		objects[i].style.display = 'none';
		for (var x in objects[i]) {
			if (typeof objects[i][x] == 'function') {
				objects[i][x] = function(){};
			}
		}
	}
}
// fixes bug in fp9 see http://blog.deconcept.com/2006/07/28/swfobject-143-released/
deconcept.SWFObjectUtil.prepUnload = function() {
	__flash_unloadHandler = function(){};
	__flash_savedUnloadHandler = function(){};
	if (typeof window.onunload == 'function') {
		var oldUnload = window.onunload;
		window.onunload = function() {
			deconcept.SWFObjectUtil.cleanupSWFs();
			oldUnload();
		}
	} else {
		window.onunload = deconcept.SWFObjectUtil.cleanupSWFs;
	}
}
if (typeof window.onbeforeunload == 'function') {
	var oldBeforeUnload = window.onbeforeunload;
	window.onbeforeunload = function() {
		deconcept.SWFObjectUtil.prepUnload();
		oldBeforeUnload();
	}
} else {
	window.onbeforeunload = deconcept.SWFObjectUtil.prepUnload;
}
/* add Array.push if needed (ie5) */
if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}

/* add some aliases for ease of use/backwards compatibility */
var getQueryParamValue = deconcept.util.getRequestParameter;
var FlashObject = deconcept.SWFObject; // for legacy support
var SWFObject = deconcept.SWFObject;﻿/// XSL CLASS ///
//© 2008 SeatQuest LLC.

//ELI this class was generated by ELI VAKNIN.
//http://www.htmlgoodies.com/primers/jsp/article.php/3600451
//http://bitstructures.com/2007/11/javascript-method-callbacks

//ELI good closure article.
//http://www.claassen.net/geek/blog/2006/07/delegates-in-javascript.html

//ELI XSLT CLASS
function XSLT(args)
{
    /// <sumary>Represents an XSLT parser</sumary>
    //ELI PRIVATE DECLERATIONS
    //-------------------------
    function get_type()
    {
        if (window.ActiveXObject)
        {
            return "IE";
        } else if (document.implementation && document.implementation.createDocument){
            return "GECKO";
        }
        return null;    
    }
    this.type=get_type();
     
    if(!args){return;}
    this.debug=args.debug;
//    if(args.xml_url && args.xsl_url && (args.id || args.pre_render || args.post_render || args.xml_ready || args.xsl_ready) ){this.download(args);}
}

XSLT.prototype.type=null;
XSLT.prototype.debug=null;
XSLT.prototype.args={debug:null}

//ELI process the XSL
//PARAMS: 
//xml - Ajax.responseXML;
//xsl - string;
//string_params - string parameters to replace in XSL.
// RETURNS: a DOM object of the result XML+XSL document.
XSLT.prototype.merge = function(xml, xsl, string_params)
{
    this.debug.time("Merge");
    var dom = null;
    try {
        //ELI error proofing themerge operation.        
        if (!xml && !xsl) { throw 'XML or XSL not present!'; }

        //ELI parse parameters
        var xsl_s = this.parse_string_params(string_params, xsl);

        var xsl_doc = null;
        if (this.type == "GECKO") {
        
            var xslt = new XSLTProcessor();

            //ELI apply string parsed xsl
            xsl_doc = XMLDOMObject().parseFromString(xsl_s, "text/xml");
            
            //ELI import the style sheet.
            xslt.importStylesheet(xsl_doc);

            //ELI generate result
            dom = xslt.transformToFragment(xml.responseXML, document );
            
        } else if (this.type == "IE") {

            //ELI create the XSL object.
            xsl_doc = XMLDOMObject();
            xsl_doc.loadXML(xsl_s);

            //ELI IE has a weird condition in which it doesnt generate an XMLDOM if the XSL
            // document does not contain surrounding DIV or HTML element.
            // this code checks for it.
            var html = xml.responseXML.transformNode(xsl_doc);
            dom = XMLDOMObject();
            dom.loadXML(html);
            if (html && !dom.xml) { throw { message: "DOM creation failed!" }; }
            //            dom=new ActiveXObject("Msxml2.DOMDocument.3.0");
            //            var ret=xml.responseXML.transformNodeToObject(xsl_doc,dom);
        }
    } catch (err) {
        this.debug.error("XSL->merge", err);
        dom = null;
    }
    this.debug.time("Merge", true);
    return dom;
};

//ELI PARSING FUNCTIONS
//---------------------
//ELI XSL is a string
XSLT.prototype.parse_string_params=function (string_params,xsl)
{
    ///<summary>Parse the string_params in orer to create a dynamic XSL.</summary>
    if(!string_params) return xsl;
    var xsl_s=xsl;
    
    var sp=string_params;
    if(typeof sp=='function'){sp=sp();}
    
    for(s in sp){
        var re = new RegExp(s, 'gi');
        if(sp[s]!=null)
        {
            var s=sp[s];
            if(typeof s=='function'){s=s();}
            xsl_s=xsl_s.replace(re,s);
        }
    }
    return xsl_s;
}
﻿/// XSL_LOADER CLASS ///
function XSL_LOADER(args)
{
    var _this=this;
    this.args={};
    if(args){this.args=args;}

    if(!this.args.debug){this.debug=new DEBUG();}else{this.debug=this.args.debug;}

    this.xslt=new XSLT({debug:this.debug});

    //ELI create queue
    this.queue={};
    this.flags={};
        
    //ELI start looking for the ticket list DIV element.
    if(this.args.id)
    {
        this.flags.load=true;
        framework.observe(this.args.id,'onload',function(){_this.load();});
    }
   
    //ELI if we have XML and XSL urls we can start he download.
    if( this.args.xsl_url)
    {
        this.download();
        this.apply();
    }  
  
}

////ELI default parameters
//XSL_LOADER.prototype.args={
//    id:null,
//    xml_url:null,
//    xsl_url:null,
//    xml_ready:null,
//    string_params:null,
//    pre_render:null,
//    post_render:null,
//    debug:null
//}

XSL_LOADER.prototype.debug=null;
//XSL_LOADER.prototype.xslt=null;
XSL_LOADER.prototype.xml=null;
XSL_LOADER.prototype.xsl=null;

XSL_LOADER.prototype.flags={
    load:null,          //ELI FLAG which indicates that we are waiting for the ticket list DIV to load.
    download:null      //ELI FLAG which indicates that we started a download.
};

XSL_LOADER.queue={
    apply:null      //ELI apply() request was made but XSL & XML havent arrived yet.
};

XSL_LOADER.prototype.load=function()
{
    var _this=this;
    
    this.flags.load=null;
    if(this.queue.apply){this.queue.apply();}
};

//ELI in charge of firing the appropriate callbacks + mergin and rendering the XHTML to the document.
XSL_LOADER.prototype.inner_callback=function(ajax,url)
{

    var _this=this;
    if(url==this.args.xml_url && this.xml==null){this.xml=ajax; this.debug.time("Download XML",true); if(this.args.xml_ringdown){setTimeout(function(){_this.xml_ringdown(ajax,url);},1);}; }  
    if(url==this.args.xsl_url && this.xsl==null){this.xsl=ajax; this.debug.time("Download XSL",true); }

    //ELI return the parsed result with the ajax objects.
    if(this.xml && this.xsl )
    {
        //ELI make sure that we have valid xml, xsl before we proceed.
        if(this.xml.status!=200 || this.xsl.status!=200 ) { if(this.args.post_render){setTimeout(function(){_this.args.post_render(_this);},1);} return;}

        //ELI execute this.apply if it is in the queue.
        this.flags.download=null;
        var cb= function(){try{_this.queue.apply();}catch(ee){};} 
        if(this.queue.apply){setTimeout(cb,1);}
    }
};

XSL_LOADER.prototype.xml_ringdown= function (ajax,url)
{
    //ELI expecting an array
    if(this.args.xml_ringdown && this.args.xml_ringdown.length>0)
    {
        for(var i=0;i<this.args.xml_ringdown.length;i++)
        {
            var loader=this.args.xml_ringdown[i];
            loader.args.xml_url=url;
            loader.inner_callback(ajax,url);        
        }
     }
};

//ELI initiate the xml,xsl download.
XSL_LOADER.prototype.download= function ()
{
    //this.args=args;
    this.dom=null;
    this.xml=null;
    this.xsl=null;
    //this.queue.apply=null;
    this.flags.download=true;
    //this.flags.xml_ready=true;
    
    //ELI without this closure we would not be able to pass "this"
    // as a parameter in the this.args.callback
    this.debug.time("Download XML");
    this.debug.time("Download XSL");
    
    var _this=this;
    var cb=function(ajax,url){_this.inner_callback(ajax,url);}
    if(this.args.xml_url) new AJAX(this.args.xml_url,cb);
    if(this.args.xsl_url) new AJAX(this.args.xsl_url,cb);
};

XSL_LOADER.prototype.apply = function ()
{   
        
    //ELI set of checks before we can apply the filter:
    //1. did the XML & XSL download finish?
    //2. is the target DIV element ready yet? 
    var _this=this;

    //ELI remove this function from the queue.
    this.queue.apply=null;    

    //ELI if download is still going on then queue this call.
    //ELI if ticket list DIV is not ready then queue this call.
    if(this.flags.download || this.flags.load)
    {
        this.queue.apply=function(){_this.apply();};
        return;
    }

    //ELI no we are ready.
    this.ready_to_apply();
 
};

XSL_LOADER.prototype.ready_to_apply=function()
{
            
    ///<summary>filter and sort to the current client page.</summary>
    ///<parm name="args.params">parameters to override.</param>
    var _this=this;

    //ELI remove this function from the queue.
    this.queue.apply=null;    

    //ELI merge xml and xsl.
    var dom=this.xslt.merge(this.xml,this.xsl.responseText,this.args.string_params);
    
    //ELI render the HTML
    if(dom)
    {
        //ELI apply to div
        this.apply_to(this.args.id,dom);
    }
    
    //ELI fire when complete

    var xsl_stats = this.extract_xsl_stats(dom);
    if (this.args.complete) { this.debug.trap("XSL_LOADER->complete", function() { _this.args.complete(xsl_stats); }); }    

}


//ELI apply the dom tree to an element.
XSL_LOADER.prototype.apply_to = function(id,dom,encode)
{
    this.debug.time("HTML Render");

    var s=null;
    if(dom)
    {
        if(document.all)
        {
            s=this.toString(dom);
        }else{
            s=this.toString(dom);
            s=this.apply_firefox_fix(s);
        }
        if(encode){s=this.html_encode(s);}
    }      

    var e=null;
    if(typeof id=='string'){e=document.getElementById(id);}
    if(typeof id=='object'){e=id;}
    
    if(e)
    {
        if(typeof s=='string')
        {
            e.innerHTML=s;
        }
        if(typeof s=='object')
        {
            e.appendChild(s);
        }
        
    }
    this.debug.time("HTML Render",true);
    
};

XSL_LOADER.prototype.toString = function(dom,encode)
{
    //alert(dom.nodeValue);
    if(typeof dom=='string'){return dom;};
    if(typeof dom=='object')
    {
       if(framework.browser=='explorer'){return dom.xml;}
       return (new XMLSerializer()).serializeToString(dom);
    }
}

//ELI apply the dumb FF fix.
XSL_LOADER.prototype.apply_firefox_fix = function(s)
{
    if(framework.browser='firefox')
    {   
            //this.replaceHTML(e,this.html_decode(e.innerHTML));
            s=this.html_decode(s);
    }    
    return s;
};

//ELI decodes HTML entities.
XSL_LOADER.prototype.html_decode=function(value)
{
        return !value ? value : String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");
};

//ELI encodes HTML entities.
XSL_LOADER.prototype.html_encode=function(value)
{
        return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/""/g, '&quot;').replace(/[<]/g, "&lt;");
};

//ELI loads XML manually from text.
XSL_LOADER.prototype.load_xml=function(text)
{
/// <param name="text"/>
    
    var xml =null;
    if(framework.browser!='explorer' )
    {
       xml = XMLDOMObject().parseFromString(text, "text/xml");
     }else {
       //ELI create the XSL object.
       xml = XMLDOMObject();
       xml.loadXML(text);
     }
     
     this.debug.time("Download XML");
     var ajax = {responseXML:xml,status:200};
     this.args.xml_url="artificial_xml";
     this.inner_callback(ajax,this.args.xml_url);   
};

//ELI loads XML manually from URL.
XSL_LOADER.prototype.load_xml_url=function(_url)
{
    if(!_url){return;}
    this.dom=null;
    this.xml=null;
    this.args.xml_url = _url;

    this.debug.time("Download XML");
    this.flags.download=true;
    var _this=this;
    var cb=function(ajax,url){_this.inner_callback(ajax,url);}
    if(this.args.xml_url) new AJAX(this.args.xml_url,cb);

};

XSL_LOADER.prototype.extract_xsl_stats=function(dom)
{

    if(!dom) {return null;}

    var xmldom = null;
    if(dom.firstChild.nodeName.toLowerCase()=='xml')
    {
        xmldom=dom;
    }else{
        xmldom=dom.firstChild;
    };

    var stats = xmldom.getElementsByTagName('stats');
    
    if(!stats || stats.length<1){return null;}else{stats=stats[0];}

    var text=null;
    if(stats.text){text=stats.text;};
    if(stats.textContent){text=stats.textContent;};
//    if(stats.innerHTML){text=stats.innerHTML;};
    try{window.eval('var filter_stats_obj =' + text + ';');}catch(e){}
    stats.parentNode.removeChild(stats);     
    return typeof(filter_stats_obj)=='undefined' ? null : filter_stats_obj ;
};

﻿/// ZOOMER CLASS ///
//© 2008 SeatQuest LLC.

function debug_trace(trace){
    alert(trace);
   //console.log("debug_trace: ", trace); 
}


//BOGDAN constructor
function ZOOMER(args)
{
    var _this=this;
    if(args){this.args=args;}
    
    //ELI override parameters that are not set with default parameters.
    this.set_default_args();
    
    //ELI wait for the zoomer div to load.
    framework.observe(this.args.id,'onload',function(){_this.load();});

};

//ELI default parameters
ZOOMER.prototype.args={
    //BOGDAN seat_selected is called when seat selected on the map.
    seat_selected:null,
    section_selected:null,
    debug:null,
    id:null,
    swf_url:null,
    //BOGDAN flash zoomer parameters
    map_xml:null,
    mg:0,
    header:0,
    prog:1,
    msg:0,
    dom:1,
    theme:null,
    mouseover_mg:1,
    stmap:null,
    usetotalprice:0,
    profile:1,
    help:1,
    zoom_ratio:1.5,
    sl:1,
	callback:null,
	enable_section_highlights:false
}

//BOGDAN variables 
//ZOOMER.prototype.swfObject=null;
ZOOMER.prototype.map=null;
ZOOMER.prototype.gmap_controls=[];
ZOOMER.prototype.geocoder=null;
ZOOMER.prototype.swf=null;
ZOOMER.prototype.init_timer=null;
ZOOMER.prototype.flash_finished_loading=false;
ZOOMER.prototype.ready=false;
ZOOMER.prototype.queue={
    load_tickets:null,
    highlight_sections:[]
};
ZOOMER.prototype.zoom_level = 1;
ZOOMER.prototype.actual_sections = [];
ZOOMER.prototype.section_logic = null;



ZOOMER.prototype.set_default_args=function()
{       
    if(!this.args.mg){this.args.mg=0;}
    if(!this.args.header) {this.args.header=0; }
    if(!this.args.prog){this.args.prog=1;}
    if(!this.args.msg){this.args.msg=0;}
    if(!this.args.dom){this.args.dom=1;}
    if(!this.args.mouseover_mg){this.args.mouseover_mg=1;}
    if(!this.args.usetotalprice){this.args.usetotalprice=0;}
    if(!this.args.profile){this.args.profile=1;}
    if((!this.args.help) && (this.args.help!=0) && (this.args.help!=false)){this.args.help=1;}
    if(!this.args.zoom_ratio){this.args.zoom_ratio=1.5;}
    if((!this.args.sl) && (this.args.sl!=0) && (this.args.sl!=false)){this.args.sl=1;}
    if(!this.args.enable_section_highlights){this.args.enable_section_highlights=false;}
};

ZOOMER.prototype.load_complete = function()
{
	framework.zoomer.ready = true;
	//console.log("framework.zoomer.ready ", framework.zoomer.ready);
}

ZOOMER.prototype.load=function()
{
    _this = this;
    //TODO finish enable_section_highlights == false
    if(this.args.enable_section_highlights){
        this.actual_sections = this.args.html_sections();
        if(!this.actual_sections){
            setTimeout(function() {_this.load()}, 500);
            return;
        }
    }
    try
    {
        var w = document.getElementById(this.args.id).offsetWidth;
        var h = document.getElementById(this.args.id).offsetHeight;

        var swfObject = new SWFObject(this.args.swf_url, "zoomer", "100%", "100%", "7", "#FFFFFF");
		
        swfObject.addVariable("xml", escape(this.args.map_xml));
        swfObject.addVariable("mg", this.args.mg);
        swfObject.addVariable("header", this.args.header);
        swfObject.addVariable("prog", this.args.prog);
        swfObject.addVariable("msg", this.args.msg);
        swfObject.addVariable("zoomer_width", w);
        swfObject.addVariable("zoomer_height", h);
        swfObject.addVariable("dom", this.args.dom);
        swfObject.addVariable("theme", this.args.theme);
        swfObject.addVariable("mouseover_mg", this.args.mouseover_mg);
        swfObject.addVariable("stmap", escape(this.args.stmap));
        swfObject.addVariable("usetotalprice", this.args.usetotalprice);
        swfObject.addVariable("profile", this.args.profile);
        swfObject.addVariable("help", this.args.help);
        swfObject.addVariable("sl", this.args.sl);
        swfObject.addVariable("browser", framework.browser);
        
        if(this.args.enable_section_highlights) {
            swfObject.addVariable("sectionSelectionMode", this.args.enable_section_highlights);
            swfObject.addVariable("actual_sections", this.actual_sections.join('$,'));
	    }
	    
        swfObject.addParam("allowScriptAccess", "always");
        swfObject.addParam("wmode", "transparent");
        swfObject.write(this.args.id);
        if(framework.browser == 'explorer') {
            if(this.args.callback) this.args.callback();
        }
        this.swf = document.getElementById("zoomer") || (function (self) {
          // flash player not accessible, falling back to JS stub
          return {
            noop: function () {},
            dom_complete_string: function (dom_complete_string) {
              // got dom_complete_string, discard
              setTimeout(function () {
                // faux flash-finished-loading
                self.load_complete();
              }, 100);
            }
          };
        })(this);
        this.swf_loaded_timer = setInterval(function() {_this.swf_loaded()},500);    
    }catch(err){
        this.debug.error("ZOOMER->load",err);
    }       
}

ZOOMER.prototype.set_section_logic = function(section_logic){
    this.section_logic = section_logic;
}


//--------------------------------------------------------------------------------------------------------------------------------------------
//BOGDAN flash callbacks
//--------------------------------------------------------------------------------------------------------------------------------------------
//ELI fires when the zoomer finished loading.
ZOOMER.swf_loaded_timer = null;
ZOOMER.prototype.swf_loaded=function()
{	
	try
	{
		this.swf.noop();
		
		clearInterval(this.swf_loaded_timer);
		this.flash_finished_loading = true;
	    if(this.queue.load_tickets && typeof(this.queue.load_tickets)=='function') 
	    {
	        var _this=this;
	        setTimeout(function(){_this.queue.load_tickets();},1);
	    }
	}	
	catch(err)
	{}
}

//ELI fires when a seat was selected in the zoomer.
ZOOMER.prototype.seat_selected=function(id)
{
    var _this=this;
    
    //ELI call the filter.apply to filter GA tickets when GA is selected.
    if(id.toLowerCase()=='ga')
    {
        setTimeout(function(){framework.filter.apply({params:{ga:1}});},1);
    }
    
    //ELI calls the user seat_selected function.
    this.args.seat_selected(id,false);
    //TODO: Debug why trap doesn't work here.
    //if(this.args.seat_selected){this.debug.trap("ZOOMER->seat_selected",function(){_this.args.seat_selected(id,false);});}
 
}

//--------------------------------------------------------------------------------------------------------------------------------------------
//BOGDAN functions to control flash
//--------------------------------------------------------------------------------------------------------------------------------------------
ZOOMER.prototype.show_seats=function(seats_to_show)
{
    if(this.swf && this.swf.show_seats) 
    {
        this.swf.show_seats(seats_to_show); 
        
        //ELI determine wheather or not to hide the bubble
        var tid=this.last_highlighted_ticket;
        if(tid && seats_to_show.indexOf(tid + '$,')<=0)
        {
            this.reset_highlights();
        };

        return true;
    }else{
        return false;
    }
}

//--------------------------------------------------------------------------------------------------------------------------------------------
ZOOMER.prototype.load_tickets=function(dom)
{
    var _this=this;
    if(this.flash_finished_loading)
    {     
        this.load_tickets_after_flash_loaded(dom);
    } else  {
        this.queue.load_tickets = function(){_this.load_tickets(dom)};
    }
}

ZOOMER.prototype.load_tickets_after_flash_loaded=function(dom){
    if(this.args.enable_section_highlights) {
        this.swf.dom_complete_string("10000$;10000$;10$;10$;10$;10$;10$;10$;10$;10$;10$;10$;10$;$;"); 
        return;
    }else{ 
        var s = this.create_dom_complete_arg(dom);
        this.swf.dom_complete_string(s);
        if(this.args.debug!=null) this.args.debug.time("Zoomer Bridge",true);
        this.unqueue_highlighted_sections_calls();
    }
}

ZOOMER.prototype.unqueue_highlighted_sections_calls=function(){
    for(var i = 0; i < this.queue.highlight_sections.length; i+=2) {
        this.highlight_sections(this.queue.highlight_sections[i], this.queue.highlight_sections[i+1]);
    }
}

ZOOMER.prototype.create_dom_complete_arg=function(dom){
    if(this.args.debug!=null) this.args.debug.time("Array 1st");
    var rows=dom.getElementsByTagName('row');
    if(!rows){return null;}
    var ra={x:[],y:[],e:[],g:[],p:[],op:[],u:[],s:[],r:[],st:[],a:[],d:[],b:[],tb:[], sp:[], bn:[], sc:[]};
    var reg_ex=new RegExp(';','g');
    //alert(reg_ex);
    for(i=0;i<rows.length;i++)
    {
        var row=rows[i];
        var coords=null;
        coords=row.getAttribute('sq_coords');
        if(coords)
        {
            var c=coords.split(';');
            
            var seats=row.getAttribute('sq_seats').split(';');
            var e=row.getAttribute('sq_exact');
            var p=row.getAttribute('TicketPrice');
            var op=row.getAttribute('SGPriceWithFees');
            var u=row.getAttribute('TicketID');
            
            if(!this.args.enable_section_highlights) {
                var s=row.getAttribute('SeatSection');
                var r=row.getAttribute('SeatRow');                
            } else {
                var s=row.getAttribute('sq_sec');
                var r=row.getAttribute('sq_row');
            }
            var a=row.getAttribute('Available');
            var d=row.getAttribute('SeatDescription');
            var tb=row.getAttribute('TB');
			var sp=row.getAttribute('ValidSplits');
			var bn=row.getAttribute('BrokerName'); //ELI broker name
			var sc="0x" + row.getAttribute("SGColor");
			if(sp != null) sp = sp.substring(0, sp.length - 1);
			else sp = '';

            for(var j=0;j<seats.length-1;j++)
            {
                var m=j*2;
                var x=c[m];
                var y=c[m+1];
                if(!this.args.enable_section_highlights) {
                    ra.x.push(x);
                    ra.y.push(y);
                } else {
                    ra.x.push(0); 
                    ra.y.push(0);
                }
                ra.st.push(seats[j]);
                ra.e.push(e);
                ra.g.push(i);
                ra.p.push(p);
                ra.op.push(op);
                ra.u.push(u);
                ra.s.push(s);
                ra.r.push(r);
                ra.a.push(a);
                ra.d.push(d);
                ra.tb.push(tb);
				ra.sp.push(sp);
				ra.bn.push(bn);
				ra.sc.push(sc);
            }
        }
    }
    if(this.args.debug!=null) this.args.debug.time("Array 1st",true);
    
    if(this.args.debug!=null) this.args.debug.time("Array 2nd");
    var params = [];
    params.push(ra.x.join("$,"));
    params.push(ra.y.join("$,"));
    params.push(ra.e.join("$,"));
    params.push(ra.g.join("$,"));
    params.push(ra.p.join("$,"));
    params.push(ra.op.join("$,"));
    params.push(ra.u.join("$,"));
    params.push(ra.s.join("$,"));
    params.push(ra.r.join("$,"));
    params.push(ra.st.join("$,"));
    params.push(ra.a.join("$,"));
    params.push(ra.d.join("$,"));
    params.push(ra.tb.join("$,"));
	params.push(ra.sp.join("$,"));
    params.push(ra.bn.join("$,"));
    params.push(ra.sc.join("$,"));
    if(this.args.debug!=null) this.args.debug.time("Array 2nd",true);
    
    if(this.args.debug!=null) this.args.debug.time("Zoomer Bridge");
    return params.join("$;");
}


//--------------------------------------------------------------------------------------------------------------------------------------------
ZOOMER.prototype.enable_magnifying_glass=function(){
    if(this.swf && this.swf.enable_magnifying_glass )  {this.swf.enable_magnifying_glass();return true;}
    else return false;
}
//--------------------------------------------------------------------------------------------------------------------------------------------
ZOOMER.prototype.disable_magnifying_glass=function(){
    if(this.swf && this.swf.disable_magnifying_glass)  {this.swf.disable_magnifying_glass();return true;}
    else return false;
}
//--------------------------------------------------------------------------------------------------------------------------------------------
ZOOMER.prototype.reset_highlights=function()
{
    if(this.swf && this.swf.reset_highlights) {
        this.swf.reset_highlights();
        return true;
    }
    else return false;
}
//--------------------------------------------------------------------------------------------------------------------------------------------
ZOOMER.prototype.show_section_labels=function(enabled)
{
    if(this.swf && this.swf.show_section_labels) 
    {
        if(enabled)
        {
            this.swf.show_section_labels(1);
        }
        else
        {
            this.swf.show_section_labels(0);
        }
        return true;
    }
    else return false;
}
//--------------------------------------------------------------------------------------------------------------------------------------------
ZOOMER.prototype.toggle_price_mode=function(enabled)
{
    if(this.swf && this.swf.toggle_price_mode )
    {
        if(enabled)
        {
            this.swf.toggle_price_mode(1);
        }
        else
        {
            this.swf.toggle_price_mode(0);
        }
        return true;
    }
    else return false;
}
//--------------------------------------------------------------------------------------------------------------------------------------------
ZOOMER.prototype.show_help=function(with_fees)
{
    var _this=this;
    
    if(this.swf && this.swf.show_help ) 
    {
        setTimeout(function() {_this.swf.show_help(with_fees);},0);
        return true;
    } else{ return false;}
}

//--------------------------------------------------------------------------------------------------------------------------------------------
//BOGDAN commented out last_zoom and started using zoom_level, so zoom_out function will work after zoom( )  call
//ZOOMER.prototype.last_zoom=null;
ZOOMER.prototype.zoom_htimer=null;
ZOOMER.prototype.zoom=function(level,delay,timer_done)
{

    var _this=this;

    //ELI kill the timer 
    if(this.zoom_htimer){clearTimeout(this.zoom_htimer);}

    //ELI fire this function with a delay.
    if(!delay){delay=0;}
    if(delay>0 && !timer_done){
        var d = function() {_this.zoom(level,delay,true);};
        this.zoom_htimer=setTimeout(d,delay);
        return;
    }
    
    //ELI execute a zoom.
	if(this.swf && this.swf.zoom_ratio ) 
	{
        if(this.zoom_level!=level ){this.zoom_level=level;}else{return;}
        var f = function() {_this.swf.zoom_ratio(level,false);};
        setTimeout(f,delay);
	    return true;
	}else{ 
	    return false;
	}
}

//--------------------------------------------------------------------------------------------------------------------------------------------
ZOOMER.prototype.zoom_in=function()
{
    if(this.zoom_level >= 4) return;
    var new_level = this.zoom_level * this.args.zoom_ratio;
    if(new_level > 4) new_level = 4;
    this.zoom(new_level);
}
//--------------------------------------------------------------------------------------------------------------------------------------------
ZOOMER.prototype.zoom_out=function()
{
    if(this.zoom_level <=1) return;
    var new_level = this.zoom_level / this.args.zoom_ratio;
    if(new_level < 1) new_level = 1;
    this.zoom(new_level);
}

//--------------------------------------------------------------------------------------------------------------------------------------------
ZOOMER.prototype.highlight_ticket=function(tid) 
{
    var _this=this;
    if(this.swf && this.swf.highlight_ticket)
    { 
        _this.swf.highlight_ticket(tid);
        //setTimeout(function() {_this.swf.highlight_ticket(tid)}, 0);
        this.last_highlighted_ticket=tid;
        return true;
    }
    else return false;
}
//--------------------------------------------------------------------------------------------------------------------------------------------
ZOOMER.prototype.highlight_sections=function(sections_list, color) 
{
   var _this=this;     
   if(this.ready){
    //if(this.swf && this.swf.highlight_sections)
    //{ 
        if(this.args.debug!=null) this.args.debug.time("highlight_sections");
        //setTimeout(function() {_this.swf.highlight_sections(sections_list, color)}, 0);
        _this.swf.highlight_sections(sections_list.join("$,"), color);
        if(this.args.debug!=null) this.args.debug.time("highlight_sections", true);
        return true;
    //}
    //else return false;
    } else {
        this.queue.highlight_sections.push(sections_list);
        this.queue.highlight_sections.push(color);
    }
    
}
//--------------------------------------------------------------------------------------------------------------------------------------------
ZOOMER.prototype.highlight_other_sections=function(sections_list, color) 
{
   var _this=this;     
   if(this.ready){
    //if(this.swf && this.swf.highlight_sections)
    //{ 
        if(this.args.debug!=null) this.args.debug.time("highlight_other_sections");
        //setTimeout(function() {_this.swf.highlight_sections(sections_list, color)}, 0);
        _this.swf.highlight_other_sections(sections_list.join("$,"), color);
        if(this.args.debug!=null) this.args.debug.time("highlight_other_sections", true);
        return true;
    //}
    //else return false;
    } else {
        this.queue.highlight_other_sections.push(sections_list);
        this.queue.highlight_other_sections.push(color);
    }  
}
//--------------------------------------------------------------------------------------------------------------------------------------------
ZOOMER.prototype.highlight_section=function(section_name, color) 
{
    
    var _this=this;
    if(this.swf && this.swf.highlight_section)
    { 
        setTimeout(function() {_this.swf.highlight_section(section_name, color)}, 0);
        return true;
    }
    else return false;
}


ZOOMER.prototype.toggle_ga=function(flag){
    var _this=this;
    if(this.swf && this.swf.toggle_ga)
    { 
        _this.swf.toggle_ga(flag);
        return true;
    }
    else return false;
} 

//--------------------------------------------------------------------------------------------------------------------------------------------
//ZOOMER.prototype.reset_section_highlights=function() 
//{
//    var _this=this;
//    if(this.swf && this.swf.reset_section_highlights)
//    { 
//        if(this.args.debug!=null) this.args.debug.time("reset_section_highlights");
//        //setTimeout(function() {_this.swf.reset_highlights()}, 0);
//        _this.swf.reset_highlights();
//        //_this.swf.reset_highlights(-1,false);
//        if(this.args.debug!=null) this.args.debug.time("reset_section_highlights", true);
//        return true;
//    }
//    else return false;
//}


ZOOMER.prototype.section_selected=function(section_name)
{
    this.section_logic.zoomer_section_selected(section_name);
}


ZOOMER.prototype.show_section_bubble=function(section_name) 
{
    var _this=this;
    if(this.swf && this.swf.show_section_bubble)
    { 
        _this.swf.show_section_bubble(section_name);
        return true;
    }
    else return false;
}

ZOOMER.prototype.reset_section_highlight=function(section_name) 
{
    var _this=this;
    if(this.swf && this.swf.reset_section_highlight)
    { 
        _this.swf.reset_section_highlight(section_name);
        return true;
    }
    else return false;
}


ZOOMER.prototype.get_section_translations = function(){
    var result = this.swf.get_section_translations();
    return result;
}



