javascript代码
1 function hasClass(target, name) {
2 return target.className.match(new RegExp('(\\s|^)' + name + '(\\s|$)'));
3 }
4
5 function removeClass(target, name) {
6 if (hasClass(target, name)) {
7 target.className = target.className.replace(new RegExp('(\\s|^)' + name + '(\\s|$)'), ' ');
8 }
9 }
10
11 function addClass(target, name) {
12 if (!hasClass(target, name)) {
13 target.className += " " + name;
14 }
15 }
16
17 function MenuControl(map) {
18 this.container = document.createElement("div");
19 this.coordinate = null;
20 this.map = map;
21 this.sender = null
22 this.isEnable = true;
23 this.container.className = "menu_casing";
24 this.hide();
25 this.items = new Array();
26 var self = this;
27 google.maps.event.addListener(map, "click", function() {
28 self.hide();
29 });
30 google.maps.event.addListener(map, "movestart", function() {
31 self.hide();
32 });
33 google.maps.event.addListener(map, "zoom_changed", function() {
34 self.hide();
35 });
36 google.maps.event.addListener(map, "dragstart", function() {
37 self.hide();
38 });
39 this.container.index = 1;
40 map.controls[google.maps.ControlPosition.TOP_RIGHT].push(this.container);
41 }
42
43 MenuControl.prototype.show = function(groupName) {
44 this.container.style.display = "block";
45 if (groupName) {
46 for (var i = 0; i < this.items.length; i++) {
47 if (groupName == this.items[i].groupName) {
48 this.items[i].show();
49 } else {
50 this.items[i].hide();
51 }
52 }
53 }
54 }
55
56 MenuControl.prototype.hide = function(groupName) {
57 this.container.style.display = "none";
58 if (groupName) {
59 for (var i = 0; i < this.items.length; i++) {
60 if (groupName == this.items[i].groupName) {
61 this.items[i].hide();
62 } else {
63 this.items[i].show();
64 }
65 }
66 }
67 }
68
69 MenuControl.prototype.enable = function() {
70 this.isEnable = true;
71 }
72
73 MenuControl.prototype.disable = function() {
74 this.isEnable = false;
75 }
76
77 MenuControl.prototype.isHide = function() {
78 return (this.container.style.display == "none");
79 }
80
81 MenuControl.prototype.addItem = function(item) {
82 item.host = this;
83 this.items.push(item);
84 this.container.appendChild(item.casing);
85 }
86
87 MenuControl.prototype.addSeparator = function(group) {
88 var separator = group || new MenuSeparator();
89 if (typeof group == "string") {
90 separator = new MenuSeparator(group);
91 }
92 this.items.push(separator);
93 this.container.appendChild(separator.casing);
94 }
95
96
97 function MenuSeparator(groupName) {
98 this.groupName = groupName;
99 this.casing = document.createElement("div");
100 this.casing.className = "menu_separator";
101 }
102
103 MenuSeparator.prototype.show = function() {
104 this.casing.style.display = "block";
105 }
106
107 MenuSeparator.prototype.hide = function() {
108 this.casing.style.display = "none";
109 }
110
111 function MenuItem(options) {
112 options = options || {};
113 this.text = options.text || "";
114 this.icon = options.icon;
115 this.handler = options.handler;
116 this.groupName = options.groupName;
117 this.host = null; //宿主
118
119 this.casing = document.createElement("div");
120 this.casing.className = "menu_item";
121
122 var menu_text = document.createElement("div");
123 menu_text.className = "menu_text";
124 var text_lable = document.createElement("span");
125 text_lable.innerHTML = this.text;
126 menu_text.appendChild(text_lable);
127 this.casing.appendChild(menu_text);
128
129 var self = this;
130 if (this.icon) {
131 var item_icon = document.createElement("div");
132 item_icon.className = "menu_icon";
133 item_icon.style.backgroundImage = "url(" + self.icon + ")";
134 self.casing.appendChild(item_icon);
135 }
136
137 if (typeof self.handler == "function") {
138 google.maps.event.addDomListener(self.casing, "click", function() {
139 if (self.host) {
140 self.handler(self.host.coordinate);
141 self.host.hide();
142 }
143 });
144 }
145 google.maps.event.addDomListener(self.casing, "mouseover", function() {
146 addClass(self.casing, "item_active");
147 });
148
149 google.maps.event.addDomListener(self.casing, "mouseout", function() {
150 removeClass(self.casing, "item_active");
151 });
152 }
153
154 MenuItem.prototype.show = function() {
155 this.casing.style.display = "block";
156 }
157
158 MenuItem.prototype.hide = function() {
159 this.casing.style.display = "none";
160 }
CSS
1 .menu_casing{background: url(images/menu.gif) repeat-y scroll 0 0 #F0F0F0;border: 1px solid #CCCCCC;margin: 0;overflow: hidden;padding: 2px; width:120px;}
2 .menu_casing .menu_item{border: none;cursor: pointer;font-size: 12px;height: 22px;line-height: 22px;margin: 0;overflow: hidden;padding: 0;position: relative;}
3 .menu_casing .menu_item .menu_text{left: 28px;position: absolute;top: 0;}
4 .menu_casing .menu_item.item_active{background: #FAFAFA;border: 1px solid #7EABCD;height: 20px;line-height: 20px;border-radius: 3px 3px 3px 3px;}
5 .menu_casing .menu_separator{background: url(images/menu_sep.png) repeat-x; height:2px;font-size:2px; line-height: 2px;margin:3px 0 3px 24px}
6 .menu_casing .menu_icon{ height: 16px;left: 2px;position: absolute;top: 3px; width: 16px; background-repeat:no-repeat;}
调用代码
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html xmlns="http://www.w3.org/1999/xhtml" >
3 <head>
4 <title>Untitled Page</title>
5 <link rel="Stylesheet" href="menu.css" type="text/css" />
6 <script src="http://maps.google.com/maps/api/js?v=3.1&sensor=true" type="text/javascript"></script>
7 <script type="text/javascript" src="menu_v3.js" charset="utf-8"></script>
8 <style type="text/css">
9 #map{ width:640px; height:450px;}
10 </style>
11 </head>
12 <body onload="initialize();">
13 <div id="map"></div>
14 <script type="text/javascript">
15 Array.prototype.remove = function(item) {
16 for (var i = 0; i < this.length; i++) {
17 if (this[i] == item) {
18 this.splice(i, 1);
19 }
20 }
21 }
22
23 Array.prototype.getItem = function(id) {
24 for (var i = 0; i < this.length; i++) {
25 if (this[i].identity == id) {
26 return this[i];
27 }
28 }
29 }
30
31 var map;
32 var markers = new Array();
33 var identity = 0;
34 function initialize() {
35 var coor = new google.maps.LatLng(23.129163, 113.264435);
36 map = new google.maps.Map(document.getElementById("map"), { zoom: 12, center: coor, mapTypeControl: false, mapTypeId: google.maps.MapTypeId.ROADMAP });
37 var menu = new MenuControl(map);
38 menu.sender = map;
39 google.maps.event.addListener(map, "rightclick", function(e) {
40 if (menu.isEnable) {
41 menu.coordinate = { point: e.pixel, latlng: e.latLng };
42 menu.container.style.left = e.pixel.x + "px";
43 menu.container.style.top = e.pixel.y + "px";
44 menu.show("map");
45 }
46 });
47
48 menu.addItem(new MenuItem({ text: "添加标记", icon: "images/marker2.png", groupName: "map", handler: function(coor) {
49 if (markers.length >= 5) {
50 alert("最多能添加5个标记!");
51 } else {
52 var marker = new google.maps.Marker({ position: coor.latlng, map: map, draggable: true });
53 marker.identity = identity++;
54
55 // 添加标记的右击事件,弹出菜单时,IE以外的浏览器会出现偏移
56 var rightclick = function(e) {
57 menu.sender = marker;
58 if (menu.isEnable) {
59 var x = e.pixel.x;
60 var y = e.pixel.y;
61
62 if (document.all) {
63 x = window.event.x;
64 y = window.event.y;
65 } else { // 在IE以外的浏览器使用鼠标的x和y坐标弹出菜单时会出现偏移,需要另外计算
66 var eve = window.event;
67 if (!eve) {
68 var c = rightclick;
69 do {
70 var arg0 = c.arguments[0];
71 if (arg0) {
72 if (arg0.constructor == MouseEvent) {
73 eve = arg0;
74 break;
75 }
76 }
77 c = c.caller;
78 } while (c.caller)
79 }
80 var scale = Math.pow(2, map.getZoom());
81 var bounds = map.getBounds();
82 var nw = new google.maps.LatLng(bounds.getNorthEast().lat(), bounds.getSouthWest().lng());
83 var point = map.getProjection().fromLatLngToPoint(nw);
84 var worldCoor = map.getProjection().fromLatLngToPoint(marker.getPosition());
85 var off = new google.maps.Point(Math.floor((worldCoor.x - point.x) * scale), Math.floor((worldCoor.y - point.y) * scale));
86 var markerImg = eve.target.parentNode.parentNode.childNodes[0];
87 x = (off.x - (markerImg.offsetWidth) / 2) + eve.layerX;
88 y = (off.y - markerImg.offsetHeight) + eve.layerY;
89 }
90
91 menu.coordinate = { point: new google.maps.Point(x, y), latlng: coor.latlng };
92 menu.container.style.left = x + "px";
93 menu.container.style.top = y + "px";
94 menu.show("marker");
95 }
96 }
97 google.maps.event.addListener(marker, "rightclick", rightclick);
98 markers.push(marker);
99 }
100 }
101 }));
102
103 menu.addItem(new MenuItem({ text: "清除所有标记", groupName: "map", handler: function(coor) {
104 if (markers) {
105 for (var i = 0; i < markers.length; i++) {
106 markers[i].setMap(null);
107 }
108 markers.length = 0;
109 }
110 }
111 }));
112
113 menu.addSeparator("map");
114 menu.addItem(new MenuItem({ text: "放大一级", icon: "<%=BaseFile %>/comm/map/google/images/zoomin.png", groupName: "map", handler: function(coor) {
115 map.setZoom(map.getZoom() + 1);
116 }
117 }));
118 menu.addItem(new MenuItem({ text: "缩小一级", icon: "<%=BaseFile %>/comm/map/google/images/zoomout.png", groupName: "map", handler: function(coor) {
119 map.setZoom(map.getZoom() - 1);
120 }
121 }));
122
123 menu.addItem(new MenuItem({ text: "清除该标记", groupName: "marker", handler: function(coor) {
124 menu.sender.setMap(null);
125 markers.remove(menu.sender);
126 }
127 }));
128
129 menu.addSeparator("marker");
130 menu.addItem(new MenuItem({ text: "添加描述", groupName: "marker", handler: function(coor) {
131 var marker = menu.sender;
132 if (!marker.win) {
133 menu.sender.win = new google.maps.InfoWindow({ content: "<textarea onblur=\"edited(this," + marker.identity + ");\" rows=\"3\" cols=\"22\"></textarea>" });
134 google.maps.event.addListener(marker, "click", function() {
135 if (marker.win) marker.win.open(map, marker);
136 });
137 marker.description = "";
138 }
139 marker.win.setContent("<textarea onblur=\"edited(this," + marker.identity + ");\" rows=\"3\" cols=\"22\">" + marker.description + "</textarea>")
140 marker.win.open(map, marker);
141 }
142 }));
143
144 menu.addItem(new MenuItem({ text: "删除描述", groupName: "marker", handler: function(coor) {
145 menu.sender.win.close();
146 menu.sender.win = null;
147 }
148 }));
149 }
150
151 function edited(sender, id) {
152 var marker = markers.getItem(id);
153 marker.win.setContent(sender.value.replace(/[\r\n]/g, "<br/>").replace(/>([^<>]+)((?=<)|$)/g, function(t) { return t.replace(/[\s]/g, " "); }) + " <a href=\"javascript:;\" onclick=\"edit(" + id + ");\">编辑</a>");
154 marker.description = sender.value;
155 }
156
157 function edit(id) {
158 var marker = markers.getItem(id);
159 marker.win.setContent("<textarea onblur=\"edited(this," + id + ");\" rows=\"3\" cols=\"22\">" + marker.description + "</textarea>");
160 }
161 </script>
162 </body>
163 </html>
效果图:
标记的右键菜单效果:
插入到kindeditor编辑器中的效果图: