        //KML objects v1.1 Updated: 20081223 by Isaac Yong
        /*
            myObj.addLayer=addLayer;
            myObj.addLayers=addLayers;
            myObj.enableLayer=enableLayer;
            myObj.enableLayers=enableLayers;
            myObj.refresh=refresh;
            myObj.refreshAll=refreshAll;
            myObj.getLayer=getLayer;
            myObj.disableLayer=disableLayer;
            myObj.disableLayers=disableLayers;
            myObj.getCtrl=getCtrl;
            myObj.createTopMostLayer=createTopMostLayer;
            myObj.setTopMostLayer=setTopMostLayer;
            myObj.removeLayer=removeLayer;
            myObj.containsLayerKey=containsLayerKey;
            myObj.popupIndicator=popupIndicator;
                    
        sample code:
            objMyKMLs = new objKMLs();
            objMyKMLs.addLayer("seleter_route", "kml/test_bus_route_morning.kml", true, true);
            objMyKMLs.enableLayer("seleter_route");        
        */        
        
        function objKMLs(){
            var myObj=new Object();
            var htbKMLLayers = new Hashtable();
            var htbKMLActLayers = new Hashtable();
            var htbKMLCtrls = new Hashtable();
            var topMostLayer;
            //added by Isaac @ 20081223: init moveEnd() & removePopup() will help to keep track of this status.
            var popupIndicator;//indicator to identify popup status.

            //object for storing raw KML data/setting
            function objKML(strId, strURL, boolRefresh, boolBalloon){
                  var myObj=new Object();
                  myObj.id    = strId;
                  myObj.url   = strURL;              
                  myObj.refresh = boolRefresh;              
                  myObj.balloon  = boolBalloon;
                  return myObj;
            }
            //end of object for storing raw KML data/setting

            //function addLayer()
            function addLayer(strId, strURL, boolRefresh, boolBalloon){
                htbKMLLayers.put(strId,new objKML(strId, strURL, boolRefresh,boolBalloon));
            }
            
            function addLayers(arrInput){
                for(var i = 0; i<arrInput.length;i++){
                    htbKMLLayers.put(arrInput[i][0],objKML(arrInput[i][0], arrInput[i][1], arrInput[i][2], arrInput[i][3]));                    
                }    
            }
            
            function enableLayer(strId){
                var rtnLayer;
                if(!htbKMLActLayers.containsKey(strId)){
                    var objKML = htbKMLLayers.get(strId);
                    var rtnLayer = new OpenLayers.Layer.GML(objKML.id, objKML.url, 
                       {
                        format: OpenLayers.Format.KML, 
                        formatOptions: {
                          extractStyles: true, 
                          extractAttributes: true
                        }
                       });
                    
                    map.addLayer(rtnLayer);
                       
                    htbKMLActLayers.put(strId, rtnLayer);
                    
                    if(objKML.balloon){
                        //alert("testing");
                        rtnLayer.preFeatureInsert=function (feature){
                            feature.style.cursor='pointer';
                            if ((feature.attributes.styleUrl) == "#PnRIcon"){
                                feature.style.graphicHeight = 20;
                                feature.style.graphicWidth = 60;
                            }
                    }
                        htbKMLCtrls.put(strId, addSelectControl(rtnLayer));
                    }else {
                        rtnLayer.preFeatureInsert=function (feature){
                            if ((feature.attributes.styleUrl) == "#taxiIcon"){
                                feature.style.graphicHeight = 25;
                                feature.style.graphicWidth = 25;
                            }
                        }
                    }
                    
                    //rtnLayer = kmlLayer;
                    if(topMostLayer != null)
                        setTopMostLayer();
                        //map.setLayerIndex(rtnLayer);
                } else{
                    rtnLayer = htbKMLActLayers.get(strId);
                    rtnLayer.setVisibility(true);                    
                    }
                    
                return rtnLayer;
            }
            
            function addSelectControl(vectorLayer){
                var selectControl = new OpenLayers.Control.SelectFeature(vectorLayer,
                            {onSelect: onFeatureSelect, onUnselect: onFeatureUnselect});
                map.addControl(selectControl);
                selectControl.activate();
                
                return selectControl;
            }
            
            function enableLayers(arrId){
                var kmlLayers = new Array();
                for(var i = 0; i<arrId.length;i++){
                    var kmlLayer = enableLayer(arrId[i]);
                    kmlLayers[i] = kmlLayer; 
                }
                
                return kmlLayers;
            }
            
            function disableLayer(strId){
                if(htbKMLActLayers.containsKey(strId)){
                    (htbKMLActLayers.get(strId)).setVisibility(false);
                }
            }
            
            function disableLayers(arrId){
                for(var i = 0; i<arrId.length;i++){
                    disableLayer(arrId[i]);
                }
            }
            
            function refresh(strId){
                var objKML = htbKMLLayers.get(strId);
                (htbKMLActLayers.get(strId)).setUrl(objKML.url);                                
            }
            
            function refreshAll(){
                var arrActKeys = htbKMLActLayers.keys();
                for(var i = 0; i<arrActKeys.length;i++){
                    var objKML = htbKMLLayers.get(arrActKeys[i]);
                    if(objKML.refresh)
                        refresh(arrActKeys[i]);
                }
            }

            function getLayer(strId){
                return htbKMLActLayers.get(strId);
            }
            
            function getCtrl(strId){
                return htbKMLCtrls.get(strId);
            }
            
            function createTopMostLayer(strId){
                htbKMLLayers.put(strId,new objKML(strId, "", false,true));
                topMostLayer = new OpenLayers.Layer.Vector(strId);
                topMostLayer.preFeatureInsert = myStyle;
                
                function myStyle(feature){
                    //feature.style = OpenLayers.Util.extend({'cursor':'pointer'}, feature.style);
                    feature.style.cursor = 'pointer';
                    if ((feature.attributes.styleUrl) == "#cameraIcon"){
                        feature.style.graphicHeight = 14;
                        feature.style.graphicWidth = 15;
                    }else if ((feature.attributes.styleUrl) == "#pgsIcon"){
                        feature.style.graphicHeight = 15;
                        feature.style.graphicWidth = 14;
                    } 
                    else if ((feature.attributes.styleUrl) == "#erpIcon"){
                        feature.style.graphicHeight = 15;
                        feature.style.graphicWidth = 26;
                    } else if ((feature.attributes.styleUrl) == "#trafficRoadAccIcon"){
                        feature.style.graphicHeight = 17;
                        feature.style.graphicWidth = 16;
                    } else if ((feature.attributes.styleUrl) == "#trafficRoadWorkIcon"){
                        feature.style.graphicHeight = 17;
                        feature.style.graphicWidth = 16;                    
                    } else if ((feature.attributes.styleUrl) == "#trafficSlowIcon"){
                        feature.style.graphicHeight = 9;
                        feature.style.graphicWidth = 10;                    
                    } else if ((feature.attributes.styleUrl) == "#trafficBreakDownIcon"){
                        feature.style.graphicHeight = 14;
                        feature.style.graphicWidth = 17;                    
                    } else if ((feature.attributes.styleUrl) == "#trafficSignalDownIcon"){
                        feature.style.graphicHeight = 13;
                        feature.style.graphicWidth = 8;                    
                    } else if ((feature.attributes.styleUrl) == "#trafficOtherIcon"){
                        feature.style.graphicHeight = 13;
                        feature.style.graphicWidth = 14;
                    } else if((feature.attributes.styleUrl).indexOf("mrt") != -1 || (feature.attributes.styleUrl).indexOf("lrt") != -1){
                        feature.style.graphicHeight = 30;
                        feature.style.graphicWidth = 130;
                    } else if ((feature.attributes.styleUrl) == "#busStopIcon"){
                        feature.style.graphicHeight = 25;
                        feature.style.graphicWidth = 25;                    
                    } else if ((feature.attributes.styleUrl) == "#busStopMixIcon"){
                        feature.style.graphicHeight = 25;
                        feature.style.graphicWidth = 25;
                    } else if ((feature.attributes.styleUrl) == "#busStopPremiumIcon"){
                        feature.style.cursor = '';
                        feature.style.graphicHeight = 5;
                        feature.style.graphicWidth = 5;
                    } else if ((feature.attributes.styleUrl) == "#PnRIcon"){
                        feature.style.graphicHeight = 20;
                        feature.style.graphicWidth = 60;
                    } else if ((feature.attributes.styleUrl) == "#busStopMixWArrivalIcon"){
                        feature.style.graphicHeight = 31;
                        feature.style.graphicWidth = 31;
                    } else if ((feature.attributes.styleUrl) == "#busStopWArrivalIcon"){
                        feature.style.graphicHeight = 31;
                        feature.style.graphicWidth = 31;
                    }
                }
                map.addLayer(topMostLayer);
                htbKMLCtrls.put(strId, addSelectControl(topMostLayer));
                htbKMLActLayers.put(strId,topMostLayer);
                setTopMostLayer();
                return topMostLayer;
            }
            
            function setTopMostLayer(objLayer){
                var rtn;
                var topIndex = map.getNumLayers()-1;                
                if(objLayer == null || objLayer == ""){                
                    rtn = map.setLayerIndex(topMostLayer,topIndex);                    
                    }
                else
                    rtn = map.setLayerIndex(objLayer,topIndex);
                return rtn;
            }
            
            function removeLayer(strId){
                if(htbKMLActLayers.containsKey(strId)){
                    (htbKMLActLayers.get(strId)).destroy();
                    map.removeLayer(htbKMLActLayers.get(strId),false);
                    htbKMLActLayers.remove(strId);
                }
            }
            
            function containsLayerKey(strId){
                return htbKMLLayers.containsKey(strId);
            }
            
            //general functions for balloon popups features
    	      function onPopupClose(evt) {
               	if (myObj.popupIndicator == 2)
               		map.panTo(popup.lonlat);
                var arrActKeys = htbKMLActLayers.keys();
                for(var i = 0; i<arrActKeys.length;i++){
                    var objKML = htbKMLLayers.get(arrActKeys[i]);
                    if(objKML.balloon)
                        (getCtrl(arrActKeys[i])).unselectAll();
                        //(getCtrl(arrActKeys[i])).unselect(selectedFeature); 
                        //improvement needed to unselect particular selectedFeature;
                }
				popup.destroy();
               	popup = null;
            }
            
            function onFeatureSelect(feature) {
                myObj.popupIndicator = 1;
                if(feature.attributes.description!="" && feature.attributes.name!="" &&
                    typeof(feature.attributes.description)!="undefined" && typeof(feature.attributes.name)!="undefined"){
                    selectedFeature = feature;
                    //alert("IE 100 ori");
                    popup = new OpenLayers.Popup.FramedCloud("chicken", 
                                             feature.geometry.getBounds().getCenterLonLat(),
                                             new OpenLayers.Size(400,200),
                                             feature.attributes.name + feature.attributes.description,
                                             null, true, onPopupClose);                                
                } else {
                    popup = new OpenLayers.Popup.FramedCloud("chicken",
                                             feature.geometry.getBounds().getCenterLonLat(),
                                             new OpenLayers.Size(400,200),
                                             "<span id=\"myPopupName\">"+feature.attributes.name + "</span>"
                                             + "<span id=\"myPopupDesc\">" + feature.attributes.description + "</span>",
                                             null, true, onPopupClose);
                    popup.hide(true);
                }
                feature.popup = popup;
                map.addPopup(popup,true);
                //popup.groupDiv.innerHTML = popup.div.innerHTML.replace("class=\"olFramedCloudPopupContent\" style=\"overflow: hidden", "class=\"olFramedCloudPopupContent\" style=\"overflow-y: auto; overflow-x: hidden");
                //popup.groupDiv.style.cssText = popup.groupDiv.style.cssText.replace("overflow: hidden;", "overflow-x: hidden");
                //popup.groupDiv.style.overflowY = "auto";
            }
            
            function onFeatureUnselect(feature) {
               	if (myObj.popupIndicator == 2)
               		map.panTo(popup.lonlat);
                map.removePopup(feature.popup);
                feature.popup.destroy();
                feature.popup = null;
            }
            
            function getInternetExplorerVersion()
            // Returns the version of Internet Explorer or a -1
            // (indicating the use of another browser).
            {
              var rv = -1; // Return value assumes failure.
              if (navigator.appName == 'Microsoft Internet Explorer')
              {
                var ua = navigator.userAgent;
                var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
                if (re.exec(ua) != null)
                  rv = parseFloat( RegExp.$1 );
              }
              return rv;
            }
            //end of general functions for balloon popups features

            //-------------------------------------------//
            myObj.addLayer=addLayer;
            myObj.addLayers=addLayers;
            myObj.enableLayer=enableLayer;
            myObj.enableLayers=enableLayers;
            myObj.refresh=refresh;
            myObj.refreshAll=refreshAll;
            myObj.getLayer=getLayer;
            myObj.disableLayer=disableLayer;
            myObj.disableLayers=disableLayers;
            myObj.getCtrl=getCtrl;
            myObj.createTopMostLayer=createTopMostLayer;
            myObj.setTopMostLayer=setTopMostLayer;
            myObj.removeLayer=removeLayer;
            myObj.containsLayerKey=containsLayerKey;
            myObj.popupIndicator=popupIndicator;
            //myObj.objMyImg=objMyImg;
            
            return myObj;        
        }
        //End of KML objects by Isaac Yong
