skip to Main Content

I am trying to write content to a google maps control div, my prefered way being to use jquery selector with div id.
The problem is that the map only seems to take the actual element referenced by variable to change it, instead of its ID.

This is exampled by the bottom control ‘testcontrol_2’ able to have its background changed, however ‘testcontrol_1’ referenced by ID remains white.

My question is why am I able to write content to the map controls with an actual html element as a jQuery selector, but not an element id.

Fiddle: https://jsfiddle.net/Tim_H/pgb9z2v1/2/

Code:

<html>
<head>
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDbFd34Z8SoF6Q9v3RQnkwy5nDDw09tvww"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <style>
      .mapframe {
        width: 100%;
        height: 50em;
      }

      .mapcontrol {
        padding: 1em;
        background-color: #ffffff;
      }
    </style>
</head>
<body>
<div id="mapframe" class="mapframe"></div>
<script>
      var map;
      var centerControlContainer;
      var centerControlId = 'mainCenterControlFrame';
      var testControl2;

      function mapinit() {
        let mapinit = {
          center: new google.maps.LatLng(51.509865, -0.118092),
          zoom: 10,
          minzoom: 15,
          maxzoom: 21,
        };
        map = new google.maps.Map(document.getElementById('mapframe'), mapinit);
        google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
          GMapready();
        });
      }

      function GMapready() {
        centerControlContainer = document.createElement('div');
        $(centerControlContainer).addClass('mapControlContainer');
        $(centerControlContainer).attr('id', centerControlId);
        
        $(centerControlContainer).html('<div id="testcontrol_1" class="mapcontrol">TestControl1</div>');

        testControl2 = document.createElement('div');
        $(testControl2).attr('id', 'testcontrol_2');

        $(testControl2).html('TestControl2');
        $(testControl2).addClass('mapcontrol');
        $(centerControlContainer).append(testControl2);

        this.map.controls[google.maps.ControlPosition.TOP_CENTER].push(this.centerControlContainer);

        $('#testcontrol_1').css('background-color', '#ff0000');
        $(testControl2).css('background-color', '#ff0000');

      }

      mapinit();
</script>
</body>
</html>

2

Answers


  1. Consider the following example: https://jsfiddle.net/Twisty/og7tru4m/

    JavaScript

    $(function() {
      var map;
      var centerControlContainer;
      var centerControlId = 'mainCenterControlFrame';
    
      function mapinit(sel) {
        let mapinit = {
          center: new google.maps.LatLng(51.509865, -0.118092),
          zoom: 10,
          minzoom: 15,
          maxzoom: 21,
        };
        map = new google.maps.Map($(sel).get(0), mapinit);
        google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
          GMapready();
        });
      }
    
      function GMapready() {
        centerControlContainer = $('<div>', {
          id: centerControlId,
          class: 'mapControlContainer'
        });
        var control_1 = $('<div>', {
          id: "testcontrol_1",
          class: "mapcontrol"
        }).html("TestControl1").appendTo(centerControlContainer).click(function(evt) {
          console.log("Control 1 was clicked.");
        });
    
        var control_2 = $('<div>', {
          id: 'testcontrol_2',
          class: "mapcontrol"
        }).html('TestControl2').appendTo(centerControlContainer).click(function(evt) {
          console.log("Control 2 was clicked.");
        });
    
        map.controls[google.maps.ControlPosition.TOP_CENTER].push(centerControlContainer.get(0));
    
        control_1.css('background-color', '#ff0000');
        control_2.css('background-color', '#0000ff');
    
      }
    
      mapinit("#mapframe");
    });
    

    As you suggested, Google JavaScript will not work well with jQuery Objects, yet this is not an issue. When you create jQuery Objects, you can still pass along the underlying HTML Element or DOM Element. There are a few ways to do this.

    One way is to use .get() (See More), which returns the DOM Element at a specific index.

    centerControlContainer.get(0)
    

    Each jQuery object also masquerades as an array, so we can use the array dereferencing operator to get at the list item instead.

    centerControlContainer[0]
    

    Using .get() is preferred.

    In this way, you can create and manage jQuery Objects and still use them with your Google Maps.

    You can also make use of jQuery’s ability to create DOM Elements on the fly.

    If a string is passed as the parameter to $(), jQuery examines the string to see if it looks like HTML (i.e., it starts with <tag ... >). If not, the string is interpreted as a selector expression, as explained above. But if the string appears to be an HTML snippet, jQuery attempts to create new DOM elements as described by the HTML. Then a jQuery object is created and returned that refers to these elements.

    See More: https://api.jquery.com/jQuery/#jQuery-html-attributes and https://learn.jquery.com/using-jquery-core/jquery-object/

    One of the main benefits to jQuery is Chaining.

    If you call a method on a selection and that method returns a jQuery object, you can continue to call jQuery methods on the object without pausing for a semicolon. This practice is referred to as "chaining".

    See More: https://learn.jquery.com/using-jquery-core/working-with-selections/

    Login or Signup to reply.
  2. The testcontrol_1 isn’t changing because it isn’t part of the DOM until after you call: $('#testcontrol_1').css('background-color', '#ff0000');.

    If you do this:

    setTimeout(function() {
      $('#testcontrol_1').css('background-color', '#ff0000');
    },100);
    
    

    to give the process a change to render it in the DOM, then jquery will be able to find it.

    proof of concept fiddle

    screenshot of resulting map

    code snippet:

    <html>
    
      <head>
        <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
        <style>
          html, body {
            width: 100%;
            height: 100%;
            padding: 0px;
            margin: 0px;
          }
          .mapframe {
            width: 100%;
            height: 100%;
          }
    
          .mapcontrol {
            padding: 1em;
            background-color: #ffffff;
          }
    
        </style>
      </head>
    
      <body>
        <div id="mapframe" class="mapframe"></div>
        <script>
          var map;
          var centerControlContainer;
          var centerControlId = 'mainCenterControlFrame';
          var testControl2;
    
          function mapinit() {
            let mapinit = {
              center: new google.maps.LatLng(51.509865, -0.118092),
              zoom: 10,
              minzoom: 15,
              maxzoom: 21,
            };
            map = new google.maps.Map(document.getElementById('mapframe'), mapinit);
            google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
              GMapready();
            });
          }
    
          function GMapready() {
            centerControlContainer = document.createElement('div');
            $(centerControlContainer).addClass('mapControlContainer');
            $(centerControlContainer).attr('id', centerControlId);
            $(centerControlContainer).html('<div id="testcontrol_1" class="mapcontrol">TestControl1</div>');
    
            testControl2 = document.createElement('div');
            $(testControl2).attr('id', 'testcontrol_2');
    
            $(testControl2).html('TestControl2');
            $(testControl2).addClass('mapcontrol');
            $(centerControlContainer).append(testControl2);
    
            this.map.controls[google.maps.ControlPosition.TOP_CENTER].push(this.centerControlContainer);
    
            setTimeout(function() {
              $('#testcontrol_1').css('background-color', '#ff0000');
            }, 100);
            $(testControl2).css('background-color', '#ff0000');
    
          }
    
          mapinit();
    
        </script>
      </body>
    
    </html>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search