Google Maps API v3 Practical Implementation

Google Maps API v3 Practical Implementation

4 66550
Google Maps API Practical Implementation

Google Maps API v3 Practical Implementation

In our new tutorial I would like to give you one interesting example of Google Maps API (v3) implementation. Let assume, that you have website with own members. And, you need to add possibility to save map positions of your members at your website. Or, you have to store map coordinates for something else (as example – business locations). I think that this is one of usual tasks in webdevelopment. For our practical realization I took the base of our chat system (I removed everything unnecessary except registration). Now, I will add here next features: index page block with map of 20 recent locations of members, profile page map (with single marker), and page to set coordinates at map.

Live Demo
download in package

Now – download the source files and lets start coding !


Step 1. SQL

If you have already had `cs_profiles` table in your database (due of tests), you don’t need remove previous version, keep it, and add second one new table `latlng268`:

CREATE TABLE `cs_profiles` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(255) NOT NULL default '',
  `first_name` varchar(255) NOT NULL default '',
  `last_name` varchar(255) NOT NULL default '',
  `email` varchar(255) NOT NULL default '',
  `password` varchar(40) NOT NULL default '',
  `salt` varchar(10) NOT NULL default '',
  `status` enum('active','passive') NOT NULL default 'active',
  `role` tinyint(4) unsigned NOT NULL default '1',
  `about` varchar(255) NOT NULL,
  `date_reg` datetime NOT NULL default '0000-00-00 00:00:00',
  `date_nav` datetime NOT NULL default '0000-00-00 00:00:00',
  `color` varchar(6) NOT NULL,
  `rate` float NOT NULL,
  `rate_count` int(11) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
CREATE TABLE `latlng268` (
  `id` int(11) unsigned NOT NULL auto_increment,
  `profile` int(11) unsigned NOT NULL,
  `name` varchar(255) NOT NULL default '',
  `lat` double NOT NULL,
  `lng` double NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Step 2. HTML

This is Login / Join form template:

templates/login_form.html

<div class="column">
    <h3>Google Maps API v3 Practical Implementation</h3>
    <p>Our demonstration contains next features: member registration, and possibility to add own custom marker at google map.</p>
</div>
<div class="column">
    <div class="tabs_container">
        <ul class="tabs">
            <li class="active"><h3>Log In</h3></li>
            <li><h3>Join</h3></li>
        </ul>
    </div>
    <div class="nav_container">
        <form class="login_form" action="index.php" method="post" id="1">
            <label>Username:</label><input type="text" name="username">
            <label>Password:</label><input type="password" name="password">
            <input type="submit" name="Login" value="Login">
        </form>
        <form class="join_form" action="index.php" method="post" id="2" style="display: none;">
            <label>Full name:</label>
            <input type="text" id="username" name="username" placeholder="Your name" maxlength="128" title="Your name" required>
            <label>First name:</label>
            <input type="text" id="firstname" name="firstname" placeholder="Your first name" maxlength="128" title="Your first name">
            <label>Last name:</label>
            <input type="text" id="lastname" name="lastname" placeholder="Your last name" maxlength="128" title="Your last name">
            <label>Email:</label>
            <input type="text" id="email" name="email" placeholder="Your email" maxlength="128" title="Format: *@gmail.com" pattern=".*@gmail\.com" required>
            <label>Password:</label>
            <input type="text" id="password" name="password" maxlength="128" title="Password" required>
            <label>Repeat Password:</label>
            <input type="text" id="password" name="password" maxlength="128" title="Repeat password" required oninput="checkpass(this)">
            <input type="submit" name="Join" value="Join">
        </form>
    </div>
    <div>Powered by <a href="https://www.script-tutorials.com/" target="_blank" title="Script Tutorials">Script Tutorials</a>
    </div>
</div>
<script>
$(document).ready(function(){
    $('.tabs li h3').click(function () {
      $('.tabs li').removeClass('active');
      $(this).parent().addClass('active');
      $('.nav_container form').hide();
      var index = $('.tabs li h3').index(this);
      $('.nav_container form').eq(index).show();
      return false;
    });
});
function checkpass(input) {
    if (input.value != document.getElementById('password').value) {
        input.setCustomValidity('Password must match.');
    } else {
        input.setCustomValidity('');
    }
}
</script>

Very easy form, isn’t it? Next template – small logout template (with link to page to set position):

templates/logout_form.html

<div class="column">
    <span style="float:right"><a href="index.php?logout">Log Out</a></span>
    <h3>Hello {name}</h3>
    <h3>Your status:</h3>
    <div>{status}</div>
    <h3><a href="setpos.php">Set my position</a></h3>
</div>

Again – very easy template. Next template – index (main) page template:

templates/main_page.html

<!DOCTYPE html>
<html lang="en" >
<head>
    <title>Google Maps API v3 Practical Implementation</title>
    <link href="css/main.css" rel="stylesheet" type="text/css" />
    <script src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
    <script src="js/update.js"></script>
</head>
<body>
    <header>
        <h2>Google Maps API v3 Practical Implementation</h2>
        <a href="https://www.script-tutorials.com/google-maps-api-v3-practical-implementation/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
    </header>
    <div class="clear"></div>
    <div class="container" id="con1">
        {form}
    </div>
    <div class="container" id="con2">
        <h2>Main Map</h2>
        <div class="gmap">
            <div id='gmap_canvas' style="position:relative; width:100%; height:550px;"></div>
        </div>
    </div>
    <div class="sidebar">
        <div>
            <h2>Online Members Block</h2>
            {online_members}
        </div>
        <div>
            <h2>Last Members</h2>
            {profiles}
        </div>
    </div>
    <script type="text/javascript">
        var map;
        function initialize() {
            var iCoordX = 40;
            var iCoordY = -75;
            var myLatlng = new google.maps.LatLng(iCoordX, iCoordY);
            var myOptions = {
                zoom: 6,
                center: myLatlng,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            map = new google.maps.Map(document.getElementById('gmap_canvas'), myOptions);
            var aMarkers = new Array();
            var aMarkerInfos = new Array();
            {add_markers}
        }
        google.maps.event.addDomListener(window, 'load', initialize);
    </script>
</body>
</html>

Here you can see google maps initialization – this is very easy JS script, where we need prepare map options and initialize map object, and then – we need to add 20 (optonal) recent positions. Next template – profile page template:

templates/profile_page.html

<!DOCTYPE html>
<html lang="en" >
<head>
    <title>Google Maps API v3 Practical Implementation</title>
    <link href="css/main.css" rel="stylesheet" type="text/css" />
    <script src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script src="js/update.js"></script>
</head>
<body>
    <header>
        <h2>Google Maps API v3 Practical Implementation</h2>
        <a href="https://www.script-tutorials.com/google-maps-api-v3-practical-implementation/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
    </header>
    <div class="clear"></div>
    <div class="container">
        <div class="column">
            <h3>Name: {name}</h3>
            <h3>First name: {fname}</h3>
            <h3>Last name: {lname}</h3>
            <h3>About: {about}</h3>
            <h3>Date Reg: {datereg}</h3>
        </div>
        <div class="column">
            <p><a href="index.php">Back to main page</a></p>
        </div>
    </div>
    {map}
    <div class="sidebar">
        <div>
            <h2>Online Members Block</h2>
            {online_members}
        </div>
        <div>
            <h2>Last Members</h2>
            {profiles}
        </div>
    </div>
</body>
</html>

At this page, we will see single profile view page, and, if he (that member) has set his coordinates, we will see google map at his page. Next template – html template of that profile’s map:

templates/profile_map.html

<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<div class="clear"></div>
<div class="container">
    <div id='gmap_canvas' style="position:relative; width:100%; height:400px;"></div>
</div>
<script type="text/javascript">
    var map;
    var marker;
    function initialize() {
        // set profile coordinates
        var myLatlng = new google.maps.LatLng({lat}, {lng});
        var myOptions = {
            zoom: 6,
            center: myLatlng,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        map = new google.maps.Map(document.getElementById('gmap_canvas'), myOptions);
        // prepare info window
        var infowindow = new google.maps.InfoWindow({
            content: "{name}"
        });
        // prepare new marker
        marker = new google.maps.Marker({
            position: myLatlng,
            map: map,
            title: "{name}",
            animation: google.maps.Animation.DROP
        });
        google.maps.event.addListener(marker, 'click', function() {
            infowindow.open(map,marker);
        });
    }
    // initialization
    google.maps.event.addDomListener(window, 'load', initialize);
</script>

You can see here new google map initialization in certain coordinates with marker, and we add event listener (when we click at marker) to display popup info (InfoWindow). And finally, we should prepare last one template file – for page where member can setup own coordinates:

templates/setpos_page.html

<!DOCTYPE html>
<html lang="en" >
<head>
    <title>Google Maps API v3 Practical Implementation</title>
    <link href="css/main.css" rel="stylesheet" type="text/css" />
    <script src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
</head>
<body>
    <header>
        <h2>Google Maps API v3 Practical Implementation</h2>
        <a href="https://www.script-tutorials.com/google-maps-api-v3-practical-implementation/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
    </header>
    <div class="clear"></div>
    <div class="container">
        <h3><a href="index.php">Back to main page</a></h3>
        <div style="margin:10px;">Type full street address into field and click on FIND to center map on location.</div>
        <div style="margin:10px;"><input id="gmap_where" type="text" name="gmap_where" /><input id="find" type="button" value="Find" name="find" onclick="findAddress(); return false;" /></div>
        <div id='gmap_canvas' style="position:relative; width:100%; height:400px;margin-bottom:25px;"></div>
        <hr />
        <h3>Please confirm your position</h3>
        <form class="login_form" action="setpos.php" method="post" name="setpos_form">
            <input type="text" name="lat" value="{lat}" />
            <input type="text" name="lng" value="{lng}" />
            <input type="submit" name="Confirm" value="Confirm positions" />
        </form>
    </div>
    <script type="text/javascript">
        var geocoder;
        var map;
        var marker;
        function initialize() {
            geocoder = new google.maps.Geocoder();
            // set initial coordinates
            var myLatlng = new google.maps.LatLng({lat}, {lng});
            var myOptions = {
                zoom: 6,
                center: myLatlng,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            map = new google.maps.Map(document.getElementById('gmap_canvas'), myOptions);
            // prepare info window
            var infowindow = new google.maps.InfoWindow({
                content: 'My position'
            });
            // prepare new marker
            marker = new google.maps.Marker({
                position: myLatlng,
                map: map,
                title: 'My position',
                draggable:true,
                animation: google.maps.Animation.DROP
            });
            google.maps.event.addListener(marker, 'click', function() {
                infowindow.open(map,marker);
            });
            google.maps.event.addListener(marker, 'dragstart', function() {
                infowindow.close();
            });
            google.maps.event.addListener(marker, 'dragend', function(obj) {
                map.setCenter(obj.latLng);
                $('form[name=setpos_form] input[name=lat]').val( obj.latLng.$a );
                $('form[name=setpos_form] input[name=lng]').val( obj.latLng.ab );
            });
        }
        // initialization
        google.maps.event.addDomListener(window, 'load', initialize);
        // find custom address function
        function findAddress() {
            var address = document.getElementById("gmap_where").value;
            geocoder.geocode( { 'address': address}, function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                map.setCenter(results[0].geometry.location);
                marker.position = results[0].geometry.location;
                $('form[name=setpos_form] input[name=lat]').val( results[0].geometry.location.$a );
                $('form[name=setpos_form] input[name=lng]').val( results[0].geometry.location.ab );
            } else {
                alert("Geocode was not successful for the following reason: " + status);
            }
            });
        }
    </script>
</body>
</html>

This Javascript is more complicated, I added here possibility to drag marker, and also I added search panel, so now we can search by exact names.

Step 3. CSS

Now, it’s time to apply styles:

css/main.css

/* page layout */
*{
    margin:0;
    padding:0;
}
body {
    background-color:#eee;
    color:#fff;
    font:14px/1.3 Arial,sans-serif;
}
header {
    background-color:#212121;
    box-shadow: 0 -1px 2px #111111;
    display:block;
    height:70px;
    position:relative;
    width:100%;
    z-index:100;
}
header h2{
    float: left;
    font-size:22px;
    font-weight:normal;
    margin-left:10px;
    margin-right:20px;
    padding:22px 0;
}
header a.stuts,a.stuts:visited{
    float: left;
    text-decoration:none;
    color:#fcfcfc;
    font-size:14px;
    height:70px;
    line-height:70px;
}
header .stuts span {
    font-size:22px;
    font-weight:bold;
    margin-left:5px;
}
/* main styles */
a {
    color: #333;
    outline: none;
    text-decoration: none;
}
a:hover,a:active {
    outline: 0;
    text-decoration: none;
}
.container {
    background-color: #F2F4F8;
    border: 1px solid rgba(0, 0, 0, 0.4);
    box-shadow: 2px 0 2px -2px #B2B9C9 inset;
    color: #333333;
    margin: 20px;
    overflow: hidden;
    padding: 20px;
    position: relative;
    width: 70%;
    float:left;
}
#con1.container {
    width: 300px;
}
#con2.container {
    width: 500px;
}
.container h2 {
    margin-bottom: 10px;
}
.column {
}
.column:first-child {
}
.column > * {
    margin-bottom: 10px;
}
.clear {
    clear: both;
    font-size: 1px;
}
.sidebar {
    background-color: #F2F4F8;
    border-left: 1px solid rgba(0, 0, 0, 0.4);
    box-shadow: 2px 0 2px -2px #B2B9C9 inset;
    color: #333333;
    display: block;
    height: 100%;
    padding: 10px;
    position: fixed;
    right: 0;
    top: 0;
    width: 250px;
    z-index: 101;
}
.sidebar > div {
    margin-bottom: 30px;
}
/* tabs section */
.tabs_container {
    margin: 0;
}
.tabs {
    overflow: hidden;
}
.tabs li {
    float: left;
    list-style: none;
}
.tabs li h3:first-child {
    margin-left: 10px
}
.tabs li h3 {
    border: 1px solid #ddd;
    border-bottom-width: 0;
    display: block;
    margin: 0 2px 0 0;
    padding: 6px 10px 4px
}
.tabs li.active h3 {
    background-color: #ccc;
    border: 1px solid #ddd;
    border-bottom-width: 0;
    -moz-border-radius: 4px 4px 0 0;
    -ms-border-radius: 4px 4px 0 0;
    -o-border-radius: 4px 4px 0 0;
    -webkit-border-radius: 4px 4px 0 0;
    border-radius: 4px 4px 0 0;
}
.tabs li h3:hover {
    background-color: #bbb;
    cursor: pointer;
}
.tabs li.active h3:hover {
    background-color: #ccc;
    cursor: normal;
}
.nav_container form {
    background-color: #ccc;
    display: block;
    padding: 15px;
}
.login_form input,.login_form label,
.join_form input,.join_form label {
    display: block;
    margin-bottom: 10px;
}
input[type=text], input[type=password], input[type=submit] {
    -moz-border-radius: 5px;
    -ms-border-radius: 5px;
    -o-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;
    border-style: groove;
}
input[type=text], input[type=password] {
    border-style: groove;
    font-size: 16px;
    height: 25px;
    margin-right: 10px;
    width: 200px;
}
input[type=submit],
input[type=file]{
    cursor: pointer;
    font-size: 16px;
    font-weight: bold;
    height: 35px;
    padding: 5px;
}
/* profiles */
.profiles {
    overflow: hidden;
}
.profiles a {
    display: block;
}
.profiles div {
    overflow: hidden;
}
.profiles div a {
    color: #333333;
    display: block;
    padding: 2px 22px 2px 10px;
    position: relative;
}
.profiles div a:hover {
    background-color: #E0E4EE;
    box-shadow: 2px 0 2px -2px #B2B9C9 inset;
}
.profiles div img {
    border: 0;
    float: left;
    height: 48px;
    margin-right: 8px;
    width: 48px;
}
.profiles div p {
    display: block;
    line-height: 28px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.profiles div img.status_img {
    border: 0;
    display: block;
    height: 7px;
    margin-top: -6px;
    position: absolute;
    right: 5px;
    top: 50%;
    width: 7px;
}

Step 4. PHP

Our PHP files are separated into two types: action files and classes. I think that you have already saw sources of most of classes of chat project. So, first two files are same:

classes/CLogin.php

classes/CMySQL.php

We don’t need to re-publish sources of both files again. Both are available in our package. But I updated Profiles class file (I removed all unnecessary here, now it contains only registration and few other functions):

classes/CProfiles.php

<?php
define('PROFILE_TIMEOUT', 5); // 5 mins
// Profiles class
class CProfiles {
    // constructor
    function CProfiles() {}
    // profile registration
    function registerProfile() {
        $sUsername = $GLOBALS['MySQL']->escape($_POST['username']);
        $sFirstname = $GLOBALS['MySQL']->escape($_POST['firstname']);
        $sLastname = $GLOBALS['MySQL']->escape($_POST['lastname']);
        $sEmail = $GLOBALS['MySQL']->escape($_POST['email']);
        $sPassword = $GLOBALS['MySQL']->escape($_POST['password']);
        if ($sUsername && $sEmail && $sPassword) {
            // check if already exist
            $aProfile = $GLOBALS['MySQL']->getRow("SELECT * FROM `cs_profiles` WHERE `email`='{$sEmail}'");
            if ($aProfile['id'] > 0) {
                $sErrors = '<h2>Another profile with same email already exist</h2>';
            } else {
                // generate Salt and Cached password
                $sSalt = $this->getRandCode();
                $sPass = sha1(md5($sPassword) . $sSalt);
                // add new member into database
                $sSQL = "
                    INSERT INTO `cs_profiles` SET
                    `name` = '{$sUsername}',
                    `first_name` = '{$sFirstname}',
                    `last_name` = '{$sLastname}',
                    `email` = '{$sEmail}',
                    `password` = '{$sPass}',
                    `salt` = '{$sSalt}',
                    `status` = 'active',
                    `role` = '1',
                    `date_reg` = NOW();
                ";
                $GLOBALS['MySQL']->res($sSQL);
                // autologin
                $GLOBALS['CLogin']->performLogin($sUsername, $sPassword);
            }
        }
    }
    // get random code (for salt)
    function getRandCode($iLen = 8) {
        $sRes = '';
        $sChars = "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
        for ($i = 0; $i < $iLen; $i++) {
            $z = rand(0, strlen($sChars) -1);
            $sRes .= $sChars[$z];
        }
        return $sRes;
    }
    // get profiles block
    function getProfilesBlock($iLim = 20, $bOnlineOnly = false) {
        $iPLimit = PROFILE_TIMEOUT;
        $sOnlineSQL = ($bOnlineOnly) ? 'AND (`date_nav` > SUBDATE(NOW(), INTERVAL ' . $iPLimit . ' MINUTE))' : '';
        $sSQL = "
            SELECT `cs_profiles`.*,
            if (`date_nav` > SUBDATE(NOW(), INTERVAL {$iPLimit} MINUTE ), 1, 0) AS `is_online`
            FROM `cs_profiles`
            WHERE `status` = 'active'
            {$sOnlineSQL}
            ORDER BY `date_reg` DESC
            LIMIT {$iLim}
        ";
        $aProfiles = $GLOBALS['MySQL']->getAll($sSQL);
        // create list of messages
        $sCode = '';
        foreach ($aProfiles as $i => $aProfile) {
            $sName = $aProfile['name'];
            $iPid = $aProfile['id'];
            $sOnline = ($aProfile['is_online'] == 1) ? '<img alt="" src="images/online.png" class="status_img" />' : '';
            $sCode .= '<div id="'.$iPid.'" title="'.$sName.'"><a href="profile.php?id='.$iPid.'"><p>'.$sName.'</p>'.$sOnline.'</a></div>';
        }
        $sClass = ($bOnlineOnly) ? 'profiles online_profiles' : 'profiles';
        return '<div class="'.$sClass.'">' . $sCode . '</div>';
    }
    // get profile info
    function getProfileInfo($i) {
        $sSQL = "
            SELECT *
            FROM `cs_profiles`
            WHERE `id` = '{$i}'
        ";
        $aInfos = $GLOBALS['MySQL']->getAll($sSQL);
        return $aInfos[0];
    }
}
$GLOBALS['CProfiles'] = new CProfiles();

Now lets review our main files:

index.php

<?php
// set error reporting level
if (version_compare(phpversion(), '5.3.0', '>=') == 1)
  error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
else
  error_reporting(E_ALL & ~E_NOTICE);
require_once('classes/CMySQL.php'); // service class to work with database
require_once('classes/CLogin.php'); // service class to work with login processing
require_once('classes/CProfiles.php'); // service class to work with profiles
// join processing
if (! isset($_SESSION['member_id']) && $_POST['Join'] == 'Join') {
    $GLOBALS['CProfiles']->registerProfile();
}
// login system init and generation code
$sLoginForm = $GLOBALS['CLogin']->getLoginBox();
if ($_SESSION['member_id'] && $_SESSION['member_status'] == 'active') {
    if ($_GET['action'] == 'update_last_nav') { // update last navigate time
        $iPid = (int)$_SESSION['member_id'];
        if ($iPid) {
            $GLOBALS['MySQL']->res("UPDATE `cs_profiles` SET `date_nav` = NOW() WHERE `id` = '{$iPid}'");
        }
        exit;
    }
}
// get profiles lists
$sProfiles = $GLOBALS['CProfiles']->getProfilesBlock();
$sOnlineMembers = $GLOBALS['CProfiles']->getProfilesBlock(10, true);
// prepare set of markers for global map
$sMarkers = '';
$aRecentMarkers = $GLOBALS['MySQL']->getAll("SELECT * FROM `latlng268` ORDER BY `id` DESC LIMIT 20");
foreach ($aRecentMarkers as $i => $sMInfo) {
    if ($sMInfo['lat'] != 0 && $sMInfo['lng'] != 0) {
        $sUnitLocation = str_replace('"', '', $sMInfo['name']);
        $sMarkers .= <<<EOF
aMarkerInfos[{$sMInfo['id']}] = new google.maps.InfoWindow({content: "{$sUnitLocation}"});
aMarkers[{$sMInfo['id']}] = new google.maps.Marker({position: new google.maps.LatLng({$sMInfo['lat']}, {$sMInfo['lng']}), map: map, title: "{$sUnitLocation}"});
google.maps.event.addListener(aMarkers[{$sMInfo['id']}], 'click', function() {
    aMarkerInfos[{$sMInfo['id']}].open(map,aMarkers[{$sMInfo['id']}]);
});
EOF;
    }
}
// draw common page
$aKeys = array(
    '{form}' => $sLoginForm,
    '{profiles}' => $sProfiles,
    '{online_members}' => $sOnlineMembers,
    '{add_markers}' => $sMarkers
);
echo strtr(file_get_contents('templates/main_page.html'), $aKeys);

Pay attention to code where we add markers for map. By default, there are only 20 last markers. You always can play with that limit. Our next file – profile page:

profile.php

<?php
// set error reporting level
if (version_compare(phpversion(), '5.3.0', '>=') == 1)
  error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
else
  error_reporting(E_ALL & ~E_NOTICE);
require_once('classes/CMySQL.php'); // service class to work with database
require_once('classes/CLogin.php'); // service class to work with login processing
require_once('classes/CProfiles.php'); // service class to work with profiles
// get basic info about profile
$iPid = (int)$_GET['id'];
$aInfo = $GLOBALS['CProfiles']->getProfileInfo($iPid);
$sName = $aInfo['name'];
$sFName = $aInfo['first_name'];
$sLName = $aInfo['last_name'];
$sAbout = $aInfo['about'];
$sDate = $aInfo['date_reg'];
// get map block
$sMap = '';
$aPosInfo = $GLOBALS['MySQL']->getRow("SELECT * FROM `latlng268` WHERE `profile` = '{$iPid}'");
if ($aPosInfo['id']) {
    $aPosKeys = array(
        '{lat}' => $aPosInfo['lat'],
        '{lng}' => $aPosInfo['lng'],
        '{name}' => str_replace('"', '', $sName)
    );
    $sMap = strtr(file_get_contents('templates/profile_map.html'), $aPosKeys);
}
// get profiles listings
$sProfiles = $GLOBALS['CProfiles']->getProfilesBlock();
$sOnlineMembers = $GLOBALS['CProfiles']->getProfilesBlock(10, true);
// draw common page
$aKeys = array(
    '{id}' => $iPid,
    '{name}' => $sName,
    '{fname}' => $sFName,
    '{lname}' => $sLName,
    '{about}' => $sAbout,
    '{datereg}' => $sDate,
    '{profiles}' => $sProfiles,
    '{online_members}' => $sOnlineMembers,
    '{map}' => $sMap
);
echo strtr(file_get_contents('templates/profile_page.html'), $aKeys);

As you can see – most of the code are already commented. So I hope that this code are pretty understandable. And, in the long run – our new file which we use to set our coordinates:

setpos.php

<?php
// set error reporting level
if (version_compare(phpversion(), '5.3.0', '>=') == 1)
  error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
else
  error_reporting(E_ALL & ~E_NOTICE);
require_once('classes/CMySQL.php'); // service class to work with database
require_once('classes/CLogin.php'); // service class to work with login processing
require_once('classes/CProfiles.php'); // service class to work with profiles
$iPid = (int)$_SESSION['member_id'];
// save coordinates
if ($_POST && $_POST['Confirm']) {
    $dLat = (double)$_POST['lat'];
    $dLng = (double)$_POST['lng'];
    if ($iPid && $dLat && $dLng) {
        $aInfo = $GLOBALS['MySQL']->getRow("SELECT * FROM `latlng268` WHERE `profile` = '{$iPid}'");
        if ($aInfo['id']) {
            $GLOBALS['MySQL']->res("UPDATE `latlng268` SET `lat` = '{$dLat}', `lng` = '{$dLng}' WHERE `profile` = '{$iPid}'");
        } else {
            $aPInfo = $GLOBALS['CProfiles']->getProfileInfo($iPid);
            $sName = $GLOBALS['MySQL']->escape($aPInfo['name']);
            $GLOBALS['MySQL']->res("INSERT INTO `latlng268` SET `lat` = '{$dLat}', `lng` = '{$dLng}', `profile` = '{$iPid}', `name` = '{$sName}'");
        }
        header('Location: profile.php?id=' . $iPid);
    }
}
// find profile coordinates
$aPosInfo = $GLOBALS['MySQL']->getRow("SELECT * FROM `latlng268` WHERE `profile` = '{$iPid}'");
$dLat = 40;
$dLng = -75;
if ($aPosInfo['id']) {
    $dLat = $aPosInfo['lat'];
    $dLng = $aPosInfo['lng'];
}
// draw page
$aKeys = array(
    '{lat}' => $dLat,
    '{lng}' => $dLng
);
echo strtr(file_get_contents('templates/setpos_page.html'), $aKeys);

Step 5. Javascript

I added that simple script in order to update (periodically) time of our last navigation (simulation of online status)

js/update.js

$(function() {
    // Update last navigation time feature
    updateLastNav = function() {
        $.getJSON('index.php?action=update_last_nav', function() {
            // refresh last nav time
            setTimeout(function(){
               updateLastNav();
            }, 180000); // 3 mins
        });
    }
    updateLastNav();
});

Live Demo
download in archive

Conclusion

I hope that our new tutorial was very useful and interesting for you. If you want to share your ideas, or you noticed any weakness – don’t hesitate to contact us. Good luck and welcome back!

SIMILAR ARTICLES

Understanding Closures

0 17840

4 COMMENTS

  1. Hi. I have downloaded the source file. How do I get this page??… When I’m opening the index.php its displaying code in the browser.

    • Hi Indranil,
      Please pay your attention, that you have to put your database details in ‘classes/CMySQL.php’ file

Leave a Reply to admin Cancel reply