/*
 *  Copyright 2007 Nature Trust of British Columbia
 */

/**
 * Tool bar for the HaBC Land Classification Map
 *
 * This was done this way because I could not get this to work inside the
 * GWT Environment.
 */
 
OpenLayers.Control.HaBCToolbar = OpenLayers.Class(OpenLayers.Control.Panel, {
    /**
     * Constructor: OpenLayers.Control.HaBCToolbar 
     * Add our four controls
     *
     * Parameters:
     * options - {Object} An optional object whose properties will be used
     *     to extend the control. (zoom - the zoom level for zoom to world, center - the center of the map, div - the div to add it to)
     * infoClickEvent - the javascript function to perform on datadrill map click event
     */
    initialize: function(options, infoClickEvent, zoomToClickEvent, upAreaEvent) {
        OpenLayers.Control.Panel.prototype.initialize.apply(this, [options]);
        var habcZoom = new OpenLayers.Control.ZoomToHaBC(options['zoom'], options['center']);
        habcZoom.title = "Zoom to BC";
        
        var nav = new OpenLayers.Control.Navigation({title: "Pan tool"});
        var zoomBox = new OpenLayers.Control.ZoomBox({title: "Zoom on an area by clicking and dragging"});

        var drill = new OpenLayers.Control.DataDrill({
                    title: "Show me everything about this hectare",
                    drillEvent: infoClickEvent
                });
        
        var zoomtoloc = new OpenLayers.Control.ZoomToLocation({
        			title: "Zoom to location",
        			zoomEvent: zoomToClickEvent
        			});
       	
        habcZoom.id = 'habcZoom';
        nav.id = 'nav';
        zoomBox.id = 'zoomBox';
        
       	var upstreamArea = null;
        if (upAreaEvent != null){
        	var upstreamArea = new OpenLayers.Control.UpstreamArea({
        			title: "Show me everything upstream of here.",
        			upstreamQueryEvent: upAreaEvent
        			});
        	upstreamArea.id = "upArea";  
        }
        if (upstreamArea != null){
        	this.addControls([habcZoom, nav, zoomBox, drill , zoomtoloc, upstreamArea]);
        }else{
        	this.addControls([habcZoom, nav, zoomBox, drill , zoomtoloc]);
        }
    },

    /**
     * Method: draw 
     * calls the default draw, and then activates mouse defaults.
     */
    draw: function() {
        var div = OpenLayers.Control.Panel.prototype.draw.apply(this, arguments);
        this.activateControl(this.controls[1]);
        return div;
    },
    CLASS_NAME: "OpenLayers.Control.HaBCToolbar"
});


/**
 *
 * Upstream area tool
 */
OpenLayers.Control.UpstreamArea = OpenLayers.Class(OpenLayers.Control, {
	type: OpenLayers.Control.TYPE_TOOL,
    
    displayClass: "upstreamarea",		//class

	upstreamQueryEvent: null, 				//event to call on click
	
	/**
     * Constructor: OpenLayers.Control.HaBCToolbar 
     * Add our four controls
     *
     * Parameters:
     * options - {Object} An optional object whose properties will be used
     *     to extend the control. (clickEvent - the function to perform onClick)
     */
	initialize: function(options){
		OpenLayers.Control.prototype.initialize.apply(this, [options]);
		upstreamQueryEvent = options['upstreamQueryEvent'];
		
	},
	
	/**
	 * activates the control and registers a click event on the map
	 */
	activate: function() {
		this.map.events.registerPriority("click", this.map, this.queryHandler);
		this.map.div.style.cursor = "crosshair";
		return OpenLayers.Control.prototype.activate.apply(this, arguments);
	},
	/**
	 * deactivates the control and removes the click event from the map
	 */
	deactivate: function() {
		this.map.events.unregister("click", this.map, this.queryHandler);
		this.map.div.style.cursor = "auto";
		return OpenLayers.Control.prototype.deactivate.apply(this, arguments);
	},
	/*
	 * 
	 */
	queryHandler: function(e) {
		upstreamQueryEvent(e.xy.x, e.xy.y);
	},
		
CLASS_NAME: "OpenLayers.Control.UpstreamArea"
});

/**
 *
 * Data Drill Tool
 */
 
OpenLayers.Control.DataDrill = OpenLayers.Class(OpenLayers.Control, {
	type: OpenLayers.Control.TYPE_TOOL,
    
    displayClass: "datadrill",		//class

	drillEvent: null, 				//event to call on click
	/**
     * Constructor: OpenLayers.Control.HaBCToolbar 
     * Add our four controls
     *
     * Parameters:
     * options - {Object} An optional object whose properties will be used
     *     to extend the control. (clickEvent - the function to perform onClick)
     */
	initialize: function(options){
		OpenLayers.Control.prototype.initialize.apply(this, [options]);
		drillEvent = options['drillEvent'];
		
	},
	
	/**
	 * activates the control and registers a click event on the map
	 */
	activate: function() {
		this.map.events.registerPriority("click", this.map, this.queryHandler);
		this.map.div.style.cursor = "crosshair";
		return OpenLayers.Control.prototype.activate.apply(this, arguments);
	},
	/**
	 * deactivates the control and removes the click event from the map
	 */
	deactivate: function() {
		this.map.events.unregister("click", this.map, this.queryHandler);
		this.map.div.style.cursor = "auto";
		return OpenLayers.Control.prototype.deactivate.apply(this, arguments);
	},
	/*
	 * 
	 */
	queryHandler: function(e) {
		drillEvent(e.xy.x, e.xy.y);
	},
		
CLASS_NAME: "OpenLayers.Control.DataDrill"
});


/**
 * 
 * Class: OpenLayers.Control.ZoomToHaBC 
 * Implements a zoom to bc
 * 
 * Inherits from:
 *  - <OpenLayers.Control>
 */
OpenLayers.Control.ZoomToHaBC = OpenLayers.Class(OpenLayers.Control, {
    /**
     * Property: type
     * TYPE_BUTTON.
     */
    type: OpenLayers.Control.TYPE_BUTTON,
    
    center: null,
    zoomlevel: null,
    
    initialize: function(zoom, center){
      OpenLayers.Control.prototype.initialize.apply(this, arguments);
      this.zoomlevel = zoom;
      this.center = center;
    }, 
     
    /*
     * Method: trigger
     * Do the zoom.
     */
    trigger: function() {
        if (this.map) {
            this.map.setCenter(this.center, this.zoomlevel);
        }    
    },

    CLASS_NAME: "OpenLayers.Control.ZoomToHaBC"
});

/**
 * 
 * Class: OpenLayers.Control.ZoomToLocation 
 * Implements a zoom to location
 * 
 * Inherits from:
 *  - <OpenLayers.Control>
 */
OpenLayers.Control.ZoomToLocation = OpenLayers.Class(OpenLayers.Control, {
	type: OpenLayers.Control.TYPE_BUTTON,
    
    displayClass: "zoomtolocation",		//class

	zoomEvent: null, 				//event to call on click
	/**
     * Constructor: OpenLayers.Control.ZoomToLocation 
     *
     * Parameters:
     * options - {Object} An optional object whose properties will be used
     *     to extend the control. (clickEvent - the function to perform onClick)
     */
	initialize: function(options){
		OpenLayers.Control.prototype.initialize.apply(this, [options]);
		zoomEvent = options['zoomEvent'];
	},
	
	 /*
     * Method: trigger
     * Do the zoom.
     */
    trigger: function() {
        zoomEvent();
    },

    CLASS_NAME: "OpenLayers.Control.ZoomToLocation"
});

/**
 *
 * Class: OpenLayers.Control.HaBCResolution
 * Display a small resolution indicator on the map.
 * Inherits from:
 *  - <OpenLayers.Control>
 */
OpenLayers.Control.HaBCResolution = OpenLayers.Class(OpenLayers.Control, {
    
    /**
     * Parameter: element
     * {DOMElement}
     */
    element: null,
    tilesize: 64,
    
    /**
     * Constructor: OpenLayers.Control.HaBCResolution
     * 
     * Parameters:
     * element - {DOMElement} 
     * options - {Object} 
     */
    initialize: function(element, options) {
        OpenLayers.Control.prototype.initialize.apply(this, [options]);
        this.element = OpenLayers.Util.getElement(element);
        this.tilesize = options['resolution'];      
    },

    /**
     * Method: draw
     * 
     * Returns:
     * {DOMElemen}
     */    
    draw: function() {
        OpenLayers.Control.prototype.draw.apply(this, arguments);
        if (!this.element) {
            this.element = document.createElement("div");
            this.div.className = this.displayClass;
            this.div.appendChild(this.element);
        }
        this.map.events.register( 'moveend', this, this.updateResolution);
        this.updateResolution();
        return this.div;
    },
   
    /**
     * Method: updateResolution
     */
    updateResolution: function() {
        var zoom = this.map.getZoom();   
        var offset = this.tilesize / 64;
		zoom = this.map.getNumZoomLevels() - offset - zoom;
		if (zoom < 0) zoom = 0;        
		if (zoom == 0){
        	this.element.innerHTML = "1 square (<img width='5px' height='5px' src='./images/red_square.gif'>) = " + (Math.pow(2, zoom) * Math.pow(2, zoom)) + " hectare";
        }else{
        	this.element.innerHTML = "1 square (<img width='5px' height='5px' src='./images/red_square.gif'>) = " + (Math.pow(2, zoom) * Math.pow(2, zoom)) + " hectares";
        }
    }, 

    CLASS_NAME: "OpenLayers.Control.HaBCResolution"
});


/**
 *
 * Class: OpenLayers.Control.HaBCMousePosition
 * Displays a custom coordinates block (BC Albers and Lat Lon) on the map.
 * Inherits from:
 *  - <OpenLayers.Control.MousePosition>
 */
OpenLayers.Control.HaBCMousePosition = OpenLayers.Class(OpenLayers.Control.MousePosition, {
	/* objects to support transformation from BC Albers to LatLon */
	grs80: null,
	bcAlbers: null,
	albPt: null,
	geoPt: null,

    /**
     * Constructor: OpenLayers.Control.HaBCMousePosition
     * 
     * Parameters:
     * element - {DOMElement}
     */
    initialize: function() {
        OpenLayers.Control.prototype.initialize.apply(this);
		grs80 = new Spheroid(6378137.0, -1.0, 298.257222101);
		bcAlbers = new Albers(grs80);
		albPt = new Point();
		geoPt = new Point();
		bcAlbers.setParameters(-126, 50, 58.5, 45, 1000000, 0);
    },

    /**
     * Method: draw
     * 
     * Returns:
     * {DOMElemen}
     */    
	draw: function() {
		OpenLayers.Control.MousePosition.prototype.draw.apply(this, arguments);
        if (!this.element) {
            this.element = document.createElement("div");
            this.div.className = this.displayClass;
            this.div.appendChild(this.element);
        }
       	this.element.innerHTML = "BC Albers: x = 0, y = 0<br>LatLon: lat = 0, lon = 0";
        return this.div;
    },
    
    /**
     * Method: redraw
     * 
     * Returns:
     * {DOMElemen}
     */    
	redraw: function(evt) {
        if (!this.element) {
            this.element = document.createElement("div");
            this.div.className = this.displayClass;
            this.div.appendChild(this.element);
        }
        if (evt != null) {
        	var lonlat = this.map.getLonLatFromPixel(evt.xy);
        	if (lonlat != null){
	        	var html = "BC Albers: x = "+lonlat.lon.toFixed(0) + ", y = " + lonlat.lat.toFixed(0) + "<BR>";
	        
	        	albPt.x = lonlat.lon;
	        	albPt.y = lonlat.lat;
	        	bcAlbers.inverse(albPt, geoPt);
	        
	        	html += "LatLon: lat = "+geoPt.y.toFixed(5)+", lon = "+geoPt.x.toFixed(5);
	        	this.element.innerHTML = html;
	        }
	    }
        return this.div;
    },

    CLASS_NAME: "OpenLayers.Control.HaBCMousePosition"
});


/*
 * Copyright 2007 Nature Trust of British Columbia
 *
 * Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
 * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
 * full text of the license. */

/*
 * This class is an extentsion of the OpenLayers Layer Switcher which adds an opacity control
 * to overlay layers.
 * 
 *   
 */
/**
 * Class: OpenLayers.Control.HaBCLayerSwitcher
 *
 * Inherits from:
 *  - <OpenLayers.Control>
 */
OpenLayers.Control.HaBCLayerSwitcher = 
  OpenLayers.Class(OpenLayers.Control.LayerSwitcher, {

    /** 
     * Size of horizontal slider
     * APIProperty: length
     */
    length: 100,

    /** 
     * Opacity from
     * APIProperty: from
     */
    from: 0,

    /** 
     * Opacity 10
     * APIProperty: sliderEvents
     */
    to: 100,
    
    /** 
     * Number of distinct values
     * APIProperty: count
     */
    count: 101,

	/**
	 * The number of baselayers in the map
	 */
	baselayercount: 0, 
	
    /** 
     * Number of decimal places to show
     * APIProperty: decimals
     */
    decimals: 0,	
    
    mouseover: false,
    
    /** 
     * Method: redraw
     * Goes through and takes the current state of the Map and rebuilds the
     *     control to display that state. Groups base layers into a 
     *     radio-button group and lists each data layer with a checkbox.
     *
     * Returns: 
     * {DOMElement} A reference to the DIV DOMElement containing the control
     */  
    redraw: function() {
        //if the state hasn't changed since last redraw, no need 
        // to do anything. Just return the existing div.
        if (!this.checkRedraw()) { 
            return this.div; 
        } 

        //clear out previous layers 
        this.clearLayersArray("base");
        this.clearLayersArray("data");
        
        var containsOverlays = false;
        var containsBaseLayers = false;
        
        // Save state -- for checking layer if the map state changed.
        // We save this before redrawing, because in the process of redrawing
        // we will trigger more visibility changes, and we want to not redraw
        // and enter an infinite loop.
        this.layerStates = new Array(this.map.layers.length);
        for (var i = 0; i < this.map.layers.length; i++) {
            var layer = this.map.layers[i];
            this.layerStates[i] = {
                'name': layer.name, 
                'visibility': layer.visibility,
                'inRange': layer.inRange,
                'id': layer.id
            };
        }

		this.dataLayersDiv.style.overflow="auto";
		this.dataLayersDiv.style.height="220px";
        this.layersDiv.style.paddingLeft = "0px";
        this.dataLayersDiv.style.width="200px";
						
        var layers = this.map.layers.slice();
        baselayercount = 0;
        if (!this.ascending) { layers.reverse(); }
        for( var i = 0; i < layers.length; i++) {
            var layer = layers[i];
            var baseLayer = layer.isBaseLayer;
			
            if (layer.displayInLayerSwitcher) {

                if (baseLayer) {
                    containsBaseLayers = true;
                    baselayercount++;
                } else {
                    containsOverlays = true;
                }    

                // only check a baselayer if it is *the* baselayer, check data
                //  layers if they are visible
                var checked = (baseLayer) ? (layer == this.map.baseLayer)
                                          : layer.getVisibility();
    
                // create input element
                var inputElem = document.createElement("input");
                inputElem.id = "input_" + layer.name;
                inputElem.name = (baseLayer) ? "baseLayers" : layer.name;
                inputElem.type = (baseLayer) ? "radio" : "checkbox";
                inputElem.value = layer.name;
                inputElem.checked = checked;
                inputElem.defaultChecked = checked;

                if (!baseLayer && !layer.inRange) {
                    inputElem.disabled = true;
                }
                var context = {
                    'inputElem': inputElem,
                    'layer': layer,
                    'layerSwitcher': this
                };
                OpenLayers.Event.observe(inputElem, "mouseup", 
                    OpenLayers.Function.bindAsEventListener(this.onInputClick,
                                                            context)
                );
                
                // create span
                var labelSpan = document.createElement("span");
                if (!baseLayer && !layer.inRange) {
                    labelSpan.style.color = "gray";
                }
                labelSpan.innerHTML = layer.name;
                labelSpan.style.verticalAlign = (baseLayer) ? "bottom" 
                                                            : "baseline";
				OpenLayers.Event.observe(labelSpan, "click", 
                    OpenLayers.Function.bindAsEventListener(this.onInputClick,
                                                            context)
                );

				/*
				//For adding color to the layer switcher
				//to make this work we need to know what color
				//to make the layer switcher
				var colorElement = document.createElement("span");
				colorElement.style.width = "8px";
				colorElement.style.height = "8px";
				colorElement.style.overflow = "hidden";
				colorElement.style.display = "-moz-inline-box";
				colorElement.style.display = "inline-box";
				colorElement.style.backgroundColor = "#FF0000";
				colorElement.style.border = "1px solid #000000";
				colorElement.style.marginTop = "7px";
				colorElement.style.marginLeft = "5px";
				*/
                
                var groupArray = (baseLayer) ? this.baseLayers
                                             : this.dataLayers;                                                    
    
                var groupDiv = (baseLayer) ? this.baseLayersDiv
                                           : this.dataLayersDiv;

				var tableDiv = document.createElement("table");
				tableDiv.style.width = "95%";
				
				groupDiv.appendChild(tableDiv);
				
				var tableBody = document.createElement("tbody");
				tableDiv.appendChild(tableBody);
				
				var rowDiv = document.createElement("tr");
				tableBody.appendChild(rowDiv);
				
				var cell1 = document.createElement("td");
				var cell2 = document.createElement("td");
				cell2.style.width="100%";
				cell2.style.color="#E6F1E3";
				rowDiv.appendChild(cell1);
				rowDiv.appendChild(cell2);

                cell1.appendChild(inputElem);
                cell2.appendChild(labelSpan);
                cell1.style.verticalAlign = "top";
                if (!baseLayer){
    				//create delete button
    				var deleteElement = document.createElement("img");
					deleteElement.id = "delete_" + layer.name;
					deleteElement.src = "./images/square_x.gif";
					deleteElement.title = "Delete Layer";
				
					OpenLayers.Event.observe(deleteElement, "click",
						OpenLayers.Function.bindAsEventListener(this.onInputDelete,
													 context)
					);
                
                	//if (layer.id.match("TMS") == null){
                		//non TMS layers add up/down option
                		var moveUpElement = document.createElement("img");
						moveUpElement.id = "moveup_" + layer.name;
						moveUpElement.src = "./images/layer_up.gif";
						moveUpElement.title = "Move Up";
						OpenLayers.Event.observe(moveUpElement, "click",
				  			OpenLayers.Function.bindAsEventListener(this.onInputMoveUp, context)
				  		);
				
						var moveDownElement = document.createElement("img");
						moveDownElement.id = "movedown_" + layer.name;
						moveDownElement.src = "./images/layer_down.gif";
						moveDownElement.title = "Move Down";
						OpenLayers.Event.observe(moveDownElement, "click",
				  			OpenLayers.Function.bindAsEventListener(this.onInputMoveDown, context)
				  		);
				  						  		
				  		var updownDiv = document.createElement("div");
				  		updownDiv.appendChild(moveUpElement);
				  		updownDiv.appendChild(moveDownElement);
				  		
				  		var cell3 = document.createElement("td");
						rowDiv.appendChild(cell3);
						
                		cell3.appendChild(updownDiv);
                		cell3.style.verticalAlign = "top";
                		updownDiv.style.styleFloat = "left";
                		//updownDiv.style.cssFloat = "left";
                		//updownDiv.style.float = "left";
				    //}
                	
                	var cell5 = document.createElement("td");
					rowDiv.appendChild(cell5);
					cell5.appendChild(deleteElement);
                	cell5.style.verticalAlign = "top";
              	}
                
                if (!baseLayer){
                	//transparency
                    var x = this.createSlider(layer);
                    //transSpan = document.createElement("span");
                    //transSpan.innerHTML = "Transparency:";
                    //transSpan.style.verticalAlign="baseline";
                    //transSpan.style.paddingLeft = "10px";
                    //groupDiv.appendChild(transSpan);
                    groupDiv.appendChild(x.table);
                    
                    //line
                    if (i != layers.length - 1){
                    	var hr = document.createElement("hr");
                    	hr.style.color = "#78B46E";
                    	hr.style.height = "2px";
                    	hr.style.width = "95%";
                    	hr.style.textAlign = "left";
                    	hr.style.margin = "0 auto 0 0";
                    	groupDiv.appendChild(hr);
                    }
                   	
                   	groupArray.push({
                    	'layer': layer,
                    	'inputElem': inputElem,
                    	'labelSpan': labelSpan,
                    	'sliderElement': x.sliderElement,
                    	'slitElement': x.slitElement
                	});
                }else{
                	groupArray.push({
                    	'layer': layer,
                    	'inputElem': inputElem,
                    	'labelSpan': labelSpan
                	});
                }
            }
        }

        // if no overlays, dont display the overlay label
        this.dataLbl.style.display = (containsOverlays) ? "" : "none";        
        
        // if no baselayers, dont display the baselayer label
        this.baseLbl.style.display = (containsBaseLayers) ? "" : "none";        

        return this.div;
    },

	/**
	 * Method: onInputDelete
	 * Deletes a layer from the map
	 * Context:  
     *  - {DOMElement} inputElem
     *  - {<OpenLayers.Control.LayerSwitcher>} layerSwitcher
     *  - {<OpenLayers.Layer>} layer
     */
	 
	onInputDelete: function(e){
	    this.layer.map.removeLayer(this.layer, true);	
		OpenLayers.Event.stop(e);
	},


	/**
	 * Method: onInputMoveUp
	 * Moves a layer up in the map
	 * Context:  
     *  - {DOMElement} inputElem
     *  - {<OpenLayers.Control.LayerSwitcher>} layerSwitcher
     *  - {<OpenLayers.Layer>} layer
     */
	 
	onInputMoveUp: function(e){
		var index = this.layer.map.getLayerIndex(this.layer);
		index = index - 1;
		if (index <= baselayercount){
			index = baselayercount;
		}
		this.layer.map.setLayerIndex(this.layer, index);
		OpenLayers.Event.stop(e);
	},
    /**
	 * Method: onInputMoveDown
	 * Moves a layer up in the map
	 * Context:  
     *  - {DOMElement} inputElem
     *  - {<OpenLayers.Control.LayerSwitcher>} layerSwitcher
     *  - {<OpenLayers.Layer>} layer
     */
	onInputMoveDown: function(e){
		this.layer.map.raiseLayer(this.layer, 1);
		OpenLayers.Event.stop(e);
	},

   /** 
     * Method: clearLayersArray
     * User specifies either "base" or "data". we then clear all the
     *     corresponding listeners, the div, and reinitialize a new array.
     * 
     * Parameters:
     * layersType - {String}  
     */
    clearLayersArray: function(layersType) {
        var layers = this[layersType + "Layers"];
        if (layers) {
            for(var i=0; i < layers.length; i++) {
                var layer = layers[i];
                OpenLayers.Event.stopObservingElement(layer.inputElem);
                OpenLayers.Event.stopObservingElement(layer.labelSpan);
                if (layer.sliderElement){
                	OpenLayers.Event.stopObservingElement(layer.sliderElement);
                	OpenLayers.Event.stopObservingElement(layer.slitElement);
                }
            }
        }
        this[layersType + "LayersDiv"].innerHTML = "";
        this[layersType + "Layers"] = [];
    },
  
	/**
 	* Method: createSlider
 	* Creates a slider element to be placed beneath the overlay layer name.
 	* The slider controls the opacity of the layer
 	* 
 	* Parameters:
 	* layer - the layer to change the opacity of
 	* 
 	* Returns:
 	*  x.table - the table element the slider is contained in
 	*  x.sliderElement - the slider element event observed on
 	*  x.slitElement - the slit element event observed on
 	*/
	createSlider: function(layer){
		if (layer.opacity == null){
			//evil hack to get wms opacits working
			layer.opacity = 0.5;
		}
		
		var defaultvalue = Math.round(layer.opacity * 100);

        var trackElement = document.createElement("div");
		trackElement.id = "horizontal_track_" + layer.name ;; 
		trackElement.className = "horizontal_track"; 
					
		var slitElement = document.createElement("div");
		slitElement.id = "horiztonal_slit_" + layer.name ;;
		slitElement.className = "horizontal_slit";
		slitElement.innerHTML = "&nbsp;";
					
		var sliderElement = document.createElement("div");
		sliderElement.id = "horizontal_slider_" + layer.name ;;
		sliderElement.className = "horizontal_slider";
		sliderElement.style.left = defaultvalue + "px";
       	sliderElement.innerHTML = "&nbsp;";
                		
       	trackElement.appendChild(slitElement);
		trackElement.appendChild(sliderElement);
         
    	var textElement = document.createElement("div");
       	textElement.id = "display_holder_" + layer.name ; ;
       	textElement.className = "display_holder";
    	
    	var inputElement = document.createElement("input");
    	inputElement.type = "text";
        inputElement.id =  "value_display_" + layer.name ;
        inputElement.className =  "value_display";
        inputElement.value = defaultvalue;      
        inputElement.readOnly = true;
        
        textElement.appendChild(inputElement);

		var tbl = document.createElement("table");
		//tbl.style.backgroundColor = "#FF0000";
		var tblBody = document.createElement("tbody");
		var row1 = document.createElement("tr");
		var cell1 = document.createElement("td");
		cell1.appendChild(trackElement);
		var cell2 = document.createElement("td");
		cell2.appendChild(textElement);
		row1.appendChild(cell1);
		row1.appendChild(cell2);
		tblBody.appendChild(row1);
		tbl.appendChild(tblBody);

		var context = {
        	'slider': this,
        	'layer': layer,
        	'outerDiv': tbl,
        	'trackElement': trackElement,
        	'sliderObj': sliderElement
		};
       OpenLayers.Event.observe(sliderElement, "mousedown", OpenLayers.Function.bindAsEventListener(this.slide,context));
       OpenLayers.Event.observe(slitElement, "click", OpenLayers.Function.bindAsEventListener(this.moveSliderFixed,context));
       
       var added = {
       		'table': tbl,
       		'sliderElement': sliderElement,
       		'slitElement': slitElement
       }
       return added;
       
    },

	carpeGetElementById: function(element){
		if (document.getElementById) element = document.getElementById(element);
		else if (document.all) element = document.all[element];
		else element = null;
		return element;
	},


	carpeLeft: function(elmnt, pos){
		if (!(elmnt = this.carpeGetElementById(elmnt))) return 0;
		if (elmnt.style && (typeof(elmnt.style.left) == 'string')) {
			if (typeof(pos) == 'number') elmnt.style.left = pos + 'px';
			else {
				pos = parseInt(elmnt.style.left);
				if (isNaN(pos)) pos = 0;
			}
		}
		else if (elmnt.style && elmnt.style.pixelLeft) {
			if (typeof(pos) == 'number') elmnt.style.pixelLeft = pos;
			else pos = elmnt.style.pixelLeft;
		}
		return pos;
	},

	carpeTop: function(elmnt, pos)
	{
		if (!(elmnt = this.carpeGetElementById(elmnt))) return 0;
		if (elmnt.style && (typeof(elmnt.style.top) == 'string')) {
			if (typeof(pos) == 'number') elmnt.style.top = pos + 'px';
			else {
				pos = parseInt(elmnt.style.top);
				if (isNaN(pos)) pos = 0;
			}
		}
		else if (elmnt.style && elmnt.style.pixelTop) {
			if (typeof(pos) == 'number') elmnt.style.pixelTop = pos;
			else pos = elmnt.style.pixelTop;
		}
		return pos;
	},

    /*
     * moves the slider to a fixed location determined by the click event e
     */
    moveSliderFixed: function (e){
		var valCount = this.slider.count ? this.slider.count - 1 : this.slider.length // Allowed number of values in the interval.
		var scale = (this.slider.to - this.slider.from) / this.slider.length;
		
		x = e.layerX ? e.layerX : e.offsetX; // Horizontal mouse position relative to allowed slider positions
		
		//alert(x);
		if (x > this.slider.length) x = this.slider.length // Limit horizontal movement
		if (x < 0) x = 0 // Limit horizontal movement
		
		this.slider.carpeLeft(this.sliderObj.id, x)  // move slider to new horizontal position
		sliderPos = (this.slider.length / valCount ) * Math.round(valCount * x / this.slider.length);
		//alert(sliderPos);
		v = Math.round((sliderPos * scale + this.slider.from) * // calculate display value
					Math.pow(10,  this.slider.decimals)) / Math.pow(10,  this.slider.decimals)
		//alert(v);	
		displayObj = this.slider.carpeGetElementById("value_display_" + this.layer.name);
		displayObj.value = v; // put the new value in the slider display element
		
		
		var opacity = v / 100;
		if (opacity >= 1){
			opacity = opacity - 0.01;
		}
		this.layer.setOpacity(opacity);  //update opacity
		return
	},
	
	/*
	 * moves the slider based on where it was dragged
	 */
	moveSlider: function (e){
		//var evnt = (!this.evnt) ? window.event : this.evnt; // The mousemove event
		var evnt = e;
		if (this.slider.mouseover) { // Only if slider is dragged
			x = this.pxLeft + evnt.screenX - this.xCoord // Horizontal mouse position relative to allowed slider positions
			y = this.pxTop + evnt.screenY - this.yCoord // Horizontal mouse position relative to allowed slider positions
			if (x > this.xMax) x = this.xMax // Limit horizontal movement
			if (x < 0) x = 0 // Limit horizontal movement
			y=0;
			this.slider.carpeLeft(this.sliderObj.id, x)  // move slider to new horizontal position
			this.slider.carpeTop(this.sliderObj.id, y) // move slider to new vertical position
			sliderVal = x + y // pixel value of slider regardless of orientation
			sliderPos = (this.sliderObj.pxLen / this.sliderObj.valCount) * Math.round(this.sliderObj.valCount * sliderVal / this.sliderObj.pxLen)
			v = Math.round((sliderPos * this.sliderObj.scale + this.sliderObj.fromVal) * // calculate display value
						Math.pow(10, this.displayObj.dec)) / Math.pow(10, this.displayObj.dec)
			this.displayObj.value = v // put the new value in the slider display element
			
			var opacity = v / 100;
			if (opacity >= 1){
				opacity = opacity - 0.01;
			}
			this.layer.setOpacity(opacity);
			return false;
		}
		return
	},
	
	// moveSlider: Handles the start of a slider move.
	slide: function (evnt)
	{
		var xMax = this.slider.length;

		var pxLeft = 0;
		var pxTop = 0;
		
		if (!evnt) evnt = window.event;
		sliderObj = (evnt.target) ? evnt.target : evnt.srcElement; // Get the activated slider element.
		sliderObj.pxLen = this.slider.length // The allowed slider movement in pixels.
		sliderObj.valCount = this.slider.count ? this.slider.count - 1 : this.slider.length // Allowed number of values in the interval.
		displayObj = this.slider.carpeGetElementById("value_display_" + this.layer.name);
		displayObj.dec = this.slider.decimals // Number of decimals to be displayed.
		sliderObj.scale = (this.slider.to - this.slider.from) / this.slider.length // Slider-display scale [value-change per pixel of movement].
		
		// Set limits for horizontal sliders.
		sliderObj.fromVal = this.slider.from;
		xMax = this.slider.length;

		pxLeft = this.slider.carpeLeft(sliderObj.id); // Sliders horizontal position at start of slide.
		pxTop  = this.slider.carpeTop(sliderObj.id); // Sliders vertical position at start of slide.
		xCoord = evnt.screenX; // Horizontal mouse position at start of slide.
		yCoord = evnt.screenY; // Vertical mouse position at start of slide.

		this.slider.mouseover = true;
		
		var context = {
        	'slider': this.slider,
        	'layer': this.layer,
        	 'xMax': xMax,
        	 'pxLeft': pxLeft,
        	 'pxTop': pxTop,
        	 'sliderObj': sliderObj,
        	 'displayObj':displayObj,
        	 'xCoord': xCoord,
        	 'yCoord': yCoord,
        	 'event1': null,
        	 'event2': null,
        	 'event3': null,
        	 'outerDiv': this.outerDiv,
        	 'trackElement': this.trackElement
		};
		var event1 = OpenLayers.Function.bindAsEventListener(this.slider.moveSlider, context);
		var event2 = OpenLayers.Function.bindAsEventListener(this.slider.sliderMouseUp, context);
		var event3 = OpenLayers.Function.bindAsEventListener(this.slider.sliderMouseOut, context);
				
		context.event1 = event1;
		context.event2 = event2;
		context.event3 = event3;
		
		OpenLayers.Event.observe(this.trackElement, "mousemove", event1);
		OpenLayers.Event.observe(this.trackElement, "mouseup", event2);
		OpenLayers.Event.observe(this.outerDiv, "mouseout", event3 );
	},
	
	sliderMouseOut:function(event){
		//get event target
		if (!event) event = window.event;
		var targetObj = (event.target) ? event.target : event.srcElement; // Get the activated slider element.
		//if still within the slider then we want to skip the event
		if (targetObj == this.trackElement) return;
		for(i = 0; i < this.trackElement.childNodes.length; i++){
			if (this.trackElement.childNodes[i] == targetObj){
				return;
			}
		}
		//otherwise fire the event
		var event2 = OpenLayers.Function.bindAsEventListener(this.slider.sliderMouseUp, this);
		event2();
	},
		
	// sliderMouseup: Handles the mouseup event after moving a slider.
	// Snaps the slider position to allowed/displayed value. 
	sliderMouseUp: function(evnt)
	{
		this.slider.mouseover = false // Stop the sliding.
		v = (this.displayObj.value) ? this.displayObj.value : 0 // Find last display value.
		pos = (v - this.sliderObj.fromVal)/(this.sliderObj.scale) // Calculate slider position (regardless of orientation).
		if (this.yMax == 0) this.slider.carpeLeft(this.sliderObj.id, pos) // Snap horizontal slider to corresponding display position.
		OpenLayers.Event.stopObserving(this.trackElement, "mousemove", this.event1);
		OpenLayers.Event.stopObserving(this.trackElement, "mouseup", this.event2);
		OpenLayers.Event.stopObserving(this.outerDiv, "mouseout", this.event3);
	},
    CLASS_NAME: "OpenLayers.Control.HaBCLayerSwitcher"
});
