var geograffiti = geograffiti || {};
geograffiti.map = {
    Defaults: {
        MapDefaultLatitude: 35.70718665682654,
        MapDefaultLongitude: -98.525390625,
        MapDefaultZoomLevel: 4,
        MapLocationFoundZoomLevel: 11
    },
    MarkerLetterLabels: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"],
    BaseIcon: null,
    DefaultVoiceMarkIcon: null,
    DefaultBizMarkIcon: null,
    DefaultProfileIcon: null,
    mapElement: null,
    map: null,
    infoWindowTabs: [null],
    infoWindowBuffer: new gg.StringBuffer(),
    voiceMarkTable: $H(),
    googleLocalResultsTable: $H(),
    viewportOverlay: null,
    
    applyOptions: function(options){
        if (options.width && options.height) {
            var style = "width:" + options.width + "px;height:" + options.height + "px;";
            this.mapElement.setStyle(style)
        }
        else {
            if (options.width) {
                var style = "width:" + options.width + "px;";
                this.mapElement.setStyle(style)
            }
            else {
                if (options.height) {
                    var style = "height:" + options.height + "px;";
                    this.mapElement.setStyle(style)
                }
            }
        }
    },
    initializeDefaultIcons: function(){
        var self = this;
        self.BaseIcon = new google.maps.Icon(G_DEFAULT_ICON);
        self.BaseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
        self.BaseIcon.iconSize = new GSize(20, 34);
        self.BaseIcon.shadowSize = new GSize(37, 34);
        self.BaseIcon.iconAnchor = new GPoint(9, 34);
        self.BaseIcon.infoWindowAnchor = new GPoint(9, 2);
        self.DefaultVoiceMarkIcon = new google.maps.Icon(self.BaseIcon, "/images/voicemark.png");
        self.DefaultVoiceMarkIcon.shadow = "/images/voicemark-shadow.png";
        self.DefaultVoiceMarkIcon.iconSize = new google.maps.Size(37, 52);
        self.DefaultVoiceMarkIcon.shadowSize = new google.maps.Size(76, 42);
        self.DefaultVoiceMarkIcon.iconAnchor = new google.maps.Point(18, 52);
        self.DefaultVoiceMarkIcon.infoWindowAnchor = new google.maps.Point(20, 25);
        self.DefaultVoiceMarkIcon.imageMap = [18, 52, 12, 35, 5, 31, 1, 25, 0, 21, 0, 16, 1, 11, 3, 7, 8, 4, 12, 1, 17, 0, 23, 0, 29, 3, 32, 5, 34, 10, 36, 13, 37, 17, 36, 21, 35, 25, 32, 30, 29, 32, 27, 34, 24, 35];
        self.DefaultVoiceMarkIcon.transparent = "/images/voicemark-transparent.png";
        self.DefaultBizMarkIcon = new google.maps.Icon(self.DefaultVoiceMarkIcon, "/images/bizmark.png");
        self.DefaultProfileIcon = new google.maps.Icon(self.DefaultVoiceMarkIcon, "/images/map-profile-icon.png")
    },
    loadCallback: null,
    load: function(callback){
        this.loadCallback = callback;
        this.loadLibraries()
    },
    initializeStarboxHack: function(){
        Starboxes.processBuildQueue()
    },
    initializeAudioPlayer: function(){
        if (gg.debug) {
            gg.log("now setting up audio player...wiht options %o", gg.AudioPlayerDefaults)
        }
        AudioPlayer.setup("/flash/player.swf", gg.AudioPlayerDefaults);
        if (gg.debug) {
            gg.log("done setting up audio player")
        }
    },
    loadLibraries: function(){
        var self = this;
        geograffiti.require("/js/swfobject-uncompressed.js");
        geograffiti.require("/js/audio-player-uncompressed.js");
        geograffiti.require("/js/starbox.js");
        geograffiti.require("/js/prototip.js");
        geograffiti.require("/js/accordion.js");
        geograffiti.setOnLoadCallback(function(){
            self.loadCallback()
        })
    },
    initialize: function(options){
        try {
            var self = this;
            this.mapElement = $("voicemarkmap");
            if (typeof options !== "undefined") {
                this.applyOptions(options)
            }
            var latitude = null;
            var longitude = null;
            gg.log("loader location %o", google.loader);
            if (google.loader.ClientLocation && google.loader.ClientLocation.latitude && google.loader.ClientLocation.longitude) {
                latitude = google.loader.ClientLocation.latitude;
                longitude = google.loader.ClientLocation.longitude;
                gg.log("set lat and lng for loader as %o %o", latitude, longitude)
            }
            this.map = new google.maps.Map2(this.mapElement);
            this.initializeMapListeners();
            this.initializeDefaultIcons();
            var point = null;
            var zoomLevel = this.Defaults.MapDefaultZoomLevel;
            if (latitude && longitude) {
                point = new google.maps.LatLng(latitude, longitude);
                zoomLevel = this.Defaults.MapLocationFoundZoomLevel;
                gg.log("setting point from google location")
            }
            else {
                point = new google.maps.LatLng(this.Defaults.MapDefaultLatitude, this.Defaults.MapDefaultLongitude)
            }
            this.map.setCenter(point, zoomLevel);
            this.map.addControl(new google.maps.LargeMapControl3D(), new google.maps.ControlPosition(G_ANCHOR_TOP_LEFT, new google.maps.Size(50, 20)));
            this.map.addControl(new google.maps.MenuMapTypeControl(), new google.maps.ControlPosition(G_ANCHOR_TOP_RIGHT, new google.maps.Size(20, 20)));
            this.map.enableScrollWheelZoom();
            this.map.enableContinuousZoom();
            this.map.savePosition();
            Event.observe(window, "resize", function(e){
                var options = {
                    width: $("viewport").getWidth() - $("sidebarcontent").getWidth(),
                    height: $("viewport").getHeight() - $("toparea").getHeight()
                };
                self.applyOptions(options);
                self.resized()
            });
            var sideBar = $("sidebar");
            sideBar.observe(gg.SideBarEvent.VoiceMarkLinkClicked, self.voiceMarkLinkClicked.bind(self));
            sideBar.observe(gg.SideBarEvent.GoogleLocalResultLinkClicked, self.googleLocalResultLinkClicked.bind(self));
            sideBar.observe(gg.SideBarEvent.VoiceMarksHidden, self.sideBarVoiceMarksHidden.bind(self));
            sideBar.observe(gg.SideBarEvent.VoiceMarksVisible, self.sideBarVoiceMarksVisible.bind(self));
            sideBar.observe(gg.SideBarEvent.GoogleLocalResultsHidden, self.sideBarGoogleLocalResultsHidden.bind(self));
            sideBar.observe(gg.SideBarEvent.GoogleLocalResultsVisible, self.sideBarGoogleLocalResultsVisible.bind(self));
            sideBar.observe(gg.SideBarEvent.ViewProfileLinkClicked, self.viewProfileLinkClicked.bind(self));
            sideBar.observe(gg.SideBarEvent.ResultUserNameClicked, self.resultUserNameClicked.bind(self));
            sideBar.observe(gg.SideBarEvent.MouseOverGoogleLocalResult, self.mouseOverGoogleLocalResult.bind(self));
            sideBar.observe(gg.SideBarEvent.MouseOverVoiceMarkResult, self.mouseOverVoiceMarkResult.bind(self));
            this.mapElement.observe(gg.MapEvent.ViewProfileLinkClicked, self.viewProfileLinkClicked.bind(self));
            document.observe(gg.SearchUsersControlEvent.UserSelected, self.userSelectedFromSearchUsersControl.bindAsEventListener(self));
            $("searcher").observe(gg.SearcherEvent.GoingToSearch, self.searcherGoingToSearch.bindAsEventListener(self));
            var myStuff = $$(".mapfilter");
            if (gg.debug) {
                gg.log("array of mapfilters is %o", myStuff)
            }
            $$(".mapfilter").each(function(filter){
                if (gg.debug) {
                    gg.log("iterating filter %o", filter)
                }
                filter.observe("click", self.mapFilterClicked.bindAsEventListener(self))
            });
            this.initializeStarboxHack();
            this.initializeAudioPlayer();
            document.observe("starbox:rated", this.updateStarRating.bindAsEventListener(this))
        } 
        catch (e) {
            if (gg.debug) {
                gg.log("ERROR %o", e)
            }
        }
    },
    mouseOverGoogleLocalResult: function(e){
        var self = this;
        var id = e.memo.id;
        gg.log("Mouse over google local result %d", id);
        var marker = self.googleLocalResultsTable.get(id);
        if (marker) {
            var imageElement = $(marker.cn);
            if (imageElement) {
                if (!imageElement.transitioning) {
                    Object.extend(imageElement, {
                        transitioning: false
                    });
                    new Effect.Move(imageElement, {
                        x: 0,
                        y: -100,
                        mode: "relative",
                        duration: 0.3,
                        beforeStart: function(effect){
                            effect.element.transitioning = true
                        },
                        afterFinish: function(effect){
                            new Effect.Move(imageElement, {
                                x: 0,
                                y: 100,
                                mode: "relative",
                                duration: 0.5,
                                transition: Effect.Transitions.spring,
                                afterFinish: function(effect){
                                    effect.element.transitioning = false
                                }
                            })
                        }
                    })
                }
            }
        }
    },
    mouseOverVoiceMarkResult: function(e){
        var self = this;
        var id = e.memo.id;
        gg.log("Mouse over voice mark result %d", id);
        var marker = self.voiceMarkTable.get(id);
        gg.log("Marker associated with result is %o", marker);
        if (marker) {
            var imageElement = $(marker.cn);
            if (imageElement) {
                if (!imageElement.transitioning) {
                    Object.extend(imageElement, {
                        transitioning: false
                    });
                    new Effect.Move(imageElement, {
                        x: 0,
                        y: -100,
                        mode: "relative",
                        duration: 0.3,
                        beforeStart: function(effect){
                            effect.element.transitioning = true
                        },
                        afterFinish: function(effect){
                            new Effect.Move(imageElement, {
                                x: 0,
                                y: 100,
                                mode: "relative",
                                duration: 0.5,
                                transition: Effect.Transitions.spring,
                                afterFinish: function(effect){
                                    effect.element.transitioning = false
                                }
                            })
                        }
                    })
                }
            }
        }
    },
    sendRateVoiceMarkRequest: function(parameters, elementToUpdate){
        var self = this;
        new Ajax.Request(gg.ApiUrl.RateVoiceMark, {
            parameters: $H(parameters),
            onSuccess: function(transport){
                var apiResponse = transport.responseText.evalJSON(true);
                if (apiResponse) {
                    if (apiResponse.status !== 0) {
                        self.updateAndFlashElement(elementToUpdate, true, "Error Rating!", "starbox-indicator-error")
                    }
                    else {
                        self.updateAndFlashElement(elementToUpdate, true, "Rating Submitted!", "starbox-indicator-success")
                    }
                }
                else {
                    self.updateAndFlashElement(elementToUpdate, true, "Error Rating!", "starbox-indicator-error")
                }
            },
            onFailure: function(transport){
                self.updateAndFlashElement(elementToUpdate, true, "Error Rating!", "starbox-indicator-error")
            }
        })
    },
    updateStarRating: function(e){
        gg.log("star rating with source element %o", e.element());
        e.stop();
        var self = this;
        var starBox = e.element();
        var indicator = starBox.down(".indicator");
        var memo = e.memo;
        var parameters = {
            vmid: memo.identity,
            value: memo.rated
        };
        if (!gg.userLoggedIn()) {
            self.createNeedLoginTip(starBox, {
                message: "You need to be logged in to rate Voice Marks.",
                onLogin: function(){
                    self.sendRateVoiceMarkRequest(parameters, indicator)
                },
                onNoLogin: function(){
                    gg.log("They did not login!")
                }
            })
        }
        else {
            self.sendRateVoiceMarkRequest(parameters, indicator)
        }
    },
    fireSearchByUser: function(systemUserId, voiceUserId, userName){
        var isAnonymous = systemUserId === null || systemUserId <= 0;
        this.mapElement.fire(gg.MapEvent.UserVoiceMarksSearchRequested, {
            id: isAnonymous ? voiceUserId : systemUserId,
            userName: userName,
            isAnonymous: isAnonymous
        })
    },
    applyFilter: function(id, systemUserId, voiceUserId){
        if (gg.debug) {
            gg.debug("apply filter with id %d", id)
        }
        var bounds = this.getBounds();
        var northEast = bounds.northEast;
        var southWest = bounds.southWest;
        this.mapElement.fire(gg.MapEvent.FilterSelected, {
            filter: id,
            userid: systemUserId,
            vid: voiceUserId,
            botLeftLat: southWest.latitude,
            botLeftLon: southWest.longitude,
            topRightLat: northEast.latitude,
            topRightLon: northEast.longitude
        })
    },
    mapFilterClicked: function(e){
        var self = this;
        if (gg.debug) {
            gg.log("filter has been clicked %o", e)
        }
        var filter = e.element().identify();
        var id = parseInt(filter.gsub("mapfilter-", ""));
		if (id === 0) {
			id = 4;
		}
        if (gg.debug) {
            gg.info("Selected filter %s with id %d", filter, id)
        }
        if (id === 1 || id === 2) {
            if (!gg.userLoggedIn()) {
                self.createNeedLoginTip(e.element(), {
                    onLogin: function(){
                    }
                })
            }
            else {
                self.applyFilter(id, gg.getMySystemUserId(), null)
            }
        }
        else {
            self.applyFilter(id, gg.getMySystemUserId(), null)
        }
    },
    searcherGoingToSearch: function(e){
        var self = this;
        self.map.clearOverlays();
        if (self.voiceMarkTable) {
            self.voiceMarkTable.each(function(pair){
                self.voiceMarkTable.unset(pair.key)
            })
        }
    },
    sideBarVoiceMarksHidden: function(e){
        var self = this;
        self.voiceMarkTable.each(function(pair){
            pair.value.hide()
        })
    },
    sideBarVoiceMarksVisible: function(e){
        var self = this;
        self.voiceMarkTable.each(function(pair){
            pair.value.show()
        })
    },
    sideBarGoogleLocalResultsHidden: function(e){
        var self = this;
        self.googleLocalResultsTable.each(function(pair){
            pair.value.hide()
        })
    },
    sideBarGoogleLocalResultsVisible: function(e){
        var self = this;
        self.googleLocalResultsTable.each(function(pair){
            pair.value.show()
        })
    },
    mapLoaded: function(){
        var self = this;
		var loadMyAccountElement = $("loadMyAccount");
        var voiceMarkToShow = $("voiceMarkToShow");
        var systemUserToShow = $("systemUserToShow");
        var tagToSearchForForm = $("tagToSearchForForm");
		var postalCodeToShowElement = $("postalCodeToShow");
		var zoomLevelToShowElement = $("zoomLevel");
		
		var postalCodeToShow = null;
		var zoomLevel = null;
		
		if (postalCodeToShowElement != null) {
			postalCodeToShow = $F(postalCodeToShowElement);
		}
		
		if (zoomLevelToShowElement != null) {
			zoomLevelToShow = $F(zoomLevelToShowElement);
		}
		
		if (postalCodeToShow) {
			var geoCoder = new google.maps.ClientGeocoder();
			geoCoder.getLatLng(postalCodeToShow, function(point) {
				gg.log("Point is %o", point);
				if (zoomLevel) {
					gg.map.map.setCenter(point, zoomLevel);
				}
				else {
					gg.map.map.setCenter(point);
				}
				
				self.applyFilter(4, null, null);
			});
		}
		
        if (voiceMarkToShow) {
            var voiceMarkId = $F(voiceMarkToShow);
            if (voiceMarkId && !String.isNullOrEmpty(voiceMarkId)) {
                this.openVoiceMarkBubble(voiceMarkId);
                voiceMarkToShow.writeAttribute("value", null)
            }
            else {
                self.applyFilter(4, null, null)
            }
        }
        else {
            if (systemUserToShow) {
                var systemUserId = $F(systemUserToShow);
                if (systemUserId && !String.isNullOrEmpty(systemUserId)) {
                    this.openProfileBubble(systemUserId);
                    systemUserToShow.writeAttribute("value", null)
                }
            }
			else if (loadMyAccountElement && !String.isNullOrEmpty($F(loadMyAccountElement))) {
				gg.SideBar.simulateTabClicked($("sidebar-tab-account"));
			}
            else {
                if (tagToSearchForForm) {
                    var tagIdToSearchFor = $F(tagToSearchForForm.tagIdToSearchFor);
                    var tagNameToSearchFor = $F(tagToSearchForForm.tagNameToSearchFor);
                    gg.log("launching search by tag on %d - %s", tagIdToSearchFor, tagNameToSearchFor);
                    self.fireSearchAllWithTag(tagIdToSearchFor, tagNameToSearchFor)
                }
                else {
					if (!String.isNullOrEmpty($F("searchbox-what")) || !String.isNullOrEmpty($F("searchbox-where"))) {
						$("searchbutton").click();
					}
					else {
						var id = gg.getMySystemUserId();
						if (id != null && id > 0) {
							new Ajax.Request(gg.ApiUrl.GetUserInfo, {
					            parameters: {
					                uid: id,
					                format: "json"
					            },
					            onSuccess: function(transport){
					                var userProfile = transport.responseText.evalJSON(true);
					                self.map.setCenter(new google.maps.LatLng(userProfile.location.latitude, userProfile.location.longitude), 10);
									self.applyFilter(4, null, null);
					            },
					            onFailure: function(){
					                if (gg.debug) {
					                    gg.log("Failure getting user info for user uid=%d ", id)
					                }
									self.applyFilter(4, null, null);
					            }
					        });
						}
						else {
							self.applyFilter(4, null, null);
						}
					}
                }
            }
        }
		
		/*
		try {
			var publisherId = "pub-5644156419851183";

			var adsManagerOptions = {
  				maxAdsOnMap : 2,
  				style: G_ADSMANAGER_STYLE_ADUNIT,
			};

			adsManager = new google.maps.AdsManager(this.map, publisherId, adsManagerOptions);
			adsManager.enable();
		}
		catch (e) {
						
		}
		*/
		
		$("load-my-account-link").observe("click", function(e) {
			e.stop();
			gg.SideBar.simulateTabClicked($("sidebar-tab-account"));
		});
    },
    initializeMapListeners: function(){
        if (gg.debug) {
            gg.log("%o", this)
        }
        var mapClickListener = google.maps.Event.addListener(this.map, "click", this.mapClicked.bind(this));
        var mapLoadListener = google.maps.Event.addListener(this.map, "load", this.mapLoaded.bind(this));
        var mapMoveEndListener = google.maps.Event.addListener(this.map, "dragend", this.mapMovedEnd.bind(this));
    },
    resized: function(){
        this.map.checkResize()
    },
    getBounds: function(){
        var bounds = this.map.getBounds();
        var northEast = bounds.getNorthEast();
        var southWest = bounds.getSouthWest();
        return {
            southWest: {
                latitude: southWest.lat(),
                longitude: southWest.lng()
            },
            northEast: {
                latitude: northEast.lat(),
                longitude: northEast.lng()
            }
        }
    },
    getCenter: function(){
        var center = this.map.getCenter();
        return {
            latitude: center.lat(),
            longitude: center.lng()
        }
    },
    getZoom: function(){
        return this.map.getZoom()
    },
    mapClicked: function(marker, point){
        if (!marker) {
            this.openPublishVoiceMarkBubble(point, null, null, true)
        }
    },
    mapMovedEnd: function(){
    },
    generatePublishVoiceMarkBubbleContent: function(point, locationInformation){
        var buffer = new gg.StringBuffer();
		var ba = buffer.append.bind(buffer);
		
		buffer.append('<div id="publish-voicemark-container">');
		
        buffer.append('<div id="publish-voicemark-title">');
        buffer.append("Voice Mark this Location!");
        buffer.append("</div>");
        var addressLineOne = city = state = postalCode = country = mainPhoneNumber = title = "";
		url = "";
        if (locationInformation != null) {
            if (gg.debug) {
                gg.log("loc info is %o", locationInformation)
            }
            title = locationInformation.title;
            addressLineOne = locationInformation.addressLineOne;
            city = locationInformation.city;
            state = locationInformation.state;
            postalCode = locationInformation.postalCode;
            country = locationInformation.country;
			url = "";
			if (typeof locationInformation.url !== "undefined") {
            	url = locationInformation.url;    
            }
			
            var phoneNumbers = locationInformation.phoneNumbers;
            if (phoneNumbers) {
                var phoneNumber = null;
                for (var i = 0, limit = phoneNumbers.length; i < limit; ++i) {
                    phoneNumber = phoneNumbers[i];
                    if (phoneNumber.type === "" || phoneNumber.type === "main") {
                        mainPhoneNumber = phoneNumber.number;
                        break
                    }
                }
            }
            buffer.append('<div id="publish-voicemark-locationinfo">');
            buffer.append('<div id="publish-voicemark-locationinfo-title">$0</div>', title);
            buffer.append('<div id="publish-voicemark-locationinfo-addresslineone">$0</div>', addressLineOne);
            buffer.append('<div id="publish-voicemark-locationinfo-city-state-zip-country">$0 $1 $2 $3</div>', city, state, postalCode, country);
            buffer.append('<div id="publish-voicemark-locationinfo-phonenumber">$0</div>', mainPhoneNumber);
            buffer.append("</div>");
        }
		
		ba('<form id="publish-voicemark-form" action="$0">', gg.ApiUrl.CreateVoiceMark);
		ba('<div class="publish-voicemark-step-container">');
		ba('<div class="publish-voicemark-bullet-container"><div class="publish-voicemark-bullet">1</div></div>');
		ba('<div id="publish-voicemark-step-1-container">');
		ba('<div id="publish-voicemark-title-container">');
        ba('<label for="publish-voicemark-form-title">Venue Name/Topic</label>');
		ba('<div id="publish-voicemark-title-description">Starbucks, Sale at Macys, dog barking</div>');
        ba('<input type="text" maxlength="40" id="publish-voicemark-form-title" name="title" value="$0"/>', title);
        ba("</div>"); //publish-voicemark-title-container
		ba('</div>'); //publish-voicemark-step-1-container
		ba('</div>'); //class=publish-voicemark-step-container;
		
		ba('<div class="publish-voicemark-step-container">');
		ba('<div class="publish-voicemark-bullet-container"><div class="publish-voicemark-bullet">2</div></div>');
		ba('<div id="publish-voicemark-step-2-container">');
		ba('<div><input type="radio" id="publish-voicemark-method-phone-call" name="publish-voicemark-method" value="phone-call" checked="checked"><label id="publish-voicemark-method-phone-call-label" for="publish-voicemark-method-phone-call">Publish via Phone Call</label></input></div>');
		ba('<div><input type="radio" id="publish-voicemark-method-upload" name="publish-voicemark-method" value="upload"><label id="publish-voicemark-method-upload-label" for="publish-voicemark-method-upload">Upload Sound File (MP3, WAV, or MP4/M4A)</label></input></div>');
		ba('</div>'); //publish-voicemark-step-2-container
		ba('</div>'); //class=publish-voicemark-step-container
		
		ba('<div class="publish-voicemark-step-container">');
		ba('<div class="publish-voicemark-bullet-container"><div class="publish-voicemark-bullet">3</div></div>');
		ba('<div id="publish-voicemark-step-3-container">');
		
		ba('<div id="publish-voicemark-usernumber-container">');
        ba('<label for="publish-voicemark-usernumber">Your Phone Number</label>');
		ba('<div id="publish-voicemark-usernumber-description">Enter a valid U.S. or Canadian number</div>');
        ba('<input type="text" maxlength="10" id="publish-voicemark-usernumber" name="phonenum" value="$0"></input>', gg.getMyPhoneNumber());
		ba('<div id="publish-voicemark-submit-container" class="disabled">');
		ba('<input type="image" src="/images/call-me.png" id="publish-voicemark-submit-button"></input>');
		ba('</div>'); //publish-voicemark-submit-container
        ba("</div>"); //publish-voicemark-usernumber-container
        
		ba('<div id="publish-voicemark-upload-container">');
        ba('<label for="publish-voicemark-fileupload">Choose File</label>');
		ba('<div id="publish-voicemark-fileupload-description">Choose an MP3, WAV, or M4A/MP4 file to upload</div>');
        ba('<input type="file" id="publish-voicemark-fileupload" name="soundfile"></input>');
		ba('<div id="publish-voicemark-submit-container" class="disabled">');
		ba('<input type="image" src="/images/upload-button.png" id="publish-voicemark-submit-button"></input>');
		ba('</div>'); //publish-voicemark-submit-container
        ba("</div>"); //publish-voicemark-fileupload-container
		
		ba('</div>'); //publish-voicemark-step-3-container
		ba('</div>'); //class=publish-voicemark-step-container;
		ba('<input type="hidden" id="publish-voicemark-latitude" name="lat" value="$0"/>', point.lat());
        ba('<input type="hidden" id="publish-voicemark-longitude" name="lon" value="$0"/>', point.lng());
        ba('<input type="hidden" id="publish-voicemark-address-line-one" name="addressLineOne" value="$0" />', addressLineOne);
        ba('<input type="hidden" id="publish-voicemark-city" name="city" value="$0"/>', city);
        ba('<input type="hidden" id="publish-voicemark-state" name="state" value="$0" />', state);
        ba('<input type="hidden" id="publish-voicemark-location-phone-number" name="locationPhoneNumber" value="$0"/>', mainPhoneNumber);
		ba('<input type="hidden" id="publish-voicemark-uid" name="uid" value="-1"/>');
		ba('<input type="hidden" id="publish-voicemark-url" name="website" value="$0">', url);
		ba('</form>'); //publish-voicemark-form
		ba('<div id="voicemark-uploader-progress-container">');
    	ba('<div id="voicemark-uploader-progress-bar-container">');
    	ba('<div id="voicemark-uploader-progress-bar"></div>');
    	ba('<div id="voicemark-uploader-progress-message"></div>');
    	ba('</div>'); //voicemark-uploader-progress-bar-container
    	ba('</div>'); //voicemark-uploader-progress-container
		ba('<iframe id="publish-voicemark-remoting-frame" name="publish-voicemark-remoting-frame" src="about:blank"></iframe>');
		
		/*
        buffer.append('<div id="publish-voicemark-messages">');
        buffer.append("Enter a Venue Name or Topic, your phone number, and GeoGraffiti will call you to record your Voice Mark.  Don't worry!  We only need your phone number so our automated system can call you.  It will never be displayed to the public.");
        buffer.append("</div>");
        buffer.append('<div id="publish-voicemark-input">');
        buffer.append('<form id="publish-voicemark-form" action="$0">', gg.ApiUrl.CreateVoiceMark);
        buffer.append('<div id="publish-voicemark-title-container">');
        buffer.append('<label for="publish-voicemark-form-title">Venue Name/Topic</label>');
        buffer.append('<input type="text" maxlength="40" id="publish-voicemark-form-title" name="title" value="$0"></input>', title);
        buffer.append("</div>");
		buffer.append('<div id="publish-voicemark-options">');
		buffer.append('<input id="publish-voicemark-method-phone-call" type="radio" name="publish-voicemark-method" value="phone-call"><label for="publish-voicemark-method-phone-call">Record via Phone Call</label></input>');
		buffer.append('<input id="publish-voicemark-method-upload" type="radio" name="publish-voicemark-method" value="upload"><label for="publish-voicemark-method-upload">Upload Sound File</label></input>');
		buffer.append('</div>');
        buffer.append('<div id="publish-voicemark-usernumber-container">');
        buffer.append('<label for="publish-voicemark-usernumber">Your Phone Number</label>');
        buffer.append('<input type="text" maxlength="10" id="publish-voicemark-usernumber" name="phonenum"/>');
        buffer.append("</div>");
        buffer.append('<input type="hidden" id="publish-voicemark-latitude" name="lat" value="$0"/>', point.lat());
        buffer.append('<input type="hidden" id="publish-voicemark-longitude" name="lon" value="$0"/>', point.lng());
        buffer.append('<input type="hidden" id="publish-voicemark-address-line-one" name="addressLineOne" value="$0" />', addressLineOne);
        buffer.append('<input type="hidden" id="publish-voicemark-city" name="city" value="$0"/>', city);
        buffer.append('<input type="hidden" id="publish-voicemark-state" name="state" value="$0" />', state);
        buffer.append('<input type="hidden" id="publish-voicemark-location-phone-number" name="locationPhoneNumber" value="$0"/>', mainPhoneNumber);
        buffer.append('<div id="publish-voicemark-submit-container" class="disabled">');
        buffer.append('<input type="submit" id="publish-voicemark-submit-button" value="Call Me!"/>');
        buffer.append('<span id="publish-voicemark-submit-button-messages">Enter 10-digit U.S. Phone Number</span>');
        buffer.append("</div>");
        buffer.append("</form>");
        buffer.append("</div>");
        if (gg.debug) {
            gg.log("about to return the buffer for the publish window")
        }
        */
		
		buffer.append('</div>'); //publish-voicemark-container
        return buffer.toString()
    },
    enableCallMeButtonSection: function(){
        var callMeButton = $("publish-voicemark-submit-button");
        if (callMeButton) {
            //callMeButton.enable()
        }
		
        //var callMeButtonSection = $("publish-voicemark-submit-container");
        //callMeButtonSection.addClassName("enabled");
        //callMeButtonSection.removeClassName("disabled");
        //var messages = $("publish-voicemark-submit-button-messages");
		//messages.addClassName("enabled");
		//messages.removeClassName("disabled");
        //messages.update("")
    },
    disableCallMeButtonSection: function(titleError, numberError){
        var callMeButton = $("publish-voicemark-submit-button");
        if (callMeButton) {
            //callMeButton.disable()
        }
        //var callMeButtonSection = $("publish-voicemark-submit-container");
        //callMeButtonSection.addClassName("disabled");
        //callMeButtonSection.removeClassName("enabled");
        
		//var messages = $("publish-voicemark-submit-button-messages");
		//messages.addClassName("disabled");
		//messages.removeClassName("enabled");
        //var errorMessage = "";
        //if (titleError) {
        //    errorMessage += "Enter a valid title"
        //}
        //if (numberError) {
       //     if (errorMessage) {
       //         errorMessage += " / "
       //     }
       //     errorMessage += "Enter a valid 10-digit U.S.or Canadian Phone Number"
       // }
       // messages.update(errorMessage)
    },
    publishVoiceMarkTitleValid: function(){
        var valid = false;
        var title = $F("publish-voicemark-form-title");
        if (title && !title.blank()) {
            valid = true
        }
        return valid
    },
	publishVoiceMarkUserNumberValid : function() {
		var valid = false;

		var phoneNumber = $F("publish-voicemark-usernumber");
		if (phoneNumber.charAt(0) === '1') {
			phoneNumber = phoneNumber.substring(1);
		}
		
		if (phoneNumber.length === 10) {
			valid = true;
		}
		
		return valid;
	},
	
	uploadVoiceMarkSoundFileValid : function() {
		var valid = false;
		var soundFile = $F("publish-voicemark-fileupload");
		if (soundFile && !soundFile.blank()) {
			if (soundFile.endsWith(".mp3") || soundFile.endsWith(".MP3") || soundFile.endsWith("wav") || soundFile.endsWith(".WAV") || soundFile.endsWith(".mp4") || soundFile.endsWith(".MP4") || soundFile.endsWith("m4a") || soundFile.endsWith("M4A")) {
				valid = true;
			}
		}
		return valid;
	},
    validatePublishVoiceMarkInput: function(){
        var phoneNumber = $F("publish-voicemark-usernumber");
        if (phoneNumber.charAt(0) === "1") {
            phoneNumber = phoneNumber.substring(1);
            $("publish-voicemark-usernumber").value = phoneNumber
        }
        gg.log("%o --", phoneNumber);
        if (phoneNumber.length === 10) {
            if (this.publishVoiceMarkTitleValid()) {
                this.enableCallMeButtonSection()
            }
            else {
                this.disableCallMeButtonSection(true, false)
            }
        }
        else {
            if (this.publishVoiceMarkTitleValid()) {
                this.disableCallMeButtonSection(false, true)
            }
            else {
                this.disableCallMeButtonSection(true, true)
            }
        }
    },
	
	createVoiceMarkFormListener : function(e) {
		var self = this;
		e.stop();
		if (!self.publishVoiceMarkTitleValid()) {
			var message = "Title not valid";
			alert(message);
			
		}
		else if (!self.publishVoiceMarkUserNumberValid()) {
			var message = "Phone Number not valid";
			alert(message);
		}
		else {
			gg.log("form %o got a submit...what's going on?");
			$("publish-voicemark-form").request({
				onSuccess: function(transport) {
					var voiceMarkId = transport.responseText.strip();
					var voiceMarkLink = String.format("/voicemarks/$0/", voiceMarkId);
					var buffer = new gg.StringBuffer();
					var ba = buffer.append.bind(buffer);
					ba('<p id="phone-publish-header">GEOGRAFFITI IS CALLING YOU NOW</p>');
					ba('<p id="phone-publish-from-number">( from 213&bull;221&bull;3802 )</p>');
					ba('<div id="phone-publish-call-to-action-container">');
					ba('<a id="phone-publish-call-to-action-link" href="$0" title="View Voice Mark $1">', voiceMarkLink, voiceMarkId);
					ba('<img id="phone-publish-call-to-action-button" src="/images/view-voicemark-button-300x64.png" alt="VIEW VOICE MARK"/>');
					ba('</a>');//phone-publish-call-to-action-link
					ba('</div>');//phone-publish-call-to-action-container
					ba('<p id="phone-publish-footer">after you hang up</p>');
					var publishContainer = $("publish-voicemark-container"); 
     				publishContainer.update(buffer.toString());
					publishContainer.writeAttribute("style", "margin-top:40px");
					
					$("phone-publish-call-to-action-link").observe("click", function(e) {
						gg.log("got a click...opening the bubble");
						e.stop();
						self.openVoiceMarkBubble(voiceMarkId);
					});
				},
				onFailure: function(){
					alert("An error occurred and we weren't able to call you.  Please try again.");
					gg.log("onFailure got hit!!!!!");
				}
			});
		}
	},
	
	uploadVoiceMarkFormListener : function(e) {
		var self = this;
		if (!self.publishVoiceMarkTitleValid()) {
			e.stop();
			var message = "Title not valid";
			alert(message);
		}
		else if (!self.uploadVoiceMarkSoundFileValid()) {
			e.stop();
			var message = "You need to select a WAV, MP3, or M4A/MP4 file to upload";
			alert(message);
		}
		else {
			gg.log("all is good so we will let the submit event go through");
			$("voicemark-uploader-progress-bar-container").setStyle("visibility:visible");
			$("voicemark-uploader-progress-message").innerHTML = "Uploading";
			new PeriodicalExecuter(function(pe) {
					var url = String.format("/api/voicemark/session-uploads/soundFile?$0", new Date().getTime());
					new Ajax.Request(url, {
						method:"GET",
						onSuccess: function(response) {
							var apiResponse = response.responseText.evalJSON(true);
							gg.info("got api response at %o", apiResponse);
							
							$("voicemark-uploader-progress-message").innerHTML = String.format("$0%", apiResponse.uploadProgress);
							var currentWidth = $("voicemark-uploader-progress-bar-container").getWidth();
							var factor = apiResponse.uploadProgress / 100;
							var newWidth = (currentWidth * factor) - 2; /* 1px border on the container */
							$("voicemark-uploader-progress-bar").setStyle(String.format("width:$0px", newWidth));
							
							if (apiResponse.uploadProgress >= 100.0) {
								pe.stop();
							}							
						},
						onFailure: function(response) {
							gg.info("failure...%o", response);
							pe.stop();
						},
						onComplete : function(response) {
							gg.info("complete....%o", response);
							
						},
						onException : function(requester, e) {
							gg.info("exception sending ajax call %o", e);
							pe.stop();
						}
					});
			}, 2);
			
			var remotingFrame = $("publish-voicemark-remoting-frame");
			if (remotingFrame.attachEvent) {
				remotingFrame.attachEvent("onload", function() {
				try {
					var result = remotingFrame.contentWindow.document.body.innerHTML.evalJSON(true);
					gg.info("result of attachEvent ... %o", result);
					$("voicemark-uploader-progress-message").innerHTML = "DONE!";
					$("voicemark-uploader-progress-bar-container").setStyle("visibility:hidden");
					$("voicemark-uploader-progress-bar").setStyle("width:0px");
					self.openVoiceMarkBubble(result.voiceMark.id);
				} 
				catch (e) {
					gg.error("error from attachEvent %o", e);
					$("voicemark-uploader-progress-message").innerHTML = "ERROR!";
					//$("voicemark-uploader-progress-bar-container").setStyle("visibility:hidden");
					//$("voicemark-uploader-progress-bar").setStyle("width:0px");
				}
			});
		}  
		else {
			try {
				Event.stopObserving(remotingFrame, "load");
				Event.observe(remotingFrame, "load", function(e) {
					e.stop();
					var result = remotingFrame.contentDocument.documentElement.textContent.evalJSON(true);
					gg.info("result of observe load is %o", result);
					$("voicemark-uploader-progress-message").innerHTML = "DONE!";
					$("voicemark-uploader-progress-bar-container").setStyle("visibility:hidden");
					$("voicemark-uploader-progress-bar").setStyle("width:0px");
					self.openVoiceMarkBubble(result.voiceMark.id);
				});				
			}
			catch (e) {
				gg.error("error from observe load... %o", e);
				$("voicemark-uploader-progress-message").innerHTML = "ERROR!";
				//$("voicemark-uploader-progress-bar-container").setStyle("visibility:hidden");
				//$("voicemark-uploader-progress-bar").setStyle("width:0px");
				
			}
		}	
		}
	},
	
    openPublishVoiceMarkBubble: function(point, locationInformation, currentMarker, create){
        var self = this;
        var marker = null;
        if (create == false) {
            marker = currentMarker
        }
        else {
            marker = new google.maps.Marker(point, self.DefaultVoiceMarkIcon);
            self.map.addOverlay(marker);
            google.maps.Event.addListener(marker, "infowindowclose", function(){
                self.map.removeOverlay(marker)
            })
        }
        google.maps.Event.addListener(marker, "infowindowopen", function(){
			if (!String.isNullOrEmpty(gg.mySystemUserId) && !isNaN(gg.mySystemUserId) && gg.mySystemUserId > -1) {
				$("publish-voicemark-uid").writeAttribute("value", gg.mySystemUserId);
				gg.info("gg.mySystemUserId was not null or empty so set value to " + gg.mySystemUserId);
			}
			else {
				new Ajax.Request(gg.ApiUrl.GetMySystemUserId, {
					method:'post',
					onSuccess:function(transport) {
						var apiResponse = transport.responseText.evalJSON(true);
						gg.info("the apiREsponse was " + transport);
    					if (apiResponse) {
        					if (!(String.isNullOrEmpty(apiResponse.id))) {
            					gg.mySystemUserId = apiResponse.id;
								$("publish-voicemark-uid").writeAttribute("value", gg.mySystemUserId);
        					}
    					}
					},
					onFailure:function(transport) {
						gg.warn("Failure with call to %o", transport);
					},
					onException:function(transport) {
						gg.warn("Exception with call to %o", transport);
					}
				});
			}
			
            self.disableCallMeButtonSection(true, true);
            var form = $("publish-voicemark-form");
            var messages = $("publish-voicemark-messages");			
			var publishViaPhoneCallRadioButton = $("publish-voicemark-method-phone-call");
			var publishViaUploadRadioButton = $("publish-voicemark-method-upload");
			
			publishViaPhoneCallRadioButton.observe("click", function(e) {
				gg.debug("Event on pub via phone call %o", e);
				$("publish-voicemark-usernumber-container").setStyle("display:block");
				$("publish-voicemark-upload-container").setStyle("display:none");
				$("publish-voicemark-form").writeAttribute("action", gg.ApiUrl.CreateVoiceMark);
				$("publish-voicemark-form").removeAttribute("target");
				$("publish-voicemark-form").removeAttribute("enctype");
				$("publish-voicemark-form").removeAttribute("method");
				if ($F("publish-voicemark-usernumber") === "0000000000") {
					$("publish-voicemark-usernumber").writeAttribute("value", "");
				}
				form.stopObserving();
				form.observe("submit", self.createVoiceMarkFormListener.bind(self));
			});
			
			publishViaUploadRadioButton.observe("click", function(e) {
				gg.debug("Event on pub via upload %o", e);
				$("publish-voicemark-usernumber-container").setStyle("display:none");
				$("publish-voicemark-upload-container").setStyle("display:block");
				$("publish-voicemark-form").writeAttribute("action", "/api/voicemark/upload/");
				$("publish-voicemark-form").writeAttribute("target", "publish-voicemark-remoting-frame");
				$("publish-voicemark-usernumber").writeAttribute("value", "0000000000");
				$("publish-voicemark-form").writeAttribute("enctype", "multipart/form-data");
				$("publish-voicemark-form").writeAttribute("method", "post");
				form.stopObserving();
				form.observe("submit", self.uploadVoiceMarkFormListener.bind(self));
			});
			
            var publishVoiceMarkFormTitle = $("publish-voicemark-form-title");
            publishVoiceMarkFormTitle.stopObserving();
            publishVoiceMarkFormTitle.observe("keypress", function(e){
                self.validatePublishVoiceMarkInput.bind(self).defer()
            });
            var publishVoiceMarkUserNumber = $("publish-voicemark-usernumber");
            publishVoiceMarkUserNumber.stopObserving();
            publishVoiceMarkUserNumber.observe("keypress", function(e){
                gg.log("Key pressed %o", e);
                var keyCode = e.charCode || e.keyCode;
                gg.log("key code is %d", keyCode);
                if (keyCode >= 48 && keyCode <= 57) {
                    self.validatePublishVoiceMarkInput.bind(self).defer()
                }
                else {
                    if (keyCode >= 58) {
                        e.stop();
                        gg.log("not number")
                    }
                    else {
                        if (keyCode != Event.KEY_BACKSPACE && keyCode != Event.KEY_DELETE && keyCode != Event.KEY_LEFT && keyCode != Event.KEY_UP && keyCode != Event.KEY_RIGHT && keyCode != Event.KEY_DOWN) {
                            e.stop()
                        }
                        else {
                            gg.log("probably some non-printable");
                            self.validatePublishVoiceMarkInput.bind(self).defer()
                        }
                    }
                }
            });
            form.stopObserving();
			form.observe("submit", self.createVoiceMarkFormListener.bind(self));
        });
		
		gg.log("going to open infowindow");
		
        marker.openInfoWindowHtml(self.generatePublishVoiceMarkBubbleContent(point, locationInformation), {
            maxWidth: 250
        });
		
        if (gg.debug) {
            gg.log("opened")
        }
    },
    openVoiceMarkBubble: function(id){
        var self = this;
        if (gg.debug) {
            gg.log("I'm going to open voice mark %d", id)
        }
        var marker = self.voiceMarkTable.get(id);
        if (marker) {
            google.maps.Event.trigger(marker, "click")
        }
        else {
            if (gg.debug) {
                gg.log("Marker for Voice Mark %d is not in the table", id)
            }
            new Ajax.Request(gg.ApiUrl.GetVoiceMarkInfo, {
                parameters: {
                    vmid: id,
                    format: "json"
                },
                onSuccess: function(transport){
                    var nakedVoiceMark = transport.responseText.evalJSON(true);
                    marker = self.addVoiceMarkToMap(nakedVoiceMark);
                    google.maps.Event.trigger(marker, "click")
                },
                onFailure: function(){
                    if (gg.debug) {
                        gg.log("Failure getting VM info for VMID=%d", id)
                    }
                }
            })
        }
    },
    openProfileBubble: function(id){
        var self = this;
        new Ajax.Request(gg.ApiUrl.GetUserInfo, {
            parameters: {
                uid: id,
                format: "json"
            },
            onSuccess: function(transport){
                var userProfile = transport.responseText.evalJSON(true);
                var marker = self.addProfileToMap(userProfile);
                if (marker) {
                    google.maps.Event.trigger(marker, "click")
                }
            },
            onFailure: function(){
                if (gg.debug) {
                    gg.log("Failure getting user info for user uid=%d ", id)
                }
            }
        })
    },
    openGoogleLocalResultBubble: function(id){
        var self = this;
        var marker = self.googleLocalResultsTable.get(id);
        if (marker) {
            if (gg.debug) {
                gg.log("marker found as GOOG %o", marker)
            }
            google.maps.Event.trigger(marker, "click")
        }
        else {
            if (gg.debug) {
                gg.log("Marker for google local result ID %d is not in table %o", id, self.googleLocalResultsTable)
            }
        }
    },
    voiceMarkLinkClicked: function(e){
        var self = this;
        e.stop();
        if (gg.debug) {
            gg.log("stopped %o", e)
        }
        self.openVoiceMarkBubble(e.memo.id)
    },
    googleLocalResultLinkClicked: function(e){
        Event.stop(e);
        if (gg.debug) {
            gg.log("stopped %o", e)
        }
        this.openGoogleLocalResultBubble(e.memo.id)
    },
    viewProfileLinkClicked: function(e){
        try {
            e.stop();
            gg.log("view profile link clicked");
            var id = e.memo.id;
            gg.log("this is for user %d", id);
            this.openProfileBubble(id)
        } 
        catch (e) {
            gg.error(e)
        }
    },
    userSelectedFromSearchUsersControl: function(e){
        e.stop();
        var id = e.memo.id;
        if (id) {
            this.openProfileBubble(id)
        }
    },
    resultUserNameClicked: function(e){
        var self = this;
        var data = e.memo;
        try {
            e.stop();
            if (data.isAnonymous) {
                self.fireSearchByUser(null, data.userId)
            }
            else {
                self.fireSearchByUser(data.userId, null)
            }
        } 
        catch (e) {
            gg.error("ERROR!...%o", e)
        }
    },
    createProfileInfoWindowContent: function(profile){
        var buffer = new gg.StringBuffer();
        var ba = buffer.append.bind(buffer);
        ba('<div id="map-userprofile-container">');
        ba('<div class="map-userprofile-pic-frame">');
		ba('<a href="/api/user/$0/pictures/0/" class="lightview" title="Profile Picture for $1">', profile.systemUserId, profile.userName);
        ba('<img src="/api/user/$0/pictures/0/thumbnail/medium/?$1" alt="Profile Picture for $2"/>', profile.systemUserId, new Date().getTime(), profile.userName);
		ba('</a>');
        ba("</div>");
        ba('<div id="map-userprofile-top-right">');
        ba('<div id="map-userprofile-name-container">');
        ba('<span id="map-userprofile-first-name" class="rightpad-medium">$0</span>', gg.textOrDefault(profile.firstName, ""));
        ba('<span id="map-userprofile-last-name">$0</span>', gg.textOrDefault(profile.lastName, ""));
        ba("</div>");
        ba('<div id="map-userprofile-aka-container">aka</div>');
        ba('<div id="map-userprofile-username-container">');
        ba('<div id="map-userprofile-username">$0</div>', gg.textOrDefault(profile.userName, ""));
        ba("</div>");
        ba('<div id="map-userprofile-gender-and-location-container">');
        ba('<span id="map-userprofile-gender-container">');
        ba('<span id="map-userprofile-gender">$0</span>', gg.textOrDefault(profile.gender, ""));
        ba("</span>");
        ba('<span id="map-userprofile-in-container"> in </span>');
        ba('<span id="map-userprofile-citystatezip-container">');
        if (!(String.isNullOrEmpty(profile.city) && String.isNullOrEmpty(profile.region))) {
            ba('<span id="map-userprofile-city">$0, </span>', gg.textOrDefault(profile.city, ""));
            ba('<span id="map-userprofile-state">$0 </span>', gg.textOrDefault(profile.region, ""))
        }
        ba('<span id="map-userprofile-postalcode">$0 </span>', gg.textOrDefault(profile.postalCode, ""));
        ba("</span>");
        ba('<span id="map-userprofile-country-container">');
        ba('<span id="map-userprofile-country"> $0 </span>', gg.textOrDefault(profile.country, ""));
        ba("</span>");
        ba("</div>");
        ba('<div id="map-userprofile-birthday-container">');
        ba('<span id="map-userprofile-birthday-label">Birthday: </span>');
        ba('<span id="map-userprofile-birthday">$0</span>', gg.textOrDefault(profile.dateOfBirth, ""));
        ba("</div>");
        ba('<div id="map-userprofile-actions">');
        ba('<div id="map-userprofile-action-become-fan" class="map-userprofile-action">Become their fan!</div>');
		ba('<div id="map-userprofile-action-listen-to-their-voicemarks" class="map-userprofile-action">Listen to their Voice Marks</div>');
        ba("</div>");
        ba("</div>");
        ba('<div id="map-userprofile-public-info-bottom">');
        ba("");
        ba("</div>");
        ba('<div id="map-userprofile-stats-section">');
        ba('<div id="map-userprofile-stats-heading">Stats</div>');
        ba('<div id="map-userprofile-stats-container">');
        gg.log("The profile object has %o", profile);
        ba('<div id="map-userprofile-stats-joined">');
        ba('<span class="map-userprofile-stats-heading">Joined On: </span>');
        ba('<span class="map-userprofile-stats-value">$0</span>', profile.joinedOn);
        ba("</div>");
        ba('<div id="map-userprofile-stats-last-login">');
        ba('<span class="map-userprofile-stats-heading">Last Login: </span>');
        ba('<span class="map-userprofile-stats-value">$0</span>', profile.lastLogin);
        ba("</div>");
        ba('<div id="map-userprofile-stats-vms-created">');
        ba('<span class="map-userprofile-stats-heading">has created $0 VoiceMarks</span>', profile.numberOfVoiceMarks);
        ba("</div>");
        ba('<div id="map-userprofile-stats-number-of-fans">');
        ba('<span class="map-userprofile-stats-heading">has $0 fan(s)!</span>', profile.numberOfFans);
        ba("</div>");
        ba('<div id="map-userprofile-stats-fan-of">');
        ba('<span class="map-userprofile-stats-heading">Is a fan of $0 user(s)!</span>', profile.numberOfSubscriptions);
        ba("</div>");
        ba("</div>");
        ba("</div>");
        ba('<div id="map-userprofile-member-of-section">');
        ba('<div id="map-userprofile-member-of-heading">Member Of</div>');
        ba('<div id="map-userprofile-member-of-container">');
        var groups = profile.groups;
        if (groups) {
            groups.each(function(group){
                ba('<div class="map-userprofile-group-container">');
                ba('<span class="map-userprofile-group-name">$0 </span>', group.name);
                ba('<span class="map-userprofile-group-action-join" id="map-userprofile-group-action-join-$0">(Join Group)</span>', group.id);
                ba("</div>")
            })
        }
        ba("</div>");
        ba("</div>");
        ba("</div>");
        return buffer.toString()
    },
    createInitialContentFromVoiceMark: function(voiceMark){
        this.infoWindowBuffer.clear();
        this.infoWindowBuffer.append('<div id="vmcontainer">');
        this.infoWindowBuffer.append('<div id="topinfo">');
        this.infoWindowBuffer.append('<div id="vmtitle">$0</div>', voiceMark.getTitle());
        if (!voiceMark.isAnonymous && voiceMark.uid && (voiceMark.uid === gg.getMySystemUserId())) {
            this.infoWindowBuffer.append('<div id="action-delete-voicemark-$0" class="delete-voicemark-link">Delete Voice Mark</div>', voiceMark.id)
        }
        this.infoWindowBuffer.append('<div id="vmaddrinfo">');
        this.infoWindowBuffer.append('<div id="left-side">');
        this.infoWindowBuffer.append('<div id="vmaddrlineone">$0</div>', voiceMark.addressLineOne);
        this.infoWindowBuffer.append('<div id="vmaddrlinetwo">$0</div>', voiceMark.addressLineTwo);
        this.infoWindowBuffer.append('<div id="vmaddrcitystatezip">$0</div>', voiceMark.getCityStateZip());
        //this.infoWindowBuffer.append('<div id="vmaddrphone"><a href="$0" title="Place a call to the venue associated with $1">$2</a></div>', voiceMark.phoneNumberUrl, voiceMark.getTitle(), voiceMark.phoneNumber);
		this.infoWindowBuffer.append('<div id="vmaddrphone">$0</div>', voiceMark.phoneNumber);
        this.infoWindowBuffer.append('<div id="vmaddrwebsite"><a href="$0" title="Visit the website for the venue associated with $1">$2</a></div>', voiceMark.website, voiceMark.getTitle(), voiceMark.website);
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append('<div id="right-side">');
        this.infoWindowBuffer.append('<a class="directions-link" target="_blank" href="http://maps.google.com/maps?daddr=$0,$1($2)">Get Directions</a>', voiceMark.lat, voiceMark.lng, encodeURIComponent(voiceMark.getTitle()));
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append('<div style="clear:both"></div>');
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append('<div id="player-and-rating-container">');
        this.infoWindowBuffer.append('<div id="vmplayer"><a href="/geogstreamer/GetVoiceMark/$0" title="Listen to this Voice Mark as an MP3 stream" rel="alternate nofollow" type="audio/mpeg"><img id="play-button-image" src="/images/fake-vmplayer-81x24.png" alt="Play Button"/>Play</a></div>', voiceMark.id);
        this.infoWindowBuffer.append('<div id="vmratingcontrol"></div>');
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append('<div id="midinfo">');
		this.infoWindowBuffer.append('<div id="more-info-toggle" class="vm_bubble_accordion_toggle"><span>More Info...</span></div>');
        this.infoWindowBuffer.append('<div id="moreinfowrapper" class="vm_bubble_accordion_content"><div id="moreinfo"></div></div>');
        this.infoWindowBuffer.append('<div id="creator-info-toggle" class="vm_bubble_accordion_toggle"><span>Creator Info</span></div>');
        this.infoWindowBuffer.append('<div id="creatorinfo" class="vm_bubble_accordion_content"><div class="accordion-content-wrapper"><div id="userinfocontainer" style="display:none"></div><div id="loader"><img id="loaderimage" src="/images/loading-32x32-blue-white.gif"/></div></div></div>');
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append('<div id="bottominfo">');
        this.infoWindowBuffer.append('<div id="respondsection">');
        this.infoWindowBuffer.append('<img src="/images/respond.png"/><span>$0</span>', /*gg.$S("VoiceMarkWindowRespond")*/"Respond!");
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append('<div id="sharesection">');
        this.infoWindowBuffer.append('<div id="sharesection-addthis"></div>');
        this.infoWindowBuffer.append('<div id="sharesection-geograffiti-links" class="small-top-margin">');
        this.infoWindowBuffer.append('<span id="sharesection-send-to-phone" class="sharesection-link"><img class="share-section-image" src="/images/phone.png"/>Send 2 Phone</span>');
        this.infoWindowBuffer.append('<span id="sharesection-link-to-this" class="small-left-margin sharesection-link"><img class="share-section-image" src="/images/link.png"/>Link 2 This</span>');
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append("</div>");
        return this.infoWindowBuffer.toString()
    },
 	newCreateInitialContentFromVoiceMark: function(voiceMark){
		var self = this;
        this.infoWindowBuffer.clear();
        this.infoWindowBuffer.append('<div id="vmcontainer">');
        this.infoWindowBuffer.append('<div id="topinfo">');
        this.infoWindowBuffer.append('<div id="vmtitle">$0</div>', voiceMark.getTitle());
        if (!voiceMark.isAnonymous && voiceMark.uid && (voiceMark.uid === gg.getMySystemUserId())) {
            this.infoWindowBuffer.append('<div id="action-delete-voicemark-$0" class="delete-voicemark-link">Delete Voice Mark</div>', voiceMark.id)
        }
	this.infoWindowBuffer.append('<div id="respondsection">');
        this.infoWindowBuffer.append('<img src="/images/PopUpCreateVM175x34.png"/>');
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append('<div id="vmaddrinfo">');
        this.infoWindowBuffer.append('<div id="left-side">');
        this.infoWindowBuffer.append('<div id="vmaddrlineone">$0</div>', voiceMark.addressLineOne);
        this.infoWindowBuffer.append('<div id="vmaddrlinetwo">$0</div>', voiceMark.addressLineTwo);
        this.infoWindowBuffer.append('<div id="vmaddrcitystatezip">$0</div>', voiceMark.getCityStateZip());
        //this.infoWindowBuffer.append('<div id="vmaddrphone"><a href="$0" title="Place a call to the venue associated with $1">$2</a></div>', voiceMark.phoneNumberUrl, voiceMark.getTitle(), voiceMark.phoneNumber);
		this.infoWindowBuffer.append('<div id="vmaddrphone">$0</div>', voiceMark.phoneNumber);
        this.infoWindowBuffer.append('<div id="vmaddrwebsite"><a href="$0" title="Visit the website for the venue associated with $1">$2</a></div>', voiceMark.website, voiceMark.getTitle(), voiceMark.website);
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append('<div id="right-side">');
        //this.infoWindowBuffer.append('<a class="directions-link" target="_blank" href="http://maps.google.com/maps?daddr=$0,$1($2)">Get Directions</a>', voiceMark.lat, voiceMark.lng, encodeURIComponent(voiceMark.getTitle()));
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append('<div style="clear:both"></div>');
        this.infoWindowBuffer.append("</div>");
		if (voiceMark.isBiz) {
			this.infoWindowBuffer.append('<div id="player-and-rating-container" class="green">');
			this.infoWindowBuffer.append('<span id="special-offers">Special Offers</span>');
		}
		else {
			this.infoWindowBuffer.append('<div id="player-and-rating-container" class="blue">');
			this.infoWindowBuffer.append('<span id="special-offers">User Review</span>');
		}
		
        this.infoWindowBuffer.append('<div id="vmplayer"><a href="/geogstreamer/GetVoiceMark/$0" title="Listen to this Voice Mark as an MP3 stream" rel="alternate nofollow" type="audio/mpeg"><img id="play-button-image" src="/images/fake-vmplayer-81x24.png" alt="Play Button"/>Play</a></div>', voiceMark.id);
		this.infoWindowBuffer.append('<div id="sharing-widget"><span id="sharing-widget-text">SHARE</span> ');
		this.infoWindowBuffer.append('<span id="sharesection-addthis"><a class="addthis-link addthis_button_facebook" href="http://www.addthis.com/bookmark.php">');
		this.infoWindowBuffer.append('<img class="mini-sharing-image" src="/images/facebook_icon.png"/>');
	        this.infoWindowBuffer.append('</a>');
	        this.infoWindowBuffer.append('<a class="addthis_button_twitter" href="http://www.addthis.com/bookmark.php">');
		this.infoWindowBuffer.append('<img class="mini-sharing-image" src="/images/twitter_icon.png"/>');
	        this.infoWindowBuffer.append('</a>');
		this.infoWindowBuffer.append('<a class="addthis_button_email" href="http://www.addthis.com/bookmark.php">');
		this.infoWindowBuffer.append('<img class="mini-sharing-image" src="/images/mail_icon-1.png"/>');
		this.infoWindowBuffer.append('</a>');
		this.infoWindowBuffer.append('<span id="sharesection-send-to-phone" class="sharesection-link"><img class="mini-sharing-image" src="/images/phone_icon.png"/></span>');
		this.infoWindowBuffer.append('</span>');
		
		this.infoWindowBuffer.append('</div>');
        //this.infoWindowBuffer.append('<div id="vmratingcontrol"></div>');
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append('<div id="midinfo">');
		this.infoWindowBuffer.append('<div id="more-info-toggle" class="vm_bubble_accordion_toggle_fake"><span>Information & Reviews</span><div class="get-directions-container"><a class="directions-link" target="_blank" href="http://maps.google.com/maps?daddr=$0,$1($2)">Get Directions</a></div></div>', voiceMark.lat, voiceMark.lng, encodeURIComponent(voiceMark.getTitle()));
        this.infoWindowBuffer.append('<div id="moreinfowrapper" class="vm_bubble_accordion_content"><div id="moreinfo"></div></div>');
        this.infoWindowBuffer.append('<div id="creator-info-toggle" class="vm_bubble_accordion_toggle_fake"><span>Photos</span><div id="add-voicemark-picture-container"><a class="add-pictures-link" id="add-voicemark-picture-link" href="#">Upload a Photo</a></div></div>');
        this.infoWindowBuffer.append('<div id="creatorinfo" class="vm_bubble_accordion_content"><div class="accordion-content-wrapper"><div id="userinfocontainer" style="display:none"></div><div id="loader"><img id="loaderimage" src="/images/loading-32x32-blue-white.gif"/></div></div></div>');
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append('<div id="bottominfo">');
		this.infoWindowBuffer.append('<div id="picture-gallery">');
		
		var pictures = voiceMark.pictures;
		var defaultImage;
		var defaultThumbnail;
		if (pictures !== null && pictures.length > 0) {
			var currentPicture = pictures[0];
			defaultImage = String.format("/api/voicemark/$0/pictures/$1/", voiceMark.id, currentPicture.id);
			defaultThumbnail = String.format("/api/voicemark/$0/pictures/$1/thumbnail/small/", voiceMark.id, currentPicture.id);
			//this.infoWindowBuffer.append('<div id="add-voicemark-picture-container"><a id="add-voicemark-picture-link" href="#">Add Pics!</a></div>');
			this.infoWindowBuffer.append('<div id="default-voicemark-picture-and-add-control-container">');
			this.infoWindowBuffer.append('<div id="default-voicemark-picture-container">');
			this.infoWindowBuffer.append('<a href="$0" class="lightview" rel="gallery[voicemarkgallery]"><img src="$1" id="default-voicemark-picture"/></a>', defaultImage, defaultThumbnail);
			this.infoWindowBuffer.append('</div>'); // default-voicemark-picture-container
			
			this.infoWindowBuffer.append('</div>'); // default-voicemark-picture-and-add-control-container
			var imageUrl;
			var thumbnailUrl;
			for (var i = 0; i < pictures.length; ++i) {
				currentPicture = pictures[i];
				imageUrl = String.format("/api/voicemark/$0/pictures/$1/", voiceMark.id, currentPicture.id);
				thumbnailUrl = String.format("/api/voicemark/$0/pictures/$1/thumbnail/small/", voiceMark.id, currentPicture.id);
				this.infoWindowBuffer.append('<div class="voicemark-picture-container"><a href="$0" class="lightview" rel="gallery[voicemarkgallery]"><img src="http://cdn$1.$2$3"/></a></div>', imageUrl, i%3, gg.Environment.ServerRunningOn, thumbnailUrl);
			}
		}
		//else {
		//	defaultImage = "/images/add-pics.png";
		//	this.infoWindowBuffer.append('<div id="default-voicemark-picture-and-add-control-container">');
		//	this.infoWindowBuffer.append('<div id="default-voicemark-picture-container">');
		//	this.infoWindowBuffer.append('<img src="$0" id="default-voicemark-picture"/>', defaultImage);
		//	this.infoWindowBuffer.append('</div>'); // default-voicemark-picture-container
		//	this.infoWindowBuffer.append('<div id="add-voicemark-picture-container"><a id="add-voicemark-picture-link" href="#">Add Pics!</a></div>');
		//	this.infoWindowBuffer.append('</div>'); // default-voicemark-picture-and-add-control-container
		//}
		this.infoWindowBuffer.append('</div>'); // picture-gallery
        //this.infoWindowBuffer.append('<div id="respondsection">');
        //this.infoWindowBuffer.append('<img src="/images/respond.png"/><span>$0</span>', /*gg.$S("VoiceMarkWindowRespond")*/"Respond!");
        //this.infoWindowBuffer.append("</div>");
        //this.infoWindowBuffer.append('<div id="sharesection">');
        //this.infoWindowBuffer.append('<div id="sharesection-addthis"></div>');
        //this.infoWindowBuffer.append('<div id="sharesection-geograffiti-links" class="small-top-margin">');
        //this.infoWindowBuffer.append('<span id="sharesection-send-to-phone" class="sharesection-link"><img class="share-section-image" src="/images/phone.png"/>Send 2 Phone</span>');
        //this.infoWindowBuffer.append('<span id="sharesection-link-to-this" class="small-left-margin sharesection-link"><img class="share-section-image" src="/images/link.png"/>Link 2 This</span>');
        //this.infoWindowBuffer.append("</div>");
        //this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append("</div>");
        this.infoWindowBuffer.append("</div>");
        return this.infoWindowBuffer.toString()
    },
    createVoiceMarkTab: function(voiceMark){
		if (false) {
			return new google.maps.InfoWindowTab(/*gg.$S("VoiceMarkTabTitle")*/"Voice Mark", this.createInitialContentFromVoiceMark(voiceMark))
		}
		else {
			return new google.maps.InfoWindowTab("Voice Mark",  this.newCreateInitialContentFromVoiceMark(voiceMark));
		}
    },
    createResponsesTab: function(responseCount){
        var tabTitle = String.format("$0$1", /*gg.$S("ResponsesTabTitle")*/"Reviews", responseCount > 0 ? "*" : "");
        return new google.maps.InfoWindowTab(tabTitle, '<div id="voicemark-responses-content"><div id="voicemark-responses-container"></div><div id="voicemark-responses-pagingcontrol"></div></div>')
    },
    createTabsForVoiceMark: function(voiceMark){
        this.infoWindowTabs[0] = this.createVoiceMarkTab(voiceMark);
        //this.infoWindowTabs[1] = this.createResponsesTab(voiceMark.responseCount);
        return this.infoWindowTabs
    },
    responsesPageClicked: function(e){
        if (gg.debug) {
            gg.log("page click...event %o", e)
        }
        var element = Event.element(e);
        var activeClassName = "activepage";
        var inactiveClassName = "inactivepage";
        element.toggleClassName(inactiveClassName);
        element.toggleClassName(activeClassName);
        var idValue = element.getAttribute("id");
        id = parseInt(idValue.charAt(idValue.length - 1));
        if (gg.debug) {
            gg.log("the arguments array is %o", $A(arguments))
        }
        var cursor = $A(arguments)[1];
        var that = $A(arguments)[2];
        if (id === 0 && (id !== (cursor.pages.length - 1))) {
            var next = element.next();
            if (next.hasClassName(activeClassName)) {
                next.toggleClassName(activeClassName);
                next.toggleClassName(inactiveClassName);
                var obj = {
                    fx: that.responsesPageClicked
                };
                obj.bfx = obj.fx.bindAsEventListener(obj, cursor, that);
                next.observe("click", obj.bfx)
            }
        }
        else {
            if (id !== 0 && (id === (cursor.pages.length - 1))) {
                var previous = element.previous();
                if (previous.hasClassName(activeClassName)) {
                    previous.toggleClassName(activeClassName);
                    previous.toggleClassName(inactiveClassName);
                    var obj = {
                        fx: that.responsesPageClicked
                    };
                    obj.bfx = obj.fx.bindAsEventListener(obj, cursor, that);
                    previous.observe("click", obj.bfx)
                }
            }
            else {
                var previous = element.previous();
                var next = element.next();
                if (previous.hasClassName(activeClassName)) {
                    previous.toggleClassName(activeClassName);
                    previous.toggleClassName(inactiveClassName);
                    var obj = {
                        fx: that.responsesPageClicked
                    };
                    obj.bfx = obj.fx.bindAsEventListener(obj, cursor, that);
                    previous.observe("click", obj.bfx)
                }
                else {
                    if (next.hasClassName(activeClassName)) {
                        next.toggleClassName(activeClassName);
                        next.toggleClassName(inactiveClassName);
                        var obj = {
                            fx: that.responsesPageClicked
                        };
                        obj.bfx = obj.fx.bindAsEventListener(obj, cursor, that);
                        next.observe("click", obj.bfx)
                    }
                }
            }
        }
        element.stopObserving("click", this.bfx);
        if (gg.debug) {
            gg.log("at this point we need to relaunch a getResponses for the new page")
        }
    },
    activateResponsesPaging: function(cursor, pagingControl){
        var self = this;
        if (cursor) {
            var pages = cursor.pages;
            var buffer = new geograffiti.StringBuffer();
            for (var i = 0, limit = pages.length; i < limit; i++) {
                var currentPage = pages[i];
                var spanClass = "inactivepage";
                if (i === cursor.currentPageIndex) {
                    spanClass = "activepage"
                }
                buffer.append(String.format('<span id="responsespage-$0" class="pagelabel $1">$2</span>', i, spanClass, currentPage.label))
            }
            pagingControl.innerHTML = buffer.toString();
            var inactivePages = pagingControl.select("span.inactivepage");
            if (inactivePages) {
                for (var i = 0, limit = inactivePages.length; i < limit; i++) {
                    var currentPage = inactivePages[i];
                    var obj = {
                        fx: self.responsesPageClicked
                    };
                    obj.bfx = obj.fx.bindAsEventListener(obj, cursor, self);
                    currentPage.observe("click", obj.bfx)
                }
            }
        }
    },
    enableRespondFormSubmitButton: function(){
        var callMeButton = $("respondform-submit-button");
        if (callMeButton) {
            callMeButton.enable()
        }
        var callMeButtonSection = $("respondform-submit-container");
        callMeButtonSection.addClassName("enabled");
        callMeButtonSection.removeClassName("disabled");
        var messages = $("respondform-submit-button-messages");
        messages.update("")
    },
    disableRespondFormSubmitButton: function(){
        var callMeButton = $("respondform-submit-button");
        if (callMeButton) {
            callMeButton.disable()
        }
        var callMeButtonSection = $("respondform-submit-container");
        callMeButtonSection.addClassName("disabled");
        callMeButtonSection.removeClassName("enabled");
        var messages = $("respondform-submit-button-messages");
        messages.update("Enter a valid 10-digit U.S. Phone Number")
    },
    validateSendFormInput: function(){
        var phoneNumber = $F("sendform-phonenumber");
        if (phoneNumber.charAt(0) === "1") {
            phoneNumber = phoneNumber.substring(1);
            $("sendform-phonenumber").value = phoneNumber
        }
        gg.log("%o --", phoneNumber);
        if (phoneNumber.length === 10) {
            this.enableSendFormSubmitButton()
        }
        else {
            this.disableSendFormSubmitButton()
        }
    },
    validateRespondFormInput: function(){
        var phoneNumber = $F("respondform-phonenumber");
        if (phoneNumber.charAt(0) === "1") {
            phoneNumber = phoneNumber.substring(1);
            $("respondform-phonenumber").value = phoneNumber
        }
        gg.log("%o --", phoneNumber);
        if (phoneNumber.length === 10) {
            this.enableRespondFormSubmitButton()
        }
        else {
            this.disableRespondFormSubmitButton()
        }
    },
    enableSendFormSubmitButton: function(){
        var sendButton = $("sendform-submit-button");
        if (sendButton) {
            sendButton.enable()
        }
        var sendButtonSection = $("sendform-submit-container");
        sendButtonSection.addClassName("enabled");
        sendButtonSection.removeClassName("disabled");
        var messages = $("sendform-submit-button-messages");
        messages.update("")
    },
    disableSendFormSubmitButton: function(){
        var sendButton = $("sendform-submit-button");
        if (sendButton) {
            sendButton.disable()
        }
        var sendButtonSection = $("sendform-submit-container");
        sendButtonSection.addClassName("disabled");
        sendButtonSection.removeClassName("enabled");
        var messages = $("sendform-submit-button-messages");
        messages.update("Enter a valid 10-digit U.S. Phone Number")
    },
    enableResponsesRespondFormSubmitButton: function(){
        var callMeButton = $("responses-respondform-submit-button");
        if (callMeButton) {
            callMeButton.enable()
        }
        var callMeButtonSection = $("responses-respondform-submit-container");
        callMeButtonSection.addClassName("enabled");
        callMeButtonSection.removeClassName("disabled");
        var messages = $("responses-respondform-submit-button-messages");
        messages.update("")
    },
    disableResponsesRespondFormSubmitButton: function(){
        var callMeButton = $("responses-respondform-submit-button");
        if (callMeButton) {
            callMeButton.disable()
        }
        var callMeButtonSection = $("responses-respondform-submit-container");
        callMeButtonSection.addClassName("disabled");
        callMeButtonSection.removeClassName("enabled");
        var messages = $("responses-respondform-submit-button-messages");
        messages.update("Enter a valid 10-digit U.S. Phone Number")
    },
    validateResponsesRespondFormInput: function(){
        var phoneNumber = $F("responses-respondform-phonenumber");
        if (phoneNumber.charAt(0) === "1") {
            phoneNumber = phoneNumber.substring(1);
            $("responses-respondform-phonenumber").value = phoneNumber
        }
        gg.log("%o --", phoneNumber);
        if (phoneNumber.length === 10) {
            this.enableResponsesRespondFormSubmitButton()
        }
        else {
            this.disableResponsesRespondFormSubmitButton()
        }
    },
    renderResponses: function(voiceMark, apiResponse){
        try {
            var self = this;
            if (gg.debug) {
                gg.log("renderResponses with args %o %o", voiceMark, apiResponse)
            }
            if (apiResponse) {
                var pagingControl = $("voicemark-responses-pagingcontrol");
                var containerHeight = $(this.map.getInfoWindow().getContentContainers()[1]).getHeight() - pagingControl.getHeight();
                if (gg.debug) {
                    gg.log("The container height is %d", containerHeight)
                }
                $("voicemark-responses-content").setStyle(String.format("height: $0px", containerHeight));
                if (gg.debug) {
                    gg.log("The responses content style was just updated!")
                }
                if (gg.debug) {
                    gg.log("buffer being aliased with this=%o", this)
                }
                var buffer = this.infoWindowBuffer;
                var ba = buffer.append.bind(buffer);
                if (gg.debug) {
                    gg.debug("created an alias for buffer.append")
                }
                buffer.clear();
                if (gg.debug) {
                    gg.log("cleared the buffer")
                }
                var audioPlayerContainers = new Array();
                if (gg.debug) {
                    gg.log("created new array")
                }
                var responsePlayerId;
                if (gg.debug) {
                    gg.log("declared responsePlayerId")
                }
                var responses = apiResponse.voiceMarks;
                if (gg.debug) {
                    gg.log("declared responses")
                }
                var response;
                var userLink;
                if (responses.length === 0) {
                    ba('<p id="responses-no-responses-message">This Voice Mark does not have responses yet.  Be the first to respond by publishing your opinion by clicking below!</p>');
                    ba('<div id="responses-respond-link">Respond!</div>')
                }
                else {
                    for (var i = 0, limit = responses.length; i < limit; ++i) {
                        response = responses[i];
                        if (gg.debug) {
                            gg.log("Buffer add for response%d", response.id)
                        }
                        ba('<div id="response$0" class="voicemark-response-container">', response.id);
                        ba('<div id="response$0-info" class="voicemark-response-info">', response.id);
                        if (response.isAnonymous) {
                            userLink = String.format("$0/$1", gg.SEOFriendlyUrl.ViewAnonymousUser, response.vid);
                            ba("Created by $0 on $1", response.userName, response.createdOn)
                        }
                        else {
                            userLink = String.format("$0/$1", gg.SEOFriendlyUrl.ViewUser, response.uid);
                            ba('Created by <a class="user-link" href="$0">$1</a> on $2', userLink, response.userName, response.createdOn)
                        }
                        ba("</div>");
                        responsePlayerId = String.format("response-player-$0", response.id);
                        audioPlayerContainers.push(responsePlayerId);
                        ba('<div id="$0" class="response-player-container"><span class="flash-alternative-content">Download <a href="http://www.adobe.com/go/getflashplayer">Adobe Flash Player</a> to listen to Voice Marks.</span></div>', responsePlayerId);
						ba('<div id="response-sharing-section-$0">SHARE SHARE</div>', response.id);
                        ba("</div>")
                    }
                }
                if (gg.debug) {
                    gg.log("Going to set innerHTML for responses")
                }
                var responsesContainer = $("voicemark-responses-container");
                responsesContainer.innerHTML = buffer.toString();
                if (gg.debug) {
                    gg.log("Set innerHTML for responses")
                }
                var nakedResponse = null;
                var voiceMarkResponse = null;
                if (responses.length !== 0) {
                    for (var i = 0, limit = responses.length; i < limit; ++i) {
                        nakedResponse = responses[i];
                        voiceMarkResponse = Object.extend(nakedResponse, gg.VoiceMarkBase);
                        voiceMarkResponse.title = voiceMark.getTitle();
                        this.embedAudioPlayer(voiceMarkResponse, audioPlayerContainers[i])
                    }
                    this.activateResponsesPaging(apiResponse.cursor, pagingControl);
                    $$(".user-link").each(function(userLink){
                        userLink.observe("click", function(e){
                            e.stop();
                            var userId = userLink.getAttribute("href").gsub(String.format("$0/", gg.SEOFriendlyUrl.ViewUser), "");
                            self.openProfileBubble(userId)
                        })
                    })
                }
                else {
                    var respondSection = $("responses-respond-link");
                    respondSection.stopObserving();
                    respondSection.observe("prototip:shown", function(){
                        self.disableResponsesRespondFormSubmitButton();
                        var responsesRespondFormPhoneNumber = $("responses-respondform-phonenumber");
                        responsesRespondFormPhoneNumber.stopObserving();
                        responsesRespondFormPhoneNumber.observe("keypress", function(e){
                            gg.log("Key pressed %o", e);
                            var keyCode = e.charCode || e.keyCode;
                            gg.log("key code is %d", keyCode);
                            if (keyCode >= 48 && keyCode <= 57) {
                                self.validateResponsesRespondFormInput.bind(self).defer()
                            }
                            else {
                                if (keyCode >= 58) {
                                    e.stop();
                                    gg.log("not number")
                                }
                                else {
                                    if (keyCode != Event.KEY_BACKSPACE && keyCode != Event.KEY_DELETE && keyCode != Event.KEY_LEFT && keyCode != Event.KEY_UP && keyCode != Event.KEY_RIGHT && keyCode != Event.KEY_DOWN) {
                                        e.stop()
                                    }
                                    else {
                                        gg.log("probably some non-printable");
                                        self.validateResponsesRespondFormInput.bind(self).defer()
                                    }
                                }
                            }
                        });
                        var respondForm = $("responses-respondform");
                        respondForm.stopObserving();
                        respondForm.observe("submit", function(e){
                            var respondMessage = $("responses-respond-message");
                            e.stop();
                            respondForm.request({
                                onSuccess: function(transport){
                                    respondMessage.innerHTML = "You should now receive a call from GeoGraffiti enabling you to record your Voice Mark response!";
                                    respondMessage.addClassName("respond-success")
                                },
                                onFailure: function(){
                                    respondMessage.innerHTML = "We weren't able to call you.  Try that again and if it fails, please contact us using the \"Contact\" link on the top right corner of the page and we'll get back to you within a day.";
                                    respondMessage.addClassName("respond-error")
                                }
                            })
                        })
                    });
                    new Tip(respondSection, self.createResponsesRespondTipContent(voiceMark), {
                        style: "geograffiti",
                        hook: {
                            target: "bottomRight",
                            tip: "topLeft"
                        },
                        offset: {
                            x: -350,
                            y: 0
                        },
                        stem: "topMiddle",
                        title: "Leave a Voice Response"
                    })
                }
            }
            else {
                if (gg.debug) {
                    gg.log("Responses for Voice Mark %d was null!", voiceMark.id)
                }
            }
        } 
        catch (e) {
            if (gg.debug) {
                gg.log("EERRRRR ----> %o", e)
            }
        }
    },
    createNeedVerifiedPhoneTipContent: function(){
        var message = "You need at least 1 verified phone number to use Send 2 Phone.  Please add and verify your phone number then click Send 2 Phone again.";
        var buffer = new gg.StringBuffer();
        var ba = buffer.append.bind(buffer);
        ba('<p class="need-verified-phone-tip-message">$0</p>', message);
        return buffer.toString()
    },
    createNeedLoginTipContent: function(message){
        var buffer = new gg.StringBuffer();
        var ba = buffer.append.bind(buffer);
        ba('<p class="need-login-tip-message">$0</p>', message);
        ba('<div class="need-login-tip-link">Login!</div>');
        return buffer.toString()
    },
    createNeedLoginTip: function(element, options){
        var defaultOptions = $H({
            message: "You need to login to perform this action.",
            onLogin: gg.EmptyFunction,
            onNoLogin: gg.EmptyFunction
        });
        var mergedOptions = defaultOptions.merge(options);
        try {
            var self = this;
            var targetElement = $(element);
            var tip = null;
            var noLoginHandler = null;
            var loginHandler = document.observe(gg.UserEvent.UserLoggedIn, function(e){
                mergedOptions.get("onLogin")();
                document.stopObserving(gg.UserEvent.UserLoggedIn, loginHandler);
                document.stopObserving(gg.UserEvent.UserDidNotLogIn, noLoginHandler)
            });
            noLoginHandler = document.observe(gg.UserEvent.UserDidNotLogIn, function(e){
                mergedOptions.get("onNoLogin")();
                document.stopObserving(gg.UserEvent.UserLoggedIn, loginHandler);
                document.stopObserving(gg.UserEvent.UserDidNotLogIn, noLoginHandler)
            });
            targetElement.stopObserving("prototip:shown");
            targetElement.observe("prototip:shown", function(e){
                try {
                    e.stop();
                    var prototip = e.element().prototip;
                    var loginTipLink = $$(".need-login-tip-link")[0];
                    loginTipLink.stopObserving("click");
                    loginTipLink.observe("click", function(e){
                        if (prototip) {
                            prototip.remove();
                            targetElement.stopObserving("prototip:shown");
                            targetElement.stopObserving("prototip:hidden")
                        }
                        gg.userWantsToLogIn()
                    })
                } 
                catch (e) {
                    gg.error("error with prototip shown handler %o", e)
                }
            });
            targetElement.stopObserving("prototip:hidden");
            targetElement.observe("prototip:hidden", function(e){
                e.stop();
                gg.log("prototip was hidden - createNeedLoginTip");
                if (tip) {
                    gg.log("removing the tip");
                    var prototip = e.element().prototip;
                    if (prototip) {
                        prototip.remove()
                    }
                }
            });
            tip = new Tip(targetElement, self.createNeedLoginTipContent(mergedOptions.get("message")), {
                style: "geograffiti",
                hook: {
                    target: "bottomMiddle",
                    tip: "topMiddle"
                },
                offset: {
                    x: 0,
                    y: -10
                },
                stem: "topMiddle",
                title: "Login Needed"
            });
            gg.log("tip created with %o", tip);
            tip.target.prototip.show()
        } 
        catch (e) {
            gg.error("Error in createNeedLoginTip - %o", e)
        }
    },
    loadVoiceMarkResponses: function(voiceMark){
        var self = this;
        var offset = 0;
        var responseOffsetToShow = $("responseOffsetToShow");
        if (responseOffsetToShow) {
            offset = $F(responseOffsetToShow);
            if (offset && !String.isNullOrEmpty(offset)) {
                responseOffsetToShow.writeAttribute("value", null);
            }
        }
        var callParameters = {
            vmid: voiceMark.id,
            offset: offset,
            format: "json"
        };
        new Ajax.Request(gg.ApiUrl.GetResponses, {
            parameters: $H(callParameters),
            onSuccess: function(response){
                var apiResponse = response.responseText.evalJSON(true);
                self.renderResponses(voiceMark, apiResponse);
                var responseIdToShow = $("responseIdToShow");
                if (responseIdToShow) {
                    var id = $F(responseIdToShow);
                    if (id && !String.isNullOrEmpty(id)) {
                        responseIdToShow.writeAttribute("value", null);
                        self.map.getInfoWindow().selectTab(1);
                        var responseContainer = $(String.format("response$0", id));
                        if (responseContainer) {
                            responseContainer.scrollTo();
                            var playerId = String.format("response-player-$0", id);
                            gg.log("player id is %s with object %o", playerId, $(playerId));
                            AudioPlayer.open.delay(1, playerId)
                        }
                    }
                }
            },
            onFailure: function(response){
                if (gg.debug) {
                    gg.log("Error occurred while trying to fetch VM responses [ %d:%s:%s]", response.status, response.statusText, response.responseText)
                }
            }
        })
    },
    hackTabs: function(voiceMark){
    },
    embedAudioPlayer: function(voiceMark, elementId){
        AudioPlayer.embed(elementId, {
            soundFile: String.format("/geogstreamer/GetVoiceMark/$0", voiceMark.id),
            titles: encodeURIComponent(voiceMark.getTitle()),
            artists: encodeURIComponent(voiceMark.userName)
        })
    },
    createStarRatingControl: function(voiceMark){
        new Starbox("vmratingcontrol", voiceMark.starRating, {
            rerate: true,
            identity: voiceMark.id,
            indicator: "#{average} stars out of #{total} votes",
            total: voiceMark.totalVotes
        })
    },
    createAccordionControl: function(){
        var midInfoAccordion = new accordion("midinfo", {
            mode: "2toggles1on",
            classNames: {
                toggle: "vm_bubble_accordion_toggle",
                toggleActive: "vm_bubble_accordion_toggle_active",
                content: "vm_bubble_accordion_content"
            }
        });
        midInfoAccordion.activate($$("#midinfo .vm_bubble_accordion_toggle")[0])
    },
    sendBecomeFanRequest: function(parameters, elementToUpdate){
        var self = this;
        new Ajax.Request(gg.ApiUrl.BecomeFan, {
            parameters: $H(parameters),
            onSuccess: function(response){
                self.updateAndFlashElement(elementToUpdate, true, "User Added to your Hood!", "action-become-fan-success")
            },
            onFailure: function(response){
                self.updateAndFlashElement(elementToUpdate, true, "Error becoming their Fan", "action-become-fan-error");
                gg.log("Error becoming fan...%o", response)
            }
        })
    },
    populateUserData: function(data){
        try {
            var self = this;
            var buffer = new gg.StringBuffer();
					//ba('<a href="/api/users/$0/pictures/0/" class="lightview" title="Profile Picture for $1">', profile.systemUserId, profile.userName);
        //ba('<img src="/api/users/$0/pictures/0/thumbnail/medium/?$1" alt="Profile Picture for $2"/>', profile.systemUserId, new Date().getTime(), profile.userName);
		//ba('</a>');

            buffer.append('<div id="profile-top-section">');
            buffer.append('<div id="profile-pic-container"><a href="/api/user/$0/pictures/0/" class="lightview" title="Profile Picture for $1"><img src="/api/user/$0/pictures/0/thumbnail/medium/?$2" alt="Profile Picture for $1"/></a></div>', data.systemUserId, data.userName, new Date().getTime());
            buffer.append('<div id="profile-right-section">');
            buffer.append('<div id="profile-information">');
            buffer.append('<div id="profile-username">$0</div>', data.userName);
            buffer.append('<div id="profile-user-statistics">');
            buffer.append('<div id="profile-num-voicemarks-created">has created $0 Voice Mark(s)</div>', data.numberOfVoiceMarks);
            buffer.append('<div id="profile-num-fans">has $0 fan(s)</div>', data.numberOfFans);
            buffer.append('<div id="profile-num-subscriptions">is a fan of $0 user(s)</div>', data.numberOfSubscriptions);
            buffer.append("</div>");
            buffer.append("</div>");
            buffer.append('<div id="profile-actions">');
            if (!data.isAnonymous) {
                buffer.append('<div id="action-view-their-profile" class="profile-action">Profile</div>')
            }
            buffer.append('<div id="action-listen-to-their-voicemarks" class="profile-action">Their Voice Marks</div>');
            buffer.append('<div id="action-become-their-fan" class="profile-action">Become Their Fan</div>');
            buffer.append("</div>");
            buffer.append("</div>");
            buffer.append("</div>");
            $("userinfocontainer").innerHTML = buffer.toString();
            new Effect.Parallel([Effect.Fade("loader", {
                sync: true
            }), Effect.Appear("userinfocontainer", {
                sync: true
            })], {
                delay: 1
            });
            if (!data.isAnonymous) {
                var actionViewTheirProfile = $("action-view-their-profile");
                actionViewTheirProfile.stopObserving();
                actionViewTheirProfile.observe("click", function(e){
                    e.stop();
                    self.mapElement.fire(gg.MapEvent.ViewProfileLinkClicked, {
                        id: data.systemUserId
                    })
                })
            }
            var actionListenToTheirVoiceMarks = $("action-listen-to-their-voicemarks");
            actionListenToTheirVoiceMarks.stopObserving();
            actionListenToTheirVoiceMarks.observe("click", function(e){
                e.stop();
                self.fireSearchByUser(data.systemUserId, data.voiceUserId, data.userName)
            });
            var becomeFanElement = $("action-become-their-fan");
            becomeFanElement.stopObserving();
            becomeFanElement.observe("click", function(e){
                e.stop();
                var parameters = {
                    subscriptiontype: data.isAnonymous === true ? "voiceuser" : "systemuser",
                    uid: data.systemUserId,
                    vid: data.voiceUserId
                };
                if (!gg.userLoggedIn()) {
                    self.createNeedLoginTip(becomeFanElement, {
                        message: "You need to login in order to become a user's fan.",
                        onLogin: function(){
                            gg.info("user logged in...");
                            self.sendBecomeFanRequest(parameters, becomeFanElement)
                        },
                        onNoLogin: function(){
                            gg.info("user did not login")
                        }
                    })
                }
                else {
                    self.sendBecomeFanRequest(parameters, becomeFanElement)
                }
            })
        } 
        catch (e) {
            gg.error("CRAP %o", e)
        }
    },
    updateAndFlashElement: function(element, restore, content, contentClass){
        var targetElement = $(element);
        var previousContent = restore ? targetElement.innerHTML : null;
        targetElement.update(content);
        targetElement.toggleClassName(contentClass);
        targetElement.pulsate({
            afterFinish: function(e){
                if (restore) {
                    targetElement.update(previousContent);
                    targetElement.toggleClassName(contentClass)
                }
            }
        })
    },
    deleteVoiceMark: function(voiceMarkId){
        var parameters = $H({
            vmid: voiceMarkId
        });
        new Ajax.Request(gg.ApiUrl.DeleteVoiceMark, {
            parameters: parameters,
            onSuccess: function(transport){
                var apiResponse = transport.responseText.evalJSON(true);
                if (apiResponse.status === 0) {
                    gg.info("deleted Voice Mark!!")
                }
                else {
                    gg.error("api response reports failure...%o", apiResponse)
                }
            },
            onFailure: function(transport){
                gg.error("request failed %o", transport)
            }
        })
    },
    fireSearchAllWithTag: function(tagId, tagName){
        var self = this;
        var bounds = self.getBounds();
        var northEast = bounds.northEast;
        var southWest = bounds.southWest;
        var center = self.getCenter();
        self.mapElement.fire(gg.MapEvent.SearchAllWithTagRequested, {
            tag: tagName,
            tagId: tagId,
            botLeftLat: southWest.latitude,
            botLeftLon: southWest.longitude,
            topRightLat: northEast.latitude,
            topRightLon: northEast.longitude,
            centerLat: center.latitude,
            centerLon: center.longitude
        })
    },
    populateMoreInfoSection: function(voiceMark){
        if (gg.debug) {
            gg.log("VM is %o", voiceMark)
        }
        var self = this;
        var buffer = new gg.StringBuffer();
        buffer.append('<div id="moreinfo-top">');
		buffer.append('<div id="picture-gallery">');
		
		var pictures = voiceMark.pictures;
		var defaultImage;
		var defaultThumbnail;
		if (pictures !== null && pictures.length > 0) {
			var currentPicture = pictures[0];
			defaultImage = String.format("/api/voicemark/$0/pictures/$1/", voiceMark.id, currentPicture.id);
			defaultThumbnail = String.format("/api/voicemark/$0/pictures/$1/thumbnail/small/", voiceMark.id, currentPicture.id);
			buffer.append('<div id="add-voicemark-picture-container"><a id="add-voicemark-picture-link" href="#">Add Pics!</a></div>');
			buffer.append('<div id="default-voicemark-picture-and-add-control-container">');
			buffer.append('<div id="default-voicemark-picture-container">');
			buffer.append('<a href="$0" class="lightview" rel="gallery[voicemarkgallery]"><img src="$1" id="default-voicemark-picture"/></a>', defaultImage, defaultThumbnail);
			buffer.append('</div>'); // default-voicemark-picture-container
			
			buffer.append('</div>'); // default-voicemark-picture-and-add-control-container
			var imageUrl;
			var thumbnailUrl;
			for (var i = 1; i < pictures.length; ++i) {
				currentPicture = pictures[i];
				imageUrl = String.format("/api/voicemark/$0/pictures/$1/", voiceMark.id, currentPicture.id);
				thumbnailUrl = String.format("/api/voicemark/$0/pictures/$1/thumbnail/small/", voiceMark.id, currentPicture.id);
				buffer.append('<div class="voicemark-picture-container"><a href="$0" class="lightview" rel="gallery[voicemarkgallery]"><img src="http://cdn$1.$2$3"/></a></div>', imageUrl, i%3, gg.Environment.ServerRunningOn, thumbnailUrl);
			}
		}
		else {
			defaultImage = "/images/add-pics.png";
			buffer.append('<div id="default-voicemark-picture-and-add-control-container">');
			buffer.append('<div id="default-voicemark-picture-container">');
			buffer.append('<img src="$0" id="default-voicemark-picture"/>', defaultImage);
			buffer.append('</div>'); // default-voicemark-picture-container
			buffer.append('<div id="add-voicemark-picture-container"><a id="add-voicemark-picture-link" href="#">Add Pics!</a></div>');
			buffer.append('</div>'); // default-voicemark-picture-and-add-control-container
		}
		buffer.append('</div>'); // picture-gallery
		/*
        buffer.append('<div id="moreinfo-voicemark-id" class="moreinfo-label">ID: $0</div>', voiceMark.id);
		var dateData = voiceMark.isBiz ? String.format("Updated: $0", voiceMark.modifiedOn) : String.format("Created: $0", voiceMark.createdOn);
        buffer.append('<div id="moreinfo-voicemark-createdon" class="moreinfo-label">$0</div>', dateData);
        buffer.append('<div id="moreinfo-voicemark-listens" class="moreinfo-label">Listens: $0</div>', voiceMark.listens);
        buffer.append("</div>");
        if (gg.debug) {
            gg.log("set buffer for top")
        }
        buffer.append('<div id="moreinfo-category-edit-section">');
        buffer.append('<div id="moreinfo-category-edit-labels">');
        buffer.append('<div id="moreinfo-category-label" class="moreinfo-label">Category (owner: click below to edit)</div>');
        buffer.append("</div>");
        if (gg.debug) {
            gg.log("set buffer cat section")
        }
        buffer.append('<div id="moreinfo-category-edit-controls">');
        buffer.append('<div id="moreinfo-category-edit-control">$0</div>', voiceMark.category);
        buffer.append("</div>");
        buffer.append("</div>");
        buffer.append('<div id="moreinfo-voicemark-tags-section">');
        buffer.append('<div id="moreinfo-voicemark-tags-label" class="moreinfo-label linkify">Tags - Click Here to Add</div>');
        buffer.append('<div id="moreinfo-voicemark-tags-edit-control">');
        var tagsList = null;
        var tags = voiceMark.tags;
        if (tags) {
            tagsList = new Array();
            var urlEncodedTagName = null;
            var tagName = null;
            var tagId = null;
            var currentTag = null;
            for (var i = 0, limit = tags.length; i < limit; ++i) {
                currentTag = tags[i];
                tagName = currentTag.name;
                tagId = String.format("vm-$0-tag-$1", voiceMark.id, currentTag.id);
                tagsList.push({
                    id: tagId,
                    name: tagName
                });
                buffer.append('<a href="$0/$1" id="$2" class="moreinfo-voicemark-tag">$3</a> ', gg.SEOFriendlyUrl.ViewTag, tagName.gsub(" ", "-"), tagId, tagName)
            }
        }
        buffer.append("</div>");
        buffer.append("</div>");
        */
        $("moreinfo").update(buffer.toString());
		
		var uploaderContainer = $("voicemark-pictures-uploader-container");
		gg.info("uploader container is %o", uploaderContainer);
		uploaderContainer.stopObserving();
		document.observe("lightview:opened", function(e) {
			gg.log("got the event %o", e);
			if ($("lightview").down("#voicemark-pictures-uploader-container")) {
				$("voicemark-picture-upload-form").reset();
				$("progress-message").innerHTML = "";
				$("progress-bar-container").setStyle("visibility:hidden");
				$("voicemark-pictures-uploader-container").setStyle("visibility:visible");
			}
		});
		
		document.observe("lightview:hidden", function(e) {
			gg.log("got the event %o", e);
			$("voicemark-pictures-uploader-container").setStyle("visibility:hidden");
		});
		
		Lightview.updateViews(); // needed b/c of the picture gallery.
		$("add-voicemark-picture-link").observe("click", function(e) {
			e.stop();
			$("voicemark-picture-upload-form").writeAttribute("action", String.format("/api/voicemark/$0/pictures/", voiceMark.id));
			Lightview.show({href: "#voicemark-pictures-uploader-container"});
		});
		
		$("voicemark-picture-upload-form").observe("submit", function(e) {
			if (String.isNullOrEmpty($F("voicemark-picture-file"))) {
				alert("Please choose a picture to upload");
			}
			else {
				$("progress-bar-container").setStyle("visibility:visible");
				$("progress-message").innerHTML = "Uploading";
				new PeriodicalExecuter(function(pe) {
					var url = String.format("/api/voicemark/$0/pictures/session-uploads/pictureFile/?$1", voiceMark.id, new Date().getTime());
					new Ajax.Request(url, {
						method:"GET",
						onSuccess: function(response) {
							var apiResponse = response.responseText.evalJSON(true);
							gg.info("got api response at %o", apiResponse);
							
							$("progress-message").innerHTML = String.format("$0%", apiResponse.uploadProgress);
							var currentWidth = $("progress-bar-container").getWidth();
							var factor = apiResponse.uploadProgress / 100;
							var newWidth = (currentWidth * factor) - 2; /* 1px border on the container */
							$("progress-bar").setStyle(String.format("width:$0px", newWidth));
							
							if (apiResponse.uploadProgress >= 100.0) {
								pe.stop();
							}							
						},
						onFailure: function(response) {
							gg.info("failure...%o", response);
							pe.stop();
						},
						onComplete : function(response) {
							gg.info("complete....%o", response);
							
						},
						onException : function(requester, e) {
							gg.info("exception sending ajax call %o", e);
							pe.stop();
						}
					});
				}, 2);
			}
		});
		
		var remotingFrame = $("voicemark-pictures-remoting-frame");
		if (remotingFrame.attachEvent) {
			remotingFrame.attachEvent("onload", function() {
				try {
					var result = remotingFrame.contentWindow.document.body.innerHTML.evalJSON(true);
					gg.info("result of attachEvent ... %o", result);
					$("progress-bar-container").setStyle("visibility:hidden");
					$("progress-message").innerHTML = "DONE!";
					$("progress-bar").setStyle("width:0px");
					self.openVoiceMarkBubble(voiceMark.id);
					/*
					$("progress-message").pulsate({
						duration:2.0,
						afterFinish:function(effect) {
							Lightview.hide();
						}
					});
					*/
					Lightview.hide();
				} 
				catch (e) {
					gg.error("error from attachEvent %o", e);
					$("progress-bar-container").setStyle("visibility:hidden");
					$("progress-message").innerHTML = "ERROR!";
					$("progress-message").pulsate({
						duration:2.0
					});
				}
			});
		}  
		else {
			try {
				Event.stopObserving(remotingFrame, "load");
				Event.observe(remotingFrame, "load", function(e) {
					e.stop();
					var result = remotingFrame.contentDocument.documentElement.textContent.evalJSON(true);
					gg.info("result of observe load is %o", result);
					$("progress-bar-container").setStyle("visibility:hidden");
					$("progress-message").innerHTML = "DONE!";
					$("progress-bar").setStyle("width:0px");
					self.openVoiceMarkBubble(voiceMark.id);
					/*
					$("progress-message").pulsate({
						duration:2.0,
						afterFinish:function(effect) {
							Lightview.hide();
						}
					});
					*/
					Lightview.hide();
				});				
			}
			catch (e) {
				gg.error("error from observe load... %o", e);
				$("progress-bar-container").setStyle("visibility:hidden");
				$("progress-message").innerHTML = "ERROR!";
				$("progress-message").pulsate({
						duration:2.0
					});
			}
		}
		
        if (tagsList) {
            tagsList.each(function(tagRecord){
                var tagRecordId = $(tagRecord.id);
                tagRecordId.stopObserving();
                tagRecordId.observe("click", function(e){
                    if (gg.debug) {
                        gg.log("will launch tag search for tag %s", tagRecord.name)
                    }
                    e.stop();
                    var bounds = self.getBounds();
                    var northEast = bounds.northEast;
                    var southWest = bounds.southWest;
                    var center = self.getCenter();
                    self.mapElement.fire(gg.MapEvent.TagLinkClicked, {
                        tag: tagRecord.name,
                        botLeftLat: southWest.latitude,
                        botLeftLon: southWest.longitude,
                        topRightLat: northEast.latitude,
                        topRightLon: northEast.longitude,
                        centerLat: center.latitude,
                        centerLon: center.longitude
                    })
                })
            })
        }
        if (voiceMark.isAnonymous || (voiceMark.uid === gg.getMySystemUserId())) {
            new Ajax.InPlaceCollectionEditor("moreinfo-category-edit-control", gg.ApiUrl.SetVoiceMarkCategory, {
                htmlResponse: false,
                loadCollectionURL: gg.ApiUrl.GetVoiceMarkCategories,
                clickToEditText: "Click to set category",
                cancelControl: "button",
                highlightcolor: "#fcdf35",
                callback: function(form, value){
                    return String.format("vmid=$0&category=$1", voiceMark.id, encodeURIComponent(value))
                },
                onComplete: function(transport, element){
                    new Ajax.Request(String.format("$0?vmid=$1&format=json", gg.ApiUrl.GetVoiceMarkCategory, voiceMark.id), {
                        onSuccess: function(response){
                            var apiResponse = response.responseText.evalJSON(true);
                            if (apiResponse) {
                                element.innerHTML = apiResponse.category
                            }
                        }
                    })
                }
            })
        }
        var tagsControl = new Ajax.InPlaceEditor("moreinfo-voicemark-tags-edit-control", gg.ApiUrl.AddTags, {
            htmlResponse: false,
            clickToEditText: "Click to add tags",
            highlightcolor: "#fcdf35",
            cancelControl: "button",
            externalControl: "moreinfo-voicemark-tags-label",
            externalControlOnly: true,
            callback: function(form, value){
                return String.format("vmid=$0&tags=$1", voiceMark.id, encodeURIComponent(value))
            },
            onComplete: function(transport, element){
                new Ajax.Request(String.format("$0?vmid=$1&format=json", gg.ApiUrl.GetVoiceMarkTags, voiceMark.id), {
                    onSuccess: function(response){
                        var tagBuffer = new gg.StringBuffer();
                        var tags = response.responseText.evalJSON(true);
                        if (gg.debug) {
                            gg.log("got tags with %o", tags)
                        }
                        if (tags) {
                            tagsList = new Array();
                            var urlEncodedTagName = null;
                            var tagName = null;
                            var tagId = null;
                            var currentTag = null;
                            for (var i = 0, limit = tags.length; i < limit; ++i) {
                                currentTag = tags[i];
                                tagName = currentTag.name;
                                tagId = String.format("vm-$0-tag-$1", voiceMark.id, currentTag.id);
                                tagsList.push({
                                    id: tagId,
                                    name: tagName
                                });
                                tagBuffer.append('<a href="$0/$1" id="$2" class="moreinfo-voicemark-tag">$3</a>', gg.SEOFriendlyUrl.ViewTag, tagName.gsub(" ", "-"), tagId, tagName)
                            }
                            element.innerHTML = tagBuffer.toString();
                            if (tagsList) {
                                tagsList.each(function(tagRecord){
                                    var tagRecordId = $(tagRecord.id);
                                    tagRecordId.stopObserving();
                                    tagRecordId.observe("click", function(e){
                                        if (gg.debug) {
                                            gg.log("will launch tag search for tag %s", tagRecord.name)
                                        }
                                        e.stop();
                                        var bounds = self.getBounds();
                                        var northEast = bounds.northEast;
                                        var southWest = bounds.southWest;
                                        var center = self.getCenter();
                                        self.mapElement.fire(gg.MapEvent.TagLinkClicked, {
                                            tag: tagRecord.name,
                                            botLeftLat: southWest.latitude,
                                            botLeftLon: southWest.longitude,
                                            topRightLat: northEast.latitude,
                                            topRightLon: northEast.longitude,
                                            centerLat: center.latitude,
                                            centerLon: center.longitude
                                        })
                                    })
                                })
                            }
                        }
                    },
                    onFailure: function(response){
                        if (gg.debug) {
                            gg.error("Error getting tags for VM  %o", response)
                        }
                    }
                })
            }
        });
        Object.extend(tagsControl, {
            getText: function(){
                return ""
            }
        })
    },
	newPopulateMoreInfoSection : function(voiceMark) {
	 	var self = this;
        var offset = 0;
        var responseOffsetToShow = $("responseOffsetToShow");
        if (responseOffsetToShow) {
            offset = $F(responseOffsetToShow);
            if (offset && !String.isNullOrEmpty(offset)) {
                responseOffsetToShow.writeAttribute("value", null);
            }
        }
        var callParameters = {
            vmid: voiceMark.id,
            offset: offset,
            format: "json"
        };
		
		/*
		if (!data.isAnonymous) {
                var actionViewTheirProfile = $("action-view-their-profile");
                actionViewTheirProfile.stopObserving();
                actionViewTheirProfile.observe("click", function(e){
                    e.stop();
                    self.mapElement.fire(gg.MapEvent.ViewProfileLinkClicked, {
                        id: data.systemUserId
                    })
                })
            }
			*/
        new Ajax.Request(gg.ApiUrl.GetResponses, {
            parameters: $H(callParameters),
            onSuccess: function(response){
                var apiResponse = response.responseText.evalJSON(true);
				var buffer = new gg.StringBuffer();
				var audioPlayerContainers = new Array();
				var profileLinkContainers = new Array();
				if (apiResponse.voiceMarks) {
					var currentResponse;
					for (var i = 0; i < apiResponse.voiceMarks.length; ++i) {
						currentResponse = apiResponse.voiceMarks[i];
						buffer.append('<div class="response-row" id="response$0">', currentResponse.id);
						buffer.append('<img class="vmresultimage" alt="Voice Mark Result Imgae" src="/images/voicemark-23x33.png"/>');
						if (!currentResponse.isAnonymous) {
							buffer.append('<div class="response-row-creator"><a id="response-profile-link-$0" href="/users/$1">$2</a></div>', i, currentResponse.uid, currentResponse.userName);
							profileLinkContainers.push(i);
						}
						else {
							buffer.append('<span class="response-row-creator">$0</span>', currentResponse.userName);
						}
						var theDate = new Date(currentResponse.createdOnTimestamp);
						buffer.append('<div class="response-row-createdon">$0/$1/$2</div>', theDate.getMonth()+1, theDate.getDate(), theDate.getFullYear());
						var responsePlayerId = String.format("response-player-$0", currentResponse.id);
                        audioPlayerContainers.push(responsePlayerId);
						buffer.append('<div class="response-player-container">');
                        buffer.append('<div id="$0"><span class="flash-alternative-content">Download <a href="http://www.adobe.com/go/getflashplayer">Adobe Flash Player</a> to listen to Voice Marks.</span></div>', responsePlayerId);
                        buffer.append("</div>");
						buffer.append('<div id="response-share-section-$0" class="response-share-section">', currentResponse.id);
						buffer.append('<div id="response-sharing-widget-$0"><span class="response-sharing-widget-text">SHARE</span> ', currentResponse.id);
						buffer.append('<span id="response-sharesection-addthis-$0"><a class="addthis_button_facebook" href="http://www.addthis.com/bookmark.php">', currentResponse.id);
						buffer.append('<img class="mini-sharing-image" src="/images/facebook_icon.png"/>');
						buffer.append('</a>');
						buffer.append('<a class="addthis_button_twitter" href="http://www.addthis.com/bookmark.php">');
						buffer.append('<img class="mini-sharing-image" src="/images/twitter_icon.png"/>');
						buffer.append('</a>');
						buffer.append('<a class="addthis_button_email" href="http://www.addthis.com/bookmark.php">');
						buffer.append('<img class="mini-sharing-image" src="/images/mail_icon-1.png"/>');
						buffer.append('</a>');

						buffer.append('<span id="response-sharesection-send-to-phone-$0" class="sharesection-link"><img class="mini-sharing-image" src="/images/phone_icon.png"/></span>', currentResponse.id);
						buffer.append('</span>');
						buffer.append('</div>');
						buffer.append('</div>');//response-share-section
						buffer.append('</div>'); //response-row
						buffer.append('<div class="response-row-separator"></div>');
					}
				}
				
                $("moreinfo").update(buffer.toString());
				
		var responseIdToShow = $("responseIdToShow");
                if (responseIdToShow) {
                    var id = $F(responseIdToShow);
                    if (id && !String.isNullOrEmpty(id)) {
                        responseIdToShow.writeAttribute("value", null);
                        //self.map.getInfoWindow().selectTab(1);
                        var responseContainer = $(String.format("response$0", id));
                        if (responseContainer) {
                            responseContainer.scrollTo();
                            var playerId = String.format("response-player-$0", id);
                            gg.log("player id is %s with object %o", playerId, $(playerId));
                            AudioPlayer.open.delay(1, playerId)
                        }
                    }
                }
				//boobs
				if (apiResponse.voiceMarks) {
					var currentRespone;
					for (var i = 0; i < apiResponse.voiceMarks.length; ++i) {
						currentResponse = Object.extend(apiResponse.voiceMarks[i], gg.VoiceMarkBase);
						//self.generateResponseAddThisButton(currentResponse);
						self.addSendToPhoneSectionListeners(currentResponse, String.format("response-sharesection-send-to-phone-$0", currentResponse.id));
								var shareUrl = String.format("http://$0$1/$2", gg.Environment.ServerRunningOn, gg.SEOFriendlyUrl.ViewVoiceMark, currentResponse.id); 
				// This updates the toolbox addthis toolbox
				var toolboxId = String.format("response-sharesection-addthis-$0", currentResponse.id);
				addthis.toolbox(String.format("#$0", toolboxId), {}, {
					url : shareUrl,
					title : currentResponse.getTitle()
				});
					}
				}
				
				try {
					for (var i = 0; i < profileLinkContainers.length; ++i) {
						var profileLinkId = String.format("response-profile-link-$0", profileLinkContainers[i]);
                                                var profileLinkIdElement = $(profileLinkId);
						var href = profileLinkIdElement.getAttribute("href");
						var userId = href.gsub("/users/", "");
						profileLinkIdElement.observe("click", function(e){
							e.stop();
							self.openProfileBubble(userId);
						});
					}
				}
				catch (e) {
					gg.error("What????? %o", e);
				}
				
				for (var i = 0; i < audioPlayerContainers.length; ++i) {
					
						var nakedResponse = apiResponse.voiceMarks[i];
						var voiceMarkResponse = Object.extend(nakedResponse, gg.VoiceMarkBase);
						//voiceMarkResponse.title = voiceMark.getTitle();
						self.embedAudioPlayer(voiceMarkResponse, audioPlayerContainers[i])
					
				}
            },
            onFailure: function(response){
                if (gg.debug) {
                    gg.log("Error occurred while trying to fetch VM responses [ %d:%s:%s]", response.status, response.statusText, response.responseText)
                }
            }
        })

	},
    createMidInfoSection: function(voiceMark){
        var self = this;
		if (false) {
			self.createAccordionControl();
		}
        new Ajax.Request(gg.ApiUrl.GetUserInfo, {
            parameters: {
                uid: voiceMark.uid,
                vid: voiceMark.vid,
                format: "json"
            },
            onSuccess: function(transport){
                var response = transport.responseText.evalJSON(true);
                self.populateUserData(response)
            },
            onFailure: function(){
                if (gg.debug) {
                    gg.log("Failure getting user info for user uid=%d vid=%d!!!", voiceMark.uid, voiceMark.vid)
                }
            }
        });
        new Ajax.Request(gg.ApiUrl.GetVoiceMarkInfo, {
            parameters: {
                vmid: voiceMark.id,
                format: "json"
            },
            onSuccess: function(transport){
                var nakedVoiceMark = transport.responseText.evalJSON(true);
                var voiceMark = Object.extend(nakedVoiceMark, gg.BaseVoiceMark);
				if (false) {
					self.populateMoreInfoSection(voiceMark);
				}
				else {
					self.newPopulateMoreInfoSection(voiceMark);
				}
            },
            onFailure: function(){
                if (gg.debug) {
                    gg.log("Failure getting VM info for VMID=%d", voiceMark.id)
                }
            }
        })
    },
    createResponsesRespondTipContent: function(voiceMark){
        if (gg.debug) {
            gg.log("going to start with content")
        }
        var buffer = new gg.StringBuffer();
        if (gg.debug) {
            gg.log("buffer up")
        }
        buffer.append('<p id="responses-respond-message">');
        buffer.append("To record your message, enter your phone number and GeoGraffiti will call you from (213) 221-3802.");
        buffer.append("</p>");
        buffer.append('<form id="responses-respondform" action="$0">', gg.ApiUrl.RespondToVoiceMark);
        buffer.append('<label id="responses-respondform-phonenumber-label" for="responses-respondform-phonenumber">Phone Number:</label>');
        buffer.append('<input id="responses-respondform-phonenumber" name="phonenum" type="text"/>');
        buffer.append('<input id="responses-respondform-latitude" name="lat" type="hidden" value="$0"/>', voiceMark.lat);
        buffer.append('<input id="responses-respondform-longitude" name="lon" type="hidden" value="$0"/>', voiceMark.lng);
        buffer.append('<input id="responses-respondform-voicemark-id" name="vmid" type="hidden" value="$0"/>', voiceMark.id);
        buffer.append('<input id="responses-respondform-submit-button" type="submit" value="Call Me!"/>');
        buffer.append("</form>");
        buffer.append('<div id="responses-respondform-submit-container" class="disabled">');
        buffer.append('<span id="responses-respondform-submit-button-messages">Enter a valid 10-digit U.S Phone Number</span>');
        buffer.append("</div>");
        if (gg.debug) {
            gg.log("buffer done...returning")
        }
        return buffer.toString()
    },
    createRespondTipContent: function(voiceMark){
        if (gg.debug) {
            gg.log("going to start with content")
        }
        var buffer = new gg.StringBuffer();
        if (gg.debug) {
            gg.log("buffer up")
        }
        buffer.append('<p id="respond-message">');
        buffer.append("To record your message, enter your phone number and GeoGraffiti will call you from (213) 221-3802.");
        buffer.append("</p>");
        buffer.append('<form id="respondform" action="$0">', gg.ApiUrl.RespondToVoiceMark);
        buffer.append('<label id="respondform-phonenumber-label" for="respondform-phonenumber">Phone Number:</label>');
        buffer.append('<input id="respondform-phonenumber" name="phonenum" type="text"/>');
        buffer.append('<input id="respondform-latitude" name="lat" type="hidden" value="$0"/>', voiceMark.lat);
        buffer.append('<input id="respondform-longitude" name="lon" type="hidden" value="$0"/>', voiceMark.lng);
        buffer.append('<input id="respondform-voicemark-id" name="vmid" type="hidden" value="$0"/>', voiceMark.id);
        buffer.append('<input id="respondform-submit-button" type="submit" value="Call Me!"/>');
        buffer.append("</form>");
        buffer.append('<div id="respondform-submit-container" class="disabled">');
        buffer.append('<span id="respondform-submit-button-messages">Enter a valid 10-digit U.S. Phone Number</span>');
        buffer.append("</div>");
        if (gg.debug) {
            gg.log("buffer done...returning")
        }
        return buffer.toString()
    },
    createSendToPhoneTipContent: function(voiceMark){
        var buffer = new gg.StringBuffer();
        buffer.append('<p id="send-to-phone-message" class="tip-message">');
        buffer.append("Enter friend's phone number so we can call their phone and play this VoiceMark.");
        buffer.append("</p>");
        buffer.append('<form id="sendform" action="$0">', gg.ApiUrl.SendVoiceMarkToPhone);
        buffer.append('<label id="sendform-phonenumber-label" for="sendform-phonenumber">Friend\'s Phone Number:</label>');
        buffer.append('<input id="sendform-phonenumber" name="phonenum" type="text"/>');
        buffer.append('<input id="sendform-voicemark-id" name="vmid" type="hidden" value="$0"/>', voiceMark.id);
        buffer.append('<input id="sendform-submit-button" type="submit" value="Send!"/>');
        buffer.append("</form>");
        buffer.append('<div id="sendform-submit-container" class="disabled">');
        buffer.append('<span id="sendform-submit-button-messages">Enter a valid 10-digit U.S. Phone Number</span>');
        buffer.append("</div>");
        return buffer.toString()
    },
    createLinkToThisTipContent: function(voiceMark){
        var buffer = new gg.StringBuffer();
        buffer.append('<p id="link-to-this-message" class="tip-message">');
        buffer.append("Copy and Paste the link below into an Email, IM, or blog post!");
        buffer.append("</p>");
        buffer.append('<input type="text" id="link-to-this-textbox" class="link-to-this-textbox" value="http://$0$1/$2"/>', gg.Environment.ServerRunningOn, gg.SEOFriendlyUrl.ViewVoiceMark, voiceMark.id);
        buffer.append("</div>");
        return buffer.toString()
    },
    addLinkToThisSectionListeners: function(voiceMark){
        var self = this;
        var linkToThisLink = $("sharesection-link-to-this");
		if (linkToThisLink != null) {
			var currentTip = linkToThisLink.prototip;
			if (currentTip) {
				currentTip.remove()
			}
			linkToThisLink.observe("prototip:shown", function(e){
				$("link-to-this-textbox").observe("focus", function(e){
					$("link-to-this-textbox").select();
				});
				$("link-to-this-textbox").focus()
			});
			linkToThisLink.observe("prototip:hidden", function(e){
				$("link-to-this-textbox").stopObserving("focus")
			})
		}
    },
    activateSendToPhoneTip: function(voiceMark, linkId){
        var self = this;
        var sendLink = $("sharesection-send-to-phone");
		if (linkId != null) {
			sendLink = $(linkId);
		}
        var currentTip = sendLink.prototip;
        if (currentTip) {
            currentTip.remove()
        }
        sendLink.observe("prototip:hidden", function(e){
            var sendFormPhoneNumber = $("sendform-phonenumber");
            if (sendFormPhoneNumber) {
                sendFormPhoneNumber.stopObserving("keypress")
            }
        });
        sendLink.observe("prototip:shown", function(e){
            var sendFormPhoneNumber = $("sendform-phonenumber");
            if (sendFormPhoneNumber) {
                sendFormPhoneNumber.observe("keypress", function(e){
                    gg.log("Key pressed %o", e);
                    var keyCode = e.charCode || e.keyCode;
                    gg.log("key code is %d", keyCode);
                    if (keyCode >= 48 && keyCode <= 57) {
                        self.validateSendFormInput.bind(self).defer()
                    }
                    else {
                        if (keyCode >= 58) {
                            e.stop();
                            gg.log("not number")
                        }
                        else {
                            if (keyCode != Event.KEY_BACKSPACE && keyCode != Event.KEY_DELETE && keyCode != Event.KEY_LEFT && keyCode != Event.KEY_UP && keyCode != Event.KEY_RIGHT && keyCode != Event.KEY_DOWN) {
                                e.stop()
                            }
                            else {
                                gg.log("probably some non-printable");
                                self.validateSendFormInput.bind(self).defer()
                            }
                        }
                    }
                });
                var sendForm = $("sendform");
                sendForm.stopObserving();
                sendForm.observe("submit", function(e){
                    var sendMessage = $("send-to-phone-message");
                    e.stop();
                    sendForm.request({
                        onSuccess: function(transport){
                            sendMessage.innerHTML = "VoiceMark has been sent!";
                            sendMessage.addClassName("send-success")
                        },
                        onFailure: function(){
                            sendMessage.innerHTML = "VoiceMark could not be sent!";
                            sendMessage.addClassName("send-error")
                        }
                    })
                })
            }
        });
        var tip = new Tip($(sendLink), self.createSendToPhoneTipContent(voiceMark), {
            style: "geograffiti",
            hook: {
                target: "bottomRight",
                tip: "topLeft"
            },
            offset: {
                x: -200,
                y: 0
            },
            stem: "topMiddle",
            title: "Send 2 Phone"
        });
        tip.target.prototip.show()
    },
    createNeedVerifiedPhoneTip: function(targetElement){
        var self = this;
        document.fire(gg.MapEvent.ShowMyPhonesRequested);
        var tip = new Tip($("sharesection-send-to-phone"), self.createNeedVerifiedPhoneTipContent(), {
            style: "geograffiti",
            hook: {
                target: "bottomRight",
                tip: "topLeft"
            },
            offset: {
                x: -200,
                y: 0
            },
            stem: "topMiddle",
            title: "Need Verified Phone Number"
        });
        tip.target.prototip.show();
    },
    addSendToPhoneSectionListeners: function(voiceMark, linkId){
        var self = this;
        var sendLink = $("sharesection-send-to-phone");
		if (linkId != null) {
			sendLink = $(linkId);
		}
        sendLink.observe("click", function(e){
            if (!gg.userLoggedIn()) {
                self.createNeedLoginTip(sendLink, {
                    message: "To forward VoiceMarks to your friends' phones, you need to be logged in and have a verified phone number.",
                    onLogin: function(){
                        if (gg.userHasVerifiedNumber()) {
                            self.activateSendToPhoneTip(voiceMark, sendLink)
                        }
                        else {
                            self.createNeedVerifiedPhoneTip(sendLink)
                        }
                    },
                    onNoLogin: function(){
                    }
                })
            }
            else {
                if (gg.userHasVerifiedNumber()) {
                    self.activateSendToPhoneTip(voiceMark, sendLink)
                }
                else {
                    self.createNeedVerifiedPhoneTip(sendLink)
                }
            }
        })
    },
    addRespondSectionListeners: function(voiceMark){
        var self = this;
        var respondSection = $("respondsection");
		if (respondSection != null) {
			respondSection.stopObserving("prototip:shown");
			respondSection.observe("prototip:shown", function(){
				var respondFormPhoneNumber = $("respondform-phonenumber");
				respondFormPhoneNumber.stopObserving();
				respondFormPhoneNumber.observe("keypress", function(e){
					gg.log("Key pressed %o", e);
					var keyCode = e.charCode || e.keyCode;
					gg.log("key code is %d", keyCode);
					if (keyCode >= 48 && keyCode <= 57) {
						self.validateRespondFormInput.bind(self).defer()
					}
					else {
						if (keyCode >= 58) {
							e.stop();
							gg.log("not number")
						}
						else {
							if (keyCode != Event.KEY_BACKSPACE && keyCode != Event.KEY_DELETE && keyCode != Event.KEY_LEFT && keyCode != Event.KEY_UP && keyCode != Event.KEY_RIGHT && keyCode != Event.KEY_DOWN) {
								e.stop()
							}
							else {
								gg.log("probably some non-printable");
								self.validateRespondFormInput.bind(self).defer()
							}
						}
					}
				});
				var respondForm = $("respondform");
				respondForm.stopObserving();
				respondForm.observe("submit", function(e){
					var respondMessage = $("respond-message");
					e.stop();
					respondForm.request({
						onSuccess: function(transport){
							respondMessage.innerHTML = "You should receive a call from (213) 221-3802 soon.  Speak your response and follow the simple prompts to have it published.";
							respondMessage.addClassName("respond-success")
						},
						onFailure: function(){
							respondMessage.innerHTML = "We weren't able to call you.  Try that again and if it fails, please contact us using the \"Contact\" link on the top right corner of the page and we'll get back to you within a day.";
							respondMessage.addClassName("respond-error")
						}
					})
				})
			});
			new Tip(respondSection, this.createRespondTipContent(voiceMark), {
				style: "geograffiti",
				hook: {
					target: "topLeft",
					tip: "bottomRight"
				},
				offset: {
					x: 200,
					y: 0
				},
				stem: "bottomMiddle",
				title: "Leave a Voice Mark Review"
			})
		}
    },
    addBottomSectionListeners: function(voiceMark){
        this.addRespondSectionListeners(voiceMark)
    },
    generateAddThisButton: function(voiceMark){
        try {
            var shareSection = $("sharesection-addthis");
            shareSection.update('<a class="addthis-link" href="http://www.addthis.com/bookmark.php"><img class="share-section-image" src="/images/add.png" alt="Bookmark and Share"/>Share (Email, Twitter, Facebook ...)</a>');
            var customButton = shareSection.down("a");
            customButton.stopObserving();
            customButton.observe("mouseout", function(e){
                e.stop()
            });
            customButton.observe("click", function(e){
                e.stop();
                addthis_open(customButton, "", String.format("http://$0$1/$2", gg.Environment.ServerRunningOn, gg.SEOFriendlyUrl.ViewVoiceMark, voiceMark.id), voiceMark.getTitle())
            })
        } 
        catch (e) {
            gg.error("AddThis has fucked up...%o", e)
        }
    },
	newGenerateAddThisButton: function(voiceMark){
        try {
	    var shareUrl = String.format("http://$0$1/$2", gg.Environment.ServerRunningOn, gg.SEOFriendlyUrl.ViewVoiceMark, voiceMark.id); 
				// This updates the toolbox addthis toolbox
				var toolboxId = String.format("sharesection-addthis");
				addthis.toolbox(String.format("#$0", toolboxId), {}, {
					url : shareUrl,
					title : voiceMark.getTitle()
				});
					//}
				//}

            //var shareSection = $("sharesection-addthis");
            //shareSection.update('<a class="addthis-link" href="http://www.addthis.com/bookmark.php"><img class="share-section-image" src="/images/add.png" alt="Bookmark and Share"/>Share (Email, Twitter, Facebook ...)</a>');
            //var customButton = shareSection.down("a");
            //customButton.stopObserving();
            //customButton.observe("mouseout", function(e){
            //    e.stop()
            //});
            //customButton.observe("click", function(e){
            //    e.stop();
            //    addthis_open(customButton, "", String.format("http://$0$1/$2", gg.Environment.ServerRunningOn, gg.SEOFriendlyUrl.ViewVoiceMark, voiceMark.id), voiceMark.getTitle())
            //})
        } 
        catch (e) {
            gg.error("AddThis has fucked up...%o", e)
        }
    },
	generateResponseAddThisButton : function(voiceMark) {
		try {
			var shareSection = $(String.format('response-sharesection-addthis-$0', voiceMark.id));
			var customButton = shareSection.down('a');
			customButton.stopObserving();
			customButton.observe("mouseout", function(e) {
				e.stop();
			});
			customButton.observe("click", function(e) {
				e.stop();
				addthis_open(customButton, "", String.format("http://$0$1/$2", gg.Environment.ServerRunningOn, gg.SEOFriendlyUrl.ViewVoiceMark, voiceMark.id), voiceMark.getTitle());
			});
		}
		catch (e) {
			gg.error("AddThis has fucked up...%o", e);
		}
	},
    createMarkerFromGoogleLocalResult: function(googleLocalResult, id){
        try {
            var self = this;
            var label = "";
            if (id >= 0 && id < self.MarkerLetterLabels.length) {
                label = self.MarkerLetterLabels[id]
            }
            var options = {
                title: googleLocalResult.titleNoFormatting,
                icon: new google.maps.Icon(self.BaseIcon, String.format("http://www.google.com/mapfiles/marker$0.png", label))
            };
            var marker = new google.maps.Marker(new google.maps.LatLng(googleLocalResult.lat, googleLocalResult.lng), options);
            google.maps.Event.addListener(marker, "click", function(){
                var locationInformation = {
                    title: googleLocalResult.titleNoFormatting,
                    addressLineOne: googleLocalResult.streetAddress,
                    city: googleLocalResult.city,
                    state: googleLocalResult.region,
                    postalCode: "",
                    country: googleLocalResult.country,
                    phoneNumbers: googleLocalResult.phoneNumbers,
					url : googleLocalResult.url
                };
                if (gg.debug) {
                    gg.log("going to open GOOG bubble")
                }
                self.openPublishVoiceMarkBubble(marker.getLatLng(), locationInformation, marker, false)
            });
            return marker
        } 
        catch (e) {
            if (gg.debug) {
                gg.log("Error from GOOG result %o", e)
            }
        }
    },
    createMarkerFromProfile: function(profile){
        var self = this;
        var options = {
            labelText: profile.userName,
            title: profile.userName,
            icon: geograffiti.map.DefaultProfileIcon
        };
        if (gg.debug) {
            gg.log("options are %o", options)
        }
        var marker = new google.maps.Marker(new google.maps.LatLng(profile.location.latitude, profile.location.longitude), options);
        google.maps.Event.addListener(marker, "click", function(){
            marker.openInfoWindowHtml(self.createProfileInfoWindowContent(profile), {
                maxWidth: 400
            })
        });
        google.maps.Event.addListener(marker, "infowindowopen", function(){
            var userProfileBecomeFan = $("map-userprofile-action-become-fan");
            userProfileBecomeFan.stopObserving();
            userProfileBecomeFan.observe("click", function(e){
                e.stop();
                var params = {
                    subscriptiontype: profile.isAnonymous === true ? "voiceuser" : "systemuser",
                    uid: profile.systemUserId,
                    vid: profile.voiceUserId
                };
                if (!gg.userLoggedIn()) {
                    self.createNeedLoginTip(userProfileBecomeFan, {
                        message: "You need to be logged in to become their fan.",
                        onLogin: function(){
                            self.sendBecomeFanRequest(params, userProfileBecomeFan)
                        },
                        onNoLogin: function(){
                            gg.log("they did not log in!")
                        }
                    })
                }
                else {
                    self.sendBecomeFanRequest(params, userProfileBecomeFan);
                }
            });
			
			var actionListenToTheirVoiceMarks = $("map-userprofile-action-listen-to-their-voicemarks");
            actionListenToTheirVoiceMarks.stopObserving();
            actionListenToTheirVoiceMarks.observe("click", function(e){
                e.stop();
                self.fireSearchByUser(profile.systemUserId, profile.voiceUserId, profile.userName)
            });
			
            var mapUserProfileMemberOfContainer = $("map-userprofile-member-of-container");
            mapUserProfileMemberOfContainer.stopObserving();
            mapUserProfileMemberOfContainer.observe("click", function(e){
                e.stop();
                var source = e.element();
                var sourceId = source.identify();
                if (sourceId.startsWith("map-userprofile-group-action-join-")) {
                    var groupId = sourceId.gsub("map-userprofile-group-action-join-", "");
                    var parameters = {
                        gid: groupId
                    };
                    if (!gg.userLoggedIn()) {
                        self.createNeedLoginTip(source, {
                            message: "You need to be logged in to join a group.",
                            onLogin: function(){
                                self.sendJoinGroupRequest(parameters, source)
                            },
                            onNoLogin: function(){
                                gg.info("The didn't log in!")
                            }
                        })
                    }
                    else {
                        self.sendJoinGroupRequest(parameters, source)
                    }
                }
            })
        });
        return marker
    },
    sendJoinGroupRequest: function(parameters, elementToUpdate){
        var self = this;
        new Ajax.Request(gg.ApiUrl.JoinGroup, {
            parameters: $H(parameters),
            evalJSON: true,
            onSuccess: function(transport){
                gg.log("Success joining group...%o", transport);
                var apiResponse = transport.responseText.evalJSON(true);
                if (apiResponse.status !== 0) {
                    self.updateAndFlashElement(elementToUpdate, true, "Error joining group.", "action-join-group-error")
                }
                else {
                    self.updateAndFlashElement(elementToUpdate, true, "You are now a member!", "action-join-group-success")
                }
            },
            onFailure: function(transport){
                self.updateAndFlashElement(elementToUpdate, true, "Error joining group.", "action-join-group-error")
            }
        })
    },
	startPictureUploader : function(voiceMark) {
		var self = this;
		var uploaderContainer = $("voicemark-pictures-uploader-container");
		gg.info("uploader container is %o", uploaderContainer);
		uploaderContainer.stopObserving();
		document.observe("lightview:opened", function(e) {
			gg.log("got the event %o", e);
			if ($("lightview").down("#voicemark-pictures-uploader-container")) {
				$("voicemark-picture-upload-form").reset();
				$("progress-message").innerHTML = "";
				$("progress-bar-container").setStyle("visibility:hidden");
				$("voicemark-pictures-uploader-container").setStyle("visibility:visible");
			}
		});
		
		document.observe("lightview:hidden", function(e) {
			gg.log("got the event %o", e);
			$("voicemark-pictures-uploader-container").setStyle("visibility:hidden");
		});
		
		Lightview.updateViews(); // needed b/c of the picture gallery.
		$("add-voicemark-picture-link").observe("click", function(e) {
			e.stop();
			$("voicemark-picture-upload-form").writeAttribute("action", String.format("/api/voicemark/$0/pictures/", voiceMark.id));
			Lightview.show({href: "#voicemark-pictures-uploader-container"});
		});
		
		$("voicemark-picture-upload-form").observe("submit", function(e) {
			if (String.isNullOrEmpty($F("voicemark-picture-file"))) {
				alert("Please choose a picture to upload");
			}
			else {
				$("progress-bar-container").setStyle("visibility:visible");
				$("progress-message").innerHTML = "Uploading";
				new PeriodicalExecuter(function(pe) {
					var url = String.format("/api/voicemark/$0/pictures/session-uploads/pictureFile/?$1", voiceMark.id, new Date().getTime());
					new Ajax.Request(url, {
						method:"GET",
						onSuccess: function(response) {
							var apiResponse = response.responseText.evalJSON(true);
							gg.info("got api response at %o", apiResponse);
							
							$("progress-message").innerHTML = String.format("$0%", apiResponse.uploadProgress);
							var currentWidth = $("progress-bar-container").getWidth();
							var factor = apiResponse.uploadProgress / 100;
							var newWidth = (currentWidth * factor) - 2; /* 1px border on the container */
							$("progress-bar").setStyle(String.format("width:$0px", newWidth));
							
							if (apiResponse.uploadProgress >= 100.0) {
								pe.stop();
							}							
						},
						onFailure: function(response) {
							gg.info("failure...%o", response);
							pe.stop();
						},
						onComplete : function(response) {
							gg.info("complete....%o", response);
							
						},
						onException : function(requester, e) {
							gg.info("exception sending ajax call %o", e);
							pe.stop();
						}
					});
				}, 2);
			}
		});
		
		var remotingFrame = $("voicemark-pictures-remoting-frame");
		if (remotingFrame.attachEvent) {
			remotingFrame.attachEvent("onload", function() {
				try {
					var result = remotingFrame.contentWindow.document.body.innerHTML.evalJSON(true);
					gg.info("result of attachEvent ... %o", result);
					$("progress-bar-container").setStyle("visibility:hidden");
					$("progress-message").innerHTML = "DONE!";
					$("progress-bar").setStyle("width:0px");
					self.openVoiceMarkBubble(voiceMark.id);
					/*
					$("progress-message").pulsate({
						duration:2.0,
						afterFinish:function(effect) {
							Lightview.hide();
						}
					});
					*/
					Lightview.hide();
				} 
				catch (e) {
					gg.error("error from attachEvent %o", e);
					$("progress-bar-container").setStyle("visibility:hidden");
					$("progress-message").innerHTML = "ERROR!";
					$("progress-message").pulsate({
						duration:2.0
					});
				}
			});
		}  
		else {
			try {
				Event.stopObserving(remotingFrame, "load");
				Event.observe(remotingFrame, "load", function(e) {
					e.stop();
					var result = remotingFrame.contentDocument.documentElement.textContent.evalJSON(true);
					gg.info("result of observe load is %o", result);
					$("progress-bar-container").setStyle("visibility:hidden");
					$("progress-message").innerHTML = "DONE!";
					$("progress-bar").setStyle("width:0px");
					self.openVoiceMarkBubble(voiceMark.id);
					/*
					$("progress-message").pulsate({
						duration:2.0,
						afterFinish:function(effect) {
							Lightview.hide();
						}
					});
					*/
					Lightview.hide();
				});				
			}
			catch (e) {
				gg.error("error from observe load... %o", e);
				$("progress-bar-container").setStyle("visibility:hidden");
				$("progress-message").innerHTML = "ERROR!";
				$("progress-message").pulsate({
						duration:2.0
					});
			}
		}
	},
    createMarkerFromVoiceMark: function(voiceMark){
        var self = this;
        var options = {
            labelText: voiceMark.id,
            title: voiceMark.getTitle(),
            icon: voiceMark.isBiz ? geograffiti.map.DefaultBizMarkIcon : geograffiti.map.DefaultVoiceMarkIcon
        };
        if (gg.debug) {
            gg.log("options are %o", options)
        }
        var marker = new google.maps.Marker(new google.maps.LatLng(voiceMark.lat, voiceMark.lng), options);
        google.maps.Event.addListener(marker, "click", function(){
            marker.openInfoWindowTabsHtml(self.createTabsForVoiceMark(voiceMark), {
                maxWidth: 400
            })
        });
        google.maps.Event.addListener(marker, "infowindowopen", function(){
            self.embedAudioPlayer(voiceMark, "vmplayer");
            self.createStarRatingControl(voiceMark);
            gg.log("done creating star rating ctrl");
            self.createMidInfoSection(voiceMark);
            gg.log("done creating mid info section");
            self.addBottomSectionListeners(voiceMark);
            gg.log("done with bootom section listeners");
            //self.generateAddThisButton(voiceMark);
			self.newGenerateAddThisButton(voiceMark);
            gg.log("done with gen share this button");
            //self.loadVoiceMarkResponses(voiceMark);
            self.addSendToPhoneSectionListeners(voiceMark, null);
            self.addLinkToThisSectionListeners(voiceMark);
			self.startPictureUploader(voiceMark);
/*
            new Tip($("sharesection-link-to-this"), self.createLinkToThisTipContent(voiceMark), {
                style: "geograffiti",
                hook: {
                    target: "bottomRight",
                    tip: "topLeft"
                },
                offset: {
                    x: -150,
                    y: 0
                },
                stem: "topMiddle",
                title: "Direct link to VoiceMark"
            });
*/
            $$(".delete-voicemark-link").each(function(link){
                gg.log("The current link is %o", link);
                link.stopObserving();
                link.observe("click", function(e){
                    gg.log("Delete Link in VM bubble clicked!");
                    e.stop();
                    var id = e.element().identify();
                    var voiceMarkId = id.gsub("action-delete-voicemark-", "");
                    self.deleteVoiceMark(voiceMarkId)
                })
            })
			
			try {
				var shareUrl = String.format("http://$0$1/$2", gg.Environment.ServerRunningOn, gg.SEOFriendlyUrl.ViewVoiceMark, voiceMark.id); 
				// This updates the toolbox addthis toolbox
				addthis.toolbox("#main-header-share-right-side", {}, {
					url : shareUrl,
					title : voiceMark.getTitle()
				});
			
				// This updates the actual addthis share button
				addthis.button("#addthis-button-link", {}, {
					url : shareUrl,
					title : voiceMark.getTitle()
				});
				
				// This updates the Facebook like button
				var facebookLikeButtonSection = $("map-main-header-share-facebook");
				if ($("fb-root")) {
					facebookLikeButtonSection.update(String.format('<fb:like href="$0" layout="button_count" show_faces="false"></fb:like>', shareUrl));
					FB.XFBML.parse(facebookLikeButtonSection);
				}
				else {
					facebookLikeButtonSection.update(String.format('<iframe src="http://www.facebook.com/plugins/like.php?href=$0&amp;layout=button_count&amp;show_faces=false&amp;width=200&amp;action=like&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:450px; height:21px;" allowTransparency="true"></iframe>', encodeURIComponent(shareUrl)));
				}
			}
			catch (e) {
				gg.warn("While trying to update the social sharing buttons...%o", e);	
			}
        });
        google.maps.Event.addListener(marker, "infowindowbeforeclose", function(){
            $("sharesection-send-to-phone").stopObserving("click");
            //var linkToThisTip = $("sharesection-link-to-this").prototip;
            //if (linkToThisTip) {
            //    linkToThisTip.remove()
            //}
            var sendToPhoneTip = $("sharesection-send-to-phone").prototip;
            if (sendToPhoneTip) {
                sendToPhoneTip.remove();
            }
        });
		
		
		
        return marker;
    },
    addVoiceMarkToMap: function(nakedVoiceMark){
        var self = this;
        var voiceMark = Object.extend(nakedVoiceMark, geograffiti.VoiceMarkBase);
        if (gg.debug) {
            gg.log("augmented VM: %o", voiceMark)
        }
        var marker = self.createMarkerFromVoiceMark(voiceMark);
        if (gg.debug) {
            gg.log("marker is %o", marker)
        }
        self.map.addOverlay(marker);
        self.voiceMarkTable.set(voiceMark.id, marker);
        return marker
    },
    addProfileToMap: function(profile){
        var self = this;
        var marker = self.createMarkerFromProfile(profile);
        if (gg.debug) {
            gg.log("marker is %o", marker)
        }
        self.map.addOverlay(marker);
        return marker
    },
    addGoogleLocalResultToMap: function(id, googleLocalResult){
        var self = this;
        var marker = self.createMarkerFromGoogleLocalResult(googleLocalResult, id);
        self.map.addOverlay(marker);
        self.googleLocalResultsTable.set(id, marker);
        return marker
    },
    addVoiceMarkResultsToMap: function(voiceMarks){
        var self = this;
        var marker = null;
        if (voiceMarks) {
            var voiceMark = null;
            for (var i = 0, limit = voiceMarks.length; i < limit; ++i) {
                voiceMark = voiceMarks[i];
                if (i === 0) {
                    marker = self.addVoiceMarkToMap(voiceMark)
                }
                else {
                    self.addVoiceMarkToMap(voiceMark)
                }
            }
        }
        return marker
    },
    addGoogleLocalResultsToMap: function(googleLocalResults, hidden){
        var self = this;
        var marker = null;
        if (googleLocalResults) {
            var localResult = null;
            for (var i = 0, limit = googleLocalResults.length; i < limit; ++i) {
                localResult = googleLocalResults[i];
                if (localResult.GsearchResultClass === "GlocalSearch") {
                    if (i === 0) {
                        marker = self.addGoogleLocalResultToMap(i, localResult);
                        if (hidden === true) {
                            marker.hide()
                        }
                    }
                    else {
                        var addedMarker = self.addGoogleLocalResultToMap(i, localResult);
                        if (hidden === true) {
                            addedMarker.hide()
                        }
                    }
                }
            }
        }
        return marker
    },
    displayGoogleViewport: function(viewport){
        var self = this;
        var southWest = viewport.southWest;
        var northEast = viewport.northEast;
        var vertices = [new google.maps.LatLng(southWest.latitude, southWest.longitude), new google.maps.LatLng(northEast.latitude, southWest.longitude), new google.maps.LatLng(northEast.latitude, northEast.longitude), new google.maps.LatLng(southWest.latitude, northEast.longitude), new google.maps.LatLng(southWest.latitude, southWest.longitude)];
        self.viewportOverlay = new google.maps.Polyline(vertices, "#ff0000", 10, 1);
        self.map.addOverlay(self.viewportOverlay)
    },
    displayResults: function(results){
        var self = this;
        var firstVoiceMarkMarker = firstGoogleLocalResultMarker = null;
        if (gg.debug) {
            gg.log("display results %o", results)
        }
        if (gg.debugging) {
            if (self.viewportOverlay !== null) {
                self.map.removeOverlay(self.viewportOverlay)
            }
            self.displayGoogleViewport(results.googleViewport)
        }
        if (results) {
			var googleViewport = results.googleViewport;
			
			
			var allResults = $A();
			results.voiceMarksResponse.voiceMarks.each(function(item) {
				allResults.push(new google.maps.LatLng(item.lat, item.lng));
			});
			results.googleLocalResults.each(function(item) {
				allResults.push(new google.maps.LatLng(item.lat, item.lng));
			});
			var lowestLatitude = null;
			var lowestLongitude = null;
			var highestLatitude = null;
			var highestLongitude = null;
			allResults.each(function(item) {
				if (lowestLatitude == null) {
					lowestLatitude = item.lat();
					lowestLongitude = item.lng();
					highestLatitude = lowestLatitude;
					highestLongitude = lowestLongitude;
				}
				else {
					if (item.lat() < lowestLatitude) {
						lowestLatitude = item.lat();
					}
					
					if (item.lng() < lowestLongitude) {
						lowestLongitude = item.lng();
					}
					
					if (item.lat() > highestLatitude) {
						highestLatitude = item.lat();
					}
					
					if (item.lng() > highestLongitude) {
						highestLongitude = item.lng();
					}
				}
			});
			
			var sw = new google.maps.LatLng(lowestLatitude, lowestLongitude);
			var ne = new google.maps.LatLng(highestLatitude, highestLongitude);
			var bounds = new google.maps.LatLngBounds(sw, ne);
			var zoomLevel = self.map.getBoundsZoomLevel(bounds);
			self.map.setCenter(bounds.getCenter(), zoomLevel);
				
            var voiceMarksFound = results.voiceMarksResponse.voiceMarks !== null && results.voiceMarksResponse.voiceMarks.length > 0;
            firstVoiceMarkMarker = self.addVoiceMarkResultsToMap(results.voiceMarksResponse.voiceMarks);
            var hidden = voiceMarksFound === true;
            firstGoogleLocalResultMarker = self.addGoogleLocalResultsToMap(results.googleLocalResults, hidden);
            var marker = firstVoiceMarkMarker || firstGoogleLocalResultMarker;
            if (marker) {
				if (marker === firstGoogleLocalResultMarker) {
					google.maps.Event.trigger(marker, "click")
				}
            }
        }
    },
    displayUserVoiceMarksResults: function(results){
        try {
            var self = this;
            var firstVoiceMarkMarker = null;
            if (gg.debug) {
                gg.log("display results %o", results)
            }
            if (results) {
                firstVoiceMarkMarker = self.addVoiceMarkResultsToMap(results.voiceMarks);
                var marker = firstVoiceMarkMarker;
                if (marker) {
                    //google.maps.Event.trigger(marker, "click")
                }
            }
        } 
        catch (e) {
            if (gg.debug) {
                gg.error("ERRRRRROOOORRRRRRR   %o", e)
            }
        }
    },
    displayGroupVoiceMarksResults: function(results){
        try {
            var self = this;
            var firstVoiceMarkMarker = null;
            if (gg.debug) {
                gg.log("display group results %o", results)
            }
            if (results) {
                firstVoiceMarkMarker = self.addVoiceMarkResultsToMap(results.voiceMarks);
                var marker = firstVoiceMarkMarker;
                if (marker) {
                    //google.maps.Event.trigger(marker, "click")
                }
            }
        } 
        catch (e) {
            if (gg.debug) {
                gg.error("ERRRRRROOOORRRRRRR   %o", e)
            }
        }
    },
    displayFilterResults: function(results){
        try {
            var self = this;
            var firstVoiceMarkMarker = null;
            if (gg.debug) {
                gg.log("display results %o", results)
            }
            if (results) {
                firstVoiceMarkMarker = self.addVoiceMarkResultsToMap(results.voiceMarks);
                var marker = firstVoiceMarkMarker;
                if (marker) {
                    //google.maps.Event.trigger(marker, "click")
                }
            }
        } 
        catch (e) {
            if (gg.debug) {
                gg.error("ERRRRRROOOORRRRRRR   %o", e)
            }
        }
    }
};

