Skip to content

Programming Guide Events

citadel-eu edited this page Mar 21, 2014 · 26 revisions

Mobile Application Template: ‘Events in the city’

1. Configuring the template

Every template comes with a set of configuration settings. These settings can be found in ‘Config.php’. They hold information about the city that the template is about, the use or not of a database as well as other configuration details that can change the appearance or the functionality of the template. Table 1 presents the available settings for the ‘Events in the city’ template:

Table 1

setting Default value meaning
USE_DATABASE false Indicates weather the template will use data from the database or not.
DATASET_FILE Citadel-POI-common-event-Issy.json The name of the .json file that will be loaded if no database is used.
DATASET_ID 1 The dataset id is created when a dataset is imported in the backend. The template comes with a prepopulated database which includes the same dataset as the default .json file.
SERVERNAME localhost The name of the local web server instance. It should be changed to the IP address in order to be able to access the template from another device of the same network.
DATASET_URL dataset.php The url to the service that retrieves the dataset.
HTDOCS_ROOT The root directory of the web server. There is no standard path for this so it should be changed to match the current root directory.
BASE_DIR Citadel-Events-Template/ This is the root folder of the application. This should not be changed in no backend is used.
CLASSES_DIR php This is the folder containing the php files. This should be not changed if the default folder structure is followed.
MAP_CENTER_LATITUDE 48.8275910 The latitude of the centre of the map. This should be the centre of the city in which the dataset refers to.
MAP_CENTER_LONGITUDE 2.27699460 The longitude of the centre of the map. This should be the centre of the city in which the dataset refers to.
MAP_ZOOM 16 The initial zoom level of the google map.
DB_NAME citadel The name of the database. It should not be changed if the database dump is used to create the database.
DB_USERNAME The username of a user with full rights to the database.
DB_PASSWORD The password of the user.
DB_HOSTNAME 127.0.0.1 The default host name.
DB_PORT 3306 The default port.

2. Structure of the code

The following sections provide a description and code examples of the way the mobile application templates are structured. The focus is on html, javascript and php files as they contain the implementation of the core functionality.

2.1 HTML
The templates follow a Single Page Application (SPA) approach. This choice has been made in conjunction with the use of Jquery mobile for the appearance of the templates. There are three main ‘pages’ in the template, the map, the list and the details page. Each of them is actually a ‘div’ element with the ‘data-role’ attribute set to ‘page’. For example, the markup for the map page looks like this:

<!-- Home Page: Contains the Map -->
<div data-role="page" id="page1" class="page">
    <header data-role="header" data-posistion="fixed" data-id="constantNav" data-fullscreen="true">
        <a href="#info" data-rel="dialog" data-icon="info" data-iconpos="notext" data-theme="b" title="Info">&nbsp;</a>
        <span class="ui-title">Find Events in the city</span>
        <div data-role="navbar" class="navbar">
            <ul>
                <li><a href="#" class="pois-nearme" data-theme="b">Near me</a></li>
                <li><a href="#" class="pois-showall ui-btn-active" data-theme="b">Show all</a></li>
                <li><a href="#page2" class="pois-list" data-theme="b">List</a></li>
            </ul>
        </div><!-- /navbar -->
    </header>

    <div data-role="content" id="map-container">
        <div id="map_canvas" class="map_canvas"></div>
    </div>
</div>       

In the above code, you can also see the ‘header’ element which includes the navigation links. This must be present in every page that we want the navigation bar to be visible.

2.2 Javascript
Much of the functionality provided in the templates is based on javascript libraries and the HTML5 javascript apis. The main actions involving javascript are:

  • Read the POIs from the dataset
    • function ‘getPoisFromDataset’
  • Load the google map
    • function ‘initializeMap’
  • Create Infobubbles for every POI and add them on the map
    • function ‘setInfoWindowPoi’, function ‘addMarkers’
  • Switch between the pages
    • ‘Event Handlers’ section in events-lib.js

Functionality inside JQuery mobile has been also used in order to assist with page switching. The code snippet presented below demonstrates such a case where a handler is added on the ‘click’ event of a button in the navigation bar. It is the ‘List’ button which presents the user with the POIs in a list view.

/* Click handler for the 'list' button */
    $('.pois-list').click(function() {
        $.mobile.changePage("#page2", { transition: "none"});
    });

2.3 PHP
Php is used to support the backend functionalities of the template. Firstly, the configuration file is a php file which is included in the template and holds the values for the various setting of the template. The database communication as well as the exposure of the data through web services is also implemented in php. An object-oriented approach has been followed to represent the data model of the CITADEL common POI format (see Section 3). The database schema is presented in Figure 1:

Figure 1: Database Schema
Figure 1: Database Schema

3. CITADEL common POI format

3.1 Introduction
All the mobile application templates make use of a common data schema in order to ensure interoperability among different cities. The ‘Events in the city’ template uses the CITADEL common POI format which has been derived from the Editor’s draft of the Points of Interest Core of W3C. The schema uses a JSON representation which is described in details in the example below.

3.2 JSON Example
The example presented in this paragraph provides an example of the JSON representation of data used by the templates. Data for the example has been taken by the publicly available dataset of Events in the city of the city of Issy les Moulineaux. The first elements, id, updated, created, lang, author, license, link and updatefrequency, provide the available metadata of the dataset and then an array, poi, with the POIs follows. Every element of this array includes an id, title, description, category, location and a set of attributes. The attributes are inside the attribute array and they contain information that is only available for Events in the city. The ‘tplIdentifier’ values denote these events-specific attributes and will be later used by the templates in order to provide a UI that is specific for Events in the city.

{
  "dataset": {
    "id": " http://www.issy.fr",
    "updated": "20091018T00:00:00-5:00",
    "created": "20040122T09:38:21-5:00",
    "lang": "fr-FR",
    "author": {
      "id": "http://www.issy.fr",
      "value": "Issy les Moulineaux"
    },
    "license": { },
    "link": {
      "href": "http://www.issy.fr",
      "term": "source"
    },
     "updatefrequency":"semester",
    "poi": [
      {
        "id": "citadel_event_issy_1",
        "title": "Je me demande",
        "description": "",
        "category": [
          "théâtre"           
        ],
        "location": {
          "point": {
            "term": "centroid",
            "pos": {
              "srsName": "http://www.opengis.net/def/crs/EPSG/0/4326",
              "posList": "48.8275910 2.27699460"
            }
          },
          "address":{
		       "value":"31, bd Gambetta",
		       "postal":"92130",
		       "city":"Issy-Les-Moulineaux"
		  }
        },
        "attribute": [
          {
            "term": "Tel",
            "type": "tel",
            "text": "01 40 93 44 50",
            "tplIdentifier" : "#Citadel_telephone" 
          },
          {
            "term": "Place",
            "type": "string",
            "text": "Espace Icare",
            "tplIdentifier" : "#Citadel_eventPlace"
          },
          {
            "term": "Transports",
            "type": "string",
            "text": "M12 Mairie d'Issy",
            "tplIdentifier" : "#Citadel_nearTransport"
          },
          {
            "term": "Start date",
            "type": "date",
            "text": "1/10/2012",
            "tplIdentifier" : "#Citadel_eventStart" 
          },          
          {
            "term": "End date",
            "type": "date",
            "text": "6/10/2012",
            "tplIdentifier" : "#Citadel_eventEnd"
          },
          {
            "term": "url",
            "type": "url",
            "text": "http://www.espace-icare.com",
            "tplIdentifier" : "#Citadel_website"
          },
          {
            "term": "Schedule",
            "type": "string",
            "text": "20h30",
            "tplIdentifier" : "" 
          },          
          {
            "term": "Rates",
            "type": "string",
            "text": "entrée libre",
            "tplIdentifier" : "" 
          },          
          {
            "term": "Sort",
            "type": "string",
            "text": "philosophie",
            "tplIdentifier" : "" 
          }             
        ]
      }      
    ]
  }
}

The current schema includes mandatory fields and optional fields that could be used for a more complete presentation of the Event. Optional fields will be blank if not available.

Mandatory fields: Optional fields:
updated updatefrequency
created address postal
lang address city
author id attribute term
link href attribute type
poi title attribute text
poi category
posList
address value

Elements inside the ‘attribute’ array will be different for every category of Events. Moreover, if an Open Data provider possesses other pieces of information for a particular type of data, in this example ‘Events in the city’, these could easily be added as a new element of the ‘attribute’ array. For example, adding the participants’ names to a specific event would require the addition of the following element in the ‘attribute’ array:

"attribute": [
     {
            "term": "Participants",
            "type": "string",
            "text": "John Doe, Mary Leins, Nick Boss",
            "tplIdentifier" : ""
     },
]

The ‘tplIdentifier’ field would remain empty in this case so the participants’ names would be displayed in a list under the rest of the details for an event.

3.3 Using tplIdentifier to customize the user interface of an application
The element ‘tplIdentifier’ has a special meaning for the template, as described in the example of the previous paragraph. This element is a system-defined string that can be used to allow the templates to display attributes with different ‘tplIdentifier’ values in an aesthetically different way. If the attribute cannot be matched to one of the predefined ‘tplIdentifiers’ it will be displayed in a standard “list view” visualization, as seen in Figure 2.

photo
Figure 2: Event Details

The predefined values for ‘tmpIdentifier’ are:

  1. "#Citadel_website"
  2. "#Citadel_email"
  3. "#Citadel_parkType"
  4. "#Citadel_parkFloors"
  5. "#Citadel_parkCapacity"
  6. "#Citadel_telephone"
  7. "#Citadel_image"
  8. "#Citadel_eventEnd"
  9. "#Citadel_eventPlace”
  10. "#Citadel_eventDuration"
  11. "#Citadel_openHours"
  12. "#Citadel_nearTransport"

The template recognizes and picks up the fields marked with a valid ‘tplIdentifier’. These can be displayed in predefined positions in the template’s interface, e.g. the place of the event could be displayed in the upper right corner in red color. Depending on their type, they can also be rendered as telephone, email or website links. Terms that have not been matched with any of the available ‘tplIdentifiers’ would be just displayed as a simple list like ‘term1’ and ‘term2’ in Figure 1. The predefined list of ‘tplIdentifiers’ will be populated with fields coming from the original dataset provided by the pilot cities. An implementation of the above scenario is followed in the ‘Events in the city’ template. The setDetailPagePoi function searches for the events-specific ‘tplIdentifier’ values ‘#Citadel_eventStart’, ‘#Citadel_eventEnd’ and ‘#Citadel_eventPlace’ in order to display them on top of the details page of an Event. The code of the function that searches for them and initializes the contentTemplate variable follows:

function setDetailPagePoi(poi)
{
    /* Get the Event specific attributes of the POI */
    var eventStart = getCitadel_attr(poi, "#Citadel_eventStart").text;
    var eventEnd = getCitadel_attr(poi, "#Citadel_eventEnd").text;
    var eventPlace = getCitadel_attr(poi, "#Citadel_eventPlace").text;
    var contentTemplate =
        "<h1>" + poi.title + "</h1>" +
        "<div class='event-data'>" +
        "<ul>";

If the attributes are found we also want to display a relevant icon before their values:

if (eventStart)
        contentTemplate += "<li><span>" + getCitadel_attr(poi, "#Citadel_eventStart").term + "</span>" 
+ eventStart + "</li>";
if (eventEnd)
        contentTemplate += "<li><span>" + getCitadel_attr(poi, "#Citadel_eventEnd").term + "</span>"
 + eventEnd + "</li>";
if (eventPlace)
        contentTemplate += "<li><span>" + getCitadel_attr(poi, "#Citadel_eventPlace").term + "</span>"
 + eventPlace + "</li>";

When we are done with these checks, we display all the rest attributes by taking their name (‘term’) and value (‘text’). We finally close the list of attributes and return the result to the main function.

for (i = 0; i < otherAttributes.length; i++) {
        contentTemplate += "<li><span>" + otherAttributes[i].term + "</span>" + otherAttributes[i].text + "</li>";
    }
    contentTemplate += "</ul>" +
        "</div>";
    return contentTemplate;
} 

Changing the contents and markup of the ‘contentTemplate’ variable can result in different ways of visualisation that suit the application developer’s needs. Another example of easy layout customization is the content of the infobubbles. Infobubbles popup when a marker on the map is clicked. They may contain any information that is available about the selected POI. The function that contains the template for the infobubbles in the ‘Events in the city’ template is ‘setInfoWindowPoi’. As presented in the following code snippet, the chosen details for the infobubble are the title and the category of the Event.

/* Sets the content of the infoBubble for the given 
 * event
 */
function setInfoWindowPoi(poi)
{
    var category = "";

    /* Get the Event specific attributes of the POI */
    if (poi.category.length > 0) {
        category = "<div class='category'>" +
            poi.category.join(', ') +
            "</div>";
    }

    var contentTemplate =
        "<div id='eventBubble'><a href='#page3' onclick='overrideDetailClick(\"" + poi.id 
+ "\"); return false;'>" +
        "<div class='title'>" +
        poi.title +
        "</div>" +
        "<div class='address'>" + poi.location.address.value +
        "</div>\n" + category +
        "</a></div><div id='bubbleClose'><a href='' onclick='return overrideBubbleCloseClick();'><img src='images/close.png' width='25' height='25' alt='close' /></a></div>";

    return contentTemplate;
}

If the start date of the event is what we want to show in the infobubble instead of the category, the code would have to change to (changes with bold font):

/* Sets the content of the infoBubble for the given 
 * event
 */
function setInfoWindowPoi(poi)
{
    var startdate = "";

    /* Get the Event specific attributes of the POI */
    if (getCitadel_attr(poi, "#Citadel_eventStart").term != '') {
        startdate = "<div class='startdate'>" +
            getCitadel_attr(poi, "#Citadel_eventStart").term +
            ":" + getCitadel_attr(poi, "#Citadel_eventStart").text +
            "</div>";
    }

    var contentTemplate =
        "<div id='eventBubble'><a href='#page3' onclick='overrideDetailClick(\"" + poi.id 
+ "\"); return false;'>" +
        "<div class='title'>" +
        poi.title +
        "</div>" +
        "<div class='address'>" + poi.location.address.value +
        "</div>\n" + startdate +
        "</a></div><div id='bubbleClose'><a href='' onclick='return overrideBubbleCloseClick();'><img src='images/close.png' width='25' height='25' alt='close' /></a></div>";

    return contentTemplate;
}

As seen in the example, what is required to change is mainly the ‘tplIdentifier’ value. The name of the variable and the css class could remain the same but changing them improves readability of the code. Of course changing the css class also means that the appearance in the page will also change.

4. Translation mechanism

The templates follow a simple mechanism to translate the user interface elements. A translation file named ‘translations.xx-XX.php’ contains a list of php variables that correspond to all the translatable strings of the user interface. The ‘xx-XX’ part of the filename must be replaced by the relevant language code and locale, e.g. en-GB for English (Great Britain) or fr-FR for French. The ‘lang’ setting must be set accordingly when changing languages. The template will try to load the translation file with the given locale and will fall back to the default English version if the file is not found. A part of the English translation file for the ‘Events in the city’ template follows:

File: translations.en-GB.php
…
$near_me = 'Near me';
$show_all = 'Show all';
$info = 'Info';
$details_title = 'Details Page';
…
…

The translation file should be in UTF-8 encoding