Monday, February 27, 2012

Working notes February 27

8:30 a.m.
I am working on the Google Maps API 3 again today. One of my goals is to allow users to use their preference of geographic coordinates to locate a spot on the map.

References I have found:

Friday, February 24, 2012

Working notes February 24, 2012: Google Maps API

Today's focus is on creating a user interface for the Google Maps API.  Using basic HTML5, Javascript and the Google Maps API 3, I set out to create a reference of three methods for creating markers on a map, each with different properties.

Here is the source code of the result:
<!DOCTYPE HTML>

<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var geocoder = new google.maps.Geocoder();
var theMap;

function geocodePosition(pos) {
  geocoder.geocode({
    latLng: pos
  }, function(responses) {
    if (responses && responses.length > 0) {
      updateMarkerAddress(responses[0].formatted_address);
    } else {
      updateMarkerAddress('Cannot determine address at this location.');
    }
  });
}

function updateMarkerStatus(str) {
  document.getElementById('markerStatus').innerHTML = str;
}

function updateMarkerPosition(latLng) {
  document.getElementById('info').innerHTML = [
    latLng.lat(),
    latLng.lng()
  ].join(', ');
}

function updateMarkerAddress(str) {
  document.getElementById('address').innerHTML = str;
}

function initialize() {
      //initialize map with pin at Capitol & Front in Boise.
      var latLng = new google.maps.LatLng(43.61351466, -116.203798);
      theMap = new google.maps.Map(document.getElementById('mapCanvas'), {
        zoom: 13,
        center: latLng,
        mapTypeId: google.maps.MapTypeId.HYBRID
      });
     
      var marker = new google.maps.Marker({
        position: latLng,
        title: 'Initialization marker',
        map: theMap,
        draggable: true
      });
     
      // Update current position info.
      updateMarkerPosition(latLng);
      geocodePosition(latLng);
     
      // Add dragging event listeners.
      google.maps.event.addListener(marker, 'dragstart', function() {
      updateMarkerAddress('Dragging...');
      });
     
      google.maps.event.addListener(marker, 'drag', function() {
      updateMarkerStatus('Dragging...');
      updateMarkerPosition(marker.getPosition());
      });
     
      google.maps.event.addListener(marker, 'dragend', function() {
      updateMarkerStatus('Drag ended');
      geocodePosition(marker.getPosition());
      });
     
      //add click listener for new marker http://stackoverflow.com/questions/7083264/google-maps-api-v3-set-marker-and-get-point
      google.maps.event.addListener(theMap, 'click', function(e) {
      placeMarkerByMapClick(e.latLng, theMap);
      });
}

function addMarkerByExternalButton()
    {
        //alert("addMarker");
        var latLng = new google.maps.LatLng(43.60283295462482, -116.19584164278416);
        //var theMap = google.maps.Map(document.getElementById('mapCanvas'));
        var blueMapMarker = "http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png";
               
        // Set up our GMarkerOptions object
        markerOptions = {  };
        
        http://stackoverflow.com/questions/4236522/google-maps-api-v3-info-window-displaying-same-information-for-all-the-markers
        var contentString_1 =  "<b>BSU Broncos Stadium</b><br /> Boise, Idaho, USA<br><b><a href='http://broncosports.com'>BSU Athletics site</a></b><br /><img src='http://image.cdnllnwnl.xosnetwork.com/fls/9900/images/facilities/new_turf.jpg' />";
        var infowindow_1 = new google.maps.InfoWindow({content: contentString_1});
        
        
        var newMarkerFromExtButton = new google.maps.Marker({
            position: latLng,
            title: 'Marker added by external button',
            map: theMap,
            icon: blueMapMarker,
            animation: google.maps.Animation.DROP,
            draggable: false
            });

        newMarkerFromExtButton.setMap(theMap);
        
        // Update current position info.
        updateMarkerPosition(latLng);
        geocodePosition(latLng);
          
        // Add dragging event listeners.
        google.maps.event.addListener(newMarkerFromExtButton, 'dragstart', function() {
        updateMarkerAddress('Dragging...');
        });
          
        google.maps.event.addListener(newMarkerFromExtButton, 'drag', function() {
        updateMarkerStatus('Dragging...');
        updateMarkerPosition(newMarkerFromExtButton.getPosition());
        });
          
        google.maps.event.addListener(newMarkerFromExtButton, 'dragend', function() {
        updateMarkerStatus('Drag ended');
        geocodePosition(newMarkerFromExtButton.getPosition());
        });
        
        //add other listeners
        google.maps.event.addListener(newMarkerFromExtButton, 'click', function() {
        infowindow_1.open(theMap,newMarkerFromExtButton);
        });
        
    }


//reference http://stackoverflow.com/questions/7083264/google-maps-api-v3-set-marker-and-get-point
function placeMarkerByMapClick(position, map) {
    //alert("placeMarker");
    var yellowMapMarker = "http://www.google.com/intl/en_us/mapfiles/ms/micons/yellow-dot.png";
     
    var newMarkerFromMapClick = new google.maps.Marker({
        position: position,
        map: map,
        title: "marker added by map click",
        icon: yellowMapMarker,
        animation: google.maps.Animation.DROP,
        draggable: true
        });
   
    // Update current position info.
    updateMarkerPosition(position);
    geocodePosition(position);
   
     
    // Add dragging event listeners.
    google.maps.event.addListener(newMarkerFromMapClick, 'dragstart', function() {
    updateMarkerAddress('Dragging...');
    });
     
    google.maps.event.addListener(newMarkerFromMapClick, 'drag', function() {
    updateMarkerStatus('Dragging...');
    updateMarkerPosition(newMarkerFromMapClick.getPosition());
    });
     
    google.maps.event.addListener(newMarkerFromMapClick, 'dragend', function() {
    updateMarkerStatus('Drag ended');
    geocodePosition(newMarkerFromMapClick.getPosition());
    });
     
    //next line centers the map on the newly created marker. Disabled since the movement is a bit annoying.
    //map.panTo(position);
    }
     

function addMarkerByTypedCoords()
{
    //alert("addMarker");
    var lat=document.getElementById("lat").value;
    var lon=document.getElementById("lon").value;
   
    var latLng = new google.maps.LatLng(lat, lon);
    //var theMap = google.maps.Map(document.getElementById('mapCanvas'));
    var greenMapMarker = "http://www.google.com/intl/en_us/mapfiles/ms/micons/green-dot.png";
    // Set up our GMarkerOptions object
    markerOptions = { };

    var markerContent =  document.getElementById("markertitle").value;
    var infowindow_1 = new google.maps.InfoWindow({content: markerContent});

    var newMarkerFromTypedCoords = new google.maps.Marker({
        position: latLng,
        title: 'Marker added by typed coordinates',
        map: theMap,
        icon: greenMapMarker,
        animation: google.maps.Animation.DROP,
        draggable: true
        });
   
    newMarkerFromTypedCoords.setMap(theMap);
   
    // Update current position info.
    updateMarkerPosition(latLng);
    geocodePosition(latLng);
   
    // Add dragging event listeners.
    google.maps.event.addListener(newMarkerFromTypedCoords, 'dragstart', function() {
    updateMarkerAddress('Dragging...');
    });
   
    google.maps.event.addListener(newMarkerFromTypedCoords, 'drag', function() {
    updateMarkerStatus('Dragging...');
    updateMarkerPosition(newMarkerFromTypedCoords.getPosition());
    });
   
    google.maps.event.addListener(newMarkerFromTypedCoords, 'dragend', function() {
    updateMarkerStatus('Drag ended');
    geocodePosition(newMarkerFromTypedCoords.getPosition());
    });
   
    //add other listeners
    google.maps.event.addListener(newMarkerFromTypedCoords, 'click', function() {
    infowindow_1.open(theMap,newMarkerFromTypedCoords);
    });
   
    theMap.panTo(latLng);
    }

    
// Onload handler to fire off the app.
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
  <style>
  #mapCanvas {
    width: 800px;
    height: 800px;
    float: left;
  }
  #infoPanel {
    float: left;
    margin-left: 10px;
  }
  #infoPanel div {
    margin-bottom: 5px;
  }
  </style>
 
  <div id="mapCanvas"></div>
 
  <div id="infoPanel">
      <p>NOTE: Marker generated at map initialization is red.</p>
      <hr />
      <h3>Current marker information</h3>
      <b>Marker status:</b>
      <div id="markerStatus"><i>Click and drag the marker.</i></div>
      <b>Current position:</b>
      <div id="info"></div>
      <b>Closest matching address:</b>
      <div id="address"></div>
      <hr />
     
      <h3>Method 1: Add a predefined location marker</h3>
      <p>Marker will be blue. Click the blue marker to get an info window with photo.</p>
      <button onclick="addMarkerByExternalButton()"> Add marker at BSU Stadium</button>
     
      <hr />
      <h3>Method 2: Add new marker from manually entered coordinates</h3>
      <p>Marker will be green</p>
      <form id="typedcoords">
          <fieldset>
          <legend>Type coordinates to add a new marker</legend>
          <label for="lat">Title your new marker:</label>
          <input type="text" name="markertitle" id="markertitle" /><br />
          <label for="lat">Latitude (decimal degrees)</label>
          <input type="text" name="lat" id="lat" /><br />
          <label for="lon">Longitude (decimal degrees)</label>
          <input type="text" name="lon" id="lon" />
          <br />
          <button id="addMarker" title="Add Marker" type="button" onclick="addMarkerByTypedCoords()">Add Marker</button>
          </fieldset>
      </form>
      <hr />
     
      <h3>Method 3: Click map to create new marker</h3>
      <p>Marker will be yellow</p>
      <p>Just click anywhere on the map to create a simple new marker</p>
 
  </div>
</body>
</html>
This example has been tested successfully in Firefox 10 and Safari 5.1 on Mac, and IE and Firefox on Windows XP

References utilized to create this example:

http://code.google.com/apis/maps/documentation/javascript/reference.html

http://code.google.com/apis/maps/documentation/javascript/overlays.html#Markers

http://stackoverflow.com/questions/4236522/google-maps-api-v3-info-window-displaying-same-information-for-all-the-markers

http://code.google.com/apis/maps/documentation/javascript/overlays.html#SimpleIcons

http://groups.google.com/group/google-maps-js-api-v3/browse_thread/thread/5865e223d316b238/e221a5a33c7775d3?pli=1

I'll be working with the GM API for several days, and will likely add more examples as I progress through this project.

Tuesday, February 14, 2012

Working notes for February 14, 2012

Today I am working on integrating SlickGrid into a project. So far, so good.

One task this has required is the insertion of a new CSS file into the page. My project structure displays all content inside of a single PHP file based on URL parameters. Therefore, when individual pages require special CSS, I need to make that happen within the page, not in the wrapper, to avoid unnecessary bandwidth usage.

Here is some Javascript that will load a CSS file into the page's header when called in the body:

<script type="text/javascript">
var fileref=document.createElement("link");
fileref.setAttribute("rel", "stylesheet");
fileref.setAttribute("type", "text/css");
fileref.setAttribute("href", "thedir/thefile.css");
document.getElementsByTagName("head")[0].appendChild(fileref);
</script>

Friday, February 3, 2012

Working notes Feb. 3, 2012

I am so thankful to be able to work from my home office on occasion. I can create the ideal atmosphere for maximum productivity. That's where I am today, and things are coming together nicely so far.

Today, I am working on integrating an Elgg social network installation with a custom-built PHP/JS/jQuery/MySQL site for a continent-wide, and potentially worldwide, research project.

Step 1 is to get the main site to check the user's login status in the Elgg site. Being logged into Elgg will open access to multiple tools not available to the public.

Based on example code provided by Steve Clay, I have been able to access the Elgg session data for a user and return a string to tell the user they are logged in.

<?php
/*require a PHP PDO database instance here */

$elggstatus=$_COOKIE["Elgg"]; //capture the session ID

if($elggstatus)
    {
    $user_id = 0;
    $sql = ("SELECT `data` FROM `elgg_users_sessions` WHERE `session` = :sessVal");
    $params=array("sessVal"=>$elggstatus);
   
    $elggUser=$thePDO->thePDOselectfunction($sql,$params);
   
    $userData=$elggUser[(dissect your PDO data structure here)];

        $userData=explode('attributes";', $userData); //split the user object after the attributes segment

        $userData=unserialize($userData[1]); //use PHP's unserialize() function to convert the data back to a PHP value
                      
        $userDisplayName=$userData["name"]; //capture the user's "display name"
    print "You are logged in as $displayName";//provide the feedback to the user.
    }
?>
Update 12:00
I sure enjoy these rare occasions when everything falls into place.  Since my original posting I have been able to create a PHP class to communicate with Elgg and return user status and data.  By using this method I'll be able to extend the communication between Elgg and the main site as needed in the future.

It took a little while to get past some bumps in establishing a new PHP PDO MySQL class separate from the primary instance used for the other database, but once that was fixed it works fine.  The next step is to make sure this works regardless of which URL option the user chooses to access the site. (There is a subdomain that goes directly to it, or they can use a long URL including the primary domain + directory tree)

Update 14:25
No real surprise, what I thought was working earlier failed upon testing by a user.  Evidently Elgg returned the user object in a different order for different users, so the code I had posted earlier did not work.  I revisited Steve's example, found where I had taken a wrong turn, and revised my code. Now it accurately converts the stored value into a standard PHP array for easy and consistent parsing.  The code above has been edited to show my corrections.

Next goal: make Elgg write its session cookies so that it can be read from other subdomains.

Update 15:35
Since the last update, I have been working on trying to make the session cookie visible regardless of subdomain. No success.

I tried creating a new php.ini file in the Elgg root directory with this line:
session.cookie_domain=.mydomain.org
and logged in. My browser's cookie library showed that Elgg did properly set the cookie to be owned by .mydomain.com instead of mydomain.com as previously.

However, login now fails totally. When I try to log in, Elgg shows a red bar in the upper right corner saying 'you have to be logged in to see this file.' I had to disable my php.ini file to get my site back.

Back to researching...

Update 17:30
The joys of software architecture... nothing to show for the past 3 hours of work. I detailed my work to get a solution for cookie visibility across subdomains in a post on the Elgg community. With an immovable deadline looming and having lost 3 hours to fruitless research on the problem, I am considering changing the entire installation configuration to minimize the chance of problems. I had hoped to build Elgg into a multisite-capable system, since we have at least 5 different projects that could utilize its social networking functionality. Given that development of the multisite plugin appears to be inactive, I'll probably have to reconfigure my system to reside completely within a single subdomain to avoid these cookie issues. Maybe in the future a multi-site version of Elgg will be viable and I will reconfigure at that point in time.