// MapController class // Scrollable, switchable (in amount of detail) map // Uses functions from shared.js // Requires html page with two imgs for each level of detail; one of which is style="display:none" at start // Requires mainFrame is scrollable (for Netscape/Mozilla to work // MapController class function MapController (frameObject, dragMultiplier) { this.objectClass = "MapController"; // used as name for cookie this.DRAG_THRESHOLD = 4; // minimum distance before a drag can not be treated as a click; in pixels this.DRAG_MAX_FIRST_STEP = 10; // largest distance permitted within single mousemove; used to detect invalid drag on IE this.frameObject = frameObject; // scrollable frame containing mapImages this.mapImages = []; // array storing each mapImage (2 images) this.activeMapImage = 1; // index of active/visible image; default to first map image this.dragMultiplier = dragMultiplier ? dragMultiplier : 1; // 1 = default; 2 = 2x speed dragging; can be any number //this.temp = 0; //this.systemInfo = new SystemInfo(); } MapController.prototype.init = function(initialMap) { // setup dragScrolling this.dragScrolling = false; // indicates that user is dragging image around this.wasDraggedEnoughToNotBeAClick = false; this.mouseJustPressed = false; this.mouseDownX, this.mouseDownY = null; this.oldScrollX, this.oldScrollY = null; // Note: Changed following from document.onmousedown; fixes dragging on scroll bar triggering onmousedown in Mozilla/NS var mapContentElement = this.frameObject.document.getElementById("mapContent"); if (!mapContentElement) mapContentElement = this.frameObject.document; mapContentElement.onmousedown = this.onMouseDown; //this.frameObject.document.onmousedown = this.onMouseDown; this.frameObject.document.onmousemove = this.onMouseMove; this.frameObject.document.onmouseup = this.onMouseUp; this.frameObject.document.onclick = this.onClick; this.frameObject.document.onscroll = this.onScroll; // var cookieValue = this.getCookieValue(); //window.status = cookieValue; if (cookieValue==false) { // there was no saved state, so the map is presumably loading for the first time this.selectMapImage(initialMap); // select active map } else { // the state is saved; use the cookieValue to figure out the state this.initFromCookieValue(cookieValue); } //trace(this.systemInfo); } // Note: In following, e = event object passed in automatically MapController.prototype.onMouseDown = function(e) { // Note: Ends up running in context of the frame, so this = frameObject, not mapController // Get a reference mapController object to be able to use it here. var mc = parent.topFrame.mapController; // HACK: Must be more elegant way to get reference. if (!e) var e = mc.frameObject.event; if (wasLeftButton(e)) { // TODO: Double-check wasLeftButton code; now only works for IE? mc.mouseDownX = /* e.x ? e.x : */ e.screenX; mc.mouseDownY = /* e.y ? e.y : */ e.screenY; // Note: In Mozilla/NS, the mainFrame must be scrollable for the .scrollLeft and .scrollTop properties to be accessible mc.oldScrollX = mc.frameObject.document.body.scrollLeft; mc.oldScrollY = mc.frameObject.document.body.scrollTop; //window.status = "mc.frameObject.document.body.scrollTop:"+mc.frameObject.document.body.scrollLeft; mc.dragScrolling = true; mc.mouseJustPressed = true; mc.wasDraggedEnoughToNotBeAClick = false; //window.status = "mouseDown: " + " | " + mc.mouseDownX + "," + mc.mouseDownY+ " | " + mc.oldScrollX + "," + mc.oldScrollY; } return false; // stops browser behavior of dragging image to copy it to the desktop (at least on Mac Safari) } MapController.prototype.onMouseMove = function(e) { var mc = parent.topFrame.mapController; // HACK: Must be more elegant way to get reference. if (!e) var e = mc.frameObject.event; //window.status = "MouseMove:" + mapController.temp++; if (mc.dragScrolling) { if (!e) var e = mc.frameObject.event; var newMouseX = /* e.x ? e.x :*/ e.screenX; var newMouseY = /* e.y ? e.y : */ e.screenY; var newOffsetX = newMouseX - mc.mouseDownX; var newOffsetY = newMouseY - mc.mouseDownY; // Test if move from old to new position is unreasonably large, as in the case when // user drags scroll bar in IE -- then dragScrolling is true, but mouseUp is lost. // So, this code stops dragScrolling in that case. if (mc.mouseJustPressed) { if (Math.abs(newOffsetX) > mc.DRAG_MAX_FIRST_STEP | Math.abs(newOffsetY) > mc.DRAG_MAX_FIRST_STEP) { mc.dragScrolling = false; return false; } mc.mouseJustPressed = false; } //window.status = '(' + newOffsetX +',' + newOffsetY+')' if (Math.abs(newOffsetX) > mc.DRAG_THRESHOLD | Math.abs(newOffsetY) > mc.DRAG_THRESHOLD) mc.wasDraggedEnoughToNotBeAClick = true; var newScrollX = mc.oldScrollX - mc.dragMultiplier * newOffsetX; var newScrollY = mc.oldScrollY - mc.dragMultiplier * newOffsetY; mc.frameObject.scrollTo(newScrollX,newScrollY); //window.status = "dragging: " + " | " + newMouseX + "," + newMouseY+ " | " + newScrollX + "," + newScrollY; return false; } else { //window.status = "not dragging "+ mapController.temp++; } } MapController.prototype.onMouseUp = function(e) { //window.status = "up"; var mc = parent.topFrame.mapController; // HACK: Must be more elegant way to get reference. mc.dragScrolling = false; return false; // Doesn't seem to have any useful affect } MapController.prototype.onClick = function(e) { var mc = parent.topFrame.mapController; // HACK: Must be more elegant way to get reference. //window.status = "onclick"; if (mc.wasDraggedEnoughToNotBeAClick) { //window.status = "onclick return false"; return false; // cancels onClick event; if mouseUp was on hotshop, navigation can not happen } return true; } MapController.prototype.onScroll = function(e) { //window.status = "scroll"; // Opera: Triggered when mapContent dragged // Mozilla/NS: Triggered when scroll bar dragged (but not mapContent dragged) // IE: Never triggered //var mc = parent.topFrame.mapController; // HACK: Must be more elegant way to get reference. //mc.dragScrolling = false; //return false; // Doesn't seem to have any useful affect } MapController.prototype.addMapImage = function(imgId, centerX, centerY) { this.mapImages.push( new MapImage ( this.frameObject, imgId, centerX, centerY) ); } MapController.prototype.selectMapImage = function(newActiveMapImage) { // make mapImageToSelect active and make others inactive var lastImage = this.mapImages.length - 1; for (var i=0; i <= lastImage; i++ ) { this.mapImages[i].makeActive( i==newActiveMapImage ); } this.activeMapImage = newActiveMapImage; this.saveStateToCookie(); this.scrollToCenter(); } MapController.prototype.scrollToCenter = function() { // scrolls to the center of active map image var activeMapImage = this.mapImages[this.activeMapImage]; var frameObject = this.frameObject; //trace(activeMapImage); this.frameObject.scrollTo( activeMapImage.centerX - (getWindowWidth(frameObject)/2), activeMapImage.centerY - (getWindowHeight(frameObject)/2)); } MapController.prototype.saveStateToCookie = function() { // stores state of controller in cookie var cookieName = this.objectClass; var cookieValue = ""; // save which map is selected/active cookieValue += "active:" + this.activeMapImage; // TODO: save scroll position // save cookie; will be only accessible to this html page document.cookie = cookieName + "=" + cookieValue; } /* MapController.prototype.savedStateExists = function() { // returns true is saved state (cookie) exists } */ MapController.prototype.getCookieValue = function() { // checks saved state of controller from cookie; returns string of values or false if desired cookie does not exist var cookieName = this.objectClass; var allCookies = document.cookie; if (allCookies=="") return false; // extract the named cookie we want var start = allCookies.indexOf(cookieName + "="); if (start == -1) return false; start += cookieName.length + 1; // skip over name and = sign var end = allCookies.indexOf(";", start); if (end==-1) end = allCookies.length; var cookieValue = allCookies.substring(start,end); return cookieValue; } MapController.prototype.initFromCookieValue = function(cookieValue) { // parses cookieValue; initializes object accorded to saved values /* var a = cookieValue.split("&"); // create array from name/value pairs delimited by ampersand for (var i=0; i < a.length; i++) { // then break each pair into an array a[i] = a[i].split(":"); } */ // TODO: Rewrite. Currently a hack. if (cookieValue=="active:1") this.selectMapImage(1); else this.selectMapImage(0); // this.selectMapImage(initialMap); } /* MapController.prototype.moveTo = function(x,y) { // move image (i.e. scroll window) window.scrollTo(x,y); } */ // MapImage class - one for each img/view of the map function MapImage ( frameObject, imgId, centerX, centerY ) { this.objectClass = "MapImage"; this.centerX = centerX; this.centerY = centerY; // get image reference this.imgElement = getElement(frameObject,imgId); this.imgStyle = getElementsStyleObject(frameObject,imgId); } MapImage.prototype.makeActive = function (newIsActiveState) { //this.trace(); var newDisplayStyle = newIsActiveState ? "block" : "none"; this.imgStyle.display = newDisplayStyle; }