Web Developer Training

The following material provides examples and advice for making use of iShare throughout an organisation's website. This type of development generally involves a developer from the web team working with a member of the GIS team. The developer is there to build the tools that make use of the spatial data prepared by the GIS team. The material assumes a competent knowledge of iShare, spatial data and web skills.

Data Considerations

These considerations are the domain of the GIS team. They'll have to decide how spatial data fits the requirements of the project. Typically consideration must be made to the following;

  1. A .map layer definition must exist for the dataset. The .map file must be associated with a mapsource. Layer names in .map files should be alphanumeric, no spaces, don't start with a number.
  2. The styling is best handled through MapServer styling within the Layer definition. 
    1. The .map must be WMS compliant. See the following for detail on what is required: https://astuntech.atlassian.net/wiki/display/ISHAREHELP/Configure+MapServer+to+be+a+WMS+or+WFS+Server You can also use static legend graphics for a layer. Those are configured through Studio in the mapsource layer's screen.
    2. Styling may require zoom level controlled styling using additional CLASS items using MINSCALEDENOM/MAXSCALEDENOM. 
  3. Attribute information must exist suitable for the task. Provide correct labels for data.
  4. Any URLs held as attributes can be wrapped around other fields such as school name.
  5. Any serious custom attribution is best handled by storing html as an attribute and making it available through the _raw suffix (select *, html as html_raw from mytable) - see Workshop > MyHouse > Elected Members > County Councillors
  6. Purely for MyHouse & MyNearest mapsources: If we want to run find nearest options against the data that must be selected, choose range and result number in the mapsource layer screen
  7. Again, just for MyHouse and MyNearest: if we want to do a point-in-polygon operation against the data select Show My instead in the mapsource layer screen
  8. If we want the layer to be searchable select the field to search in the Mapsource layer screen. You may wish to concatenate fields by select *, (field1 || ' ' || field2) as searchField from mytable. This typically used for the search panel in MyMaps and Solo Maps.
  9. If existing mapsources do not fit the requirements of the project then sometimes it is easier to copy a mapsource, hide it from view and manipulate the data so it is suitable for the project's requirements. It might well be that a mapsource is only used for a particular project and no more. For example Lite maps always use the default base map. If that is not suitable copy the mapsource and choose a different default base map.

Web Developer Exercises

In this series of exercises we will look at what is available to the web developer in an iShare installation. We will focus on the use of Lite and Solo maps and useful web services by which the developer can search addresses and find local information.

Resources

  1. A web development tool set such as Firebug for Firefox.
  2. The iShare My Council page: My House, My Nearest and My Maps.
  3. Solo and Lite maps for embedded, configurable slippy maps.
  4. Mapsource information. Examine the use of getData.aspx in a My Council page. These requests return information on what layers are held in which mapsources.
  5. Localised information through the GetData web service and Local Info Data request.
  6. Address searching through the GetData web service and the Address Search request.
  7. Static map images. These can generated by calling MapGetImage.aspx.
  8. Astun's online help - found here.

Lite Map

The Lite Map is a simple OpenLayers slippy map that can be embedded within a page. It can be configured to show a set of layers from a mapsource within a particular starting location if required. Further manipulation can be achieve using javascript.

Various templates for the lite map exist in the ishare.web folder. For this exercise take the atLiteMap.html and copy & rename to schools_lite_map.html.

Test this page in a browser to make sure that it works before we apply any configuration changes. Point your browser to http://127.0.0.1/ishare.web/schools_lite_map.html (assuming we are working on the local machine with the ishare application named as ishare.web)

Mapsource and single layer

Now open the file in a text editor and identify the options available: mapsource, layers and starting position. See How to create your iShare Lite Map - from v5.4.0

Assuming the use of the Astun workshop data find the liteMap.createMap line contains the following;

liteMap.createMap('atMap', { mapSource: 'Astun/Default', layers: 'primary_schools' });

We are using a single layer from the Astun/Default mapsource. The layer name is the name of the layer in the .map file. This is different from the layer's display name. It is generally lower case and contains no spaces.

Save and reload. The page should now show a map of primary schools in Surrey. The map centre is defined in the mapsource though we could override this if required.

Multiple layers

Now modify the line to include secondary schools;

liteMap.createMap('atMap', { mapSource: 'Astun/Default', layers: 'primary_schools,secondary_schools' });

Save and reload. The order by which these layers are displayed is controlled by the order of the layers in the .map file. To identify other available layers inspect the GetData.aspx request where ms=Astun/Default and service=mapsource.

Adjusting the height and width

Make the following alteration to increase the map width leaving an edge suitable for phone and tablet use;

<div id="atMap" style="border: 1px solid #CCC; height: 512px; width: 90%; margin: auto !important">

iShare 5.4.4 provides a responsive design front-end which is generally developed by Astun staff. This will automatically adjust the number of columns in My House according the screen width of the browser.

In any case style rules can be used to accommodate changes in screen width such as;

@media only screen and (min-width:480px) and (max-width:800px) and (orientation:portrait) { 
    div.olMap#atMap {
        width: 80% !important;
    }
}

The above CSS rule will be applied when the screen width is between 480 and 800 pixels in portrait mode. You may have a different set of rules for landscape orientation.

Styling

Common styling adjustments to a Lite map would be the content of the pop up windows when an info click is made on the map. Click on a school on the map and then right-click on the pop up's title and select Inspect Element with Firebug. 

You can change the colour of the header's background creating an additional css file and referencing it in the page's head section;

<link rel="stylesheet" type="text/css" href="custom/css/workshop.css" />

create a new file and save it as workshop.css in the custom/css/ folder under your iShare web directory. Add the following rules.

#atMap .atPopupFeatureInfo h3 { background-color: #000060 !important;}

Lets change the font and line spacing of the text by adding this rule to the css file;

#atMap .atPopupFeatureInfo p { line-height: 1.5em !important; font-family: "Tahoma";}

Lite Map with Feature List

In this exercise we are going to create a lite map with a list of features down the side. When a user hovers on a feature an arrow on the map will mark the feature's location. Clicking on the feature in the list will recentre the map to the selected feature.

Copy the atLiteMap-callout.html page and rename it schools_lite_map_list.html

Change the mapsource and layer as above using solely the primary schools layer. Check for references to both mapsource and layers in the pageLoad function and the lite map definition towards the end of the file.

Save and reload. No list appears but the map should display the primary schools.

Our primary schools data has a name field. This needs to be used in the definition of the linkInfo variable;

linkInfo = typeof ($this.properties.fields.name) !== "undefined" ? $this.properties.fields.name : '',

The request we are making carries a spatial filter in the form of a polygon definition. This can be removed if a complete list of schools is required; 

jQuery.getJSON(url,
{
	MapSource: mapSource,
	Layers: layers
},

Save and reload. The list of schools should now appear on the page. Click a school to recentre and hover to see a marker appear.

Feature List with URLs

We may wish to make use of a feature's URL by replacing the map recentre function with the a new tab window showing the school's website. The attribute for our data set is website_address. Change the hrefLink assignment to be

hrefLink = $this.properties.fields.website_address;

And change the .click function to read

window.open(hrefLink, '_blank');
return false;

Map Interaction

Further interaction can be made of a Lite map by the use of javascript. For example: finding features on a map, setting scale and adding and removing layers. All of which can be found here

Solo Map

Solo maps provide ready built functionality identical to the My Maps tab in an iShare My Council page. They offer the same configuration as a Lite map i.e. mapsource, layers and starting position. Additionally one can alter the panels. In this exercise we are simply going to alter the name of the address panel and remove the Find My Nearest panel.

Take the atSoloMap.html page. Copy / rename to schools_solo_map.html.

Edit the mapsource and layer name as we did for the Lite map.

Change the Feature Search Panel title to 'Feature Search' and remove the TakeMeTo panel;

soloMap.addFindNearestPanel();
soloMap.addSearchForPanel({ 'title': 'Feature Search' });
soloMap.addSearchPanel({ 'title': 'Address Search' });
soloMap.addShowmapCategoriesPanel({ collapseInStart: false });
//soloMap.addTakeMeToPanel();

Save and reload.

For the web developer new to iShare the Solo map offers a good opportunity to observe the underlying data requests in an iShare application. With Firebug's Net tab enabled we can observe the requests being made to iShare and the responses returned.

  1. Find Nearest - this will return the nearest features to a given location. It will use the map centre if no address search has been made. A request to MapGetImage.aspx is made using these key parameters: activeTool: MultiInfo, ServiceAction: findMyNearest
  2. Address Search - this will return a set of matching addresses based upon user input. Selecting an address will recentre the map. No location cookie is stored. However a location cookie is stored by the My House address search mechanism. The request is made to GetData.aspx using service: LocationSearch
  3. Search for - this will search datasets against a chosen attribute. Results are displayed in a results element below the Solo map. Requests are made to MapGetImage.aspx using activeTool: MultiInfo, service: SearchLayer
  4. Map Categories - changing a layer's visibility will generate a request for a new map image. This is sent to MapGetImage.aspx with a series of parameters that define the height, width and location of the map image.
  5. Clicking on the map will request an info click. This is sent to MapGetImage.aspx with the following key parameters: activeTool: MultiInfo, ServiceAction: GetMultiInfoFromPoint

Address Search

In this example we are going to explore the sample page 'address.html'. This file is not part of a standard installation (as of 5.4.10) but is attached to this document. Download the file and place in in the ishare web application along with the other files we have been working with. Edit the resource links at the top of the file so that they can be found correctly.

Download address.html

This page provides emulates some typical iShare functionality in a client's website. Any user of the iShare Maps My Council page who provides an address has a location cookie recorded. This can be retrieved and used to identify spatial information relevant to that user's location.

The address.html file runs through the following steps;

  1. The page displays the address found in the location cookie if present
  2. The user can enter an address and results are shown
  3. Selecting an address from the results will
    1. store a new location cookie
    2. do a localInfo request. In this case it simply detects which ward the location is within

The web developer is encouraged to look at the following key areas;

  1. the check for the location cookie is at line 55
  2. the location cookie contains: address, uprn, easting and northing
  3. the performSearch function contains the getData.aspx request for address searching
  4. each address result carries a call to the findLocalInfo function passing the location cookie contents
  5. the findLocalInfo function performs a localInfo request (getData.aspx) against the wards layer with a given location

A standalone address search mechanism is typically used on a local authority's main page. Selecting an address will typically take the user to the My Council page with the My House tab shown.

Cookie detection is commonly used on a departmental page designed for a particular purpose - such as the list of recycling centres in the neighbourhood. If a location cookie is detected the page can make a request to iShare to list all nearby facilities for the given location and present them in a suitable manner as well as a map if need be.

Lite Map with Cookie Detection

Take the atLiteMap.html page and copy / rename to cookie_lite_map.html

Change mapsource to Astun/Default and layers to primary_schools as we did earlier.

Include the jquery library by adding the following line to the head section of the page;

<script type="text/javascript" src="js/lib/jquery/jquery-1.6.4.js"></script>

Then replace the lite map line with the following code;

jQuery.noConflict();
jQuery(document).ready(function() {
	var atLocation = readCookie("atLocation");
	if (atLocation !== null && atLocation !== "") { 
		var location = atLocation.split("&"); 
		var x=location[2].split("=")[1];
		var y=location[3].split("=")[1];
		liteMap.createMap('atMap', { 
			mapSource: 'Astun/Default', 
			layers: 'primary_schools',
			view: {easting:x, northing:y, zoom:2000}
		});
	} 
});
function readCookie(name) { 
	var ca = document.cookie.split(';'); 
	var nameEQ = name + "="; 
	for (var i = 0; i < ca.length; i++) { 
		var c = ca[i]; 
		c = unescape(c); //this clears the URL encoding that seems to be applied to the cookie. 
		while (c.charAt(0) == ' ') { c = c.substring(1, c.length); } 
		if (c.indexOf(nameEQ) === 0) { return c.substring(nameEQ.length, c.length); } 
	} 
	return null; 
}

Save and reload. If a location cookie is present the map will recentre before loading.

Lite Map with Cookie Detection and Local Features

In this example we are going to make use of the atLiteMap-callout.html example by modifying it to include a location cookie detection followed by a localInfo getData request to bring back nearby features. In this case the whole page has been placed below for ease of reference. The jQuery getJSON ajax method is used to request and process the features. Note that the mapsource has been changed. In this example we are using a My Nearest mapsource which has been configured to return X number of results within a set distance. We could also use a normal My Maps mapsource and a request to MapGetImage.aspx using these key parameters: activeTool: MultiInfo, ServiceAction: findMyNearest. The iShare administrator will be expected to provide the web developer with this additional knowledge.

<!DOCTYPE html>
<html>
	<head>
		<title>iShare - Lite</title>
		
		<link rel="stylesheet" type="text/css" href="custom.example/css/iShareCommon.css" />
		<link rel="stylesheet" type="text/css" href="custom.example/css/Map.css" />
		<script type="text/javascript" src="js/lib/prototype-1.6.0.3.js"></script>
		<script type="text/javascript" src="FileIncluderJS.aspx"></script>
		<script type="text/javascript" src="js/litemap.js"></script>
		<script type="text/javascript" src="js/lib/jquery/jquery-1.6.4.js"></script>
		<script type="text/javascript">	
			jQuery.noConflict();
			
			jQuery(document).ready(function() {
				var atLocation = readCookie("atLocation"); //read the contents of the astun cookie (note that the domain must be the same) 
				if (atLocation !== null && atLocation !== "") { 
					var location = atLocation.split("&"); 
					var x=location[2].split("=")[1];
					var y=location[3].split("=")[1];
					liteMap.createMap('atMap', { 
						mapSource: 'Astun/Default', 
						layers: 'primary_schools',
						view: {easting:x, northing:y, zoom:2000}
					});
					findLocalInfo(atLocation);
				} 
			});
			
			function readCookie(name) { //this little script is just to help read stuff from the cookie 
				var ca = document.cookie.split(';'); 
				var nameEQ = name + "="; 
				for (var i = 0; i < ca.length; i++) { 
					var c = ca[i]; 
					c = unescape(c); //this clears the URL encoding that seems to be applied to the cookie. 
					while (c.charAt(0) == ' ') { c = c.substring(1, c.length); } 
					if (c.indexOf(nameEQ) === 0) { return c.substring(nameEQ.length, c.length); } 
				} 
				return null; 
			};
			function findLocalInfo(atLocationCookie) {
				var output = "";
				var mapsource = "Astun/MyNearest";
				group = "Education%20and%20Learning";
				layer = "Primary%20Schools%20Nearby";
				var arrLocationCookie = atLocationCookie.split("&");
				var uid = arrLocationCookie[1].split("=")[1];
				var url = "http://127.0.0.1/ishare.web/getdata.aspx?" + 
					"RequestType=LocalInfo&ms=" + mapsource + 
					"&format=JSONP&group=" + group + "|" + layer + "&uid=" + uid;
				jQuery.ajax({
					dataType: 'jsonp',
					url: url,
					success: function(res) {
						output += "<ul>";
						for (i = 0; i < res.Results.Primary_Schools_Nearby.length; i++) {
							var school_name = "";
							if ( res.Results.Primary_Schools_Nearby[i]._.indexOf("|") != -1) {
								school_name = res.Results.Primary_Schools_Nearby[i]._.split("|")[1];
							} else {
								school_name = res.Results.Primary_Schools_Nearby[i]._;
							}
							output += "<li>" + school_name + ": " + res.Results.Primary_Schools_Nearby[i].Distance + "m</li>";
						}
						output += "</ul>";
						jQuery("#localInfoOutput").append(output);
					}
				});
			}
		</script>	
	</head>
	<body>
		<!-- #atMap -->
		<div id="atMap" style="border: 1px solid #CCC; height: 512px; width: 512px">
			<div id="atInitialLoader" style="border: 1px solid #CCC; padding: 5px; margin: 125px auto auto; text-align: center; width: 75px; font-family: Helvetica; -moz-border-radius: 5px; -webkit-border-radius: 5px;">Loading...</div>
		</div>
		
		<a id="atPoweredBy" title="Powered by Astun Technology" href="http://www.astuntechnology.com">
			<img src="images/astun/poweredbyishare-online.png" height="18" width="175" style="border: 0" alt="Powered by Astun"/>
		</a>
		<div id="localInfoOutput"></div>
	</body>
</html>

Linking to My Maps

As well as the methods described above there are a number of methods that can be applied to My Maps. See here.

1st example: atMyCouncil.aspx?action=SetAddress&UniqueId=<uprn>

2nd example: atMyCouncil.aspx?mapsource=Astun/Default&layers=primary_schools will take the user to the My Maps tab on the My Council with the primary schools layer shown. Any other layers that were visible during the user's previous visit will also be shown. This does enable the web developer to make use of My Maps without creating an embedded map when a simple link will suffice.

This page also covers linking to My Maps using UPRNs, address searches and controlling which tab to display.