Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the acf domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home/jwblogger/jwBlogger/wp-includes/functions.php on line 6121

Notice: Function wp_enqueue_script was called incorrectly. Scripts and styles should not be registered or enqueued until the wp_enqueue_scripts, admin_enqueue_scripts, or login_enqueue_scripts hooks. This notice was triggered by the codepen-embed-script handle. Please see Debugging in WordPress for more information. (This message was added in version 3.3.0.) in /home/jwblogger/jwBlogger/wp-includes/functions.php on line 6121
api development – Jeff Wilkerson's Blog https://blog.jeffwilkerson.net The yoga of web development Fri, 17 Apr 2015 18:34:57 +0000 en-US hourly 1 https://wordpress.org/?v=6.8.5 Google Maps Demo https://blog.jeffwilkerson.net/2015/04/17/google-maps-demo/ https://blog.jeffwilkerson.net/2015/04/17/google-maps-demo/#respond Fri, 17 Apr 2015 18:34:57 +0000 http://www.jeffwilkerson.net/?p=161 Below is the process and code that I used to create this map showing Instagram pictures from a road trip I took starting in Nashville, TN and ending in Portland, OR. This exercise demonstrates:

  • API Development
  • Consumption of JSON Data
  • Object-Oriented Principles

Live Demo Page

The Process

  1. First, I gathered the Instagram pictures I wanted to show on my map. Because I didn’t properly tagged the original Instagram posts with any location info, or anything that would distinguish the posts from my other posts, I had to build my own custom results set using the results set from Instagram as a foundation. I employed Instafeed.js to help build my results set. Here is the final JSON object.
  2. Next, I got my App Key from Google and built a “Hello, World!” test to make sure everything worked.
  3. Finally, I created two javascript classes, MyList and MyMap. MyList is a glorified array of Map Markers, with an internal pointer that tracks the “current” index. MyMaps is a wrapper class for the google.maps.Map object, adding UI controls.

The Code

Class: MyList

/***************** CLASS: MyList **********************/
/* * 
    Stores a list of pbjects, and a a reference pointing to a selected list item
    Functions:
        add - Adds item to the list
        saveAll - Adds an array of items to the list
        count - returns number of items in list
        getAll - returns entire list
        get - gets the item at a specified index
        indexOf - returns index number of specified object, making that object the new selection
        next - returns the next object in the list
        previous - returns the previous object in the list
        triggerMarkerIcon - toggles marker icon of the selected index;
            Parameter toggle - boolean. False for default red flag; true for green flag
    */
function MyList() {
    this.list = [];
    this.pointer = -1;	
}

MyList.prototype.add = function(obj) { return this.list.push(obj); };
MyList.prototype.saveAll = function(array) { if(array.constructor === Array) this.list = array; };
MyList.prototype.count = function() { return this.list.length; };
MyList.prototype.getAll = function() { return this.list; };
MyList.prototype.get = function(i) {
    if(i > -1 && i < this.list.length) {
        this.triggerMarkerIcon();
        this.pointer = i;
        this.triggerMarkerIcon(true);			
        return this.list[i];
    }
};
MyList.prototype.indexOf = function(marker) {
    this.triggerMarkerIcon();
    for(var i = 0; i < this.list.length; i++) {
        if(this.list[i] === marker) {
            this.pointer = i;
            this.triggerMarkerIcon(true);
            return i;
        }
    }
    return -1;
};
MyList.prototype.next = function() {
    this.triggerMarkerIcon();
    this.pointer++;
    if(this.pointer == this.list.length) this.pointer = 0;
    this.triggerMarkerIcon(true);
        
    return this.list[this.pointer];
};
MyList.prototype.previous = function() {
    this.triggerMarkerIcon();
    this.pointer--;
    if(this.pointer < 0) this.pointer = this.list.length - 1;
    this.triggerMarkerIcon(true);
        
    return this.list[this.pointer];
};
MyList.prototype.triggerMarkerIcon = function(toggle) {
    var icon = red_icon;
    if(toggle) icon = green_icon;
    
    if(this.pointer > -1 && this.list[this.pointer]) {
        this.list[this.pointer].setIcon(icon);
    }
};

Class: MyMaps

/***************** CLASS: MyMap **********************/
/* * 
    Wrapper class for Google Maps Object. 
    customized to show a list of Instagram images, each marked on a map
    Functions:
        changeMarker: activates the marker chosen by the user. Displays infoWindow
        addMarker: creates a custom marker object, including the content for the marker, 
            extrracted from the data object.
            Expands the bounds of the map.
        initControls: Adds the 'Next' and 'Previous' click event handlers allowing the user to go back
            and forth between markers
        initMap: initializes Map, stores the markers in a list
    */
function MyMap() {
    this.map = undefined;
    this.el = undefined;
    this.infoWindow = new google.maps.InfoWindow();
    this.bounds = new google.maps.LatLngBounds();
    this.markers = new MyList();
}

MyMap.prototype.changeMarker = function(marker, origin) {

    if(!origin)
        this.markers.indexOf(marker);

    this.infoWindow.setContent(marker.content);
    this.infoWindow.open(this.map, marker);	
};

MyMap.prototype.addMarker = function(mark) {
    var self = this, date, date_string, latlng, gMarker;
    if (mark.location.lat != undefined && mark.location.long != undefined) {
        
        date = new Date(mark.created_time * 1000);
        date_string = monthnames[date.getMonth()] + ' ' + date.getDate();
                    
        latlng = new google.maps.LatLng(mark.location.lat, mark.location.long);
        
        gMarker = new google.maps.Marker({
            position: latlng,
            map: self.map,
            title: date_string
        });
        
        gMarker.content = "
"+date_string+"

"+mark.caption.text + "
Filter: " + mark.filter + "
"; google.maps.event.addListener(gMarker, 'click', function() { self.changeMarker(gMarker); }); this.markers.add(gMarker); this.bounds.extend(latlng); } } MyMap.prototype.initControls = function() { var self = this; $('.next-marker').click(function(e) { e.preventDefault(); self.changeMarker(self.markers.next(), this); }); $('.previous-marker').click(function(e) { e.preventDefault(); self.changeMarker(self.markers.previous(), this); }); }; MyMap.prototype.initMap = function(id, data) { this.el = $(id)[0]; this.map = new google.maps.Map(this.el, {zoom: 8}); var self = this; for(var i = 0; i < data.length; i++) { this.addMarker(data[i]); } this.map.fitBounds(self.bounds); this.changeMarker(this.markers.next()); };

$(document).ready()

map_to_pdx = new MyMap();
	
$(function() {
    
    if(!pdx_trip_data_uri) {
        console.log("ERROR. No input.");
    }
    else {
    	//#map-container is hidden on small screens
        if($('#map-container').is(':visible')) {
            //Get Data from JSON Object
            var jqxhr = $.getJSON(pdx_trip_data_uri.path);
            
            jqxhr.done(function(data) {
                if(data.length > 0) {
                    map_to_pdx.initMap('#map-canvas', data);
                    map_to_pdx.initControls();
                }
            });
        }
    }
});

Links

Special Thanks To:

]]>
https://blog.jeffwilkerson.net/2015/04/17/google-maps-demo/feed/ 0