0% found this document useful (0 votes)
17 views224 pages

Geospatial Web 101

Uploaded by

Kati Yoewono
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views224 pages

Geospatial Web 101

Uploaded by

Kati Yoewono
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 224

INTRODUCTION TO

WEB PROGRAMMING
FOR GIS APPLICATIONS
WHO THIS COURSE IS FOR

• Anyone who is interested in a more conceptual understanding of how web


applications work.
• HTML, CSS, Bootstrap, JavaScript, JQuery, PHP, SQL and how they all work together.
• Web development is very different than programming an application for a single computer,
so even if you are an experienced programmer there can be a steep learning curve when
moving to the web.

• In particular, we will be talking about geospatial applications.


• Leaflet, OpenLayers, PostGIS, geoJSON, geospatial data storage, retrieval, analysis, and
display.
• There are some aspects of geospatial web applications that differ from standard database
applications, which we will identify and explore.
WHO THIS COURSE IS FOR

• Two main groups of people


• GIS specialists, analysts, and/or developers interested in deploying internet based
applications.
• Publish content onto the web for external consumption.
• Escape the costs of commercial licenses for internal users of GIS.
• Develop spatial tools that are free from dependencies on ESRI update cycles.
• Web programmers interested in expanding their skillset into geospatial
applications.
• Geospatial data
• Web maps
• Spatial Analysis
• Server-side tools
MY BACKGROUND

• I’ve been programming computers since the early 80s. There was very little canned software
at the time so you almost had to program to get much use out of a computer.
• I remember cassette tape drives, 8” floppies, and the first PC with a 10MB hard drive and
wondering how you would ever fill that much space.
• I remember monochrome monitors with only a single font and dot matrix printers with only a
single font, and word processing software that you had to use in-text tags to make bold print or
indent a paragraph so you wouldn’t really know what the document looked like until you
printed it.
• I remember when Apple McIntosh came out and blew everybody away with a mouse and What-
You-See-Is-What-You-Get graphical display so you could actually see on the screen what your
documents would look like and you could control the computer without typing commands.
MY BACKGROUND

• I sold my first software, a flash card program, in 1984 as a senior in high school to PC Disk
magazine.
• I developed database applications for video store rentals for several years between high
school and college.
• In 1990 I changed course and started a degree in Wildlife Biology. Soon after I learned about
GIS and realized I had found my calling.
• I began programming in ArcInfo with AML, then ArcView with Avenue. In 2000, as I was
starting a PhD program, ESRI introduced ArcGIS 8.0 and I quickly realized I would need to
learn to program in Visual Basic and ArcObjects as well.
• When ESRI introduced ArcGIS 9.0 I had to learn Python to speed up the development process
and create more portable extensions.
MY BACKGROUND

• When maps first started being served over the internet I immediately
saw the advantages but I did not have the resources to set up an
ArcServer instance on a server and learn to program against it.
• I took some classes on ESRI’s JavaScript API but struggled to use it for
anything productive for two main reasons.
• They skipped over the basics of web application programming.
• Without a server installation I had no way to practice what I learned.
MY BACKGROUND

• In 2014 I saw some talks at a GIS conference on open-source GIS programming and the light went on.
• With an open source approach I could develop web applications on my own for free without spending tens of
thousands of dollars on ESRI software.
• The only cost would be my time and even though I had three decades of experience programming database
applications and two decades of experience developing GIS applications in a large number of languages and
environments, the web development world sounded like a foreign language.
• What did all the jargon mean? How did all the pieces work together? Which pieces did I really need to focus on?
• I began trying to learn it all, and spent extensive amounts of time reading books and taking on-line classes and
setting up software and developing applications both at work and for fun.
• This course is my attempt to share what I learned with others in my position, and help them ease through the
process. If you are a programmer or GIS analyst who is struggling with making the transition to the on-line
world then I hope this course can help you.
COURSE PHILOSOPHY

• Although this is a course on web application development you will not


learn much code.
• You will see some code in examples of course, but there are many
courses available to teach you the actual nuts and bolts of writing
code.
• I believe that it is more important to understand things conceptually
before diving into the details. Web programming, in particular, has a
lot of bits and pieces that aren’t intuitively obvious, even to
experienced desktop developers. This course is intended to fill in those
gaps.
COURSE GOALS - UNDERSTANDING

• Understand the basics of client-server architecture and how it differs from


single-user applications
• Understand the basics of client side technologies (HTML, CSS, JavaScript)
• Understand the basics of server-side technologies (PHP, SQL, Databases)
• Understand how to communicate between client and server (AJAX)
• Understand commonly available libraries and frameworks (JQuery, Boostrap)
• Understand the tools available for geospatial applications (Leaflet, Turf,
PostGIS, GeoJSON)
HOW IS PROGRAMMING FOR THE WEB DIFFERENT THAN A
SINGLE USER DESKTOP ENVIRONMENT?

• Client-Server Architecture
• Hundreds or thousands of clients accessing one server.
• Clients can be using different browsers, different operating systems, different screen
sizes, etc.
• Data is stored on the server and requested by the client.
• User interaction occurs on the client, data access is handled by the server, and data
processing can occur on either end.
• As a result you need to know how to program on the client side as well as the server
side.
• More importantly you need to know WHEN to handle things on the client and when to
handle things on the server and how to communicate between client and server.
CLIENT-SERVER ARCHITECTURE

• Servers process requests and return a result, then Clients do something with the results
• Just like a server in a restaurant
• You (the client) tell the server what you want (Request)
• The server delivers it to you (Result), and then you do something with it.

• This requires things to happen on both ends


• In order to process your request, the server informs the cook of your order and the cook
prepares the food from scratch and then the server delivers it to the client.
• This happens behind the scene. The details are unknown and unimportant to the client. This is
server-side processing.
• Once the food is delivered, the client has to cut the steak, put salad dressing on the salad, and
spoon it into his mouth. This is client-side processing.

• The server and the cook handle multiple clients simultaneously.


CLIENT-SERVER ARCHITECTURE

Client (HTML,
CSS,
JavaScript)

Result (AJAX)
Request
(AJAX)

Web Server Data Database (PostgreSQL,


(PHP, ASP,.Net Request SQLServer, Oracle,
Java, Node) (SQL) MySQL)
MAJOR COMPONENTS

• Client
• HTML, CSS, JavaScript (Work together)

• Server
• PHP, Java, ASP.NET, Ruby, Python, Node (Choose one)

• Database
• SQL (MySQL, PostgreSQL, SQLite, SQLServer, Oracle, DB2)
• No SQL (Mongo, Couch, IndexDB)
MINOR COMPONENTS

• Communication
• GET, POST, ECHO, AJAX, JSON

• Libraries, API’s, and Frameworks


• Client - JQuery, Dojo, Bootstrap,
• Server – Cake, CodeIgnitor, Laravel

• Mapping Components
• Google Maps, Leaflet, OpenLayers, ESRI Javascript API, Turf.js, PostGIS
CLIENT SIDE

• In terms of the Web, client means browser.


• Netscape, Chrome, Firefox, Safari, Internet Explorer, Edge, Opera, “Webkit”

• All browsers understand HTML, CSS, JavaScript


• Minor differences in how they are implemented and supported, especially
IE.

• HTML – HyperText Markup Language


• CSS – Cascading Style Sheets
• JavaScript – Programming Language
CLIENT SIDE

• In terms of the Web, client means browser.


• All browsers understand HTML, CSS, Javascript
• HTML – HyperText Markup Language
• Provides structure and content
• Original web technology

• CSS – Cascading Style Sheets


• JavaScript – Programming Language
CLIENT SIDE

• In terms of the Web, client means browser.


• All browsers understand HTML, CSS, Javascript
• HTML – HyperText Markup Language
• CSS – Cascading Style Sheets
• Makes things pretty
• Colors, borders, positioning, etc.

• JavaScript – Programming Language


CLIENT SIDE

• In terms of the Web, client means browser.


• All browsers understand HTML, CSS, Javascript
• HTML – HyperText Markup Language
• CSS – Cascading Style Sheets
• JavaScript – Programming Language
• Makes things happen.
• Respond to user input, calculations, animations.
• NOT Java
HTML DOCUMENT STRUCTURE

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
………….
</body>
</html>
HTML

• Tag based • Opening and closing tags


• Headings • <h1>GIS</h1>
• Paragraph • <p>Lorem ipsum</p>
• Lists • <ul> ( <ol> )
<li> item 1</li>
<li> item 2 </li>

• </ul> ( </ol> )
HTML

• Links • <a href=“http://www.google.com”>Go to


Google</a>
• Images
• <img src=“images/picture.jpg” width=“200px”>
• Div
• <div class=“text-bold” id=“div1”>……</div>
• Span • <p>Lorem Ipsum<span
class=“super-script”>2</span> Lorem Ipsum </p>

• Breaks • <br><hr>
• <b>Bold</b><i>Italics</i><small>Small
• Style
text</small>
HTML TABLES

<table> A B C
1 2 3
<tr>
<td>A</td><td>B</
td><td>C</td>
</tr>
<tr>
<td>1</td><td>2</
td><td>3</td>
</tr>

</table>
HTML FORMS

<form action=“process.php” method=“post”>


<input type=“text” name=“firstName” value=“Bob” ><br><br>
<input type=“date” name=“birthday”><br><br>
<select name=“registered”>
<option value=“true”>Yes</option>
<option value=“false”>No</option>
</select><br><br>
<input type=“checkbox” name=“active” value=“active” checked>
Active?<br><br>
<hr>
<input type=“radio” name=“gender” value=“male” checked>
Male<br><br>
<input type=“radio” name=“gender” value=“female” >
Female<br><br>
<hr>
<input type=“submit name=“submit” value=“Submit Button”>
</form>
CSS

• Cascading Style Sheets p{


font-size: 20pt;
• Introduced in the mid 90’s color:red;
background-color:black;
• Standardized in the mid 00’s
}
• Separation of content from .text-bold {
font-weight:bold;
presentation
}
• CSS is composed of RULES that #first-row {
act on SELECTORS padding-left:30px;

}
CSS – SELECTORS & RULES

p{
• Tags font-size: 20pt;
color:red;
background-color:black;

• Classes - . }
.text-bold {
font-weight:bold;

• ID - # }
#first-row {
padding-left:30px;

• Pseudo Classes }
a{
color:yellow;

• :visited }
a:visited {
color:orange;
• :hover }
a:hover {
background-color:black;
}
CSS – WHERE IT LIVES

• Inline • <h1 style=“color:#000;background-color:#FFF”>Title</h1>


• <style>
• Internal
• h2 {
• color:#FFF
• background-color:#000;
• }

• </style
• <link rel=“stylesheet” type=“txt/css”
href=“master_style.css”>
• External
CSS - PRECEDENCE

• Specificity takes precedence <div class=“default-text”>


over generality. <p> These are a few of my
• id>class>tag favorite things
<ul id=“favorite-things-list”>
• inline>internal>external <li>Pizza</li>
<li>Beer</li>
</ul>
</p>

</div>
CSS - PRECEDENCE

• Specificity takes precedence <div class=“default-text”>


over generality. <p> These are a few of my favorite
• id>class>tag things
<ul id=“favorite-things-list”>
• inline>internal>external
<li>Pizza</li>
<li>Beer</li>
</ul>
</p>

</div>
CSS - PRECEDENCE

<div class=“default-text”> p{
<p> These are a few of my color: red;
favorite things }
<ul id=“favorite-things-list”>
.default-text {
<li>Pizza</li>
color:black;
<li>Beer</li>
</ul> }
</p> #favorite-things-
list {
</div>
color:darkblue;

}
CSS - PRECEDENCE

<div> External CSS Internal CSS


<p class=“default-text”> These are a few p{ p{
of my favorite things color: red; color: black
<ul id=“favorite-things-list”
} }
style=“color:black”>
.default-text { .default-text {
<li>Pizza</li>
color:black; color:blue;
<li>Beer</li>
</ul> } }

</p> #favorite-things-list { #favorite-things-list {


color:darkblue; color:red;
</div>
} }
CSS – PSEUDO-SELECTORS

• Links • Focus
• a:link {color:blue} • input:focus {background-
• a:visited {color:purple} color:yellow)

• a:active {color:black} • Children


• li:firstchild {font-weight:bold}
• Hover
• ul .multi-list>li {color:red}
a:hover {
• ul .multilist>li>ul>li {color:blue}
background-color:blue;
• ul .multilist>li>ul>li>ul>li
color:white; {color:green}
}
COLORS ON THE WEB

• Constants • RGB (Continued)


• red • #F0F ?????
• azure • #FFF ?????
• saddlebrown • RGB 24 bit
• RGB • #FF0000 Red
• #000 Black • #FF0088 Magenta
• #800 Pink • #6AD029 ????????
• #F00 Red
CSS – PRIMARY USES

• Style • Layout
• Font • Relative
• Color
• Absolute
• Size
• Float
• Borders
• Animation
• Formatting
• Indents • Hover and focus pseudo:selectors
• Margin • Turn content on and off, change
• Alignment its position, or change styles on
• Spacing the fly (with Javascript)
BEYOND CSS

• LESS and SASS


• Use variables in CSS
• Use conditional statements

• Compile to CSS
DOCUMENT OBJECT MODEL (DOM)

• The DOM is an object oriented depiction of the HTML and CSS in a web
page.
• Every time a page is loaded its HTML and CSS are translated into a
DOM.
• The DOM is actually what the browser uses to display the page.
WHAT IS AN OBJECT?

• Objects are a way of describing the world into language a computer can
understand.
• An object is a data structure that has both properties and methods.
• Properties are data and can be a single value, an array, or another object.
• In computer lingo these are analogous to variables.
• Methods are actions that an object can perform.
• In computer lingo these are analogous to a function.

• Objects can inherit the properties and methods of its parent object and
overwrite them or add to them.
WHAT IS AN OBJECT?

• Animal Object
• Properties
• Skin Type
• Movement Type
• Color
• Temperament
• Methods
• Make a noise
• Move
• Eat
INHERITING FROM AN OBJECT

• Reptile Object – Inherit from animal • Mammal Object – Inherit from animal
• Properties • Properties
• Skin Type:Hair
• Skin Type: Scales
• Movement Type:[walk, hop, fly,]
• Movement Type: crawl
• Color
• Color • Temperament
• Temperament • Methods
• Methods • Make a noise{}

• • Move {if Rabbit then hop, if bat then fly,


Make a noise {}
else walk}
• Move {crawl}
• Eat{}
• Eat{} • Grow Hair{}
• Grow Scales{} • Produce Milk{}
INHERITING FROM AN OBJECT

• Mouse Object – Inherit from Mammal • Dog Object – Inherit from Mammal
• Properties • Properties
• Skin Type:Hair • Skin Type:Hair
• Movement Type:Walk • Movement Type:Walk
• Color • Color
• Temperament: Nervous • Temperament: Friendly
• Methods • Methods
• Make a noise {squeak} • Make a noise {bark}
• Move {walk} • Move {walk}
• Eat {search for cheese} • Eat {beg for treats}
• Grow Hair {} • Grow Hair {}
• Produce Milk {} • Produce Milk {}
• Scare Ladies {} • Catch Frisbee {}
• Avoid cats {} • Chase cats {}
ABSTRACTION AND INSTANTIATION

• To instantiate an object means to create an individual object from the object blueprint.
• In computer lingo, the blueprint is known as a “class”

• An “Abstract” class is one that can have its properties and methods inherited but can not be instantiated.
• If I say “get me an animal” you will say “what kind?”.
• Defining an animal is useful as a blueprint that other things can inherit from but cannot be an actual thing.
• Mammals inherit properties of animals and modify or add new ones. Reptiles do the same but in a different manner
• Dogs and mice also inherit properties of mammals and add new ones, but you can go to the store and actually buy a dog
or a mouse.
• In computer lingo each individual dog is an instance of the dog class which inherits some properties from the mammal
abstract class which inherits some properties from the animal class.
• Some properties can not actually be set until the object is instantiated. We know that dogs have a color and temperament
property but we won’t know what color or what temperament until we have an actual instance of the dog class.

• This object hierarchy is an intuitive way to describe the world and translate it into language that a computer can
understand.
OBJECTS IN COMPUTERS

• The concept of objects and object hierarchies is very common in computer software.
• If I right click on a graphic object in PowerPoint I can see and change its color, transparency, size,
etc.
• Those properties are different if it’s a line or a polygon or an image.

• In GIS terms we can think of a feature as an instantiation of a feature class and the
coordinates and attributes as its properties.
• The feature class can inherit different properties depending on whether it is a point, line, or
polygon.
• When we display a layer on a map we can also set its display properties
• Size
• Color
• Transparency, etc.
DOCUMENT OBJECT MODEL (DOM)

• The DOM is an object oriented depiction of the HTML and CSS in a web
page.
• Every time a page is loaded its HTML and CSS are translated into a
DOM.
• The DOM is actually what the browser uses to display the page.
DOCUMENT OBJECT MODEL (DOM)

<html>
<head> html
<title> My Page</title>
</head>
<body> head body
<div id=“col1”>
<p>Lorem Ipsum</p>
</div> div: div:
<div id=“col2”> title
col1 col2
<ul id=“colorlist”>
<li>Red</li>
ul: ul:
<li>Green</li> p
</ul> colorlist animallist
<ul id=“animallist”>
<li>dog</li>
<li>cat</li>
li li li li
</ul>
</div>
</body>
</html>
IMPORTANT PROPERTIES OF HTML ELEMENTS

• childElementCou • eventhandlers (onclick


nt etc.)
• parentElement
• children[5]
• style
• innerHTML
• style.color=“red”
• innerText • style.display=“none”
• id • tagname
EVENTS

• Event Driven Programming


• When Apple introduced the McIntosh in 1984 it introduced an entirely new paradigm into computer
programming.
• Prior to this, computer code was written and processed in a top down manner
• First line of code was executed, then the second, etc.

• The McIntosh allowed the user to interact with the computer via the mouse.
• Click, double click, drag, drop, right click, scroll up, scroll down, etc. I.E. events.

• Event handlers are snippets of code that are executed in response to an event.
• Events also can occur when the mouse hovers over an object, when a window is resized, before and/or after a
page is loaded, when the text in an input box is changed, etc.

• Modern programming is largely object oriented and event driven.


• Programmers need to understand the events that occur in the environment that they are programming in and
write event handlers for those events.
• They also need to understand the object model behind their environment so that they can manipulate those
objects in response to events.
DOCUMENT OBJECT MODEL (DOM)

<html>
<head> html
<title> My Page</title>
</head>
<body> head body
<div id=“col1”>
<p> Lorem Ipsum
</div> div: div:
title
<div id=“col2”> col1 col2
<ul id=“colorlist”>
<li>Red</li>
ul: ul:
<li>Green</li> p
</ul> colorlist animallist
<ul id=“animallist”>
<li>dog</li>
li li li li
<li>cat</li>
</ul>
</div>
</body>
</html>
JAVASCRIPT

• Also began in the mid 90’s as Netscape’s scripting technology


• Microsoft used JScript and VBScript
• Adobe used ActionScript in Flash

• Standardized in the mid-00’s as the dominant client-side scripting language in browsers


• Allows manipulation of the DOM.

• Also available for server-side scripting in NODE.js


• Open Source – This is good. It is not subject to the whims of a single company.
• Object Oriented – EVERYTHING in JavaScript is an object. Even functions.
• Event Driven – Much of the JavaScript code that you write will be event handlers.
HOW DO WE ACCESS THE DOM?

• Every browser makes the DOM accessible through the document object
• The document object is available to all JavaScript code
• document.head or document.body to reference the head or body.
• Children of the body are an array of HTML elements
• document.body.children[2] to reference the third child element of the body.
• document.body.children[2].children[1] to reference the second child of the
third child of the body.
DOCUMENT OBJECT MODEL (DOM)

<html>
<head> html
<title> My Page</title>
</head>
<body> head body
<div id=“col1”>
<p> Lorem Ipsum
</div> div: div:
title
<div id=“col2”> col1 col2
<ul id=“colorlist”>
<li>Red</li>
ul: ul:
<li>Green</li> p
</ul> colorlist animallist
<ul id=“animallist”>
<li>dog</li>
li li li li
<li>cat</li>
</ul>
</div>
</body>
</html>
ACESSING THE DOM

• var colorlist =
document.body.children[1].children[0]
DOCUMENT OBJECT MODEL (DOM)

<html>
<head> html
<title> My Page</title>
</head>
<body> head body
<div id=“col1”>
<p> Lorem Ipsum
</div> div: div:
title
<div id=“col2”> col1 col2
<ul id=“colorlist”>
<li>Red</li>
ul: ul:
<li>Green</li> p
</ul> colorlist animallist
<ul id=“animallist”>
<li>dog</li>
li li li li
<li>cat</li>
</ul>
</div>
</body>
</html>
ACESSING THE DOM

• colorlist = document.body.children[1].children[0]
• animallist = document.body.children[1].children[1]
• firstanimallist =
document.body.children[1].children[1].children[0]
DOCUMENT OBJECT MODEL (DOM)

<html>
<head> html
<title> My Page</title>
</head>
<body> head body
<div id=“col1”>
<p> Lorem Ipsum
</div> div: div:
title
<div id=“col2”> col1 col2
<ul id=“colorlist”>
<li>Red</li>
ul: ul:
<li>Green</li> p
</ul> colorlist animallist
<ul id=“animallist”>
<li>dog</li>
li li li li
<li>cat</li>
</ul>
</div>
</body>
</html>
JAVASCRIPT

<script>
console.log(“Hello World!”);
console.log(document);
console.log(document.body.children[0].children[0].innerHTML)
</script>
DOCUMENT OBJECT MODEL (DOM)

<html>
<head> html
<title> My Page</title>
</head>
<body> head body
<div id=“col1”>
<p>Lorem Ipsum</p>
</div> div: div:
<div id=“col2”> title
col1 col2
<ul id=“colorlist”>
<li>Red</li>
ul: ul:
<li>Green</li> p
</ul> colorlist animallist
<ul id=“animallist”>
<li>dog</li>
<li>cat</li>
li li li li
</ul>
</div>
</body>
</html>
JAVASCRIPT

<script>
console.log(“Hello World!”);
console.log(document);
console.log(document.body.children[0].children[0].innerHTML)
</script>
IMPORTANT PROPERTIES OF HTML ELEMENTS

• childElementCou • eventhandlers (onclick


nt etc.)
• parentElement
• children[5]
• style
• innerHTML
• style.color=“red”
• innerText • style.display=“none”
• id • tagname
JAVASCRIPT

• Since most of the JavaScript we write will be event handlers lets write one.
<script>
document.body.addEventListener(“click”, function(e){
console.log(“Clicked in the body”);
console.log(e);
alert(“Clicked in the body\nX: ”+e.clientX+”\nY: “+e.clientY);
alert(e);
});
</script>
EVENT HANDLER

<div id=“col2”> #colorlist {


<ul id=“colorlist”> display:block;
<li>Red</li> } #switch-list:click {
#animallist { if #colorlist is displayed
<li>Green</li>
display:none; hide #colorlist
</ul> } show
<ul id=“animallist”> #switch-list { #animallist
<li>dog</li> color:red;
else
<li>cat</li> background-
hide
</ul> color:black;
#animallist
}
<button show
#switch-list:hover {
id=“switch-list”>Switch</button> #colorlist
color:black;
</div> background-color:red; }
}
JAVASCRIPT CONDITIONAL STATEMENTS

If (condition) { • Condition
• Always evaluate to true or false
…….. Code
• document.title == “My Page”
} elseif (condition) { • document.body.childElements >
4
……... Code
• e.shiftKey
} else { • document.title != “My Page”

……... Code
}
EVENT HANDLER

document.body.children[1].children[2].addEventListener('click', function(e){ //
#switch-list:click
if (document.body.children[1].children[0].style.display != "none") { // If
#colorlist is displayed
document.body.children[1].children[0].style.display = "none"; //
Hide #colorlist
document.body.children[1].children[1].style.display = "block"; //
Show #animallist
} else {
// Else
document.body.children[1].children[1].style.display = "none"; //
Hide #animallist
document.body.children[1].children[0].style.display = "block"; //
Show #colorlist
}
});
ACESSING THE DOM

• var colorlist = document.body.children[1].children[0];


• var animallist = document.body.children[1].children[1];
• var firstanimallist = animallist.children[0];
• var firstanimallist =
document.body.children[1].children[1].children[0];
EVENT HANDLER

document.body.children[1].children[2].addEventListener('click', function(e){ //
#switch-list:click
if (document.body.children[1].children[0].style.display!="none") { // If
#colorlist is displayed
document.body.children[1].children[0].style.display="none"; //
Hide #colorlist
document.body.children[1].children[1].style.display="block"; //
Show #animallist
} else { // Else
document.body.children[1].children[1].style.display="none"; //
Hide #animallist
document.body.children[1].children[0].style.display="block"; //
Show #colorlist
}
});
EVENT HANDLER

var btnSwitch = document.body.children[1].children[2];


var colorlist = document.body.children[1].children[0];
var animallist = document.body.children[1].children[1];

btnSwitch.addEventListener('click', function(e){// #switch-list:click


if (colorlist.style.display!="none") { // If #colorlist is displayed
colorlist.style.display="none"; // Hide #colorlist
animallist.style.display="block"; // Show #animallist
} else { // Else
animallist.style.display="none"; // Hide #animallist
colorlist.style.display="block"; // Show #colorlist
}
});
EVENT HANDLER

var btnSwitch = document.getElementById(‘switch-button’);


var colorlist = document.getElementById(‘colorlist’);
var animallist = document.getElementById(‘animallist’);

btnSwitch.addEventListener('click', function(e){// #switch-list:click


if (colorlist.style.display!="none") { // If #colorlist is displayed
colorlist.style.display="none"; // Hide #colorlist
animallist.style.display="block"; // Show #animallist
} else { // Else
animallist.style.display="none"; // Hide #animallist
colorlist.style.display="block"; // Show #colorlist
}
});
DOM MANIPULATION – EXAMPLE 2

var btnChange = document.getElementById('change-color');


<div id="col2"> btnChange.addEventListener('click', function(e){
<ul id="colorlist"> var col1=document.getElementById('col1');
switch (col1.style.color) {
<li>Red</li>
case "red":
<li>Green</li> col1.style.color="orange";
</ul> break;
case "green":
<ul id="animallist">
col1.style.color="blue";
<li>dog</li> break;
<li>cat</li> case "blue":
</ul> col1.style.color="purple";
break;
<button id="switch-button">Switch</button>
case "black":
<button id="change-color">Change col1.style.color="red";
Color</button> break;
default:
</div>
col1.style.color="red";
break;
}
});
SWITCH STATEMENT

switch (col1.style.color) {
If (col1.style.color==”red”){
case "red":
col1.style.color=“green"; col1.style.color=" green ";
break; } else if (col1.style.color==” green”){
case "green":
col1.style.color="blue";
col1.style.color=“blue";
break; } else if (col1.style.color==” blue”){
case "blue": col1.style.color=“black";
col1.style.color=“black";
break; } else if (col1.style.color==” black”){
case "black": col1.style.color=“purple";
col1.style.color=“purple";
} else {
break;
default: col1.style.color="red";
col1.style.color="red"; }
break;
}
DOM MANIPULATION – EXAMPLE 2

var btnChange = document.getElementById('change-color');


<div id="col2"> btnChange.addEventListener('click', function(e){
<ul id="colorlist"> var col1=document.getElementById('col1');
switch (col1.style.color) {
<li>Red</li>
case "red":
<li>Green</li> col1.style.color=“green";
</ul> break;
case "green":
<ul id="animallist">
col1.style.color="blue";
<li>dog</li> break;
<li>cat</li> case "blue":
</ul> col1.style.color=“black";
break;
<button id="switch-button">Switch</button>
case "black":
<button id="change-color">Change col1.style.color=“purple";
Color</button> break;
default:
</div>
col1.style.color="red";
break;
));
CALCULATIONS AND VALIDATION

…… var
<button btnMultiply=document.getElementById("multiply");
id="switch-button">Switch</button> var inputValue1=document.getElementById("value1");
<button id="change-color">Change var inputValue2=document.getElementById("value2");
Color</button>
</div> btnMultiply.addEventListener('click', function(e) {
var val1=inputValue1.value;
var val2=inputValue2.value;
<input id="value1" type="text" value="5">
alert(val1+" X "+val2+" = "+(val1*val2))
<input id="value2" type="text" value=“6">
});
<button id="multiply">Multiply</button>
CALCULATIONS AND VALIDATION

…… var btnMultiply=document.getElementById("multiply");
<button var inputValue1=document.getElementById("value1");
id="switch-button">Switch</button> var inputValue2=document.getElementById("value2");
<button id="change-color">Change
Color</button> btnMultiply.addEventListener('click', function(e) {
</div> var val1=inputValue1.value;
var val2=inputValue2.value;
<input id="value1" type="text" value="5"> if (isNaN(val1) || isNaN(val2)) {
<input id="value2" type="text" value=“6"> alert("At least one of the values is not a number");
<button id="multiply">Multiply</button> } else {
alert(val1+" X "+val2+" = "+
(val1*val2).toFixed(2));
}
});
CALCULATIONS AND VALIDATION

…… …..
<button btnMultiply.addEventListener('click', function(e) {
var val1=inputValue1.value;
id="switch-button">Switch</button> var val2=inputValue2.value;
<button id="change-color">Change if (isNaN(val1) || isNaN(val2)) {
alert("At least one of the values is not a number");
Color</button> } else {
</div> alert(val1+" X "+val2+" = "+(val1*val2).toFixed(2));
}
});
<input id="value1" type="text" value="5">
<input id="value2" type="text" value=“6">
inputValue1.addEventListener('keyup', function(e) {
<button id="multiply">Multiply</button>
if (isNaN(inputValue1.value)) {
alert("Please enter a number.");
}
});
THE PROBLEM WITH ALERTS

• Many people find alerts annoying.


• The first time a user visits your site
and sees an alert everything is fine
• But the SECOND time they have the
option of preventing anymore dialogs
by clicking the box.
• Because of this, alerts are not a
reliable method for getting a message
to the user.
SO HOW DO WE COMMUNICATE TO THE
USER?
• Use a third party library such as Impromptu.
• Simulate alerts through HTML, CSS, JavaScript
• <div> that’s normally hidden with a button to remove it.
• Jquery
• Bootstrap

• DOM manipulation
• Add or modify text, change colors, border, etc.
CALCULATIONS AND VALIDATION

…… …..
btnMultiply.addEventListener('click', function(e) {
<button var val1=inputValue1.value;
id="switch-button">Switch</button> var val2=inputValue2.value;
if (isNaN(val1) || isNaN(val2)) {
<button id="change-color">Change alert("At least one of the values is not a number");
} else {
Color</button> alert(val1+" X "+val2+" = "+(val1*val2).toFixed(2));
}
</div> });

<input id="value1" type="text" value="5"> inputValue1.addEventListener('keyup', function(e) {


<input id="value2" type="text" value=“6"> if (isNaN(inputValue1.value)) {
<button id="multiply">Multiply</button> inputValue1.style.border="2px solid red";
} else {
inputValue1.style.border="";
}
});
PASSING FUNCTIONS AS PARAMETERS

inputValue1.addEventListener('keyup', function(e) { function validateNumber() {


if (isNaN(inputValue1.value)) {
if (isNaN(this.value)) {
inputValue1.style.border="2px solid red";
this.style.border="2px solid red";
} else {
inputValue1.style.border=""; } } else {
}); this.style.border="";
}
inputValue2.addEventListener('keyup', function(e) {
if (isNaN(inputValue2.value)) {
inputValue1.addEventListener(‘keyup',
inputValue2.style.border="2px solid red";
} else { validateNumber)
inputValue2.style.border="";
} inputValue2.addEventListener(‘keyup',
}); validateNumber)
CALCULATIONS AND VALIDATION

…… …..
<button var result=document.getElementById(‘result’)
btnMultiply.addEventListener('click', function(e) {
id="switch-button">Switch</button>
var val1=inputValue1.value;
<button id="change-color">Change
var val2=inputValue2.value;
Color</button> if (isNaN(val1) || isNaN(val2)) {
</div> result.innerHTML="One or both of the input values is
invalid";
<input id="value1" type="text" value="5"> result.style.color="red";
<input id="value2" type="text" value=“6"> } else {
result.innerHTML=val1+" X "+val2+" = " + val1*val2;
<button id="multiply">Multiply</button>
result.style.color="green";
<hr>
}
<p id="result"></p> });
……
LOOPS IN JAVASCRIPT

• While Loop • For Loop


var i=0; for (var i=0;i<myArray.length;i++){

while (i<9){ alert(myArray[i]);

alert(i); }

i++; // i=i+1
}
ARRAY’S IN JAVASCRIPT

• Arrays are indexed numerically using the [ ] • myArray[0] = 45;


notation.
• Arrays can hold any type of objects • myArray[1] = ‘dog’;
• Arrrays can hold different types of objects in • myArray[2] = [1,2,3];
the same array.
• myArray[2][2]=3;
• An empty array is created using
• var myArray=[ ]; • myArray[3]={color:red;size:10};
• You can add items to an array at initiation
using
• myArray[3].size = 10;
• var myArray=[45, ‘dog’, [1,2,3],
{color:red;size:10}]
ARRAYS IN JAVASCRIPT (CONT’D)

• Arrays have a length property • Deleting elements from an array


holding the number of elements in • From the top
an array.
• x=myArray.pop();
• myArray.length = 4;
• From the bottom
• You can add an element to an array
• x=myArray.shift();
in three ways.
• myArray[myArray.length]=‘Bob’;
• myArray.push(‘Bob’);
• myArray.push(‘Bob’, ‘Bill’,103);
• myArray.unshift(‘Bob’, ‘Bill’, 103)
OBJECTS IN JAVASCRIPT

• Everything in JavaScript is an object • You reference an objects


• Unlike many programming languages you
properties and/or methods
don’t have to define an object class.
using the ‘dot’ notation.
• You can create your own objects on the fly
using the following notation • myDog.name = “Lola”;
myDog = {
species:”dog”, • myDog.legs[2] = ‘rear-left’
color:”blue”,
name:”Lola”, • myDog.displayAge();
age: 14,
legs: [‘front-left’, ‘front-right’, ‘rear-left’,
‘rear-right’],
displayAge:function(){
alert(“Lola is 14 years old”);
}
}
OBJECT LITERALS AND JSON

• Object Literal and Binary Objects • JSON


var myDog = {species:”dog”, var myDogJSON = ‘{"species":"dog",
color:”blue”, "color":"blue",
name:”Lola”, "name":"Lola",
age: 14, "age":14,
legs: [‘front-left’, ‘front-right’, "legs":["front-left","front-
‘rear- right","rear-
left’, ‘rear-right’] left","rear-right"]
}; }’;

myDogJSON=JSON.stringify(myDog); myDog = JSON.parse(myDogJSON);


FRAMEWORKS, LIBRARIES, API’S, PLUG-INS

• Bootstrap – CSS library for responsive web sites.


• Layout, formatting tables and forms, lists, menus, tooltips, etc.

• JQuery – Very popular for manipulating the DOM, event handlers, animations, AJAX, etc.
• JQuery Mobile – for mobile devices.
• Dojo – Similar functionality to JQuery, less popular but common in GIS applications.
• Leaflet.js – Mapping library
• Accessing different types of data
• Editing
• Measuring
• Routing

• Turf.js – JavaScript library for GIS operations.


• Impromptu – Deal with the alert box issue and make stylized popups with forms and pages.
MVC FRAMEWORKS

• Not a product, but a programming philosophy for organizing your code


• Model – View – Controller
• Model – Data access
• View – User Interface
• Controller – Connects user interface to data.

• Adaptations – MVA, MVP, HMVC, MVVM


• MVC Frameworks exist in many languages
• Django – Python
• Rails – Ruby
• ASP.NET MVC – Microsoft
• CodeIgnitor, Cake, Laravel – PHP
• Angular, Backbone, Ember - JavaScript
BOOTSTRAP

• CSS Library
• Cross Browser Compatibility
• Pre-defined classes

• Responsive Design
• Grid design
• 12 columns
• 4 screen size classes
• xs, small, medium, large

• Glyphicons – Fonts for standard web symbols.


• Javascript Library – tooltips, dialogs, etc.
• Makes your pages responsive, pretty, and standardized.
JQUERY - ”WRITE LESS, DO MORE”

• Cross Browser Compatibility


• Javascript Library for DOM manipulation
• Respond to Events
• Add and remove classes, attributes, and CSS
• Modify content

• Other Functionality
• AJAX – communicate with server from within Javascript
• Animations
• Validation
• JQuery UI – User interface – Tabs, Dialogs, Menu’s, etc.
JQUERY – STEP 1 SELECT A DOM ELEMENT OR GROUP OF DOM
ELEMENTS

• Document • $(document)
• Tags • $(“p”)
• Classes • $(“.link-buttons”)
• ID • $(“#my-link”)
JQUERY – SELECTORS (ADVANCED)

• $(“#navBar a”) • Descendants (a tags within the navBar element)


• $(“img[alt]”) • Attributes (image tags with the alt attribute set)
• $(“#col2 p:first”) • Filters (first paragraph in the col2 element)
• $(“tr:odd”) • Filters (odd table rows)
• $(“a:not(#googleLink)”)
• Filters (Links except the one with an id of
• $(“p:hidden”) googleLink)
• Filters (hidden paragraphs)
JQUERY – STEP 2 DO SOMETHING WITH THE ELEMENTS YOU
SELECTED

• Run code automatically when the $(document).ready(function(){})


page is loaded $(“#myButton”).click(function(){
alert(“You clicked myButton”);
• Add an event handler });

$(“.lights”).hide();

• Hide or display an element $(“.lights”).show();


var frstHTML = $(“p:first”).html();
$(“p:first”).html(“Replacing with this”);
• Get the content
$(“.lights”).addClass(“text-center”);
• Replace the content $(“.lights”).removeClass(“text-center”);
• Add or Remove a class
JQUERY – STEP 2 DO SOMETHING WITH THE ELEMENTS YOU
SELECTED

• Read the CSS var size = $(“#header”).css(“font-size”);


• Change the CSS $(“.main-points”). css(“font-weight”, “bold”);

• Read an HTML attribute var headerSrc = $


(“#header_image”).attr(“src”);
• Change an HTML attribute
$(“#header_image”).attr(“src”,“images/
• Read an HTML form element
header2.jpg”);
• Change an HTML form element
var name = $(“#name”).val();
$(“#name”).val(“Joe Smith”);
JQUERY – STEP 2 DO SOMETHING WITH THE ELEMENTS YOU
SELECTED

• Loop through a set $(“#myForm_submit”).click(function(){


$(“.numericField”).each(function(){
if (isNan($(this).val()) {
$(this).addClass(“has-error”);
} else {
$(“.numericField”).on(“keyup”,
$(this).removeClass(“has-
function(){
error”);
} // if NaN
}); // each numeric field
});
}); // click myForm_submit
GEOSPATIAL DATA ON THE WEB

• Binary Formats
• ESRI
• Coverages, Shapefile, Personal Geodatabase, File Geodatabase, Enterprise Geodatabase
• Open Source
• Shapefile, PostGIS., Spatiallite

• Text Based Formats


• XML based formats
• KML - Google
• GPX – GPS
• JSON based formats
• geoJSON
• topoJSON
XML

• GPX • KML
<time>2016-10-17T10:08:03Z</time> </description>
<styleUrl>#IconStyle00</styleUrl>
<wpt lat="20.38333" lon="-100"> <MultiGeometry>
<name>1</name> <Point>
<altitudeMode>clampToGround</altitudeMode>
<cmt>08:54 17-Oct-16</cmt> <coordinates>
</wpt> -100.5166700003203,21.29999999980021,0</coordinates>
</Point>
<wpt lat="20.51667" lon="-100.81667">
</MultiGeometry>
<name>2</name> </Placemark>
<cmt>08:54 17-Oct-16</cmt> </Folder>
<Style id="IconStyle00">
</wpt> <IconStyle>
<wpt lat="20.6" lon="-100.38333"> <Icon><href>Layer0_Symbol_153b24f0_0.png</href></Icon>
<scale>0.250000</scale>
<name>3</name> </IconStyle>
<cmt>08:54 17-Oct-16</cmt> <LabelStyle>
<color>00000000</color>
</wpt>
<scale>0.000000</scale>
<wpt lat="21.3" lon="-100.51667"> </LabelStyle>
<name>4</name> <PolyStyle>
<color>ff000000</color>
<cmt>08:54 17-Oct-16</cmt> <outline>0</outline>
</wpt> </PolyStyle>
</Style>
</Document>
GEOJSON

• A specification for creating, identifying, and storing geospatial data in JavaScript Object Notation
• Mapping API’s
• Leaflet
• Google
• OpenLayers
• ESRI????

• Other software
• QGIS
• PostGIS
• Turf.js
• PHP
• Databases
GEOJSON - POINT

{“type”: “Point”, {“type”: “MultiPoint”,

“coordinates”:[-108.5, 33.7] “coordinates”:[[-108.5, 33.7], [-


108.4, 33.5], [-108.6, 33.2]]
}
}

coordinates[0] = -108.5
coordinates[1][0] = -108.4
coordinates[1] = 33.7
coordinates[0][1] = ??????
coordinates[2,0] = ??????
coordinates[0,2] = ??????
GEOJSON - LINE

{“type”: “LineString”, {“type”: “MultiLineString”,


“coordinates”:[[-108.5, 33.7], [- “coordinates”:[[[-108.5, 33.7], [-
108.4, 33.5], [-108.6, 33.2]] 108.4, 33.5], [-108.6, 33.2]], [[-
} 108.5, 33.7], [-108.4, 33.5], [-
108.6, 33.2]], [[-108.5, 33.7], [-
108.4, 33.5], [-108.6, 33.2]]]
}
GEOJSON - POLYGON

{“type”: “Polygon”, {“type”: “MultiPolygon”,


“coordinates”:[[[-108.5, 33.7], [- “coordinates”:[[[[-108.5, 33.7], [-
108.4, 33.5], [-108.6, 33.2], [- 108.4, 33.5], [-108.6, 33.2], [-
108.5, 33.7]], [[-108.5, 33.7], [- 108.5, 33.7]], [[-108.5, 33.7], [-
108.4, 33.5], [-108.6, 33.2], [- 108.4, 33.5], [-108.6, 33.2], [-
108.5, 33.7]]] 108.5, 33.7]]],
} [[[-108.5, 33.7], [-108.4, 33.5], [-
108.6, 33.2], [-108.5, 33.7]]]]
}
GEOJSON – FEATURES AND
FEATURECOLLECTIONS
{“type”:”feature”, {“type”:”featureCollection”,
“features”: [{“type”:”feature”,
“geometry”: {“type”: “Point”, “geometry”: {“type”: “Point”,
“coordinates”:[-108.5, 33.7]
“coordinates”:[-108.5, 33.7]
},
}, “properties”: {“species”:”Bald Eagle”,
“sex”:”male”,
“properties”: {“species”:”Bald Eagle”, “age”:7
}
“sex”:”male”,
}, {“type”:”feature”,
“age”:7 “geometry”: {“type”: “Point”,
“coordinates”:[-109.1, 32.5]
} },
“properties”: {“species”:”Golden Eagle”,
}
“sex”:”female”,
“age”:2
}
}]
}
GEOJSON

var county = { "type": "FeatureCollection",


"features": [ { "type": "Feature",
"properties": { "id": 1180,
"name": "San Juan del Rio",
"population": 118173.000000,
"country": "Mexico",
"state": "Queretaro",
"county": "San Juan del Rio“ },
"geometry": { "type": "MultiPoint",
"coordinates": [ [ -99.999, 20.3833 ] ] }
}]
}
MAPPING API’S FOR THE WEB

• Google Maps API • Open Layers


• Pro: Familiarity • Pro: Open Source
• Pro: Perspective, Streetview • Pro: Many features
• Con: Proprietary • Pro: Rotation, 3D
• Con: Limited to Google background maps • Con: Large footprint
• Leaflet • Con: Learning curve
• Pro: Open Source
• ESRI Javascript API
• Pro: Small Footprint
• Con: Proprietary
• Pro: Newer codebase
• Pro: Many Features
• Pro: Easy to use
• Pro: Integrates well with ESRI products if
• Con: Limited in scope(but lots of plug-ins)
you use them.
WHAT DO YOU GET WITH A MAPPING API?

• Map canvas
• Occupies a div on your web page
• Control size and placement of the map by setting the CSS of the div

• JavaScript library
• Add controls (zoom, select layers, scale bar, coordinates, edit tools, etc)
• Display data
• Manipulate data
• Analyze data using turf.js
WHAT CAN YOU DO WITH A MAPPING API ON
THE CLIENT SIDE
• Display a background map
• Streets
• Topography
• Aerial Photos

• Display your own GIS data


• Zoom, pan, search, select, view attributes, etc.
• Display your location
• Analyze (intersections, nearest features, distances, areas, buffers, etc.)
BUT…..

• You are only working with static data.


• You cannot change the data.
• You cannot add new data (at least not that anyone else can see).
• In order to make changes to the base data that others will be able to
see, you need…..
• A database server.
• You can’t secure your web page to prevent others from accessing it.
WHAT YOU NEED A DATABASE SERVER FOR

• Any changes that need to be persisted longer than the current session.
• Any changes that others will be to see when they open the web page.
• Security – If you want to password protect your web pages or
implement any kind of log-in system you will need some a database
system.
EDITORS

• HTML, CSS, and JavaScript are just text files.


• You can write code in any program that will save a plain asci text file.

• There are many advantages to having an actual code editor and many are free.
• Colors
• Automatic indenting
• Code “hinting”
• Code completion
• Code collapsing
• Parenthesis highlighting
• Run time environment
• Debugging
• Plug-Ins
• Emmet
EDITORS

• Brackets • Sublime Text


• Free • Notepad++
• All Platforms
• Emacs
• Supports all languages
• Supports Emmet • Text Wrangler
• Live Preview • Komodo
• Atom
• Netbeans
LETS MAKE A MAP!

1. Make a directory
2. HTML
3. CSS
4. JavaScript
HTML
CSS
JAVASCRIPT

• Load Leaflet

• Load Jquery
• Initialize Map
JAVASCRIPT – ADD DATA

• Create a marker and add it to the map

• Add a popup to the marker

• Chaining

• Pop-ups can include HTML and be complex


JAVASCRIPT – HANDLE DOM EVENT

• HTML

• CSS

• JavaScript

$(“zoomToZocalo”).on(“click”, function(){
JAVASCRIPT – HANDLE MAP EVENT

• Choose an event to respond to


• Write an event handler
JAVASCRIPT – ADD EXTERNAL DATA

• Add Leaflet.ajax.js plug-in to map document

• Add the JavaScript code to read the ajax file and add it to the map.

• Add a pointToLayer option that creates the popup for each attraction
{
"type": "Feature",
"properties": {
"id": 3,
"name": "Chapultepec Park",
"image": "chapultepec.jpg",
"web": "https://en.wikipedia.org/wiki/Chapultepec"
},
"geometry": {
"type": "Point",
"coordinates": [ -99.18654, 19.41933 ]
}
}
JAVASCRIPT – ADD EXTERNAL DATA

• Add Leaflet.ajax.js plug-in to map document

• Add the JavaScript code to read the ajax file and add it to the map.

• Add a pointToLayer option that creates the popup for each attraction
JAVASCRIPT – BUILD HTML FROM GEOJSON

• Add buttons for each feature

• Add event handlers for each button


JAVASCRIPT - ANALYSIS

• Turf.js – Client side geospatial analysis


• HTML
• JavaScript
QGIS

• Open Source Desktop GIS


• Equivalent of ArcGIS Desktop in the ESRI suite

• Advantages
• Free
• Raster manipulation without Spatial Analyst
• Includes functionality only available in ArcEditor or ArcInfo
• Multi-user capable out of the box with PostGIS
• Wide range of data formats and easily converts between them
SUMMARY

• So far we have learned a little bit about


• The three primary technologies that drive the internet and how they interact.
• HTML
• CSS
• JavaScript
• Two very popular libraries that make web development easier
• Bootstrap (CSS)
• jQuery (JavaScript)
• Two open source libraries for geospatial applications
• Leaflet – Web mapping
• Turf – Geospatial Analysis
SUMMARY

• With the knowledge we have so far we can


• Create a web map with our own data
• Respond to user input
• Perform relatively complex spatial analysis

• The caveat is that the data is relatively static


• What we cannot do is develop an application where the clients can create or
edit data and send it back to the server so that it is accessible by other
clients.
• For that we need a database server.
SERVER SIDE TECHNOLOGIES

• Database
• Allows for storage and retrieval of information
• Structured Query Language (SQL)

• Programming Language
• PHP
• Java
• Perl
• Ruby
• ASP.Net
• JavaScript via Node.js
DATABASES

• Most GIS people are brought up in the world of single user computers and think of
databases in terms of a program on their computer such as dBase, FoxPro or Microsoft
Access.
• These databases include both a database engine (storage and retrieval) and front end tools
(forms, reports, etc).

• In the multi-user or enterprise world a database is only the database engine.


• The front end can be written in any kind of language that has a driver for the database.
• Dedicated software: Visual Basic, C#, Python
• Internet Application: HTML, CSS, Javascript + Server side language to access the database.

• The biggest differences between a personal computer database and an enterprise level
multi-user database is that they are highly optimized for speed, security, and handling
many users simultaneously.
SQL

• Structured Query Language


• Implements CRUD
• Create
• Retrieve
• Update
• Delete
POPULAR ENTERPRISE DATABASES (RDBMS)

• Commercial
• Microsoft SQL Server
• Oracle
• IBM DB2

• Open Source
• MySQL
• PostgreSQL
• SQLite

• Advantages – Well established technology


POPULAR ENTERPRISE DATABASES (NO SQL)

• Commercial
• ???????

• Open Source
• MongoDB
• CouchDB
• PouchDB
• IndexDB – HTML5 spec in every browser.

• Advantages – Flexibility
• JSON Storage = ease of use with JavaScript
DATABASES AND GEOSPATIAL DATA
DATABASES AND GEOSPATIAL DATA

• How to handle coordinates????


• Table fields
• Store geoJSON objects in a text field.
• Utilize a spatial extension to a database
• Method for storing coordinates in a binary field
• Set of functions for dealing with spatial data
• ArcSDE
• SQL Server, Oracle, DB2, PostgreSQL
• PostGIS
• PostgreSQL
• Spatialite
• SQLite
TECHNOLOGY STACK USED IN THIS COURSE

• Database
• PostgreSQL
• PostGIS Extension

• Programming Language
• PHP
• Open source
• Widely available
• Well documented
SERVER OPTIONS

• Install on local machine


• Great for development but not great for a webserver.
• XAMPP includes Apache Web Server, MySQL, PHP, and Perl
• PostgreSQL and PostGIS

• Purchase a hosting plan


• Make sure that the plan includes the programming language and database you install on
your local machine.
• A2 Hosting includes PostgreSQL and PostGIS
• Move files back and forth using FTP.
• Control server using SSH (command line) or web application (phpPgAdmin)

• Purchase a dedicated server


WHAT DO I USE THE SERVER FOR?

• Number crunching and analysis


• You can do this locally using JavaScript.
• But the server is generally more powerful.
• Decision to process on the client or server depends on many factors.

• Retrieving data from the database


• AJAX call from JavaScript that returns text. (JSON, or HTML).

• Dynamic web pages


• .php extension instead of .html
• <?php …code…. ?>
• echo “string”; statement
COMMON FRUSTRATIONS

• The internet has grown organically as a bottom-up system


• At the time it was developed nobody really had any expectation of it
growing into what it has become
• There is a phenomenon known as “lock-in”, whereby a substandard
technology becomes established and popular to the point where it
becomes almost impossible for superior technology to replace it.
• QWERTY keyboard layout was designed to prevent manual typewriter keys
from jamming.
• Betamax vs VHS
• PC vs Mac
COMMON FRUSTRATIONS

• SQL has been around since the 70s. Long before the internet was even
dreamed of.
• PHP was developed in 1994 by Rasmus Lerdorf to help with his personal web
page.
• PHP originally stood for Personal Home Page
• Lerdorf didn’t intend for PHP to interact with databases.
• He said "I don’t know how to stop it, there was never any intent to write a
programming language. I have absolutely no idea how to write a programming
language, I just kept adding the next logical step on the way.“
• As of February 2014 PHP was the server-side language for 82% of web sites, up
from 75% in 2010.
COMMON FRUSTRATIONS

• JavaScript wasn’t developed until 1995.


• While it was being developed nobody really knew what PHP was.
• Developed by Netscape while Navigator was the #1 browser in the world.
• Everyone knew Microsoft was also developing a scripting language called VBScript.
• This led to the “Browser Wars” of the late 1990s

• Over the years JavaScript and PHP became dominant.


• PHP added the ability to interact with databases.
• Both added object oriented functionality
• In 2005 AJAX was developed allowing JavaScript in the client to communicate
directly with PHP in the server.
TAKEAWAYS

• JavaScript, PHP, and SQL were never intended to work with each other and as a result they
have very different syntax.
• This is likely to remain the case due to “Lock-in” despite developments such as Node.JS and
ASP.NET
• “Suck it up, cupcake”. You have to learn 3 different ways to
• Concatenate strings
• Format numbers
• Deal with date and time
• Deal with objects and arrays
• Etc, etc, etc.

• Don’t get taken in by people selling you the latest and greatest technologies.
SQL - INTRODUCTION

• Structured Query Language


• Started with IBM in the early 70’s. First commercial version by Oracle in 1979.
• Client Server Architecture
• Request = SQL command
• Response – Recordset / # records / error.

• Declarative Programming – Say what you want to do


• Data Definition Language
• Data Manipulation Language
• Data Control Language

• Imperative Programming – Step by step algorithms


• Triggers

• Text-based
SQL - ARCGIS

• Select by Attributes • Definition Queries


SQL - ACCESS

• Design View • SQL View


• SELECT Vehicles.Year & " " &
[Vehicles.Make] & " " &
Vehicles.Model AS Vehicles,
Expenses.*
• FROM [Vehicles Extended] INNER
JOIN Expenses ON [Vehicles
Extended].ID = Expenses.Vehicle
• ORDER BY Vehicles.Year & " " &
[Vehicles.Make] & " " &
Vehicles.Model DESC , Expenses.
[Service Date] DESC;
SQL - CREATE

• Create a new empty table


CREATE TABLE raptor_nests (
id int PRIMARY KEY DEFAULT nextval(‘raptor_nests_id’),
nest_id varchar(10) NOT NULL,
species varchar(50),
2016_status varchar(50),
current_status varchar(50),
date_found date,
last_date_inspected date,
project_id integer
)
SELECT AddGeometryColumn(‘public’, ‘raptor_nests’, ‘geom’, 4326, ‘POINT’, 2)
SQL - CREATE

• Create a new empty table


CREATE TABLE projects (
id int PRIMARY KEY DEFAULT nextval(‘project_id’),
project_id varchar(50) NOT NULL,
name varchar(255) NOT NULL,
start_date date NOT NULL,
status varchar(50),
)
SELECT AddGeometryColumn(‘public’, ‘projects’, ‘geom’, 4326, ‘LINESTRING’,
2)
SQL - INSERT

• Add data to an existing table


• INSERT INTO raptor_nests (nest_id, species, current_status, date_found,
geom) VALUES (‘RN_025’, ‘SWHA’, ‘ACTIVE’, ‘2015-11-05’,
ST_GeomFromText(‘POINT(-106.435 39.423)’, 4326));

• INSERT INTO projects (project_id, name, start_date, geom) VALUES (‘USD


10-5’, ‘UNITED SANITARY DESIGN #10, Project 5’, ‘2016-04-12’,
ST_SetSRID(ST_GeomFromGeoJSON(‘{“type”:”LineString”, “coordinates”:[[-
106.45245, 38.5642], [-106.65876, 38.80678],[-106.1952, 38.65335]]}’),
4326))
SQL - RETRIEVE

• SELECT – Single Table


• SELECT * FROM raptor_nests;
• SELECT nest_id, species, current_status, date_found, last_date_inspected FROM raptor_nests
• SELECT nest_id, species, date_found, last_date_inspected FROM raptor_nests WHERE
current_status = ‘active’;
• SELECT nest_id, species, date_found, last_date_inspected FROM raptor_nests WHERE
current_status = ‘active’ ORDER BY species, last_date_inspected DESC, nest_id;
• SELECT species, count(species), max(last_date_inspected) FROM raptor_nests GROUP BY species
ORDER BY species
• SELECT species, count(species) AS count, max(last_date_inspected) AS most_recent_inspection
FROM raptor_nests WHERE current_status <> 2016_status GROUP BY species ORDER BY species
• SELECT name, length_feet/5280 as length_miles, start_date FROM projects ORDER BY dist_miles
SQL - RETRIEVE

• SELECT - Multiple Tables


• SELECT p.start_date, p.name, r.nest_id, r.species, r.current_status FROM raptor_nests r JOIN
projects p ON p.id = r.project_id ORDER BY p.start_date, DESC, p.name, r.nest_id

• JOIN TYPES
• INNER
• LEFT
• RIGHT
• FULL

• SELECT – Spatial Queries with POSTGIS


• SELECT p.start_date, p.name, r.nest_id, r.species, r.current_status, ST_Distance(r.geom, p.geom) as
distance FROM raptor_nests r JOIN projects p ON ST_DWithin(r.geom, p.geom, 500)
SQL - UPDATE

• Modify existing data in an existing table


• UPDATE raptor_nests SET last_inspection_date=‘2016-07-18’,
current_status=‘FLEDGED’ WHERE id=13;
• UPDATE raptor_nests SET current_status=‘FLEDGED’ WHERE
upper(current_status)=‘FLEDGED’;
SQL - DELETE

• Delete data from an existing table


• DELETE FROM raptor_nests WHERE id=12;
• DELETE FROM raptor_nests WHERE (current_status=‘REMOVED’) AND
((current_date()-last_inspection_date) > 730)
SQL - DELETE

• Delete data from an existing table


• DELETE FROM raptor_nests WHERE id=12;
• DELETE FROM raptor_nests WHERE (current_status=‘REMOVED’) AND ((current_date()-
last_inspection_date) > 730)

• Operator precedence
1. ()
2. *, /
6-3*4/2 = 0 ?????
3. +, -, (6-3)*4/2 =6 ????
4. =, <, > (6-(3*4))/2 -3
= ??????
5. NOT
6. AND
7. IN, LIKE, OR
SO I HAVE A SQL STATEMENT…..

• How do you send it to the database and what do you do with the result…
• An enterprise database is not like a standalone program, they are designed to
be accessible in many ways.
• All you need is connection information
• Host – localhost, www.millermountain.com, 189.207.169.17
• Port – 5432
• Database Name – gis_test
• Username
• Password
SO I HAVE A SQL STATEMENT…..

• You can access it many ways.


• Command line – (psql)
• GUI – pgAdmin III
• Web Interface – phpPgAdmin
• Custom software – QGIS, ArcGIS, Excel, Access
• Custom web page – PHP, Java, ASP.NET, Ruby, Node.js

• Result
• Text
• Table
• Feature Class, Spreadsheet, Table
• Array of data or objects
OVERVIEW

1. User interacts with a web page or map on the client


A. Submit a form, enter a project id, select from a list, click on the map.

2. Web page sends data to the server(GET, POST, AJAX)


3. A php script on the server receives the data, processes it SQL statement, sends to the database
4. The database returns a result that is processed by a php script and returns a string (AJAX, ECHO)
A. Loop through and add HTML for a web page table
B. Loop through and return geoJSON to turn into features on a map

5. Web page does something with the result string


A. Inserts table into page.
B. Inserts features onto the map.
PHP - INTRO

• Two flavors of PHP


• Procedural
• Object Oriented <?php
$heading = “Welcome to my web
• Two ways to use PHP <h1>
page”;
Welcome to my web page
?>
</h1>
• Dynamic web page ……..
• HTML document with embedded PHP code <h1><?php echo $heading; ?></h1>
• AJAX
• Script on server receives data from Javascript and returns text to javascript
PHP - STRINGS

• All statements end with a semicolon;


• Variable names begin with $
• Do not need to be declared

• String concatenation
• $space=“ “;
“Mickey”+
• $myString1= “Micky”.$space.”Mouse”;
$space+”Mouse”;
• $myString2=“Mickey$space Mouse”;
• $myString3=“Mickey{$space}Mouse”;
PHP - ARRAYS

• Indexed Arrays – indexed numerically • $animalType[0]=“CAT”;


• $animalType = array(“CAT”, “DOG”, “CHICKEN”); • $animalType[1]=“DOG”;
• $animalType = [“CAT”, “DOG”, “CHICKEN”]; • $animalType[2]=“CHICKEN;
• $animalType[] = “BEAR” • $animalType[3]=“BEAR”;
• $animalType[6] = “FERRET” • $animalType[6]=“FERRET”;
• Associative Arrays – indexed by keys
• $geomDimension = array(“POINT”=>0, • $geomDimension[“POINT”]=0;
“LINE”=>1); • $geomDimension[“LINE”]=1;
• $geomDimension = [“POINT”=>0, “LINE”=>1]; • $geomDimension[“POLYGON”]=2
• $geomDimension[‘POLYGON’]=2; ;
PHP – ARRAY FUNCTIONS

• sizeof() or count() – returns number of elements • count($geomDimension) =


• array_push(), array_pop(), array_shift(), 3
array_unshift() • array_push($animalType,
• array_keys(), array_values() “BIRD”)
• array_unique()
• sort(), asort(), ksort()
• rsort(), arsort(), krsort()
• json_encode()
COMMUNICATION WITH SERVER - GET

• Sending information TO server


• Parameters encoded in the URL
• Syntax = localhost/webmap101/php_test.php?lat=19.25831&long=-
99.34295&alt=2207
• lat = “19.25831”
• long=“-99.34295”
• alt=“2207”
• Limited to 2048 characters
• Visible to user = Insecure
• Can be bookmarked
COMMUNICATION WITH SERVER - POST

• Sending information TO server


• Parameters encoded in the HTTP request header
• Not visible to user = More secure
• No limit on size
• Cannot be bookmarked

• So how do you send data with POST?


• Form submit button.
• AJAX
COMMUNICATION WITH SERVER

• Reading GET and POST information


• Superglobal variables in PHP
• $_GET
• $_POST
• Associative arrays
COMMUNICATION WITH SERVER - GET

• Sending information TO server


• Parameters encoded in the URL
• Syntax = localhost/webmap101/php_test.php?lat=19.25831&long=-
99.34295&alt=2207
• lat = “19.25831”
• long=“-99.34295”
• alt=“2207”
• Limited to 2048 characters
• Visible to user = Insecure
• Can be bookmarked
COMMUNICATION WITH SERVER

• Reading GET and POST information


• Superglobal variables in PHP
• $_GET
• $_POST
• Associative array
• $_GET[‘lat’]
• $_GET[‘long’]
• $_GET[‘alt’]
PHP – CONDITIONAL STATEMENTS

if (condition) { switch ($geomType[i]) {


code…… case “POINT”:
} elseif { $size = “No Dimension<br>”;
code…. break;
} else { case “LINE”:
code….. $size = “Length =
} “.lineLength($geom).”<br>”;
break
case “POLYGON”:
if (isset($_GET[‘lat’])) {
$size = “Area= “.area($geom).”<br>”;
$lat=$_GET[‘lat’];
break;
} else {
default:
$lat= “N/A”;
echo “N/A”;
}
}
PHP - LOOPS

for ($i=0;$i<count($animalType);$i++) {
echo $animalType[$i].”<br>”;
}

$i=0;
$while ($i<count($animalType) {
echo $animalType[$i].”<br>”;
$i++;
}
PHP - LOOPS

foreach ($_GET as $key=>$val) {


echo “Key: {$key} Value: {$val}<br>”;
}

$sql = “UPDATE cords SET “;


foreach ($_POST as $key=>$val) {
$sql += “{$key} = ‘{$val}’, “;
}
$sql += “ WHERE id = 13”;
SECURITY NOTE – SQL INJECTION

• One of the most common forms of security threats is a SQL Injection


attack.
• SQL statements end with a semi-colon.
• SQL Engine will process anything after a semicolon as a new
statement.
• This allows someone with knowledge of SQL to “Insert” a SQL
statement into a text input box.
SOLUTION – USE PDO

• PHP Data Objects


• Use Prepared Statements rather than a single SQL query
• Prepared statements
• Only allow one SQL statement at a time
• Separate data from code by using placeholders
• Properly escape user input values
• “\” removes any special meaning of the character following it
• VALUES (‘John’s house’) becomes VALUES (‘John\’s house’)
SOLUTION – USE PDO

• Standard
$db = pg_connect("host=localhost port=5432 dbname=gis_test user=joe password=12345");
$result = pg_query($db, “SELECT nest_id, createdate, lastsurvey, recentstatus FROM
raptor_nests”);
echo “<table>”;
while ($row = pg_fetch_array($result)) {
echo “<tr>”;
foreach ($row as $field=>$value) {
echo “<td>{$value}</td>”;
}
echo “</tr>”;
}
echo “</table>”;
SOLUTION – USE PDO

• Prepared Statements
$db = new PDO(“pgsql:host=localhost;port=5432;dbname=millermo_testgis;user=joe;password=12345");
$sql = $db->prepare(“SELECT nest_id, createdate, lastsurvey, recentstatus, recentspecies FROM
wildlife_raptor_nests WHERE lastsurvey> :ls AND recentstatus = :rs”);
$params = [“ls”=>”2016-07-06”, “rs”=>”Active”];
$sql->execute($params);
echo “<table>”;
while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {
echo “<tr>”;
foreach ($row as $field=>$value) {
echo “<td>{$value}</td>”;
}
echo “</tr>”;
}
echo “</table>”;
PHP - PROBLEMS

• Pages must be reloaded every time to see any changes


• No direct access to the DOM
• Very limited ability to get user input and respond to
events
• Requires a server connection so off-line applications are
out of the question.
• Mapping libraries are all based on JavaScript.
AJAX

• Asynchronous JavaScript And XML*


• Microsoft (1999), Google (2004), AJAX coined (2005)
• XMLHttpRequest object standardized by W3C (2006)
• Allows the client to request information from the server asynchronously
• When the request is completed a JavaScript callback function is executed.
• The callback function can process the result and manipulate the DOM.
• JQuery includes a wrapper for the XMLHttpRequest object that makes it
easy to use.
AJAX – HTML AND JAVASCRIPT
(QUERY_NESTS_AJAX.HTML)
<input type="date" id="lastsurvey" value="2015-01-01"><br>
<select id="recentstatus">
<option value='ACTIVE NEST'>Active Nest</option>
<option value='INACTIVE NEST'>Inactive Nest</option>
<option value='FLEDGED NEST'>Fledged Nest</option>
</select><br>
<button id=“filterSubmit" >Submit</button>
<hr><div id=“resultTable></div>
<script>
$(“#filterSubmit”).click(function(){
$.ajax({url:’query_nests_ajax.php’, type :‘POST’, data:{lastsurvey: $(“#lastsurvey).val(),
recentstatus:$(“#recentstatus).val()},
success: function(response){

}});
});
</script>
AJAX – HTML AND JAVASCRIPT
(QUERY_NESTS_AJAX.HTML)
$.AJAX OPTIONS

• async • Boolean indicating whether the request is asynchronous.

• beforeSend(xhr) • Function to run BEFORE the request is sent

• complete(xhr, status) • Function to run AFTER the request is complete


• data • Object containing properties that will become POST
variables
• error(xhr, status, error)
• Function to run if an error occurs on the server
• success(result, status, xhr)
• Function to run if no error occurs
• type
• The type of transfer protocol to use GET or POST
• URL
• The location of the script to run on the server
AJAX – HTML AND JAVASCRIPT
(QUERY_NESTS_AJAX.HTML)
<input type="date" id="lastsurvey" value="2015-01-01"><br>
<select id="recentstatus">
<option value='ACTIVE NEST'>Active Nest</option>
<option value='INACTIVE NEST'>Inactive Nest</option>
<option value='FLEDGED NEST'>Fledged Nest</option>
</select><br>
<button id=“filterSubmit" >Submit</button>
<hr><div id=“resultTable></div>
<script>
$(“#filterSubmit”).click(function(){
$.ajax({url:’query_nests_ajax.php’, type :‘POST’, data:{lastsurvey: $(“#lastsurvey).val(),
recentstatus:$(“#recentstatus).val()}, success: function(response){
$(“#resultTable”).html(response);
}});
});
</script>
AJAX – PHP (QUERY_NESTS_AJAX.PHP)

<?php
$ls = $_POST[‘lastsurvey’];
$rs = $_POST[‘recentstatus’];
$db = new PDO(pgsql:host=localhost;port=5432;dbname=gis_test;user=joe;password=12345");
$sql = $db->prepare(“SELECT nest_id, createdate, lastsurvey, recentstatus, recentspecies,
ST_AsGeoJSON(ST_Transform(geom, 4326),5) as geom FROM wildlife_raptor_nests WHERE lastsurvey> :ls AND
recentstatus = :rs"”;
$sql->execute([“ls”=>$ls, “rs”=>$rs]);
echo “<table>”;
while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {
echo “<tr>”;
foreach ($row as $field=>$value) {
echo “<td>{$value}</td>”;
}
echo “</tr>”;
}
echo “</table>”;
?>
AJAX - RESPONSE

<table…..>
<th>……</th>
<tr>
<td>Rnest_034</td>
<td>2011-04-23</td>
<td>2015-07-14</td>
<td>ACTIVE NEST</td>
<td>Red-Tailed Hawk</td>
</tr>
<tr>
<td>Rnest_045</td>
<td>2012-05-17</td>
<td>2015-07-08</td>
<td>ACTIVE NEST</td>
<td>Red-Tailed Hawk</td>
</tr>
</table>
AJAX – HTML AND JAVASCRIPT
(QUERY_NESTS_AJAX.HTML)
<input type="date" id="lastsurvey" value="2015-01-01"><br>
<select id="recentstatus">
<option value='ACTIVE NEST'>Active Nest</option>
<option value='INACTIVE NEST'>Inactive Nest</option>
<option value='FLEDGED NEST'>Fledged Nest</option>
</select><br>
<button id=“filterSubmit" >Submit</button>
<hr><div id=“resultTable></div>
<script>
$(“#filterSubmit”).click(function(){
$.ajax({url:’query_nests_ajax.php’, type :‘POST’, data:{lastsurvey: $(“#lastsurvey).val(),
recentstatus:$(“#recentstatus).val()}, success: function(response){
$(“#resultTable”).html(response);
}});
});
</script>
AJAX – HTML AND JAVASCRIPT
(QUERY_NESTS_AJAX.HTML)
<input type="date" id="lastsurvey" value="2015-01-01"><br>
<select id="recentstatus">
<option value='ACTIVE NEST'>Active Nest</option>
<option value='INACTIVE NEST'>Inactive Nest</option>
<option value='FLEDGED NEST'>Fledged Nest</option>
</select><br>
<button id=“filterSubmit" >Submit</button>
<hr><div id=“resultTable></div>
<script>
$(“#filterSubmit”).click(function(){
$.ajax({url:’query_nests_ajax.php’, type :‘POST’, data:{lastsurvey: $(“#lastsurvey).val(),
recentstatus:$(“#recentstatus).val()}, success: function(response){
$(“#resultTable”).html(response);
}});
});
</script>
AJAX – PHP (QUERY_NESTS_AJAX.PHP)

<?php
$ls = $_POST[‘lastsurvey’];
$rs = $_POST[‘recentstatus’];
$db = new PDO(pgsql:host=localhost;port=5432;dbname=gis_test;user=joe;password=12345");
$sql = $db->prepare(“SELECT nest_id, createdate, lastsurvey, recentstatus, recentspecies,
ST_AsGeoJSON(ST_Transform(geom, 4326),5) as geom FROM wildlife_raptor_nests WHERE lastsurvey> :ls AND
recentstatus = :rs"”;
$sql->execute([“ls”=>$ls,
$features=[]; “rs”=>$rs]);
echo “<table>”;
while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {
$row[‘geom’]=json_decode($row[‘geom
echo “<tr>”;
array_push($features,
’]);
foreach ($row as $field=>$value) {
$row);
echo “<td>{$value}</td>”;
}
echo “</tr>”;
echo
}
json_encode($features);
echo “</table>”;
?>
AJAX - RESPONSE

[
{ {
"nest_id":"RNest_291 ", "nest_id":"RNest_294 ",
"createdate":"2011-04-06", "createdate":"2011-04-06",
"lastsurvey":"2015-08-10", "lastsurvey":"2015-08-24",
"recentstatus":"FLEDGED NEST ", "recentstatus":"FLEDGED NEST ",
"recentspecies":"Red-tail Hawk ",
"recentspecies":"Swainsons Hawk ",
"geom":{
"geom":{
"type":"Point",
"type":"Point",
"coordinates":[-104.80846,40.15926]
"coordinates":[-
}
104.91081,40.1328]
}
}
]
},
AJAX – HTML AND JAVASCRIPT

$.ajax({url:’query_nests_ajax.php’, type :‘POST’, data:{lastsurvey: $(“#lastsurvey).val(), recentstatus:$


(“#recentstatus).val()}, success: function(response){
var objResponse = JSON.parse(response);
var strResponse = “<table>”;
for (var i=0;i<objResponse.length;i++){
strResponse += "<tr>”’
strResponse += “<td>"+objResponse[i].nest_id+"</td>";
strResponse += "<td>"+objResponse[i].createdate+"</td>";
strResponse += "<td>"+objResponse[i].lastsurvey+"</td>";
strResponse += "<td>"+objResponse[i].recentstatus+"</td>";
strResponse += "<td>"+objResponse[i].recentspecies+"</td>";
strResponse += "<td>"+JSON.stringify(objResponse[i].geom)+"</td>;
strResponse += “</tr>";
}
strResponse += “</table>”;
$(“#resultTable”).html(strResponse);
}
AJAX - RESPONSE

[
{ {
"nest_id":"RNest_291 ", "nest_id":"RNest_294 ",
"createdate":"2011-04-06", "createdate":"2011-04-06",
"lastsurvey":"2015-08-10", "lastsurvey":"2015-08-24",
"recentstatus":"FLEDGED NEST ", "recentstatus":"FLEDGED NEST ",
"recentspecies":"Red-tail Hawk ",
"recentspecies":"Swainsons Hawk ",
"geom":{
"geom":{
"type":"Point",
"type":"Point",
"coordinates":[-104.80846,40.15926]
"coordinates":[-
}
104.91081,40.1328]
}
}
]
},
AJAX - RESPONSE

[
{ {
"nest_id":"RNest_291 ", "nest_id":"RNest_294 ",
"createdate":"2011-04-06", "createdate":"2011-04-06",
"lastsurvey":"2015-08-10", "lastsurvey":"2015-08-24",
"recentstatus":"FLEDGED NEST ", "recentstatus":"FLEDGED NEST ",
"recentspecies":"Red-tail Hawk ",
"recentspecies":"Swainsons Hawk ",
"geom":{
"geom":{
"type":"Point",
"type":"Point",
"coordinates":[-104.80846,40.15926]
"coordinates":[-
}
104.91081,40.1328]
}
}
]
},
GEOJSON – FEATURES AND
FEATURECOLLECTIONS
{“type”:”Feature”, {“type”:”FeatureCollection”,
“features”: [{“type”:”feature”,
“geometry”: {“type”: “Point”, “geometry”: {“type”: “Point”,
“coordinates”:[-108.5, 33.7]
“coordinates”:[-108.5, 33.7]
},
}, “properties”: {“species”:”Bald Eagle”,
“sex”:”male”,
“properties”: {“species”:”Bald Eagle”, “age”:7
}
“sex”:”male”,
}, {“type”:”feature”,
“age”:7 “geometry”: {“type”: “Point”,
“coordinates”:[-109.1, 32.5]
} },
“properties”: {“species”:”Golden Eagle”,
}
“sex”:”female”,
“age”:2
}
}]
}
AJAX – PHP (QUERY_NESTS_AJAX.PHP)

<?php

$features=[];
while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {
$feature=[‘type’=>’Feature’];
$feature[‘geometry’]=$json_decode($row[‘geom’]);
unset($row[‘geom’]);
$feature[‘properties’]=$row;
array_push($features, $feature)
}
$featureCollection=[‘type’=>’FeatureCollection’, ‘Features’=>$features];
echo json_encode($featureCollection);
?>
GEOJSON

{ {
"type":“FeatureCollection", "type":“Feature",
"features":[{ "geometry":{
"type":“Feature", "type":"Point",
"geometry":{ "coordinates":[-104.80846,40.15926]
"type":"Point", },
"coordinates":[-104.91081,40.1328] "properties":{
}, “nest_id":"RNest_294 ",
"properties":{ "createdate":"2011-04-06",
"nest_id":"RNest_291 ", "lastsurvey":"2015-08-24",
"createdate":"2011-04-06", "recentstatus":"FLEDGED NEST ",
"lastsurvey":"2015-08-10", "recentspecies":"Red-tail Hawk “
"recentstatus":"FLEDGED NEST ", }
"recentspecies":"Swainsons Hawk “ }]
} }
},
AJAX – HTML (QUERY_NESTS_AJAX.HTML)

<input type="date" id="lastsurvey" value="2015-01-01"><br>


<select id="recentstatus">
<option value='ACTIVE NEST'>Active Nest</option>
<option value='INACTIVE NEST'>Inactive Nest</option>
<option value='FLEDGED NEST'>Fledged Nest</option>
</select><br>
<button id=“filterSubmit" >Submit</button>
<hr><div id=“mapdiv”
style=“width:800px;height:600px”></div>
AJAX – JAVASCRIPT
(QUERY_NESTS_AJAX.HTML)
<script>
var mymap = L.map('mapdiv')
mymap.setView([19.4, -99.1], 11);

var backgroundLayer = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png');


mymap.addLayer(backgroundLayer);

$(“#filterSubmit”).click(function(){
$.ajax({url:’query_nests_ajax.php’, type :‘POST’, data:{lastsurvey: $(“#lastsurvey).val(),
recentstatus:$(“#recentstatus).val()}, success: function(response){
var queryLayer=L.geoJSON(JSON.parse(response)).addTo(mymap);
mymap.fitBounds(queryLayer.getBounds());
}});
});
</script>
POSTGIS

• Adding geospatial functionality to the PostgreSQL database


• Standards based – Simple Features for SQL from Open Geospatial Consortium
• Spatial functions – calculating distances, areas, conversion
• Relationship operators –crosses, contains, within, etc
• Spatial operators - intersection, union, difference, buffer, etc
• Conversion – GeoJSON, GML, KML
• Geography types – storing geometry based on spheroid
• Raster operations
• Spatial indexing – R-tree over GIST
SIMPLE FEATURES FOR SQL - GEOMETRY
SIMPLE FEATURES FOR SQL –SPATIAL
REFERENCE
• Spatial Reference includes
• Coordinate system
• Geographic
• Projected.
• Zone
• Datum

• Single Integer, the SRID


• Examples
• Lat/Long WGS84 – 4326
• UTM Zone 13N NAD83 – 26913

• www.spatialreference.org
SFS - FUNCTIONS

• Conversion • Calculations
• ST_AsText • ST_Distance
• ST_PointFromText • ST_Length
• ST_LineFromText • ST_Area
• ST_PolygonFromText • Accessing
• Description • ST_X
• ST_SRID • ST_Y

• ST_IsEmpty • ST_StartPoint

• ST_IsSimple • ST_EndPoint

• ST_IsClosed • ST_PointN

• ST_IsRing • ST_ExteriorRing

• ST_IsValid • ST_InteriorRingN

• ST_GeometryType • ST_GeometryN
SFS – SPATIAL ANALYSIS

• Relational Operators • Spatial Operators


• ST_Equals • ST_Intersection
• ST_Disjoint • ST_Difference
• ST_Touches • ST_Union
• ST_Within • ST_SymDifference
• ST_Contains • ST_Buffer
• ST_Intersects • ST_ConvexHull
• ST_Crosses • ST_Transform
• ST_Overlaps
• ST_DWithin
POSTGIS – BEYOND SFS

• Conversion
• GeoGSON – ST_AsGeoJSON, ST_GeomFromGeoJSON
• KML, GML, EWKT

• Geography Types
• Based on a spheroid.
• Only lat/long WGS84 coordinates
WHY GEOGRAPHY?
POSTGIS – BEYOND SFS

• Conversion
• GeoGSON – ST_AsgeoJSON, ST_GeomFromGeoJSON
• KML, GML

• Geography Types
• Based on a spheroid.
• Only lat/long WGS84 coordinates
• Limited functionality
• More accurate over large spatial areas.

• Raster
• Store rasters in the database
• Map algebra
• Reclass
• Resample
• Slope, aspect, hillshade
POSTGIS – SPATIAL INDEXING

• CREATE INDEX pipeline_geom_idx ON pipelines USING GIST (geom);


• Based on Bounding Boxes

• VACCUM ANALYZE pipelines;


• EXPLAIN ANALYZE sql;
POSTGIS – LOADING (AND EXPORTING) DATA

• Command Line
• shp2pgsql/pgsql2shp
• ogr2ogr
• raster2pgsql
• GDAL utilities

• GUI
• pgShapeLoader

• QGIS
• DB Manager
• Load Raster To PostGIS plug-in

• FME - Commercial
POSTGIS – EXAMPLES (SINGLE TABLE)

• Include the latitude and longitude of the point in the table


• SELECT nest_id, recentstatus, ST_Y(geom) as latitude, ST_X(geom) as longitude

• Given a lat and long, return all nests within 2 miles


• SELECT nest_id, recentstatus FROM raptor_nests WHERE ST_DWithin(ST_FromText(‘POINT(-
99.2314, 19.3451)’,4326), geom, 3218);

• Given a lat and long return the 5 closest nests buffered by one mile
• SELECT nest_id, recentstatus, ST_Distance(ST_FromText(‘POINT(-99.2314, 19.3451)’,4326),
geom) as distance, ST_Buffer(geom, 1609) as buffer FROM raptor_nests ORDER BY distance
LIMIT 5;

• Given a pipeline table sum up the length of pipelines by category.


• SELECT pipline_category, sum(ST_Length(geom)) as total FROM pipelines GROUP BY
pipeline_category ORDER BY total DESC
• SELECT pipline_category, sum(ST_Area(ST_Buffer(geom, 50))) as total……….
POSTGIS – EXAMPLES (MULTIPLE TABLES)

• Given a pipeline table and a raptor_nest table display pipelines with an active raptor nest within 1
mile.
• SELECT p.project_name, r.nest_id FROM pipeline p JOIN raptor_nests r ON ST_DWithin(p.geom, r.geom,
1609) WHERE r.recentstatus=‘ACTIVE’;

• Given an animal home range table and a vegetation table display the vegetation types found in
each animals home range
• SELECT h.animal_id, v.class FROM home_ranges h JOIN vegetation v ON ST_Intersects(h.geom, v.geom)

• Given an animal home range table and a vegetation table display the acres and percent of each
animals home range for every vegetation type.
• SELECT h.animal_id, v.class, ST_Area(ST_Intersection(h.geom, v.geom))/4045 as acres,
ST_Area(ST_Intersection(h.geom, v.geom))/ST_Area(g.geom) as percent FROM home_ranges h JOIN
vegetation v ON ST_Intersects(h.geom, v.geom)
• SELECT h.animal_id, v.class, sum(ST_Area(ST_Intersection(h.geom, v.geom))/4045) as acres,
sum(ST_Area(ST_Intersection(h.geom, v.geom))/ST_Area(h.geom)) as percent FROM home_ranges h JOIN
vegetation v ON ST_Intersects(h.geom, v.geom) GROUP BY h.animal, v.class
SERVER SIDE EXAMPLE

• Modify the Mexico City attraction application we started at the end of


the client side section to
• Store the attractions data in a PostGIS table
• Add the ability for end users to
• Add attractions
• Modify attractions
• Delete attractions
• Filter attractions by category
• Find the attractions closest to a point clicked on the map.
SERVER SIDE EXAMPLE - SETUP

1. Create a new database specific for this application


2. Add the data currently in the GeoJSON data file to the new PostGIS
database
3. Add a category field to the attractions table
4. Populate category field for existing data
5. Modify the map to load the attractions via an AJAX call to the
database rather than from a file.
AJAX – PHP (LOAD_ATTRACTIONS.PHP)

<?php
$db = new PDO("pgsql:host=localhost;port=5432;dbname=webmap101;user=joe;password=12345");
$sql = $db->query("SELECT id, name, image, web, category, ST_AsGeoJSON(geom,5) as geom FROM
cdmx_attractions";
$features=[];
while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {
$feature=[‘type’=>’Feature’];
$feature[‘geometry’]=$json_decode($row[‘geom’]);
unset($row[‘geom’]);
$feature[‘properties’]=$row;
array_push($features, $feature)
}
$featureCollection=[‘type’=>’FeatureCollection’, ‘Features’=>$features];
echo json_encode($featureCollection);
?>
AJAX – HTML AND JAVASCRIPT

var lyrAttractions;
$.ajax({url:'load_attractions.php', success: function(response){
if (lyrAttractions) {mymap.removeLayer(lyrAttractions)};
lyrAttractions=L.geoJSON(JSON.parse(response), {pointToLayer:function(feature,latlng)
{
……..
var strPopup = "<h4>"+feature.properties.name+"</h4><hr>";
strPopup += "<h5>Category: "+feature.properties.category+"</h5>";
strPopup += "<a href='"+feature.properties.web+"' target='blank'>";
strPopup += "<img src='img/"+feature.properties.image+"' width='200px'>";
strPopup += "</a>";
return L.marker(latlng).bindPopup(strPopup);
}}).addTo(mymap);
mymap.fitBounds(lyrAttractions.getBounds());
});
SERVER SIDE EXAMPLE – ADD NEW
ATTRACTION
• HTML
• Modal dialog
• Data entry form
• Save and Cancel buttons.

• CSS
• Styling, positioning, and making visible the data entry form.
• Bootstrap classes for the buttons and form controls.

• JavaScript
• Event handlers to respond to map click
• Event handler to respond button clicks
• Save button will send an AJAX request to the server and process the result.
• Cancel Button will simply close the dialog.
SERVER SIDE EXAMPLE – ADD NEW
ATTRACTION
• PHP
• Receive the ajax requests
• Process into SQL query
• Submit to database
• Process results
SERVER SIDE EXAMPLE – HTML

<div id="dlgAttraction" class="modal">


<div class="modal-content col-md-7 col-md-offset-4">
FORM INPUT CONTROLS………
<button id="btnSave" class="btn btn-
success">Save</button>
<button id="btnCancel" class="btn btn-
danger">Cancel</button>
</div>
</div>
SERVER SIDE EXAMPLE – CSS

.modal { .modal-content {
display: none; padding: 20px;
z-index: 1000; background-
width: 100%; color:tan;
height: 100%; margin-top: 10%;
background-color: }
rgba(0,0,0,0.4);
}
SERVER SIDE EXAMPLE – JAVASCRIPT

mymap.on('click', function(e){ $("#btnSave").click(function(){


$("#dlgAttraction").show(); $.ajax({url:'add_attraction.php',
$("#latitude").val(e.latlng.lat.toFixed(5)); type:'POST',
$ data:{name:$("#name").val(),
("#longitude").val(e.latlng.lng.toFixed(5)); image:$("#image").val(),
web:$("#website").val(),
$("#idDisplay").html("New");
category:$("#category").val(),
});
latitude:$("#latitude").val(),
longitude:$
$("#btnCancel").click(function(){
("#longitude").val() },
$("#dlgAttraction").hide(); success:function(response){
}); alert(response);
}}); });
SERVER SIDE EXAMPLE – PHP

if (isset($_POST['name'])) {
$name=$_POST['name'];
} else {
$name="NA";
}
………………..
$db = new PDO('pgsql:host=localhost;port=5432;dbname=webmap101;', 'joe', '12345');
$sql = $db->prepare("INSERT INTO cdmx_attractions (name, image, web, category, geom) VALUES
(:nm, :im, :wb, :ct, ST_SetSRID(ST_MakePoint(:lng, :lat), 4326))");
$params = ["nm"=>$name, "im"=>$image, "wb"=>$web, "ct"=>$category, "lng"=>$longitude, "lat"=>$latitude];
if ($sql->execute($params)) {
echo "{$name} succesfully added";
} else {
echo var_dump($sql->errorInfo());
};
SERVER SIDE EXAMPLE

• Modify the Mexico City attraction application we started at the end of


the client side section to
• Store the attractions data in a PostGIS table
• Add the ability for end users to
• Add attractions
• Modify attractions
• Delete attractions
SERVER SIDE EXAMPLE – EDIT/DELETE
ATTRACTION
• HTML
• CSS
• JavaScript
• Add button in popup to open edit dialog and populate form.
• Handle save edits and delete buttons in dialog.
SERVER SIDE EXAMPLE – EDIT/DELETE
ATTRACTION
• PHP
• Receive the ajax requests
• Process into SQL query
• Submit to database
• Process results
• update_attraction.php
• delete_attraction.php
• find_attraction.php
SERVER SIDE EXAMPLE – HTML

<div id="dlgAttraction" class="modal">


<div class="modal-content col-md-7 col-md-offset-4">
FORM INPUT CONTROLS………
<button id="btnSave" class="btn btn-
success">Save</button>
<button id="btnCancel" class="btn btn-
danger">Cancel</button>
</div>
</div>
SERVER SIDE EXAMPLE – CSS

.modal { .modal-content {
display: none; padding: 20px;
z-index: 1000; background-
width: 100%; color:tan;
height: 100%; margin-top: 10%;
background-color: }
rgba(0,0,0,0.4);
}
SERVER SIDE EXAMPLE – JAVASCRIPT

mymap.on('click', function(e){ $("#btnSave").click(function(){


$("#dlgAttraction").show(); $.ajax({url:'add_attraction.php',
$("#latitude").val(e.latlng.lat.toFixed(5)); type:'POST',
$ data:{name:$("#name").val(),
("#longitude").val(e.latlng.lng.toFixed(5)); image:$("#image").val(),
web:$("#website").val(),
$("#idDisplay").html("New");
category:$("#category").val(),
});
latitude:$("#latitude").val(),
longitude:$
$("#btnCancel").click(function(){
("#longitude").val() },
$("#dlgAttraction").hide(); success:function(response){
}); alert(response);
}}); });
SERVER SIDE EXAMPLE – PHP

if (isset($_POST['name'])) {
$name=$_POST['name'];
} else {
$name="NA";
}
………………..
$db = new PDO('pgsql:host=localhost;port=5432;dbname=webmap101;', 'joe', '12345');
$sql = $db->prepare("INSERT INTO cdmx_attractions (name, image, web, category, geom) VALUES
(:nm, :im, :wb, :ct, ST_SetSRID(ST_MakePoint(:lng, :lat), 4326))");
$params = ["nm"=>$name, "im"=>$image, "wb"=>$web, "ct"=>$category, "lng"=>$longitude, "lat"=>$latitude];
if ($sql->execute($params)) {
echo "{$name} succesfully added";
} else {
echo var_dump($sql->errorInfo());
};
SERVER SIDE EXAMPLE

• Modify the Mexico City attraction application we started at the end of


the client side section to
• Store the attractions data in a PostGIS table
• Add the ability for end users to
• Add attractions
• Modify attractions
• Delete attractions
• Filter attractions by category
SERVER SIDE EXAMPLE – FILTER ATTRACTIONS

• HTML
• Add filter drop down

• CSS
• JavaScript
• Handle filter change event
• Modify refreshAttractions function to handle filter.
SERVER SIDE EXAMPLE – FILTER ATTRACTIONS

• PHP
• Modify load_attractions to handle a filter text.
SERVER SIDE EXAMPLE

• Modify the Mexico City attraction application we started at the end of


the client side section to
• Store the attractions data in a PostGIS table
• Add the ability for end users to
• Add attractions
• Modify attractions
• Delete attractions
• Filter attractions by category
• Find the attractions closest to a point clicked on the map.
SERVER SIDE EXAMPLE

• HTML
• “Closest 5” button on add atractions form
• New modal-content dialog to display the results as a table.

• CSS
• JavaScript
• Event handler to respond to button click.
• Ajax call to server
• Insert results into table
SERVER SIDE EXAMPLE

• PHP
• closest_attractions.php
• Receive latitude and longitude
• Query the closest 5 attractions
SERVER SIDE EXAMPLE – HTML

<div id="dlgAttraction" class="modal">


<div id="form" class="modal-content col-md-7 col-md-offset-4">
…………………
<div id=“addTables>
<button id="btnClosest" class="btn btn-warning">Closest 5</button>
………………
</div>
……………………………..
</div>
<div id="table" class="modal-content col-md-7 col-md-offset-4">
<div id="tableData"></div>
<button class="btn btn-danger btnCancel">Close</button>
</div>
</div>
SERVER SIDE EXAMPLE – JAVASCRIPT

$("#btnClosest").click(function(){
mymap.on('click', function(e){
$.ajax({
$("#dlgAttraction").show(); url:'closest_attractions.php',
$("#form").show()l type:'POST',
data:{
$("#table").hide()); latitude:$("#latitude").val(),
…………………… longitude:$("#longitude").val()
},
}); success:function(response){
$("#form").hide();
$("#table").show();
$("#tableData").html(response);}
});
});
SERVER SIDE EXAMPLE – PHP

<?php
……………………..
$db = new PDO('pgsql:host=localhost;port=5432;dbname=webmap101;',
'joe', '12345');
$sql = $db->prepare("SELECT
ST_DistanceSphere(ST_SetSRID(ST_MakePoint( :lng, :lat), 4326), geom)/1000
as dist, name, category, image FROM cdmx_attractions ORDER BY dist
LIMIT 5");
$params = ["lng"=>$longitude, "lat"=>$latitude];
$sql->execute($params);
SERVER SIDE EXAMPLE – PHP

while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {


echo "<tr>";
foreach ($row as $field=>$value) {
if ($field=="image"){
echo "<td><img src='img/{$value}' width='100px'></td>";
} elseif ($field==“dist”) {
echo”<td>”.number_format($value, 3).”</td>”;
} else {
echo "<td>{$value}</td>";
}}
echo "</tr>";
}

You might also like