﻿/*
    Behaviours for the Price Range control
        
    Note: DO NOT create this control in a dom:loaded event. It MUST be created in a window load event 
          (since offsetWidths aren't always available just after the DOM loads)
*/

Site.Widgets.PriceRange = Class.create
(
    Site.Base,
    {
        initialize: function($super, container, options)
        {
            $super();
    
            this.setOptions
            (
                options,
                {
                    rangeBarMinimumWidth: 1,
                    startValues: [0, 1],
                    startBounds: [0, 1000]
                }
            );
            
            this.container = container;
            this.handleLower = this.container.select("div.price-range-handle-lower:first").first();
            this.handleUpper = this.container.select("div.price-range-handle-upper:first").first();
            this.track = this.container.select("div.price-range-track:first").first();
            this.valueLower = this.container.select("div.price-range-value-lower:first").first();
            this.valueUpper = this.container.select("div.price-range-value-upper:first").first();
            this.rangeBar = this.container.select("div.price-range-range-bar:first").first();

            this.addBlocks("handleLowerSnap", "handleLowerOnDrag", "handleOnEnd", "handleUpperOnDrag", "handleUpperSnap");
            
            if (this.rangeBar)
                this.rangeBar.hide();

            if (!this.handleLower || !this.handleUpper)
            {
                throw("Cannot create price range control - handles are not defined in XHTML.");
            }
            
            if (!this.track)
            {
                throw("Cannot create price range control - track is not defined in XHTML.");
            }

            this.values = this.options.startValues;
            
            this.handleLowerDraggable = new Draggable(this.handleLower, { starteffect: false, endeffect: false, constraint: "horizontal", snap: this.blocks.handleLowerSnap, onDrag: this.blocks.handleLowerOnDrag, onEnd: this.blocks.handleOnEnd });
            this.handleUpperDraggable = new Draggable(this.handleUpper, { starteffect: false, endeffect: false, constraint: "horizontal", snap: this.blocks.handleUpperSnap, onDrag: this.blocks.handleUpperOnDrag, onEnd: this.blocks.handleOnEnd });
            
            
            // record the width of the track
            this.width = this.track.offsetWidth;
            this.handleLowerWidth = this.handleLower.offsetWidth;
            this.handleUpperWidth = this.handleUpper.offsetWidth;
            
            this.valueWidth = this.width - this.handleUpperWidth;
            
            this.setBounds(this.options.startBounds[0], this.options.startBounds[1]);
            this.setValues(this.options.startValues[0], this.options.startValues[1]);
        },
        
        setBounds: function(lower, upper)
        {            
            this.bounds = [lower, upper];
            this.multiplier = (upper - lower);
            this.updateValueDisplays();
            
        },
        
        setValues: function(lower, upper)
        {
            
            this.values[0] = Math.min(Math.max(0, lower));
            this.values[1] = Math.max(Math.min(1, upper), (this.handleLower.offsetLeft + this.handleLowerWidth + this.options.rangeBarMinimumWidth) / this.valueWidth);  

            this.handleLower.setStyle({ "left": Math.round(this.values[0] * this.valueWidth) + "px" });
            this.handleUpper.setStyle({ "left": Math.round(this.values[1] * this.valueWidth) + "px" });
            
            this.updateValueDisplays();
            
            this.updateRangeBar();
        },
        
        setBounds2: function(lower, upper)
        {            
            this.bounds = [lower, upper];
            this.multiplier = (upper - lower);
            this.updateValueDisplays();
            
        },
        
        setValues2: function(lower, upper)
        {
            
            this.values[0] = Math.min(Math.max(0, lower));
            this.values[1] = Math.max(Math.min(1, upper), (this.handleLower.offsetLeft + this.handleLowerWidth + this.options.rangeBarMinimumWidth) / this.valueWidth);  

            this.handleLower.setStyle({ "left": Math.round(this.values[0] * this.valueWidth) + "px" });
            this.handleUpper.setStyle({ "left": Math.round(this.values[1] * this.valueWidth) + "px" });
            
            this.updateValueDisplays(); 
            
            //this.valueLower.update("$" + Site.formatNumber(this.outputValues[0], "#,###,##0"));
            //this.valueUpper.update("$" + Site.formatNumber(this.outputValues[1], "#,###,##0"));
            
            this.updateRangeBar();
        },
            
        handleLowerSnap: function(x, y)
        {
            if (x <= 0)
                return [0, y];
            else if (x + this.handleLowerWidth >= this.handleUpper.offsetLeft - this.options.rangeBarMinimumWidth)
                return [this.handleUpper.offsetLeft - this.handleLowerWidth - this.options.rangeBarMinimumWidth, y];
            
            return [x, y];
        },

        handleUpperSnap: function(x, y)
        {
            if (x + this.handleUpperWidth >= this.width)
            {
                // prevent the handle going past the end of the track
                return [this.width - this.handleUpperWidth, y];
            }
            else if (x <= this.handleLower.offsetLeft + this.handleLowerWidth + this.options.rangeBarMinimumWidth)
            {
                // prevent the handle going before the lower handle
                return [this.handleLower.offsetLeft + this.handleLowerWidth + this.options.rangeBarMinimumWidth, y];
            }

            return [x, y];
        },
        
        handleLowerOnDrag: function()
        {
            this.updateRangeBar();
            this.deriveLowerValue();
            this.updateValueDisplays();
        },
        
        handleUpperOnDrag: function()
        {
            this.updateRangeBar();
            this.deriveUpperValue();
            this.updateValueDisplays();
        },
        
        deriveLowerValue: function()
        {
            // the lower value is regarded as where the right of the handle is 
            this.values[0] = (this.handleLower.offsetLeft) / this.valueWidth;
        },

        deriveUpperValue: function()
        {
            // the upper value is regarded as where the left of the handle is 
            this.values[1] = this.handleUpper.offsetLeft / (this.valueWidth);
        },
        
        updateValueDisplays: function()
        {
            this.outputValues = [this.bounds[0] + (this.values[0] * this.multiplier), this.bounds[0] + (this.values[1] * this.multiplier)];
            this.valueLower.update("$" + Site.formatNumber(this.outputValues[0], "#,###,##0"));
            this.valueUpper.update("$" + Site.formatNumber(this.outputValues[1], "#,###,##0"));
        },
        
        handleOnEnd: function()
        {
            this.updateRangeBar();
            
            if (this.options.onChange)
            {
                this.options.onChange(this.outputValues);
            }
        },
        
        updateRangeBar: function()
        {
            this.rangeBar.show();

            var left = Math.round(this.handleLower.offsetLeft + this.handleLowerWidth - (this.handleLowerWidth / 2));
            var width = Math.round(this.handleUpper.offsetLeft - left + this.handleLowerWidth / 2);
            
            this.rangeBar.setStyle
            (
                {
                    "left": left + "px",
                    "width": width + "px"
                }
            );
        },
        
        destroy: function()
        {
            this.handleLowerDraggable.destroy();
            this.handleUpperDraggable.destroy();
        }
    },
    {
        
    }
);

        