locked
Google map Context Menu RRS feed

  • Question

  • User728122777 posted

    Hi all

    i am creating gps tracking system

    i have to do two things with the marker

    1- create context menu with some functions on the marker

    2- add car number as label on the marker

    the first thing is finished

    http://codepen.io/mmkhalil/pen/xRbBbj

    when i tried to do the second issue  a conflict (i think) happened

    i included a JS library

    https://github.com/googlemaps/js-map-label/blob/gh-pages/src/maplabel-compiled.js

    both are working alone but when combined no thin work

    code after combine

    http://codepen.io/mmkhalil/pen/RoNdyN

    some details

    both depend on overlay

    errors

    TypeError: a.lng is not a function
    ...b=b||new _.G(0,0);var c=this.b;b.x=c.x+a.lng()*this.j;a=_.Za(Math.sin(_.Sb(a.lat...
    js?key=...QQ9UEYg (line 112, col 3438)
    InvalidValueError: not a LatLng or LatLngLiteral: in property lat: not a number
    TypeError: c.lat is not a function
    ...,c=d.b.search(_.vi)):(c=a.ca,c=new _.G(c.lat(),c.lng()),a.da=c,_.uJ(d.j,{da:c,ye...
    marker.js (line 26, col 177)
    InvalidValueError: not a LatLng or LatLngLiteral: in property lat: not a number

    thank yoyu

    Monday, November 7, 2016 11:36 AM

All replies

  • User283571144 posted

    Hi MaherKhalil,

    both are working alone but when combined no thin work

    According to your description and codes, I had written a test demo on my computer.

    I found you set wrong mapLabel's position.

    So it will not worked.

    I suggest you could change your codes as below:

    <!doctype html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
        <title>Map Label Utility Library Example</title>
        <style>
            #map {
        width:750px;
        height:400px;
    }
    .context-menu-marker {
        border-style:none;
        border-width:0px;
        ;
        visibility:hidden;
        background:white;
    }
    
    .options-marker {
        width:96%;
        height:18px;
        padding:3px 0px 3px 2px;
        border:1px solid #ccc;
        cursor:pointer;
    }
    
    .options-marker:hover {
        background:#ccc;   
    }
    
        </style>
        <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAdN8sDyYifiM3hAKcnW2ceZ2CoQQ9UEYg"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
        <script src="../src/maplabel-compiled.js"></script>
        <script>
    
    
    
            var loc, map, marker, contextMenu;
    
            ContextMenu.prototype = new google.maps.OverlayView();
    
            /**
              * onAdd is called when the map's panes are ready and the overlay has been
              * added to the map.
              */
            ContextMenu.prototype.onAdd = function () {
    
                $("<div id='cMenu' class='context-menu-marker'></div>").appendTo(document.body);
                var divOuter = $("#cMenu").get(0);
    
                for (var i = 0; i < this.menuItems.length; i++) {
                    var mItem = this.menuItems[i];
                    $('<div id="' + mItem.id + '" class="options-marker">' +
                      mItem.label + '</div>').appendTo(divOuter);
                }
    
                this.div_ = divOuter;
    
                // Add the element to the "overlayLayer" pane.
                var panes = this.getPanes();
                //panes.overlayLayer.appendChild();
                panes.overlayMouseTarget.appendChild(this.div_);
    
                var me = this;
    
                for (var i = 0; i < this.menuItems.length; i++) {
                    var mItem = this.menuItems[i];
    
                    var func = function () {
                        me.clickedItem = this.id;
                        google.maps.event.trigger(me, 'click');
                    };
    
                    google.maps.event.addDomListener($("#" + mItem.id).get(0), 'click', $.proxy(func, mItem));
                }
    
    
                google.maps.event.addListener(me, 'click', function () {
                    alert(me.clickedItem);
                });
    
            };
    
            ContextMenu.prototype.draw = function () {
                var div = this.div_;
                div.style.left = '0px';
                div.style.top = '0px';
                div.style.width = '100px';
                div.style.height = '50px';
            };
    
            // The onRemove() method will be called automatically from the API if
            // we ever set the overlay's map property to 'null'.
            ContextMenu.prototype.onRemove = function () {
                this.div_.parentNode.removeChild(this.div_);
                this.div_ = null;
            };
    
            // Set the visibility to 'hidden' or 'visible'.
            ContextMenu.prototype.hide = function () {
                if (this.div_) {
                    // The visibility property must be a string enclosed in quotes.
                    this.div_.style.visibility = 'hidden';
                }
            };
    
            ContextMenu.prototype.show = function (cpx) {
                if (this.div_) {
                    var div = this.div_;
                    div.style.left = cpx.x + 'px';
                    div.style.top = cpx.y + 'px';
    
                    this.div_.style.visibility = 'visible';
                }
            };
    
            function ContextMenu(map, options) {
                options = options || {}; //in case no options are passed to the constructor
                this.setMap(map); //tells the overlay which map it needs to draw on
                this.mapDiv = map.getDiv(); //Div container that the map exists in
                this.menuItems = options.menuItems || {}; //specific to context menus
                this.isVisible = false; //used to hide or show the context menu
            }
    
            function initialize() {
    
                loc = new google.maps.LatLng(62.323907, -150.109291);
    
                var options = {};
                var menuItems = [];
    
                menuItems.push({ id: "zoomIn", className: 'context_menu_item', eventName: 'zoom_in_click', label: 'Zoom in' });
                menuItems.push({ id: "zoomOut", className: 'context_menu_item', eventName: 'zoom_out_click', label: 'Zoom out' });
                //menuItems.push({}); //we’ll add code later to make empty menuItems into separators
    
    
                options.menuItems = menuItems;
                //=========================================
    
                map = new google.maps.Map(document.getElementById("map"), {
                    zoom: 12,
                    center: loc,
                    mapTypeId: google.maps.MapTypeId.ROADMAP
                });
                cerateMarker();
    
    
                contextMenu = new ContextMenu(map, options);
    
                google.maps.event.addListener(marker, 'rightclick', function (mouseEvent) {
                    contextMenu.hide();
                    this.clickedMarker_ = this;
                    var overlayProjection = contextMenu.getProjection();
                    var cpx = overlayProjection.fromLatLngToContainerPixel(mouseEvent.latLng);
                    contextMenu.show(cpx);
    
                    map.setOptions({ draggableCursor: 'pointer' });
                });
    
                // Hide context menu on several events
                google.maps.event.addListener(map, 'click', function () {
                    map.setOptions({ draggableCursor: 'grab' });
                    contextMenu.hide();
                });
    
            }
    
            google.maps.event.addDomListener(window, 'load', initialize);
            function cerateMarker() {
                var mapLabel = new MapLabel({
                    text: 'Text',
                    ,
                    map: map,
                    fontSize: 35,
                    align: 'right'
                });
                marker = new google.maps.Marker({
                    map: map,
                    ,
                    visible: true
                });
                marker.bindTo('map', mapLabel);
                marker.bindTo('position', mapLabel);
            }
    
        </script>
      
    </head>
    <body>
        <div id="map"></div>
    </body>
    </html>
    

    Result:

    Best Regards,

    Brando

    Tuesday, November 8, 2016 7:08 AM
  • User728122777 posted

    Thank you for your answer

    i managed to make it working but having some trouble

    it show on the wrong place

    its place is changed when i zoom

    here is my Code

      function placeMarker(location, ID, Date, IconFile, speed, PlatNumber) {
    
                var mapLabel = new MapLabel({
                    text: PlatNumber,
                    ,
                    map: map,
                    fontSize: 15,
                    align: 'center'
                });
                mapLabel.set('position', location);
    
    
                marker = new google.maps.Marker({
                    ,
                    map: map,
                    MID: ID,
                    MDate: Date,
                    icon: IconFile,
    
                });
                marker.bindTo('map', mapLabel);
                marker.bindTo('position', mapLabel);
                var infoBubble;
                var contentString = "";
                // Creating / Initiating Infobox					
                infoBubble = new InfoBox({
                    //content: contentString, // Tab content gets appended here.
                    disableAutoPan: false,
                    maxWidth: 0,
                    pixelOffset: new google.maps.Size(-140, 0),
                    zIndex: null,
    
                    boxStyle: {
                        //background: "url('tipbox.gif') no-repeat", 
                        opacity: 1,
                        width: "350px"
                    },
                    closeBoxMargin: "0px",
                    closeBoxURL: "http://www.google.com/intl/en_us/mapfiles/close.gif",
                    infoBoxClearance: new google.maps.Size(1, 1),
                    isHidden: false,
                    pane: "floatPane",
                    enableEventPropagation: true
                });
                
                marker.addListener('click', function () {
    
                    //$.each(infoBubbles, function (ix, vx) {
    
    
                    ////==========================================
                    downloadUrl("Queries.aspx?Action='CarLocation'&CarId=" + ID, function (data) {
    
                        var xml = data.responseXML;
    
                        // alert(xml);
                        //  alert(data.responseText);
    
                        // var markers = xml.documentElement.getElementsByTagName("marker");
                        var markers = xml.documentElement.getElementsByTagName("Marker");
                        // alert(markers);
                        for (var i = 0; i < markers.length; i++) {
                            // alert(i);
    
    
                            var PlatNumber = markers[i].getElementsByTagName("PlateNO")[0].childNodes[0].nodeValue;
                            var SubModelName = markers[i].getElementsByTagName("SubModelName")[0].childNodes[0].nodeValue;
                            var CarModelName = markers[i].getElementsByTagName("ModelName")[0].childNodes[0].nodeValue;
                            var IMEI = markers[i].getElementsByTagName("IMEI")[0].childNodes[0].nodeValue;
                            var DeviceModelName = markers[i].getElementsByTagName("DeviceModelName")[0].childNodes[0].nodeValue;
                            var DeviceVenderName = markers[i].getElementsByTagName("DeviceVenderName")[0].childNodes[0].nodeValue;
                            contentString = "<div class='main'><input id='tab1' type='radio' name='tabs' checked> <label for='tab1'>السيارة</label><input id='tab2' type='radio' name='tabs'>";
                            contentString = contentString + "<label for='tab2'>السائق</label><input id='tab3' type='radio' name='tabs'> <label for='tab3'>الجهاز</label><input id='tab4' type='radio' name='tabs'>";
                            contentString = contentString + " <label for='tab4'>الموقع</label><div class='content'> <div id='content1'> <p> رقم اللوحة:" + PlatNumber + " </br> نوع السيارة :" + CarModelName + "  </br> موديل السيارة : " + SubModelName + "</br> السرعة :" + speed + "</p> ";
                            contentString = contentString + " </div> <div id='content2'><p> Driver Data </p>";
                            contentString = contentString + " </div> <div id='content3'><p> رقم الجهاز : " + IMEI + " </br> الشركة المصنعة : " + DeviceVenderName + " </br> الموديل : " + DeviceModelName + " </br> أخر ظهور: " + Date + "</p>";
                            contentString = contentString + " </div><div id='content4'><p>خط الطول " + location.lng() + " </br> خط العرض " + location.lat() + "</br> AAdd </p></div> </div> </div>   ";
                            //   contentString = "<div id='tabs'><ul><li><a href='#tab-1'><span> السيارة</span></a></li><li><a href='#tab-2'><span> السائق</span></a></li><li><a href='#tab-3'><span> الجهاز</span></a></li><li><a href='#tab-4'><span>الموقع</span></a></li></ul><div id='tab-1'><p> رقم اللوحة:" + PlatNumber + " </br> نوع السيارة :" + CarModelName + "  </br> موديل السيارة : " + SubModelName + "</p></div><div id='tab-2'><p>Tab 2 content</p></div><div id='tab-3'><p> رقم الجهاز : " + IMEI + " </br> الشركة المصنعة : " + DeviceVenderName + " </br> الموديل : " + DeviceModelName + " </p></div><div id='tab-4'><p>خط الطول " + location.lng() + " </br> خط العرض " + location.lat() + "</br> AAdd </p></div></div>";
    
                            var geocoder = new google.maps.Geocoder();
                            geocoder.geocode({
                                latLng: location
                            },
                                function (responses) {
                                    if (responses && responses.length > 0) {
    
                                        infoBubble.setContent(contentString.replace("III", marker.IDD).replace("AAdd", responses[0].formatted_address));
                                        // infoBubble.setContent(contentString.replace("III", marker.IDD).replace("CurrentAddress", responses[0].formatted_address));
                                        if (isInfoWindowOpen(infoBubble)) {
                                            // do something if it is open
                                            infoBubble.close();
                                            return;
                                        } else {
                                            // do something if it is closed
                                            infoBubble.open(map, marker);
                                        }
                                    }
                                    else {
                                        // alert("2");
                                        //infoBubble.setContent(contentString.replace("III", marker.IDD));
                                        //  infoBubble.setContent(contentString.replace("III", marker.IDD));
                                    }
                                }
                        );
                            var sv = new google.maps.StreetViewService();
    
                            sv.getPanoramaByLocation(location, 50, function (data, status) {
                                if (status == 'OK') {
                                    // console.log('SV');
                                    contentString = contentString.replace("AAdd", "<img src='https://maps.googleapis.com/maps/api/streetview?size=200x200&location=" + location.lat() + "," + location.lng() + "&fov=90&heading=235&pitch=10%20&key=AIzaSyAdN8sDyYifiM3hAKcnW2ceZ2CoQQ9UEYg' alt='https://maps.googleapis.com/maps/api/streetview?size=200x200&location=" + location.lat() + "," + location.lng() + "&fov=90&heading=235&pitch=10%20&key=AIzaSyAdN8sDyYifiM3hAKcnW2ceZ2CoQQ9UEYg>");
                                }
                                else {
                                    //  console.log('no SV');
                                    //   contentString = ['<div id="tabs">', '<ul>', '<li><a href="#tab-1"><span>Car Info</span></a></li>', '<li><a href="#tab-2"><span>Driver</span></a></li>', '<li><a href="#tab-3"><span>Tab3</span></a></li>', '<li><a href="#tab-4"><span>Address</span></a></li>', '</ul>', '<div id="tab-1">', '<p> ' + Date + '    </p>', '</div>', '<div id="tab-2">', '<p>Tab 2 content</p>', '</div>', '<div id="tab-3">', '<p> Tab3 Data </p>', '</div>', '<div id="tab-4">', '<p>CurrentAddress</p>', '</div>', '</div>'].join('');
    
                                }
                            });
                            
                        }
    
                    });
    
                    ////////========================
    
    
    
                });
    
                marker.addListener('rightclick', function (e) {
                    contextMenu.hide();
                    this.clickedMarker_ = this;
                    var overlayProjection = contextMenu.getProjection();
                    var cpx = overlayProjection.fromLatLngToContainerPixel(e.latLng);
                    contextMenu.show(cpx);
    
                    map.setOptions({ draggableCursor: 'pointer' });
    
    
                });
    
                // Hide context menu on several events
    
    
                //var infoWindow = new google.maps.InfoWindow;
                markersArr.push(marker);
    
                //bindInfoWindow(marker, map, infoWindow, html);
    
    
            }

    Map context menu

    Tuesday, November 8, 2016 9:29 AM
  • User283571144 posted

    Hi MaherKhalil,

    i managed to make it working but having some trouble

    it show on the wrong place

    its place is changed when i zoom

    here is my Code

    According to your description and codes, you need to reset the ContextMenu.prototype.draw function.

    In this function, you set the left and top value is "0px".

    So it will return 0, after zoomed.

    More details, you could refer to follow codes:

    Note: I used my previous post's codes.

    <!doctype html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
        <title>Map Label Utility Library Example</title>
        <style>
            #map {
        width:750px;
        height:400px;
    }
    .context-menu-marker {
        border-style:none;
        border-width:0px;
        ;
        visibility:hidden;
        background:white;
    }
    
    .options-marker {
        width:96%;
        height:18px;
        padding:3px 0px 3px 2px;
        border:1px solid #ccc;
        cursor:pointer;
    }
    
    .options-marker:hover {
        background:#ccc;   
    }
    
        </style>
        <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAdN8sDyYifiM3hAKcnW2ceZ2CoQQ9UEYg"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
        <script src="../src/maplabel-compiled.js"></script>
        <script>
    
    
    
            var loc, map, marker, contextMenu, left ,top1;
    
            ContextMenu.prototype = new google.maps.OverlayView();
    
            /**
              * onAdd is called when the map's panes are ready and the overlay has been
              * added to the map.
              */
            ContextMenu.prototype.onAdd = function () {
    
                $("<div id='cMenu' class='context-menu-marker'></div>").appendTo(document.body);
                var divOuter = $("#cMenu").get(0);
    
                for (var i = 0; i < this.menuItems.length; i++) {
                    var mItem = this.menuItems[i];
                    $('<div id="' + mItem.id + '" class="options-marker">' +
                      mItem.label + '</div>').appendTo(divOuter);
                }
    
                this.div_ = divOuter;
    
                // Add the element to the "overlayLayer" pane.
                var panes = this.getPanes();
                //panes.overlayLayer.appendChild();
                panes.overlayMouseTarget.appendChild(this.div_);
    
                var me = this;
    
                for (var i = 0; i < this.menuItems.length; i++) {
                    var mItem = this.menuItems[i];
    
                    var func = function () {
                        me.clickedItem = this.id;
                        google.maps.event.trigger(me, 'click');
                    };
    
                    google.maps.event.addDomListener($("#" + mItem.id).get(0), 'click', $.proxy(func, mItem));
                }
    
    
                google.maps.event.addListener(me, 'click', function () {
                    alert(me.clickedItem);
                });
    
            };
    
            ContextMenu.prototype.draw = function () {
                var div = this.div_;
                var overlayProjection = contextMenu.getProjection();
                var cpx = overlayProjection.fromLatLngToContainerPixel(loc);
                div.style.left = cpx.x + 'px';
                div.style.top = cpx.y + 'px';
                div.style.width = '100px';
                div.style.height = '50px';
            };
    
            // The onRemove() method will be called automatically from the API if
            // we ever set the overlay's map property to 'null'.
            ContextMenu.prototype.onRemove = function () {
                this.div_.parentNode.removeChild(this.div_);
                this.div_ = null;
            };
    
            // Set the visibility to 'hidden' or 'visible'.
            ContextMenu.prototype.hide = function () {
                if (this.div_) {
                    // The visibility property must be a string enclosed in quotes.
                    this.div_.style.visibility = 'hidden';
                }
            };
    
            ContextMenu.prototype.show = function (cpx) {
                if (this.div_) {
                    var div = this.div_;
                    div.style.left = cpx.x + 'px';
                    div.style.top = cpx.y + 'px';
                    left = div.style.left;
                    top = div.style.top;
    
                    this.div_.style.visibility = 'visible';
                }
            };
    
            function ContextMenu(map, options) {
                options = options || {}; //in case no options are passed to the constructor
                this.setMap(map); //tells the overlay which map it needs to draw on
                this.mapDiv = map.getDiv(); //Div container that the map exists in
                this.menuItems = options.menuItems || {}; //specific to context menus
                this.isVisible = false; //used to hide or show the context menu
            }
    
            function initialize() {
    
                loc = new google.maps.LatLng(62.323907, -150.109291);
    
                var options = {};
                var menuItems = [];
    
                menuItems.push({ id: "zoomIn", className: 'context_menu_item', eventName: 'zoom_in_click', label: 'Zoom in' });
                menuItems.push({ id: "zoomOut", className: 'context_menu_item', eventName: 'zoom_out_click', label: 'Zoom out' });
                //menuItems.push({}); //we’ll add code later to make empty menuItems into separators
    
    
                options.menuItems = menuItems;
                //=========================================
    
                map = new google.maps.Map(document.getElementById("map"), {
                    zoom: 12,
                    center: loc,
                    mapTypeId: google.maps.MapTypeId.ROADMAP
                });
                cerateMarker();
    
    
                contextMenu = new ContextMenu(map, options);
    
                google.maps.event.addListener(marker, 'rightclick', function (mouseEvent) {
                    contextMenu.hide();
                    this.clickedMarker_ = this;
                    var overlayProjection = contextMenu.getProjection();
                    var cpx = overlayProjection.fromLatLngToContainerPixel(mouseEvent.latLng);
                    contextMenu.show(cpx);
    
                    map.setOptions({ draggableCursor: 'pointer' });
                });
    
                // Hide context menu on several events
                google.maps.event.addListener(map, 'click', function () {
                    map.setOptions({ draggableCursor: 'grab' });
                    contextMenu.hide();
                });
    
    
    
            }
    
            google.maps.event.addDomListener(window, 'load', initialize);
            function cerateMarker() {
                var mapLabel = new MapLabel({
                    text: 'Text',
                    ,
                    map: map,
                    fontSize: 35,
                    align: 'right'
                });
                marker = new google.maps.Marker({
                    map: map,
                    ,
                    visible: true
                });
                marker.bindTo('map', mapLabel);
                marker.bindTo('position', mapLabel);
            }
    
        </script>
      
    </head>
    <body>
        <div id="map"></div>
    </body>
    </html>
    

    Result:

    Best Regards,

    Brando

    Thursday, November 10, 2016 8:39 AM
  • User728122777 posted

    thank you for the replay

    your code is correct but for some reason it is not working for me

    the problem in the above function i sent 

    because the same thing happen in the infobox

    Infobox Wrong Location

    why ??

    the markers are placed right but the infobox show in the same location for all the markers

    Monday, November 14, 2016 1:47 PM
  • User283571144 posted

    Hi MaherKhalil,

    your code is correct but for some reason it is not working for me

    the problem in the above function i sent 

    because the same thing happen in the infobox

    According to your description, I couldn't understand clearly.

    I found in your codes, you didn't define the context menu draw function.

    In this function, we could draw the position of the context menu.

    If zoomed, the google map will automatic call this function changed the context menu again.

    Besides, I suggest you could open a new thread to talking about the infobox.

    Since the problem about context box is already solved.

    We suggest OP in one thread talking about one question, this will be more easily for someone who faces the same problem to find the solution.

    Best Regards,

    Brando

    Tuesday, November 15, 2016 1:52 AM