diff --git a/js/highlight.js b/js/highlight.js
index 8d38c6989d8d3a0f12d5171b181ce231209ddd55..74642b60fa2fa77d23e03f59ce4eac487c8b10fe 100644
--- a/js/highlight.js
+++ b/js/highlight.js
@@ -8,74 +8,182 @@
  * Highlights marker on rollover.
  * Removes highlight on previous marker.
  *
- * Creates a "circle" using 20-sided GPolygon at the given point
- * Circle polygon object is global variable as there is only one highlighted marker at a time
+ * Creates a "circle" at the given point
+ * Circle is global variable as there is only one highlighted marker at a time
  * and we want to remove the previously placed polygon before placing a new one.
- * 
+ *
  * Original code "Google Maps JavaScript API Example"
+ * JN201304:
+ *    converted rpolygons to circles (not using the shapes.js API, should we be?)
+ *    move marker highlight events to custom handler here, to handle radius in pixels (note behavior.radiusInMeters to skip geodesic calcs)
+ *    removed google.events and moved events to gmaps binds
+ *    added overlay object for creating a shape based on pixels instead of meters (seems to be the use case?)
+ *    added gmaps binds for marker higlights, and general highlights.
+ *
+ * You can add highlights to a map with:
+ *    obj.change('addHighlight',-1, {latitude:#, longitude:#} );
+ * You can highlight a marker with:
+ *    obj.change('markerHighlight',-1, marker);
+ *      marker: that marker object used when creating the marker.  It can have options set at marker.highlight
+ *
+ * A Highlight object has to have either a <LatLng>Position or a <Number>latitude and <Number>longitude
+ * Note the new highlight options = {
+ *       radius: 10, // radius in pixels
+ *       color: '#777777',
+ *       weight: 2,
+ *       opacity: 0.7,
+ *       behavior: {
+ *          draggable: false,
+ *          editable: false,
+ *       }
+ *       opts: { actual google.maps.Circle opts can be put here for super custom cases }
+ * }
  */
-highlightMarker = function (gmap, currentMarker, highlightID, color) {
-
-  var map = gmap.map;
-
-  var markerPoint = currentMarker.marker.getPosition();
-  var polyPoints = Array();
 
-  var mapNormalProj = gmap.highlight.overlay.getProjection();
+Drupal.gmap.factory.highlight = function(options) {
+  return new google.maps.Circle(options);
+}
 
-  var mapZoom = map.getZoom();
-  var clickedPixel = mapNormalProj.fromLatLngToDivPixel(markerPoint, mapZoom);
+Drupal.gmap.addHandler('gmap', function (elem) {
+  var obj = this;
+  obj.highlights = {};
 
-  var polySmallRadius = 20;
-  var polyNumSides = 20;
-  var polySideLength = 18;
+  var overlayHandler = function(map, highlight) {
+    this.setMap(map);
+    this.highlight = highlight;
+  }
+  overlayHandler.prototype = new google.maps.OverlayView();
+  overlayHandler.prototype.onAdd = function() {
+    var highlight = this.highlight;
+    if ( !highlight.opts ) { highlight.opts = {}; } // sanity
+    if ( !highlight.behavior ) { highlight.behavior = {}; } // sanity
+    if ( !highlight.position ) { highlight.position = new google.maps.LatLng( highlight.latitude, highlight.longitude ); } // if you have a pos already then use it, otherwise gimme a lat/lon
+
+    $.each({ // collect the options from either the highligh.opts object, from the passed target value, as a behavior or a default value
+        radius: {target:'radius',default:10}, // radius in pixels
+        strokeColor: {target:'border',default:'#777777'},
+        strokeWeight: {target:'weight',default:2},
+        strokeOpacity: {target:'opacity',default:0.7},
+        fillColor: {target:'color',default:'#777777'},
+        fillOpacity: {target:'opacity',default:0.7},
+        draggable: {behavior:'draggable',default:false},
+        editable: {behavior:'editable',default:false},
+      }, function( key , config ) {
+        if ( highlight.opts[key] ) { // options was passed in
+          return true;
+        }
+        else if (config.target && highlight[ config.target ]) { // highight.target should have a value
+          highlight.opts[key] = highlight[ config.target ];
+        }
+        else if ( config.behavior && highlight.behavior && highlight.behavior[ config.behavior ] ) { // value is a behaviour
+          highlight.opts[key] = highlight.behavior[ config.behavior ];
+        }
+        else if (config.default) { // default valuee
+          highlight.opts[key] = config.default;
+        }
+      });
+
+    highlight.opts.map = this.map;
+    highlight.opts.center = highlight.position;
 
-  for (var a = 0; a < (polyNumSides + 1); a++) {
-    var aRad = polySideLength * a * (Math.PI/180);
-    var polyRadius = polySmallRadius; 
-    var pixelX = clickedPixel.x + polyRadius * Math.cos(aRad);
-    var pixelY = clickedPixel.y + polyRadius * Math.sin(aRad);
-    var polyPixel = new google.maps.Point(pixelX, pixelY);
-    var polyPoint = mapNormalProj.fromDivPixelToLatLng(polyPixel, mapZoom);
-    polyPoints.push(polyPoint);
   }
-  // Using GPolygon(points,  strokeColor?,  strokeWeight?,  strokeOpacity?,  fillColor?,  fillOpacity?)
-  gmap.highlight.polygon = new google.maps.Polygon( {
-    paths: polyPoints,
-    strokeColor: color,
-    strokeWeight: 2,
-    strokeOpacity: 0,
-    fillColor: color,
-    fillOpacity: 0.5
-  } );
-  gmap.highlight.polygon.setMap( map );
-
-};
-
-unHighlightMarker = function (gmap, currentMarker, highlightID) {
-  if (gmap.highlight.polygon) {
-    gmap.highlight.polygon.setMap( null );
-    delete gmap.highlight.polygon;
+  overlayHandler.prototype.draw = function() {
+    var highlight = this.highlight;
+    if ( !this.highlight.behavior.radiusInMeters ) {
+      var projection = this.getProjection();
+      var mapZoom = this.map.getZoom();
+      var center = projection.fromLatLngToDivPixel(highlight.opts.center, mapZoom);
+      var radius = highlight.opts.radius;
+      var radial = projection.fromDivPixelToLatLng(new google.maps.Point(center.x, center.y+radius), mapZoom); // find a point that is the radius distance away in pixels
+      highlight.opts.radius = google.maps.geometry.spherical.computeDistanceBetween (highlight.opts.center, radial);
+      highlight.behavior.radiusInMeters = true;
+    }
+    highlight.highlight = Drupal.gmap.factory.highlight(highlight.opts);
+  }
+  overlayHandler.prototype.onRemove = function() {
+    if ( this.highlight.highlight ) {
+      this.highlight.highlight.setMap( null );
+    }
   }
-};
-
-Drupal.gmap.addHandler('gmap', function (elem) {
-
-  var obj = this;
-
-  function HighlightOverlay(m) { this.setMap(m); }
 
-  HighlightOverlay.prototype = new google.maps.OverlayView();
+  Drupal.gmap.highlight = function (highlight) {
+    new overlayHandler(obj.map, highlight); // all actions happen in an overlayview, so that we can input pixels for radius instead of meters and positions
+  };
+  Drupal.gmap.unhighlight = function( highlight ) { // this can take an object that has a highlight, or a highlight/circle object
+    if ( highlight.highlight && highlight.highlight.setMap ) {
+      highlight.highlight.setMap( null );
+    }
+    else if ( highlight.setMap ) {
+      highlight.setMap( null );
+    }
+  }
 
-  HighlightOverlay.prototype.onAdd = function() { }
-  HighlightOverlay.prototype.onRemove = function() { }
-  HighlightOverlay.prototype.draw = function() { }
+  // set and remove map highlights
 
-  obj.bind('init', function () {
+  obj.bind('addHighlight', function(highlight) {
+    Drupal.gmap.highlight( highlight );
+  });
+  obj.bind('removeHighlight', function(highlight) {
+    Drupal.gmap.unhighlight( highlight );
+  });
 
-    obj.highlight = {};
-    obj.highlight.overlay = new HighlightOverlay( obj.map );
+ // Marker specific code:
+  var activeMarker; // remember that last marker activated.  In the default case we only allow one highlighted marker at a time
+  obj.bind('markerHighlight', function (marker) {
+    if ( activeMarker && !obj.vars.behavior.allowMultipleMarkerHighlight ) { obj.change('markerUnHighlight',-1, activeMarker); } // deactivate the active marker
+
+    // If the highlight arg option is used in views highlight the marker.
+    if ( !marker.highlight ) { marker.highlight = {} }
+    if ( !marker.highlight.color && obj.vars.styles.highlight_color ) { marker.highlight.color = '#' + obj.vars.styles.highlight_color; }
+    marker.highlight.position = marker.marker.getPosition();
+    Drupal.gmap.highlight( marker.highlight );
+    activeMarker = marker;
+  });
+  obj.bind('markerUnHighlight', function(marker) {
+    if ( !marker ) { marker = activeMarker; } // remove the active marker if no marker is passed in
+    if ( activeMarker === marker ) { activeMarker = null; }
+    if ( marker.highlight ) {
+      Drupal.gmap.unhighlight(marker.highlight);
+    }
+  });
 
+  /**
+   * Marker Binds
+   *
+   * Marker highlight code has been moved to this file from the marker.js
+   *
+   * Note that we rely on the obj.vars.behavior.highlight var to
+   * decide if should highlight markers on events.
+   * This decision could be made as an outer if conditional, instead
+   * of repeated inside each bind, but this arrangement allows for
+   * the behaviour to change, at a small cost.
+   */
+
+  obj.bind('addmarker', function (marker) {
+    if (obj.vars.behavior.highlight) {
+      google.maps.event.addListener(marker.marker, 'mouseover', function () {
+        obj.change('markerHighlight',-1,marker);
+      });
+      google.maps.event.addListener(marker.marker, 'mouseout', function () {
+        obj.change('markerUnHighlight',-1,marker);
+      });
+    }
+    // If the highlight arg option is used in views highlight the marker.
+    if (marker.opts.highlight == 1) {
+      obj.change('markerHighlight',-1,marker);
+    }
   });
 
-} );
\ No newline at end of file
+// Originally I moved mouse highlights to the extra event binds before I realized that there is likely a usecase for highlights without enabling extra events
+//   obj.bind('mouseovermarker', function(marker) {
+//     if (obj.vars.behavior.highlight && marker) {
+//       obj.change('markerHighlight',-1,marker);
+//     }
+//   });
+//   obj.bind('mouseoutmarker', function(marker) {
+//     if (obj.vars.behavior.highlight && marker) {
+//       obj.change('markerUnHighlight',-1,marker);
+//     }
+//   });
+
+});
diff --git a/js/marker.js b/js/marker.js
index 1f58e06c9e4405e34201d76063c86f830f19a521..a6eb17ec8123c354c58f4346c39a7e94deb3a6d9 100644
--- a/js/marker.js
+++ b/js/marker.js
@@ -26,15 +26,6 @@ Drupal.gmap.addHandler('gmap', function (elem) {
     google.maps.event.addListener(m, 'click', function () {
       obj.change('clickmarker', -1, marker);
     });
-    if (obj.vars.behavior.highlight) {
-      google.maps.event.addListener(m, 'mouseover', function () {
-        var highlightColor = '#' + obj.vars.styles.highlight_color;
-        highlightMarker(obj, marker, 'hoverHighlight', highlightColor);
-      });
-      google.maps.event.addListener(m, 'mouseout', function () {
-        unHighlightMarker(obj, marker, 'hoverHighlight');
-      });
-    }
     if (obj.vars.behavior.extramarkerevents) {
       google.maps.event.addListener(m, 'mouseover', function () {
         obj.change('mouseovermarker', -1, marker);
@@ -55,12 +46,6 @@ Drupal.gmap.addHandler('gmap', function (elem) {
     if (obj.vars.behavior.autozoom) {
       obj.bounds.extend(new google.maps.LatLng(marker.latitude, marker.longitude));
     }
-    // If the highlight arg option is used in views highlight the marker.
-    if (marker.opts.highlight == 1) {
-      google.maps.event.addListener( obj.mm, 'loaded', function() {
-        highlightMarker(obj, marker, 'viewHighlight', marker.opts.highlightcolor);
-      } );
-    }
   });
 
   // Default marker actions.
@@ -116,7 +101,7 @@ Drupal.gmap.addHandler('gmap', function (elem) {
     // Tabbed content
     else if (marker.tabs) {
       var data = "";
-      //tabs in an infowindow is no longer supported in API ver3.  
+      //tabs in an infowindow is no longer supported in API ver3.
       for (var m in marker.tabs) {
         data += marker.tabs[m];
       }
@@ -137,8 +122,8 @@ Drupal.gmap.addHandler('gmap', function (elem) {
         var listener = google.maps.event.addListener(obj.map, "idle", function() {
           if (obj.vars.maxzoom) {
             var maxzoom = parseInt(obj.vars.maxzoom)
-            if (obj.map.getZoom() > maxzoom) obj.map.setZoom(maxzoom); 
-            google.maps.event.removeListener(listener);             
+            if (obj.map.getZoom() > maxzoom) obj.map.setZoom(maxzoom);
+            google.maps.event.removeListener(listener);
           }
         });
       }