diff --git a/ipmd/static/ipmd/js/ipmdlib.js b/ipmd/static/ipmd/js/ipmdlib.js
index c270c2750307b30b8c213db2b4454d5d16eb068d..8536862f8aa882cccc31b4f6b3a0c4a79ef163ff 100644
--- a/ipmd/static/ipmd/js/ipmdlib.js
+++ b/ipmd/static/ipmd/js/ipmdlib.js
@@ -18,16 +18,26 @@
  */
 
 /**
+ * Utilities and methods for using the IPM Decisions DSS and Weather APIs
+ * 
  * Dependencies:
  * momentJS
- * turf v6
+ * turf 6
+ * OpenLayers 4
  */
 
+// TODO Refactor these to be set by the user of this library
 const ipmdDSSApiURL = "https://platform.ipmdecisions.net/api/dss/";
 //const ipmdWeatherApiURL = "https://platform.ipmdecisions.net/api/wx/";
 const ipmdWeatherApiURL = "http://ipmdlocal/api/wx/";
 
 
+/**
+ * 
+ * @param {String} dssId The id of the DSS
+ * @param {String} modelId The id of the DSS model
+ * @returns {Json} metadata for the requested DSS model
+ */
 async function getModelMetadata(dssId,modelId) {
     const response = await fetch(ipmdDSSApiURL + "rest/dss/" + dssId);
     const dss = await response.json();
@@ -42,22 +52,33 @@ async function getModelMetadata(dssId,modelId) {
     return null;
 }
 
+/**
+ * 
+ * @param {String} dssId The id of the DSS
+ * @param {String} modelId The id of the DSS model
+ * @returns the UI form components of the Json schema for input data for the requested model. Hidden fields are excluded.
+ */
 async function getModelInputSchema(dssId,modelId) {
     const response = await fetch(ipmdDSSApiURL + "rest/model/" + dssId + "/" + modelId + "/input_schema/ui_form");
     return await response.json();
 }
 
-/*async function getWeatherDatasource(weatherDatasourceId)
-{
-    const response = await fetch(ipmdWeatherApiURL + "rest/weatherdatasource/" + weatherDatasourceId);
-    return await response.json();
-}*/
-
+/**
+ * 
+ * @param {Json} weatherDatasource 
+ * @returns The web service endpoint for the weather data source
+ */
 function getWeatherDatasourceEndpoint(weatherDatasource)
 {
     return weatherDatasource.endpoint.replace("{WEATHER_API_URL}",ipmdWeatherApiURL);
 }
 
+/**
+ * 
+ * @param {Json} weatherDatasources The list of weather data sources
+ * @param {String} weatherDatasourceId the id of the requested weather data source
+ * @returns {Json} Metadata for the requested weather datasource
+ */
 function getWeatherDatasource(weatherDatasources, weatherDatasourceId)
 {
     for(let i=0;i<weatherDatasources.length;i++)
@@ -70,12 +91,21 @@ function getWeatherDatasource(weatherDatasources, weatherDatasourceId)
     return null;
 }
 
+/**
+ * 
+ * @returns {Json} list of all available weather datasources
+ */
 async function getWeatherDatasources()
 {
     const response = await fetch(ipmdWeatherApiURL + "rest/weatherdatasource/");
     return await response.json();
 }
 
+/**
+ * 
+ * @param {String} weatherDatasource 
+ * @returns {Array} Weather stations listed as part of this weather data source. Example list item: {"id":"5", "name":"Merrapanna"}
+ */
 function getWeatherStationList(weatherDatasource){
     geoJson = JSON.parse(weatherDatasource.spatial.geoJSON);
     let stationList = [];
@@ -91,6 +121,11 @@ function getWeatherStationList(weatherDatasource){
     return stationList;
 }
 
+/**
+ * List all weather stations in list in the provided HTML Form select list
+ * @param {Array} stationList 
+ * @param {HTMLElement} selectList 
+ */
 function renderWeatherStationSelectList(stationList, selectList){
     selectList.options.length = 0;
     selectList.add(new Option("-- Please select weather station --", -1));
@@ -100,6 +135,16 @@ function renderWeatherStationSelectList(stationList, selectList){
     }
 }
 
+/**
+ * 
+ * @param {String} endpoint URL to web service endpoint
+ * @param {String} weatherStationId Id of the weather station
+ * @param {Array} parameters List of weather parameters (IPM Decisions codes)
+ * @param {Int} interval log interval for the weather data, provided in seconds. E.g. 3600 = hourly, 86400 = daily
+ * @param {String} dateStart (YYYY-MM-DD)
+ * @param {String} dateEnd (YYYY-MM-DD)
+ * @returns weather data from a station based weather data source
+ */
 async function getStationWeatherData(endpoint, weatherStationId, parameters, interval, dateStart, dateEnd){
     const response = await fetch(endpoint 
         + "?timeStart="        + dateStart
@@ -111,6 +156,17 @@ async function getStationWeatherData(endpoint, weatherStationId, parameters, int
     return await response.json();
 }
 
+/**
+ * 
+ * @param {String} endpoint URL to web service endpoint
+ * @param {Float} longitude Decimal degrees (WGS84) for the location
+ * @param {Float} latitude Decimal degrees (WGS84) for the location
+ * @param {Array} parameters List of weather parameters (IPM Decisions codes)
+ * @param {Int} interval log interval for the weather data, provided in seconds. E.g. 3600 = hourly, 86400 = daily
+ * @param {String} dateStart (YYYY-MM-DD)
+ * @param {String} dateEnd (YYYY-MM-DD)
+ * @returns weather data from a location based weather data source
+ */
 async function getLocationWeatherData(endpoint, longitude, latitude, parameters, interval, dateStart, dateEnd){
     const response = await fetch(endpoint 
         + "?timeStart="        + dateStart
@@ -123,6 +179,12 @@ async function getLocationWeatherData(endpoint, longitude, latitude, parameters,
     return await response.json();
 }
 
+/**
+ * Run and get results back from a DSS model
+ * @param {String} endpoint The web service endpont for that DSS model
+ * @param {Json} inputData as defined by the Json schema in the DSS model metadata property input_data
+ * @returns {Json} model results in IPM Decisions format
+ */
 async function runModel(endpoint, inputData)
 {
     const response = await fetch(endpoint, {
@@ -137,6 +199,13 @@ async function runModel(endpoint, inputData)
     return await response.json();
 }
 
+/**
+ * Util model for getting an array of consecutive dates
+ * @param {Integer} timestart UNIX epoch seconds
+ * @param {Integer} interval log interval in seconds. E.g. 3600 = hourly, 86400 = daily
+ * @param {Integer} length How many dates you want in the array
+ * @returns 
+ */
 function getDateArray(timestart, interval, length)
 {
     let dateArray = [];
@@ -149,6 +218,11 @@ function getDateArray(timestart, interval, length)
     return dateArray;
 }
 
+/**
+ * 
+ * @param {Integer} weatherParameterId the parameter di
+ * @returns {Json} parameter metadata (name, description, unit, aggregation type (MIN/MAX/AVG))
+ */
 function getWeatherParameter(weatherParameterId){
     for(let i=0;i<weatherParameterList.length;i++)
     {
@@ -160,6 +234,12 @@ function getWeatherParameter(weatherParameterId){
     return null;
 }
 
+/**
+ * 
+ * @param {Json} weatherDatasource Metadata for the weather datasource
+ * @param {String} weatherStationId the requested weather station
+ * @returns {Array} coordinate (Decimal degrees/WGS84) of the weather station. 
+ */
 function getWeatherStationCoordinate(weatherDatasource, weatherStationId)
 {
     geoJson = JSON.parse(weatherDatasource.spatial.geoJSON);
@@ -177,6 +257,20 @@ function getWeatherStationCoordinate(weatherDatasource, weatherStationId)
     return null;
 }
 
+/**
+ * Models may require weather parameters that the requested weather datasource
+ * can't provide. The difference between a requested parameter and available parameter
+ * may be insignificant. For instance, a model may require average temperature for an hour,
+ * and the data source may provide instantaneous temperature for that hour. 
+ * 
+ * This methods figures out which parameters are considered fallback parameters for each other,
+ * and returns the intersection of the requested parameters (including fallbacks) and the available 
+ * parameters
+ * 
+ * @param {Array} requestedParameters the parameters that the model requires
+ * @param {Array} availableParameters the parameters that the weather datasource provides
+ * @returns 
+ */
 function getPragmaticWeatherParameterList(requestedParameters, availableParameters)
 {
     let completeList = [];
@@ -184,13 +278,15 @@ function getPragmaticWeatherParameterList(requestedParameters, availableParamete
     {
         completeList = completeList.concat(requestedParameters[i], fallbackParams[requestedParameters[i]]);
     }
-    //console.info(completeList);
-    //console.info(availableParameters);
-
     return completeList.filter(param => availableParameters.includes(param));
-
 }
 
+/**
+ * 
+ * @param {Array} coordinate [longitude,latitude] decimal degrees (WGS84)
+ * @param {Json} datasource metadata
+ * @returns 
+ */
 async function isPointCoveredByDatasource(coordinate, datasource)
 {
     // If the geoJson is {"type":"Sphere"}, return true
@@ -212,32 +308,31 @@ async function isPointCoveredByDatasource(coordinate, datasource)
 }
 
 /**
-     * Displays the weather data in a table
-     * @param {Object} weatherData the weatherData in IPM Decisions format
-     * @param {HTMLElement} container the element to render to
-     * @param {String} tableClass for styling the table, e.g. using Bootstrap
-     */ 
-    function renderWeatherData(weatherData, container, tableClass){
-        let dates = getDateArray(weatherData.timeStart, weatherData.interval, weatherData.locationWeatherData[0].length);
-        let html = "<table" + (tableClass != undefined ? " class=\"" + tableClass + "\"" : "") + "><thead><tr><th>Time</th>";
-        weatherData.weatherParameters.forEach(function(weatherParameterId){
-                        html +="<th>" + getWeatherParameter(weatherParameterId).name + "</th>";
-                    });
-        
-        html += "</tr></thead>"
-        html += "<tbody>";
-            //console.info("Weatherdata length: " + weatherData.locationWeatherData[0].data.length);
-        for(let i=0;i< weatherData.locationWeatherData[0].data.length;i++)
-        {
-            html += "<tr><td>" + moment(dates[i]).format("YYYY-MM-DD HH:mm:ss") + "</td>";
-                weatherData.locationWeatherData[0].data[i].forEach(function(val){html+="<td>" + val + "</td>";})
-            html += "</tr>";
-        }
-        html += "</tbody>";
-        html += "</table>";
-        container.innerHTML = html;
-
+ * Displays the weather data in a table
+ * @param {Object} weatherData the weatherData in IPM Decisions format
+ * @param {HTMLElement} container the element to render to
+ * @param {String} tableClass for styling the table, e.g. using Bootstrap
+ */ 
+function renderWeatherData(weatherData, container, tableClass){
+    let dates = getDateArray(weatherData.timeStart, weatherData.interval, weatherData.locationWeatherData[0].length);
+    let html = "<table" + (tableClass != undefined ? " class=\"" + tableClass + "\"" : "") + "><thead><tr><th>Time</th>";
+    weatherData.weatherParameters.forEach(function(weatherParameterId){
+                    html +="<th>" + getWeatherParameter(weatherParameterId).name + "</th>";
+                });
+    
+    html += "</tr></thead>"
+    html += "<tbody>";
+    for(let i=0;i< weatherData.locationWeatherData[0].data.length;i++)
+    {
+        html += "<tr><td>" + moment(dates[i]).format("YYYY-MM-DD HH:mm:ss") + "</td>";
+            weatherData.locationWeatherData[0].data[i].forEach(function(val){html+="<td>" + val + "</td>";})
+        html += "</tr>";
     }
+    html += "</tbody>";
+    html += "</table>";
+    container.innerHTML = html;
+
+}
 
 /**
  * Merges the two datasets. Keeping the primaryData if both sets have data for same time and parameter
@@ -273,32 +368,6 @@ function mergeWeatherData(primaryData, secondaryData)
             {
                 mergedParams.push(primaryData.weatherParameters[j]);
             };
-            /*
-            // Check for additional parameters in secondaryData <--- DON'T DO THIS
-            // Fallback parameters are not considered additional
-            for(let j=0;j<secondaryData.weatherParameters.length; j++)
-            {
-                let element = secondaryData.weatherParameters[j];
-                if(!mergedParams.includes(element))
-                {
-                    let isNewForSure = true;
-                    let fallbacks = fallbackParams[element];
-                    if(fallbacks != undefined)
-                    {
-                        for(let i=0; i<fallbacks.length; i++)
-                        {
-                            if(mergedParams.includes(fallbacks[i]))
-                            {
-                                isNewForSure = false;
-                            }
-                        }
-                    }
-                    if(isNewForSure)
-                    {
-                        mergedParams.push(element);
-                    }
-                }
-            }*/
             return mergedParams;
         }(),
         locationWeatherData: [
@@ -312,7 +381,6 @@ function mergeWeatherData(primaryData, secondaryData)
     // The parameter ordering may differ between primaryData and secondaryData
     // We solve this by mapping the parameter in secondaryData to an index in primaryData
     paramIndexes = {};
-    //console.info(Object.keys(fallbackParams));
     secondaryData.weatherParameters.forEach(element => {
         if(mergedData.weatherParameters.includes(element))
         {
@@ -331,21 +399,16 @@ function mergeWeatherData(primaryData, secondaryData)
     });
 
     // Calculate dimensions of the merged data set
-    //console.info("timeStart=" + mergedData.timeStart.format("YYYY-MM-DD") + ", timeEnd=" + mergedData.timeEnd.format("YYYY-MM-DD"));
     let length = (getUnix(mergedData.timeEnd) - getUnix(mergedData.timeStart)) / mergedData.interval;
     let width = mergedData.weatherParameters.length;
     //console.info(length + "*" + width);
     let dataSet = Array.from(Array(length), () => new Array(width));
-    //console.info(dataSet);
     // Keeping track of offsets (if dataset does not cover the entire combined period of the merging datasets)
     let primaryOffset = (getUnix(primaryData.timeStart) - getUnix(mergedData.timeStart)) / mergedData.interval;
     let secondaryOffset = (getUnix(secondaryData.timeStart) - getUnix(mergedData.timeStart)) / mergedData.interval;
     let primaryDataSet = primaryData.locationWeatherData[0].data;
     let secondaryDataSet = secondaryData.locationWeatherData[0].data;
 
-    //console.info("primaryOffset=" + primaryOffset);
-    //console.info(primaryDataSet);
-
     // Finally: Merge the data!
     for(let i=0;i<dataSet.length;i++)
     {
@@ -362,7 +425,6 @@ function mergeWeatherData(primaryData, secondaryData)
         }
         if(primaryOffset <= i && i-primaryOffset < primaryDataSet.length )
         {
-            //console.info(i-primaryOffset);
             for(let j=0; j<primaryData.weatherParameters.length;j++)
             {
                 if(!isEmpty(primaryDataSet[i-primaryOffset][j]))
@@ -374,22 +436,28 @@ function mergeWeatherData(primaryData, secondaryData)
     }
 
     mergedData.locationWeatherData[0].data = dataSet;
-
-    //console.info(paramIndexes);
     return mergedData;
 }
 
+/**
+ * Util method if you don't know the type of object you're trying to get a Unix timestamp from
+ * @param {Object} aDate 
+ * @returns {BigInt} the Unix timestamp
+ */
 function getUnix(aDate)
 {
-    //console.info(typeof aDate);
     if(typeof aDate == "string")
     {
         aDate = moment(aDate);
     }
     return aDate.unix();
-    //return aDate.getTime()/1000;
 }
 
+/**
+ * Saves a bit of typing. Currently checks if the val is either undefined or null
+ * @param {Object} val 
+ * @returns {Boolean} true if the value is considered empty
+ */
 function isEmpty(val)
 {
     return val === undefined || val === null;
@@ -397,6 +465,22 @@ function isEmpty(val)
 
 // Keeping track of maps
 var maps = {};
+
+/**
+ * 
+ * @param {String} containerId the container where the map to destroy is anchored
+ */
+function destroyDataSourceMap(containerId)
+{
+    let map = maps[containerId];
+    // Delete whatever was there
+    if(map != undefined)
+    {
+        map.setTarget(undefined);
+        map = null;
+    }
+}
+
 /**
  * Requires OpenLayers v. 4
  * @param {String} containerId
@@ -416,7 +500,7 @@ async function initDataSourceMap(containerId, geoJson, countryCodeList, featureC
     }
 
     // If no data, no map
-    if((geoJson == undefined || geoJson == null || geoJson.features == undefined || geoJson.features.length == 0) && (countryCodeList == null || countryCodeList.length == 0))
+    if((isEmpty(geoJson) || isEmpty(geoJson.features) || geoJson.features.length == 0) && (countryCodeList == null || countryCodeList.length == 0))
     {
         document.getElementById(containerId).innerHTML = "NO GEODATA PROVIDED BY WEATHER DATA SOURCE";
         return;
@@ -426,15 +510,9 @@ async function initDataSourceMap(containerId, geoJson, countryCodeList, featureC
         document.getElementById(containerId).innerHTML = "";
     }
 
-    
+    // Using OpenStreetMap as default layer
     var backgroundLayer = new ol.layer.Tile({
-        source: new ol.source.OSM({
-                        attributions: [
-                       new ol.Attribution({
-                         html: "TEST"
-                       })
-                     ]
-               })
+        source: new ol.source.OSM()
     });
 
     // Creating the map
@@ -445,22 +523,20 @@ async function initDataSourceMap(containerId, geoJson, countryCodeList, featureC
     });
 
 
- 
-
+    // Adding it to list of maps, for bookkeeping
     maps[containerId] = map;
+
     // Setting zoom and center for the map (need to do this after creating map. so that we can transform our
 	// center to correct map projection)
 	var view = new ol.View({
 		center: ol.proj.transform([10,65], 'EPSG:4326', map.getView().getProjection().getCode()),
-		zoom: 7//,
-		//maxZoom: 7
+		zoom: 7
 	});
 	map.setView(view);
 	
+    // Read the datasource's geoJson features
 	let features = new ol.Collection();
-    
     let format = new ol.format.GeoJSON();
-    
     let drawnFeatures = await format.readFeatures(
         await getDatasourceFeatures(geoJson, countryCodeList), 
         {
@@ -469,11 +545,10 @@ async function initDataSourceMap(containerId, geoJson, countryCodeList, featureC
         }
     );
 
+    // Add any features to the featureOverlay
     let featureOverlay = undefined;
-
     if(drawnFeatures != undefined)
     {
-        //console.info(drawnFeatures);
         // Create an empty layer
         featureOverlay = new ol.layer.Vector({
             source: new ol.source.Vector({
@@ -490,11 +565,8 @@ async function initDataSourceMap(containerId, geoJson, countryCodeList, featureC
         map.getView().fit(extent, map.getSize());
     }
 
-    
-
     /*
-     * A little bit of this and that with regards to feature selection
-     * to make it work as we want
+     * A little bit of this and that to make feature selection work the way we want
      * - Highlight a selected station (but only one station, multiple select is not allowed)
      * - If user clicks on multiple stations, zoom in to make it easy to pick the right one
      */ 
@@ -516,6 +588,8 @@ async function initDataSourceMap(containerId, geoJson, countryCodeList, featureC
         }
     });
    
+    // We add this in order to detect if multiple features were clicked on, since the selectInteraction
+    // does not catch that
     map.on('singleclick', function(evt) {
     	var pixel = map.getEventPixel(evt.originalEvent);
 		var coordinate = map.getEventCoordinate(evt.originalEvent);
@@ -539,6 +613,7 @@ async function getDatasourceFeatures(geoJson, countryCodeList)
     return await getCountryBoundaries(countryCodeList);
 }
 
+// Default style for weather stations and areas
 const styleUnselected = new ol.style.Style({
     fill: new ol.style.Fill({
         color: 'rgba(173, 173, 173, 0.5)'
@@ -615,6 +690,10 @@ async function getCountryBoundaries(countryCodeList)
 }
 
 
+/**
+ * List of fallback parameters to use if the weather data source does not provide the 
+ * initially requested weather parameter
+ */
 const fallbackParams = {
         1001: [1002],
         1002: [1001],
@@ -626,8 +705,30 @@ const fallbackParams = {
         4013: [4012,4003,4002]
 }
 
+/**
+ * Util method for programmatically selecting an option in a list
+ * @param {HTMLElement} selectList 
+ * @param {String} optionValue 
+ */
+function setSelection(selectList, optionValue)
+{
+    for(let i=0;i<selectList.options.length; i++)
+    {
+        if(selectList.options[i].value == optionValue)
+        {
+            selectList.options[i].selected = true;
+        }
+        else
+        {
+            selectList.options[i].selected = false;
+        }
+    }
+}
 
 
+/**
+ * All the available weather parameters
+ */
 const weatherParameterList = [
     {
         "id": 1001,
diff --git a/ipmd/templates/ipmd/saddlegallmidgeform.html b/ipmd/templates/ipmd/saddlegallmidgeform.html
index 6035037401b7a71d27b7bcc3f5f6d4ec18dc7717..9183560386c45471ba87dd0bb7b5d33af0fe3954 100644
--- a/ipmd/templates/ipmd/saddlegallmidgeform.html
+++ b/ipmd/templates/ipmd/saddlegallmidgeform.html
@@ -161,6 +161,15 @@
 
     initPage();
 
+    /**
+     * 
+     * When the user selects a weather datasource:
+     * - Displays the description from the weather datasources's metadata
+     * - Displays a map showing the stations or area OR nothing - depending on the metadata's "spatial" property
+     * 
+     * 
+     * @param {HTMLElement} weatherDatasourcelist - the select list
+     */
     function handleWeatherDatasourceSelected(weatherDatasourceList){
         currentWeatherDatasource = getWeatherDatasource(
             weatherDatasources, 
@@ -171,6 +180,7 @@
         {
             sourceInfoPanel.style.display="none";
             document.getElementById("stationFields").style.display = "none";
+            destroyDataSourceMap("historicDatasourceMap");
             return;
         }    
 
@@ -196,15 +206,23 @@
             // Location based API
             // Display lat/lon input fields
             document.getElementById("stationFields").style.display = "none";
-            // TODO: Add map?
-
         }
-        //console.info(currentWeatherDatasource);
     }
 
+    /**
+     * This is a callback method passed on to impdlib.initDataSourceMap. When the user clicks on 
+     * - For station based datasources: a weather station
+     *   -> the correct station is selected in the station list
+     *   -> The station's location is set in the latitude/longitude form fields
+     * 
+     * - For gridded datasources: Anywhere inside the grid area
+     *   -> The location selected by the user is set in the latitude/longitude form fields
+     *
+     * @param {String} id the weatherstation id NULL => gridded weather datasource
+     * @param {Array} [lon,lat] (decimal degrees) of the clicked location. NULL => station based weather datasource
+     */ 
     function handleHistoricDatasourceMapClicked(id, coordinate)
     {
-        //console.info("Map clicked, station=" + id +", coordinate=" + coordinate + ". TODO: select station and/or populate lat/lon fields");
         // id != null => station. Pull station coordinates from source list to avoid inacurracies in user's map click coordinate
         if(id !== null)
         {
@@ -219,21 +237,12 @@
         }
     }
 
-    function setSelection(selectList, optionValue)
-    {
-        for(let i=0;i<selectList.options.length; i++)
-        {
-            if(selectList.options[i].value == optionValue)
-            {
-                selectList.options[i].selected = true;
-            }
-            else
-            {
-                selectList.options[i].selected = false;
-            }
-        }
-    }
+    
 
+    /**
+     * Shows datasource info and displays map
+     * Alerts if the selected forecast data source does not cover the selected location
+     */
     async function handleForecastSourceSelected(forecastSourceSelectList)
     {
         currentForecastWeatherDatasource = getWeatherDatasource(
@@ -242,9 +251,11 @@
         );
 
         let sourceInfoPanel = document.getElementById("forecastSourceInfoPanel");
+        // No datasource selected? Hide info panel and map and return
         if(currentForecastWeatherDatasource == null)
         {
             sourceInfoPanel.style.display="none";
+            destroyDataSourceMap("forecastDatasourceMap");
             return;
         }
 
@@ -269,33 +280,43 @@
         
     }
 
+    /**
+     * Pulls the coordinates of the selected weather station from the metadata,
+     * enters it in the form fields
+     */ 
     function handleWeatherStationSelected(weatherStationSelectList)
     {
         let weatherStationId = selectList.options[selectList.selectedIndex].value;
         let stationCoordinate = getWeatherStationCoordinate(currentWeatherDatasource, weatherStationId);
-        //console.info(stationCoordinate);
         setLatLon(stationCoordinate);
     }
 
+    /**
+     * Populate the form fields with the given coordinate
+     */ 
     function setLatLon(coordinate)
     {
         document.getElementById("longitude").value = coordinate[0];
         document.getElementById("latitude").value = coordinate[1];
     }
 
+    /**
+     * @returns {Array} [longitude,latitude] from the form fields
+     */ 
     function getLatLon()
     {
         return [document.getElementById("longitude").value, document.getElementById("latitude").value];
     }
 
+    /**
+     * Collects the input data into Json that conforms to the DSS model's Json schema
+     * Also collects weather data (which goes into the input data Json)
+     */ 
     async function submitData(){
-        //console.info("submitData!");
         let inputData = editor.getValue();
-        //console.info(inputData);
         // Add hidden parameters
         let fullSchema = JSON.parse(modelMetaData["execution"]["input_schema"]);
         const hiddenParameters = modelMetaData["execution"]["input_schema_categories"]["hidden"];
-        //console.info(hiddenParameters);
         for(let i=0;i<hiddenParameters.length;i++)
         {
             let hiddenParameter = hiddenParameters[i];
@@ -304,7 +325,6 @@
         // Check for weatherData element. Assuming it's at the root node
         if(fullSchema["properties"]["weatherData"] !== undefined)
         {
-            //console.info("Need to get weather data!");
             let forecastData = undefined;
             // 1. Historic weather data
             if(currentWeatherDatasource != undefined)
@@ -389,24 +409,22 @@
                 }
             }
 
-            
             inputData["weatherData"] = weatherData;
-            //console.info(weatherData);
         }
         // Ready to call server?
-        //console.info(JSON.stringify(inputData));
-        //let result = await runModel(modelMetaData.execution.endpoint, inputData);
         let result = mockResult;
-        //console.info(result);
         displayResult(result);
     };
 
+    /**
+     * Render results in a chart
+     */
     function displayResult(result) {
 
         let chartData = [];
         // Generate dates
         let dates = getDateArray(result.timeStart, 86400, result.locationResult[0].length);
-        //console.info(dates);
+
         for(let i=0; i< result.resultParameters.length;i++)
         {
             let dataset = {label:result.resultParameters[i], data: []}