A bit of a newbee, but I have a somewhat complex issue.

Background: I am creating a map for a client, with a filtered list beneath it. when they click one of the categories at the top, the list filters to that category, and the respective markers on my GMap view change icons from a light blue to dark blue if they are the active category, and vice-versa if inactive. I have been working on this on and off for a little over a month, but the deadline is the end of the month. I'm on the last few steps, namely optimizing.

The problem: I have everything working, but not very quickly. When I go to switch the categories, it calls

var map=Drupal.gmap.getMap('auto1map');
      map.bind('addmarker', function (m) { ... }); //bind addmarker-handler, the marker is available as callback-argument

However, I noticed, to update a marker, it calls that method for each marker, AND it calls the methods within to update each marker, which seems necessary because otherwise it stops after the first marker.... Ultimately, it hangs for a few seconds where the webpage freezes up, which is not ideal.

I get my brain all jumbled up, this is my first web dev job, and I don't have the most solid grasp on JavaScript. Do I need to extract the setIcon code from the bind event? Is there a better way to update Icons on a Google Map?

Full code is as follows:

(function ($) { 
  //When click on marker, act on related link

  //initiates drupal gmap module
  Drupal.behaviors.gmap = {
    attach: function (context, settings) {
      //I get all the html list elements 
      var listBlock = $('.project-prof'); //choose .project-prof elements
      var li = $(listBlock).parent().parent().parent(); //chooses the list item of .project-prof elements
      var activeCategory = "Healthcare"; //sets default activeCategory
      var activeLi = $("."+activeCategory).parent().parent().parent(); //chooses list item of active .project-prof
      var location = []; //this will be used to keep track of the locations of each activeLi in the array of <li> 
          // now we .push() the position(integer) of each list item that has activeCategory
      $(li).each(function(i){
        if($(this).children().children().children().hasClass(activeCategory)){
                location.push(i);
            }
      });
      console.log(location); //debug

      //Set index to associate list element and markers
      var index = 0;

      //reference for the map
      var map=Drupal.gmap.getMap('auto1map');
      //bind addmarker-handler, the marker is available as callback-argument 
      map.bind('addmarker', function (m) {
        var element = $(li)[index];
        m.marker.index=index;

        //remove listeners set automatically by the library  
        google.maps.event.clearListeners(m.marker, 'mouseover mouseout click');

        //hover over markers
        google.maps.event.addListener(m.marker, 'mouseover',function(){
          //Hide other elements
          //so activeLi toggle here hides the active category
                $(activeLi).stop().animate({
                  height: "toggle",
                  width:"toggle",
                  opacity: "toggle"
                });
      //element toggles the specific moused-over object
                $(element).stop().animate({
                  height: "toggle",
                  width:"toggle",
                  opacity: "toggle"
                });
        });
        //same thing but just mouseout
        google.maps.event.addListener(m.marker, 'mouseout',function(){
                $(activeLi).stop().animate({
                  height: "toggle",
                  width:"toggle",
                  opacity: "toggle"
                });
                $(element).stop().animate({
                  height: "toggle",
                  width:"toggle",
                  opacity: "toggle"
                });
        });
        //hover is set

        //filter list after button press (button event further down)
        function toggleCategory(thisVar) {
            //console.log("" + thisVar+ " "); //debug to make sure activeCategory is bound correctly

            activeLi = $("."+thisVar).parent().parent().parent(); //gotta set activeLi again
            var location = []; //empty out the old location array
                        //do it again
            $(li).each(function(i){
                if($(this).children().children().children().hasClass(thisVar)){
                    location.push(i);
                }
            });
            console.log(location); //more debug
            //fancy animations 
            $(activeLi).stop().animate({
                  height: "toggle",
                  width:"toggle",
                  opacity: "toggle"
            });
                        //this is how the icons are actually set for the markers to their correct active or inactive look
            if($.inArray(m.marker.index,location) != -1){
                console.log("2." + m.marker.index + " = " + "true"); //debug
                m.marker.setIcon('marker.png');
            } else {
                m.marker.setIcon('marker2.png');
            }
        }
        //filter is set

        //setting defaults
                //initial setup on page load of which markers are active and inactive
        if($.inArray(m.marker.index,location) != -1){
                console.log("2." + m.marker.index + " = " + "true"); //debug
                m.marker.setIcon('marker.png');
        } else {
                m.marker.setIcon('marker2.png');
        }
        $(listBlock).not($(".Healthcare")).parent().parent().parent().hide();
        //defaults are set

        //filtering buttons
        $("#block-block-38 input").on("click", function(){
            $(activeLi).stop().animate({
                  height: "toggle",
                  width:"toggle",
                  opacity: "toggle"
            }); //fancy animations
            activeCategory = $(this).attr('name'); //set activeCategory to this new button's name
            toggleCategory(activeCategory); //pass activeCategory into the above function (it becomes thisVar)
        });
        //buttons set

        //toggle marker location's modal, same as clicking on respective list item
        google.maps.event.addListener(m.marker, 'click',function(){
            $($(element).find('a').attr("data-target")).modal("show");
        });
        //modal is set

        index++; //increment index so we can do this all over again for each marker?
      });
    }
  }
})(jQuery);

How can I cut the fat out of this code/make this work faster?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

schnoodle created an issue. See original summary.

schnoodle’s picture

Status: Active » Closed (works as designed)

I have managed to fix the hang. I learned a lot about Google Maps in general, but as I was clicking a filter button, it would add new markers, which would make new arrays, which would then execute 66 more times, doing all of it at once. So I realized after a while, why not just take out all the code from that addmarker block, putting it below?

To replace all that code, the most important thing was to stuff each new marker into an array, to compare their index later to the "active" list that resides below the map. If this helps anyone, yet they need help, let me know, I might be able to assist.

(function($) {
    //When click on marker, act on related link
    //initiates drupal gmap module
    Drupal.behaviors.gmap = {
        attach: function(context, settings) {
            //I get all the html list elements 
            var listBlock = $('.project-prof'); //choose .project-prof elements
            var li = $(listBlock).parent().parent().parent(); //chooses the list item of .project-prof elements
            var activeCategory = "Healthcare"; //sets default activeCategory
            var activeLi = $("." + activeCategory).parent().parent().parent(); //chooses list item of active .project-prof
            var location = [];
            var markers = [];
            //Set index to associate list element and markers
            var index = 0;
            //reference for the map
            var map = Drupal.gmap.getMap('auto1map');

			//pushes the location of the active list item into the location array
            $(li).each(function(i) {
                if ($(this).children().children().children().hasClass(activeCategory)) {
                    location.push(i);
                }
            });

            //bind addmarker-handler, the marker is available as callback-argument 
            map.bind('addmarker', function(m) {
                var element = $(li)[index];
                m.marker.index = index;

                //remove listeners set automatically by the library  
                google.maps.event.clearListeners(m.marker, 'mouseover mouseout click');


                //hover over markers
                google.maps.event.addListener(m.marker, 'mouseover', function() {
                    //Hide other elements
                    //so activeLi toggle here hides the active category
                    $(activeLi).stop().animate({
                        height: "toggle",
                        width: "toggle",
                        opacity: "toggle"
                    });
                    //element toggles the specific moused-over object
                    $(element).stop().animate({
                        height: "toggle",
                        width: "toggle",
                        opacity: "toggle"
                    });
                });
                google.maps.event.addListener(m.marker, 'mouseout', function() {
                    $(activeLi).stop().animate({
                        height: "toggle",
                        width: "toggle",
                        opacity: "toggle"
                    });
                    $(element).stop().animate({
                        height: "toggle",
                        width: "toggle",
                        opacity: "toggle"
                    });
                });
                //hover set
                
                //now we push this marker into an array that contains the markers
                markers.push(m.marker);
                
                //now check if this marker's index in that array is a number in location[]
                if ($.inArray(m.marker.index, location) != -1) {
                    m.marker.setIcon('../markers/stevens.png');
                } else {
                    m.marker.setIcon('../markers/stevens2.png');
                }

                //toggle marker location's modal, same as clicking on list
                google.maps.event.addListener(m.marker, 'click', function() {
                    $($(element).find('a').attr("data-target")).modal("show");
                });
                //modal set

                index++;
            });

            //filtering buttons
            $("#block-block-38 input").on("click", function() {
                $(activeLi).stop().toggle();
                $(".prof-cat-active").removeClass("prof-cat-active");
				$(this).addClass("prof-cat-active");
                activeCategory = $(this).attr('name');
                location = [];
                $(li).each(function(i) {
                    if ($(this).children().children().children().hasClass(activeCategory)) {
                        location.push(i);
                    }
                });
                console.log(location);
                toggleCategory(activeCategory);
            });
            //buttons set

			//default for the list below map
            $(listBlock).not($(".Healthcare")).parent().parent().parent().hide();
            
			//function that toggles the category
            function toggleCategory(thisVar) {

                activeLi = $("." + thisVar).parent().parent().parent();
                $(activeLi).stop().toggle();

                for (var i = 0; i < markers.length; i++) {
                    console.log(markers[i]);
                    console.log($.inArray(markers[i].index, location));
                    if ($.inArray(markers[i].index, location) != -1) {
                        console.log("2." + markers[i] + " = " + "true");
                        markers[i].setIcon('../markers/stevens.png');
                    } else {
                        markers[i].setIcon('../markers/stevens2.png');
                    }
                }

            }
        }
    };
})(jQuery);