/* FUNCTIONS FOR DRAWING GOOGLE MAPS WITH GPS VISUALIZER (http://www.gpsvisualizer.com/) */ // Define parameters of different marker types var gv_icons = { circle: { is:[15,15],ia:[7,7],ss:[15,15],iwa:[12,4],isa:[7,11],im:[5,2, 9,2, 12,5, 12,9, 9,12, 5,12, 2,9, 2,5],letters:true } ,pin: { is:[15,26],ia:[7,25],ss:[30,26],iwa:[7,1],isa:[12,16],im:[5,25, 5,15, 2,13, 1,12, 0,10, 0,5, 1,2, 2,1, 4,0, 10,0, 12,1, 13,2, 14,4, 14,10, 13,12, 12,13, 9,15, 9,25, 5,25 ],letters:true } ,square: { is:[15,15],ia:[7,7],ss:[15,15],iwa:[12,4],isa:[7,11],im:[3,3, 11,3, 11,11, 3,11, 3,3],letters:true } ,triangle: { is:[15,15],ia:[7,7],ss:[15,15],iwa:[12,4],isa:[7,11],im:[1,12, 7,1, 13,12, 1,12],letters:false } ,diamond: { is:[15,15],ia:[7,7],ss:[15,15],iwa:[12,4],isa:[7,11],im:[7,1, 13,7, 7,13, 1,7, 7,1],letters:false } ,google: { is:[20,34],ia:[9,34],ss:[37,34],iwa:[9,2],isa:[18,25],letters:true } ,googleblank: { is:[20,34],ia:[9,34],ss:[37,34],iwa:[9,2],isa:[18,25],letters:true } ,googlemini: { is:[12,20],ia:[6,20],ss:[22,20],iwa:[5,1],isa:[10,15],letters:true } } // Make sure defaults have been set; if not, things break. if (!self.gv_marker_icon || !gv_icons[gv_marker_icon]) { gv_marker_icon = (self.default_icon_style) ? default_icon_style : 'pin'; } if (!self.gv_marker_color) { gv_marker_color = (self.default_icon_color) ? default_icon_color : 'red'; } if (!self.gv_api_version) { gv_api_version = (self.google_api_version) ? google_api_version : 0; } if (!self.gv_marker_link_target) { gv_marker_link_target = (self.marker_link_target) ? marker_link_target : '_blank'; } if (!self.gv_maptypecontrol_style) { gv_maptypecontrol_style = (self.maptypecontrol_style) ? maptypecontrol_style : 'menu'; } if (self.gv_filter_map_types==null) { gv_filter_map_types = (self.filter_map_types!=null) ? filter_map_types : 1; } // Create a default icon for all markers var defaultIcon = new GIcon(); defaultIcon.image = 'http://www.gpsvisualizer.com/misc/google_maps/icons/'+gv_marker_icon+'/'+gv_marker_color+'.png'; defaultIcon.transparent = 'http://www.gpsvisualizer.com/misc/google_maps/icons/'+gv_marker_icon+'/'+gv_marker_color+'-t.png'; defaultIcon.shadow = 'http://www.gpsvisualizer.com/misc/google_maps/icons/'+gv_marker_icon+'/shadow.png'; defaultIcon.iconSize = new GSize(gv_icons[gv_marker_icon]['is'][0],gv_icons[gv_marker_icon]['is'][1]); defaultIcon.iconAnchor = new GPoint(gv_icons[gv_marker_icon]['ia'][0],gv_icons[gv_marker_icon]['ia'][1]); defaultIcon.shadowSize = new GSize(gv_icons[gv_marker_icon]['ss'][0],gv_icons[gv_marker_icon]['ss'][1]); defaultIcon.infoWindowAnchor = new GPoint(gv_icons[gv_marker_icon]['iwa'][0],gv_icons[gv_marker_icon]['iwa'][1]); defaultIcon.infoShadowAnchor = new GPoint(gv_icons[gv_marker_icon]['isa'][0],gv_icons[gv_marker_icon]['isa'][1]); defaultIcon.imageMap = (gv_icons[gv_marker_icon]['im']) ? gv_icons[gv_marker_icon]['im'] : [ 0,0, 0,gv_icons[gv_marker_icon]['is'][1]-1, gv_icons[gv_marker_icon]['is'][0]-1,gv_icons[gv_marker_icon]['is'][1]-1, gv_icons[gv_marker_icon]['is'][0]-1,0, 0,0 ]; // Set up some styles document.writeln(' '); document.writeln(' '); function GV_Marker(map,marker_info,lon,name,desc,url,color,style,width,label_id) { // The old "GV_Marker" function had everything in a particular order; this new one uses more user-friendly named parameters. // If the second argment has a 'lat' item INSIDE of it, then it's the new version; otherwise that's just the latitude. var m = {}; if (marker_info['lat']) { m = marker_info; if (m['style'] && !m['icon']) { m['icon'] = m['style']; } // this one changed recently } else { m['lat'] = marker_info; m['lon'] = lon; m['name'] = name; m['desc'] = desc; m['url'] = url; m['color'] = color; m['icon'] = style; m['width'] = width; m['label_id'] = label_id; } var tempIcon = new GIcon(defaultIcon); if (m['icon'] || m['color'] || m['letter']) { var icon = (m['icon'] && gv_icons[m['icon']]) ? m['icon'] : gv_marker_icon; var color = (m['color']) ? m['color'] : gv_marker_color; var transparent_icon = color+'-t.png'; tempIcon.image = 'http://www.gpsvisualizer.com/misc/google_maps/icons/'+icon+'/'+color+'.png'; tempIcon.shadow = 'http://www.gpsvisualizer.com/misc/google_maps/icons/'+icon+'/shadow.png'; tempIcon.iconSize = new GSize(gv_icons[icon]['is'][0],gv_icons[icon]['is'][1]); tempIcon.iconAnchor = new GPoint(gv_icons[icon]['ia'][0],gv_icons[icon]['ia'][1]); tempIcon.shadowSize = new GSize(gv_icons[icon]['ss'][0],gv_icons[icon]['ss'][1]); tempIcon.infoWindowAnchor = new GPoint(gv_icons[icon]['iwa'][0],gv_icons[icon]['iwa'][1]); tempIcon.infoShadowAnchor = new GPoint(gv_icons[icon]['isa'][0],gv_icons[icon]['isa'][1]); tempIcon.imageMap = (gv_icons[icon]['im']) ? gv_icons[icon]['im'] : [ 0,0, 0,gv_icons[icon]['is'][1]-1, gv_icons[icon]['is'][0]-1,gv_icons[icon]['is'][1]-1, gv_icons[icon]['is'][0]-1,0, 0,0 ]; if (m['letter']) { // tempIcon.label = { url:'http://www.gpsvisualizer.com/misc/google_maps/icons/'+icon+'/transparent-'+m['letter'].toUpperCase()+'.png', anchor:new GPoint(0,0), size:new GSize(gv_icons[icon]['is'][0],gv_icons[icon]['is'][1]) }; // makes big gray boxes in IE! tempIcon.transparent = 'http://www.gpsvisualizer.com/misc/google_maps/icons/'+icon+'/transparent-'+m['letter'].toUpperCase()+'.png'; // not the most kosher solution, but it seems to work } else { tempIcon.transparent = 'http://www.gpsvisualizer.com/misc/google_maps/icons/'+icon+'/'+color+'-t.png'; } } var marker = (gv_api_version > 1) ? new GMarker( new GLatLng(m['lat'],m['lon']), tempIcon ): new GMarker( new GPoint(m['lon'],m['lat']), tempIcon ); var text = ''; if (m['name']) { if (m['url'] && m['url'] != null) { text = text + ''+m['name']+''; } else { text = text + ''+m['name']+''; } } if (m['desc']) { text = text + '
'+m['desc']+''; } var max_width = (gv_api_version > 1) ? map.getSize().width - 100 : 600; var width = (eval(m['width']) > 200 && eval(m['width']) <= max_width) ? 'width:'+m['width']+'px;' : ''; // apparently you can't make it less than 217 (let's leave 17 for the close box though) if (text) { GEvent.addListener(marker, "click", function(){ marker.openInfoWindowHtml('
'+text+'
', {maxWidth:max_width}); }); } map.addOverlay(marker); if (m['name']) { if (m['label_id']) { // draw a permanent label var label = new ELabel(new GLatLng(m['lat'],m['lon']),m['name'],"gv_label",new GSize(6,8),100,false,m['label_id']); map.addOverlay(label); } else { // do tooltips instead if (eval(gv_api_version) > 1) { // v2 tooltips, adapted from http://www.econym.demon.co.uk/googlemaps/tooltips4.htm if (!document.getElementById('gv_tooltip')) { tooltip = GV_Initialize_Marker_Tooltip(map); } // initialize it if it hasn't been done yet marker.tooltip = '
'+m['name']+'
'; GEvent.addListener(marker,'mouseover', function() { GV_Create_Marker_Tooltip(map,marker); }); GEvent.addListener(marker,'mouseout', function() { tooltip.style.visibility = 'hidden' }); } else { // v1 tooltips, adapted from http://www.econym.demon.co.uk/googlemaps1/tooltips.htm var topElement = marker.images[0]; if (marker.iconImage) { topElement = marker.iconImage; } if (marker.transparentIcon) { topElement = marker.transparentIcon; } if (marker.imageMap) { topElement = marker.imageMap; } topElement.setAttribute("title",m['name']); } } } return marker; } function GV_Initialize_Marker_Tooltip(map) { var tt = document.createElement('div'); map.getPane(G_MAP_FLOAT_PANE).appendChild(tt); tt.id = 'gv_tooltip'; tt.style.visibility = 'hidden'; return (tt); } function GV_Create_Marker_Tooltip(map,marker) { // copied almost verbatim from http://www.econym.demon.co.uk/googlemaps/tooltips4.htm tooltip.innerHTML = marker.tooltip; var point=map.getCurrentMapType().getProjection().fromLatLngToPixel(map.fromDivPixelToLatLng(new GPoint(0,0),true),map.getZoom()); var offset=map.getCurrentMapType().getProjection().fromLatLngToPixel(marker.getPoint(),map.getZoom()); var anchor=marker.getIcon().iconAnchor; var width=marker.getIcon().iconSize.width; var height=tooltip.clientHeight; var pos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(offset.x - point.x - anchor.x + width, offset.y - point.y -anchor.y -height)); pos.apply(tooltip); tooltip.style.visibility = 'visible'; } function GV_Toggle_Track_And_Label(map,id,color) { if (!color) { // older versions of this function only had two parameters color = id; id = map; map = gmap; } GV_Toggle_Opacity(map,eval(id)); // this one ("trkX") is stored in a variable GV_Toggle_Label_Opacity(document.getElementById(id+'_label'),color); // this one ("trkX_label") is a page element } function GV_Toggle_Opacity(map,overlay_array) { if (gv_api_version > 1) { var msg = ''; for (j=0; j -1 || xtext.indexOf('object SVGSVGElement') > -1) { msg = msg + x + " (" + xtype + ") = " + eval('item.'+x) + "; "; } // } if (eval(item.H) || eval(item.L)) { // first is markers, the second is polylines map.removeOverlay(item); } else { map.addOverlay(item); } // if (msg) { msg + "\n"; } } if (msg) { alert(msg); } } else { for (j=0; j 1) { var USGS_TOPO_TILES = WMSCreateMap('Topo','Topo maps by USGS via terraserver-usa.com','Topo maps unavailable',7,17,400,'http://terraservice.net/ogcmap6.ashx?version=1.1.1&request=GetMap&styles=&srs=EPSG:4326&format=image/jpeg&bgcolor=0xCCCCCC&exceptions=INIMAGE&layers=DRG'); var USGS_AERIAL_TILES = WMSCreateMap('Aerial','Imagery by USGS via terraserver-usa.com','USGS aerial imagery unavailable',7,18,400,'http://terraservice.net/ogcmap6.ashx?version=1.1.1&request=GetMap&styles=&srs=EPSG:4326&format=image/jpeg&bgcolor=0xCCCCCC&exceptions=INIMAGE&layers=DOQ'); var NRCAN_TOPO_TILES = WMSCreateMap('NRCan topo','Maps by NRCan.gc.ca','NRCan maps unavailable',8,18,600,'http://wms.cits.rncan.gc.ca/cgi-bin/cubeserv.cgi?version=1.1.3&request=GetMap&format=image/png&bgcolor=0xFFFFFF&exceptions=application/vnd.ogc.se_inimage&srs=EPSG:4326&layers=PUB_50K:CARTES_MATRICIELLES/RASTER_MAPS'); var BLUEMARBLE_TILES = WMSCreateMap('Blue Marble','Map by NASA','OnEarth server unavailable',3,8,128,'http://onearth.jpl.nasa.gov/wms.cgi?request=GetMap&styles=&srs=EPSG:4326&format=image/jpeg&layers=modis'); } function GV_Add_Custom_Layers(map) { map.addMapType(USGS_TOPO_TILES); map.addMapType(USGS_AERIAL_TILES); map.addMapType(NRCAN_TOPO_TILES); map.addMapType(BLUEMARBLE_TILES); } function WMSCreateMap(name,copyright,errorMessage,minResolution,maxResolution,tileSize,baseUrl) { var tileLayer = new GTileLayer(new GCopyrightCollection(copyright),minResolution,maxResolution); tileLayer.baseUrl = baseUrl; tileLayer.tileSize = tileSize; tileLayer.getTileUrl = WMSGetTileUrl; tileLayer.getCopyright = function() { return { prefix:'',copyrightTexts:[copyright]}; }; var tileLayers = [tileLayer]; return new GMapType(tileLayers,G_SATELLITE_MAP.getProjection(),name,{errorMessage:errorMessage,tileSize:tileSize}); } function WMSGetTileUrl(tile,zoom) { var southWestPixel = new GPoint(tile.x*this.tileSize,(tile.y+1)*this.tileSize); var northEastPixel = new GPoint((tile.x+1)*this.tileSize,tile.y*this.tileSize); var southWestCoords = G_SATELLITE_MAP.getProjection().fromPixelToLatLng(southWestPixel,zoom); var northEastCoords = G_SATELLITE_MAP.getProjection().fromPixelToLatLng(northEastPixel,zoom); var bbox = southWestCoords.lng()+','+southWestCoords.lat()+','+northEastCoords.lng()+','+northEastCoords.lat(); return this.baseUrl+'&bbox='+bbox+'&width='+this.tileSize+'&height='+this.tileSize; } /************************************************** * Custom map-type control: * more or less from Google's own documentation **************************************************/ function GV_MapTypeControl() {} if (gv_api_version > 1) { GV_MapTypeControl.prototype = new GControl(); GV_MapTypeControl.prototype.initialize = function(map) { GV_Add_Custom_Layers(map); var map_types = [ { label:'G. map',type:'G_NORMAL_MAP',title:'Google street map',bounds:[-180,-90,180,90] } ,{ label:'G. satellite',type:'G_SATELLITE_MAP',title:'Google satellite map',bounds:[-180,-90,180,90] } ,{ label:'G. hybrid',type:'G_HYBRID_MAP',title:'Google "hybrid" map',bounds:[-180,-90,180,90] } ,{ label:'USGS topo',type:'USGS_TOPO_TILES',title:'USGS topographic map',bounds:[-169,18,-66,72] } ,{ label:'USGS aerial',type:'USGS_AERIAL_TILES',title:'USGS aerial photos (black/white)',bounds:[-152,17,-65,65] } ,{ label:'Canada topo',type:'NRCAN_TOPO_TILES',title:'NRCan/Toporama maps with contour lines',bounds:[-141,41.7,-52,85] } ,{ label:'Blue Marble',type:'BLUEMARBLE_TILES',title:'NASA "Visible Earth" image',bounds:[-180,-90,180,90] } ]; var center_lat = map.getCenter().lat(); var center_lng = map.getCenter().lng(); if (gv_maptypecontrol_style == 'menu') { var map_selector = document.createElement("select"); map_selector.id = 'map_selector'; map_selector.style.font = '10px Verdana'; map_selector.style.backgroundColor = '#FFFFFF'; for (j=0; j= map_types[j]['bounds'][0] && center_lat >= map_types[j]['bounds'][1] && center_lng <= map_types[j]['bounds'][2] && center_lat <= map_types[j]['bounds'][3])) { var opt = document.createElement("option"); opt.value = map_types[j]['type']; opt.appendChild(document.createTextNode(map_types[j]['label'])); map_selector.appendChild(opt); if (map.getCurrentMapType() == eval(opt.value)) { map_selector.selectedIndex = j; } } } GEvent.addDomListener(map_selector, "change", function(){map.setMapType(eval(this.value));} ); map.getContainer().appendChild(map_selector); return map_selector; } else { var map_type_container = document.createElement("div"); for (j=0; j= map_types[j]['bounds'][0] && center_lat >= map_types[j]['bounds'][1] && center_lng <= map_types[j]['bounds'][2] && center_lat <= map_types[j]['bounds'][3])) { var maplink = document.createElement("div"); maplink.style.backgroundColor = '#FFFFFF'; maplink.style.padding = '1px 2px 1px 2px'; maplink.style.marginBottom = '3px'; maplink.style.color = '#000000'; maplink.style.font = '9px Verdana'; maplink.style.textDecoration = 'none'; maplink.style.border = '1px solid'; maplink.style.borderColor = '#999999 #333333 #333333 #999999'; maplink.style.textAlign = 'center'; maplink.style.cursor = 'pointer'; maplink.title = map_types[j]['title']; maplink.type = map_types[j]['type']; map_type_container.appendChild(maplink); maplink.appendChild(document.createTextNode(map_types[j]['label'])); GEvent.addDomListener(maplink, "click", function(){map.setMapType(eval(this.type));} ); } } map.getContainer().appendChild(map_type_container); return map_type_container; } } GV_MapTypeControl.prototype.getDefaultPosition = function() { return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7,7)); } } // These are here only for backwards compatibilty: function GPSV_Waypoint(lon,lat,name,desc,url,color,style,width,label_id) { GV_Marker(gmap,lat,lon,name,desc,url,color,style,width,label_id); } function GPSV_Toggle_Track_And_Label(id,color) { GV_Toggle_Track_And_Label(id,color); } // for backwards compatibility function GPSV_Toggle_Opacity(overlay_array) { GV_Toggle_Opacity(overlay_array); } // for backwards compatibility function GPSV_Toggle_Label_Opacity(label,original_color) { GV_Toggle_Label_Opacity(label,original_color); } // for backwards compatibility function GPSV_MapTypeControl() {} if (gv_api_version > 1) { GPSV_MapTypeControl.prototype = GV_MapTypeControl.prototype; } /************************************************** elabel.js (adapted from http://www.econym.demon.co.uk/googlemaps/elabel.htm) (My modification: adding the "label_id" parameter) **************************************************/ function ELabel(point, html, classname, pixelOffset, percentOpacity, overlap, label_id) { // Mandatory parameters this.point = point; this.html = html; // Optional parameters this.classname = classname || ""; this.pixelOffset = pixelOffset || new GSize(0,0); if (percentOpacity) { if (percentOpacity < 0) { percentOpacity = 0; } if (percentOpacity > 100) { percentOpacity = 100; } } this.percentOpacity = percentOpacity; this.overlap = overlap || false; this.label_id = label_id; } if (gv_api_version > 1) { ELabel.prototype = new GOverlay(); ELabel.prototype.initialize = function (map) { var div = document.createElement("div"); div.style.position = "absolute"; div.innerHTML = '
' + this.html + '
' ; map.getPane(G_MAP_FLOAT_SHADOW_PANE).appendChild(div); this.map_ = map; this.div_ = div; if (this.percentOpacity) { if (typeof(div.style.filter) == 'string') { div.style.filter='alpha(opacity:'+this.percentOpacity+')'; } if (typeof(div.style.KHTMLOpacity) == 'string') { div.style.KHTMLOpacity=this.percentOpacity/100; } if (typeof(div.style.MozOpacity) == 'string') { div.style.MozOpacity=this.percentOpacity/100; } if (typeof(div.style.opacity) == 'string') { div.style.opacity=this.percentOpacity/100; } } if (this.overlap) { var z = GOverlay.getZIndex(this.point.lat()); this.div_.style.zIndex = z; } } ELabel.prototype.remove = function() { this.div_.parentNode.removeChild(this.div_); } ELabel.prototype.copy = function() { return new ELabel(this.point, this.html, this.classname, this.pixelOffset, this.percentOpacity, this.overlap); } ELabel.prototype.redraw = function(force) { var p = this.map_.fromLatLngToDivPixel(this.point); var h = parseInt(this.div_.clientHeight); this.div_.style.left = (p.x + this.pixelOffset.width) + "px"; this.div_.style.top = (p.y +this.pixelOffset.height - h) + "px"; } ELabel.prototype.show = function() { this.div_.style.display=""; } ELabel.prototype.hide = function() { this.div_.style.display="none"; } ELabel.prototype.setContents = function(html) { this.html = html; this.div_.innerHTML = '
' + this.html + '
' ; this.redraw(true); } ELabel.prototype.setPoint = function(point) { this.point = point; if (this.overlap) { var z = GOverlay.getZIndex(this.point.lat()); this.div_.style.zIndex = z; } this.redraw(true); } ELabel.prototype.setOpacity = function(percentOpacity) { if (percentOpacity) { if (percentOpacity < 0) { percentOpacity=0; } if (percentOpacity > 100) { percentOpacity=100; } } this.percentOpacity = percentOpacity; if (this.percentOpacity) { if (typeof(this.div_.style.filter) == 'string') { this.div_.style.filter='alpha(opacity:'+this.percentOpacity+')'; } if (typeof(this.div_.style.KHTMLOpacity) == 'string') { this.div_.style.KHTMLOpacity=this.percentOpacity/100; } if (typeof(this.div_.style.MozOpacity) == 'string') { this.div_.style.MozOpacity=this.percentOpacity/100; } if (typeof(this.div_.style.opacity) == 'string') { this.div_.style.opacity=this.percentOpacity/100; } } } } /************************************************** * dom-drag.js * 09.25.2001 * www.youngpup.net * Script featured on Dynamic Drive (http://www.dynamicdrive.com) 12.08.2005 ************************************************** * 10.28.2001 - fixed minor bug where events * sometimes fired off the handle, not the root. **************************************************/ var Drag = { obj : null, init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper) { o.onmousedown = Drag.start; o.hmode = bSwapHorzRef ? false : true ; o.vmode = bSwapVertRef ? false : true ; o.root = oRoot && oRoot != null ? oRoot : o ; if (o.hmode && isNaN(parseInt(o.root.style.left ))) o.root.style.left = "0px"; if (o.vmode && isNaN(parseInt(o.root.style.top ))) o.root.style.top = "0px"; if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right = "0px"; if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px"; o.minX = typeof minX != 'undefined' ? minX : null; o.minY = typeof minY != 'undefined' ? minY : null; o.maxX = typeof maxX != 'undefined' ? maxX : null; o.maxY = typeof maxY != 'undefined' ? maxY : null; o.xMapper = fXMapper ? fXMapper : null; o.yMapper = fYMapper ? fYMapper : null; o.root.onDragStart = new Function(); o.root.onDragEnd = new Function(); o.root.onDrag = new Function(); }, start : function(e) { var o = Drag.obj = this; e = Drag.fixE(e); var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom); var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right ); o.root.onDragStart(x, y); o.lastMouseX = e.clientX; o.lastMouseY = e.clientY; if (o.hmode) { if (o.minX != null) o.minMouseX = e.clientX - x + o.minX; if (o.maxX != null) o.maxMouseX = o.minMouseX + o.maxX - o.minX; } else { if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x; if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x; } if (o.vmode) { if (o.minY != null) o.minMouseY = e.clientY - y + o.minY; if (o.maxY != null) o.maxMouseY = o.minMouseY + o.maxY - o.minY; } else { if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y; if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y; } document.onmousemove = Drag.drag; document.onmouseup = Drag.end; return false; }, drag : function(e) { e = Drag.fixE(e); var o = Drag.obj; var ey = e.clientY; var ex = e.clientX; var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom); var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right ); var nx, ny; if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX); if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX); if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY); if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY); nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1)); ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1)); if (o.xMapper) nx = o.xMapper(y) else if (o.yMapper) ny = o.yMapper(x) Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px"; Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px"; Drag.obj.lastMouseX = ex; Drag.obj.lastMouseY = ey; Drag.obj.root.onDrag(nx, ny); return false; }, end : function() { document.onmousemove = null; document.onmouseup = null; Drag.obj.root.onDragEnd( parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]), parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"])); Drag.obj = null; }, fixE : function(e) { if (typeof e == 'undefined') e = window.event; if (typeof e.layerX == 'undefined') e.layerX = e.offsetX; if (typeof e.layerY == 'undefined') e.layerY = e.offsetY; return e; } };