protected static function get_form_html($args, $auth, $attributes)
 {
     if ($args['includeLocTools'] && function_exists('iform_loctools_listlocations')) {
         $squares = iform_loctools_listlocations(self::$node);
         if ($squares != "all" && count($squares) == 0) {
             return lang::get('Error: You do not have any squares allocated to you. Please contact your manager.');
         }
     }
     $r = call_user_func(array(self::$called_class, 'getHeaderHTML'), $args);
     $r .= parent::get_form_html($args, $auth, $attributes);
     $r .= call_user_func(array(self::$called_class, 'getTrailerHTML'), $args);
     return $r;
 }
 public static function get_form($args, $node, $response = null)
 {
     global $indicia_templates;
     global $user;
     $indicia_templates['select_item'] = '<option value="{value}" {selected} >{caption}&nbsp;</option>';
     // we don't use the map, but a lot of the inherited code assumes the map is present.
     self::$svcUrl = data_entry_helper::$base_url . '/index.php/services';
     data_entry_helper::add_resource('openlayers');
     $indicia_templates['label'] = '<label for="{id}"{labelClass}>{label}:</label>';
     // can't have the CR on the end
     $indicia_templates['zilch'] = '';
     // can't have the CR on the end
     self::$locations = iform_loctools_listlocations($node);
     $retVal = parent::get_form($args, $node, $response);
     $reload = data_entry_helper::get_reload_link_parts();
     $reloadPath = $reload['path'];
     if (self::$mode != 0) {
         data_entry_helper::$javascript .= "\njQuery('<div class=\"ui-widget-content ui-state-default ui-corner-all indicia-button tab-cancel\"><span><a href=\"" . $reloadPath . "\">Cancel</a></span></div>').appendTo('.buttons');\n\$.validator.messages.required = \"" . lang::get('validation_required') . "\";";
         if (!iform_loctools_checkaccess($node, 'superuser')) {
             data_entry_helper::$javascript .= "\njQuery('[name=smpAttr\\:" . $args['observer_attr_id'] . "],[name^=smpAttr\\:" . $args['observer_attr_id'] . "\\:]').attr('readonly',true)";
             if (self::$mode == 1) {
                 data_entry_helper::$javascript .= ".val(\"" . $user->name . "\");";
             } else {
                 data_entry_helper::$javascript .= ";";
             }
         } else {
             $userlist = iform_loctools_listusers($node);
             data_entry_helper::$javascript .= "\nexisting = jQuery('[name=smpAttr\\:" . $args['observer_attr_id'] . "],[name^=smpAttr\\:" . $args['observer_attr_id'] . "\\:]');\nreplacement = '<select name=\"'+existing.attr('name')+'\" >";
             foreach ($userlist as $uid => $a_user) {
                 data_entry_helper::$javascript .= "<option value=\"" . $a_user->name . "\">" . $a_user->name . "&nbsp;</option>";
             }
             data_entry_helper::$javascript .= "</select>';\njQuery(replacement).insertBefore(existing).val(existing.val());\nexisting.remove();\n";
         }
         data_entry_helper::$javascript .= "\n// jQuery('#sample\\\\:date').datepicker( \"option\", \"minDate\", new Date(2010, 4 - 1, 1) );\nDate.prototype.getMonthName = function() {\nvar m = ['" . lang::get('January') . "','" . lang::get('February') . "','" . lang::get('March') . "',\n'" . lang::get('April') . "','" . lang::get('May') . "','" . lang::get('June') . "',\n'" . lang::get('July') . "','" . lang::get('August') . "','" . lang::get('September') . "',\n'" . lang::get('October') . "','" . lang::get('November') . "','" . lang::get('December') . "'];\nreturn m[this.getMonth()];\n} \nvar monthAttr = jQuery('[name=smpAttr\\\\:" . $args['month_attr_id'] . "],[name^=smpAttr\\\\:" . $args['month_attr_id'] . "\\\\:]').attr('disabled', true);\nmonthAttr.before('<input type=\"hidden\" id=\"storedMonth\" name=\"'+monthAttr.attr('name')+'\">');\nupdateSampleDate = function(context, doAlert){\n  jQuery('.displayDateDetails').empty().append('<span>'+jQuery('[name=sample\\:date]').val()+'</span>');\n  var myDate = jQuery(context).datepicker(\"getDate\").getMonthName();\n  var monthAttr = jQuery('[name=smpAttr\\\\:" . $args['month_attr_id'] . "],[name^=smpAttr\\\\:" . $args['month_attr_id'] . "\\\\:]').filter('select').val(\"\");\n  monthAttr.find(\"option:contains('\"+myDate+\"')\").attr('selected',true) ; \n  jQuery('#storedMonth').val(monthAttr.val()); // doing in this order converts the text to a number and stores that number in the storedMonth\n  if(doAlert && monthAttr.val() == \"\")\n  \talert('Given date is outside valid month range (April to September).');\n};\njQuery('#sample\\\\:date').change(function(){updateSampleDate(this, true);});\nupdateSampleDate('#sample\\\\:date', false);\njQuery('.tab-submit').unbind('click');\njQuery('.tab-submit').click(function() {\n  var current=jQuery('#controls').tabs('option', 'selected');\n  var tabinputs = jQuery('#entry_form div > .ui-tabs-panel:eq('+current+')').find('input,select');\n  var secList = '';\n  if (!tabinputs.valid()) { return; }\n  var rows = jQuery('.sectionlist').find('tr');\n  for(var i=1; i<= " . $args['max_number_sections'] . "; i++){\n    if(jQuery('.sectionlist').find('[section='+i+']').length > 0) {\n      var aucuneControl = jQuery(':checkbox[name^=\"SLA\\:'+i+'\\:\"]').filter('[name\$=\"\\:" . $args['aucune_attr_id'] . "\"]');\n      var foundEntry = false;\n      for(var j = 1; j < (rows.length-(numAttrs+1)); j++){\n        foundEntry = foundEntry || (jQuery(rows[j]).find('td').filter(':eq('+i+')').find('[value!=\"\"]').length > 0);\n      }\n      if(!foundEntry && !aucuneControl.attr('checked')){\n          secList = secList + (secList=='' ? '' : ', ') + i;\n      }\n    }\n  }\n  if (secList != ''){\n    alert('The following sections have no species recorded against them: Section(s) '+secList+'. In these circumstances, the \"No Observation\" checkbox must be checked for the relevant section.'); \n    return;\n  }\n  var form = jQuery(this).parents('form:first');\n  form.submit();\n});\n";
     } else {
         $retVal .= "<div style=\"display:none\" />\n    <form id=\"form-delete-survey\" action=\"" . $reloadPath . "\" method=\"POST\">" . self::$auth['write'] . "\n       <input type=\"hidden\" name=\"website_id\" value=\"" . $args['website_id'] . "\" />\n       <input type=\"hidden\" name=\"survey_id\" value=\"" . $args['survey_id'] . "\" />\n       <input type=\"hidden\" name=\"sample:id\" value=\"\" />\n       <input type=\"hidden\" name=\"sample:date\" value=\"2010-01-01\"/>\n       <input type=\"hidden\" name=\"sample:location_id\" value=\"\" />\n       <input type=\"hidden\" name=\"sample:deleted\" value=\"t\" />\n    </form>\n</div>";
         data_entry_helper::$javascript .= "\ndeleteSurvey = function(sampleID){\n  if(confirm(\"Are you sure you wish to delete survey \"+sampleID)){\n    jQuery.getJSON(\"" . self::$svcUrl . "/data/sample/\"+sampleID +\n            \"?mode=json&view=detail&auth_token=" . self::$auth['read']['auth_token'] . "&nonce=" . self::$auth['read']["nonce"] . "\" +\n            \"&callback=?\", function(data) {\n        if (data.length>0) {\n          jQuery('#form-delete-survey').find('[name=sample\\:id]').val(data[0].id);\n          jQuery('#form-delete-survey').find('[name=sample\\:date]').val(data[0].date_start);\n          jQuery('#form-delete-survey').find('[name=sample\\:location_id]').val(data[0].location_id);\n          jQuery('#form-delete-survey').submit();\n  }});\n  };\n};\n";
     }
     return $retVal;
 }
Example #3
0
function iform_mnhnl_lux5kgridControl($auth, $args, $node, $options)
{
    global $indicia_templates, $user;
    $options = array_merge(array('initLoadArgs' => '{}', 'Instructions1' => lang::get('LANG_CommonInstructions1'), 'Instructions2' => lang::get('LANG_DE_Instructions2'), 'MainFieldLabel' => lang::get('LANG_DE_LocationIDLabel'), 'ChooseParentLabel' => lang::get('LANG_CommonParentLabel'), 'ParentLabel' => lang::get('LANG_CommonParentLabel'), 'NameLabel' => lang::get('LANG_CommonLocationNameLabel'), 'FilterNameLabel' => lang::get('LANG_CommonFilterNameLabel'), 'CodeLabel' => lang::get('LANG_CommonLocationCodeLabel'), 'AdminMode' => false, 'disabled' => false), $options);
    switch ($args['locationMode']) {
        case 'multi':
            $options = array_merge(array('ChooseParentFieldID' => 'sample-location-id', 'ChooseParentFieldName' => 'sample:location_id', 'MainFieldID' => 'dummy-location-id', 'MainFieldName' => 'dummy:location_id'), $options);
            break;
        default:
            // parent, single, filtered
            $options = array_merge(array('ChooseParentFieldID' => 'dummy-parent-id', 'ChooseParentFieldName' => 'dummy:parent_id', 'ParentFieldID' => 'location-parent-id', 'ParentFieldName' => 'location:parent_id', 'MainFieldID' => 'location-id', 'MainFieldName' => 'location:id'), $options);
            break;
    }
    // we are using meaning_ids: for the location attributes we need to convert the id to the term for the templates. Can't just output value - convert raw value
    $attrArgs = array('valuetable' => 'location_attribute_value', 'attrtable' => 'location_attribute', 'key' => 'location_id', 'fieldprefix' => 'locAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id']);
    $locationAttributes = data_entry_helper::getAttributes($attrArgs, false);
    // this does not get values
    $termlists = array();
    $requiresConv = array();
    foreach ($locationAttributes as $locAttr) {
        if (!is_null($locAttr["termlist_id"])) {
            $termlists[] = $locAttr["termlist_id"];
            $requiresConv[] = $locAttr["attributeId"];
        }
    }
    data_entry_helper::$javascript .= "\nvar requiresConv = " . json_encode($requiresConv) . ";\n";
    if (count($termlists) > 0) {
        data_entry_helper::$javascript .= "var terms = {";
        $extraParams = $auth['read'] + array('view' => 'detail', 'preferred' => 't', 'orderby' => 'meaning_id', 'termlist_id' => $termlists);
        $terms_data_def = array('table' => 'termlists_term', 'extraParams' => $extraParams);
        $terms = data_entry_helper::get_population_data($terms_data_def);
        $first = true;
        foreach ($terms as $term) {
            data_entry_helper::$javascript .= ($first ? '' : ',') . $term['meaning_id'] . ": \"" . htmlSpecialChars($term['term']) . "\"\n";
            $first = false;
        }
        data_entry_helper::$javascript .= "};\nconvertTerm=function(id){\n\tif(typeof terms[id] == 'undefined') return id;\n\treturn terms[id];\n}\n";
    }
    $precisionAttrID = iform_mnhnl_getAttrID($auth, $args, 'location', 'Precision');
    if ($precisionAttrID && isset($args['movePrecision']) && $args['movePrecision']) {
        data_entry_helper::$javascript .= "\nvar precisionAttr = jQuery('[name=locAttr\\:" . $precisionAttrID . "],[name^=locAttr\\:" . $precisionAttrID . "\\:]');\nvar precisionLabel = precisionAttr.prev();\nprecisionAttr.next().filter('br').remove();\nprecisionLabel.addClass('auto-width prepad').insertAfter('#imp-srefY');\nprecisionAttr.insertAfter(precisionLabel).addClass('precision');\n";
    }
    $creatorAttr = iform_mnhnl_getAttrID($auth, $args, 'location', 'Creator');
    if (isset(data_entry_helper::$entity_to_load["sample:updated_by_id"])) {
        // only set if data loaded from db, not error condition
        data_entry_helper::load_existing_record($auth['read'], 'location', data_entry_helper::$entity_to_load["sample:location_id"]);
    }
    $retVal = '<div id="clickableLayersOutputDiv" style="display:none;"></div>';
    if ($args['LocationTypeTerm'] == '' && isset($args['loctoolsLocTypeID'])) {
        $args['LocationTypeTerm'] = $args['loctoolsLocTypeID'];
    }
    $primary = iform_mnhnl_getTermID($auth, 'indicia:location_types', $args['LocationTypeTerm']);
    if ($args['SecondaryLocationTypeTerm'] != '') {
        $secondary = iform_mnhnl_getTermID($auth, 'indicia:location_types', $args['SecondaryLocationTypeTerm']);
        $loctypequery = "\"&query=\"+escape(JSON.stringify({'in': ['location_type_id', [{$primary}, {$secondary}]]}))";
        $loctypeParam = array($primary, $secondary);
    } else {
        $loctypequery = "\"&location_type_id=" . $primary . "\"";
        $loctypeParam = $primary;
    }
    // $retVal .= "<p>".print_r($options,true)."</p>";
    data_entry_helper::$javascript .= "\n// Create vector layers: one to display the Parent Square onto, and another for the site locations list\n// the default edit layer is used for this sample\nParentLocStyleMap = new OpenLayers.StyleMap({\"default\": new OpenLayers.Style({strokeColor: \"Yellow\",fillOpacity: 0,strokeWidth: 4})});\nParentLocationLayer = new OpenLayers.Layer.Vector('Parents',{styleMap: ParentLocStyleMap,displayInLayerSwitcher: false});\n\ndefaultPointStyle = new OpenLayers.Style({pointRadius: 6,fillColor: \"Red\",fillOpacity: 0.3,strokeColor: \"Yellow\",strokeWidth: 1});\nselectPointStyle = new OpenLayers.Style({pointRadius: 6,fillColor: \"Blue\",fillOpacity: 0.3,strokeColor: \"Yellow\",strokeWidth: 2});\ndefaultStyle = new OpenLayers.Style({pointRadius: 6, fillColor: \"Red\",fillOpacity: 0.3,strokeColor: \"Red\",strokeWidth: 1});\nselectStyle = new OpenLayers.Style({fillColor: \"Blue\",fillOpacity: 0.3,strokeColor: \"Blue\",strokeWidth: 2});\n//defaultLabelStyle = new OpenLayers.Style({fontColor: \"Yellow\", labelAlign: \"" . $args['labelAlign'] . "\", labelXOffset: " . $args['labelXOffset'] . ", labelSelect: true});\ndragPointStyleHash={pointRadius: 6,fillColor: \"Fuchsia\",fillOpacity: 0.3,strokeColor: \"Fuchsia\",strokeWidth: 1};\n// Interesting behaviour of the Points: when any mod control is active it creates a set of vertices which can be \n// dragged, allowing the existing geometry to be modified. All fine for Lines and polygons, but for points\n// the vertices are generated in the default style, and appear over the top of our existing geometry, so\n// effectively making it appear unselected! \n// We want consistent colouring, so\n// 1) normal=red, yellow surrounds points\n// 2) highlighted=blue, yellow surrounds points\n// 3) Drag points=purple.\n\nSitePointStyleMap = new OpenLayers.StyleMap({\"default\": defaultPointStyle, \"select\": selectPointStyle});\nSiteStyleMap = new OpenLayers.StyleMap({\"default\": defaultStyle, \"select\": selectStyle});\n//SiteLabelStyleMap = new OpenLayers.StyleMap({\"default\": defaultLabelStyle});\n\n" . ($args['SecondaryLocationTypeTerm'] != '' && $options['AdminMode'] ? "SiteListPrimaryLabelStyleHash={fontColor: \"Red\", labelAlign: \"" . $args['labelAlign'] . "\", labelXOffset: " . $args['labelXOffset'] . ", labelSelect: true, fontSize: \"1.2em\", fontWeight: \"bold\"};\nSiteListSecondaryLabelStyleHash" : "\nSiteListPrimaryLabelStyleHash") . "={fontColor: \"Yellow\", labelAlign: \"" . $args['labelAlign'] . "\", labelXOffset: " . $args['labelXOffset'] . ", labelSelect: true};\n\nSitePointLayer = new OpenLayers.Layer.Vector('Site Points',{styleMap: SitePointStyleMap, displayInLayerSwitcher: false});\n//SitePointLayer = new OpenLayers.Layer.Vector('Site Points',{styleMap: SitePointStyleMap});\nSitePathLayer = new OpenLayers.Layer.Vector('Site Paths',{styleMap: SiteStyleMap, displayInLayerSwitcher: false});\nSiteAreaLayer = new OpenLayers.Layer.Vector('Site Areas',{styleMap: SiteStyleMap, displayInLayerSwitcher: false});\nSiteLabelLayer = new OpenLayers.Layer.Vector('Site Labels',{//styleMap: SiteLabelStyleMap, \ndisplayInLayerSwitcher: false});\nvar SiteNum = 0;\n";
    if (isset($args['locationLayerWMS']) && $args['locationLayerWMS'] != '') {
        // define Parent WMS Layer
        $WMSoptions = explode(',', $args['locationLayerWMS']);
        if ($args['includeLocTools'] && function_exists('iform_loctools_listlocations')) {
            $squares = iform_loctools_listlocations($node);
            if (is_array($squares) && count($squares) == 0) {
                $squares = array("-1");
            }
            // put in dummy value (all ids are > 0) to allow CQL filter to work on a blank list.
        } else {
            $squares = 'all';
        }
        // can't use the column name id in the cql_filter as this has a special (fid) meaning.
        data_entry_helper::$javascript .= "\nWMSoptions = {SERVICE: 'WMS', VERSION: '1.1.0', STYLES: '', SRS: '" . $WMSoptions[2] . "', FORMAT: 'image/png', TRANSPARENT: 'true', LAYERS: '" . $WMSoptions[1] . "',\n  CQL_FILTER: \"location_type_id=" . $args['loctoolsLocTypeID'] . " AND website_id=" . $args['website_id'] . ($squares != 'all' ? " AND location_id IN (" . implode(',', $squares) . ")" : '') . "\"\n    };\nParentWMSLayer = new OpenLayers.Layer.WMS('Parent Grid',\n  '" . (function_exists(iform_proxy_url) ? iform_proxy_url($WMSoptions[0]) : $WMSoptions[0]) . "',\n  WMSoptions, {\n    minScale: " . $WMSoptions[3] . ",\n    maxScale: " . $WMSoptions[4] . ",\n    units: '" . $WMSoptions[5] . "',\n    isBaseLayer: false,\n    singleTile: true\n  });\n";
        if ($args['locationMode'] == 'multi' && isset(data_entry_helper::$entity_to_load["sample:location_id"])) {
            data_entry_helper::$javascript .= "setClickedParent = function(features, div){ return ''; };\n";
        } else {
            data_entry_helper::$javascript .= "setClickedParent = function(features, div){\n  jQuery('[name=" . str_replace(':', '\\:', $options['ChooseParentFieldName']) . "]').val(features[0].data.id).change();\n  return '';\n};\n";
        }
    }
    data_entry_helper::$javascript .= "\n// not happy about centroid calculations: lines and multipoints seem to take first vertex\n_getCentroid = function(geometry){\n  var retVal;\n  retVal = {sumx: 0, sumy: 0, count: 0};\n  switch(geometry.CLASS_NAME){\n    case \"OpenLayers.Geometry.Point\":\n      retVal = {sumx: geometry.x, sumy: geometry.y, count: 1};\n      break;\n    case \"OpenLayers.Geometry.MultiPoint\":\n    case \"OpenLayers.Geometry.MultiLineString\":\n    case \"OpenLayers.Geometry.LineString\":\n    case \"OpenLayers.Geometry.MultiPolygon\":\n    case \"OpenLayers.Geometry.Collection\":\n      var retVal = {sumx: 0, sumy: 0, count: 0};\n      for(var i=0; i< geometry.components.length; i++){\n        var point=_getCentroid(geometry.components[i]);\n        retVal = {sumx: retVal.sumx+point.sumx, sumy: retVal.sumy+point.sumy, count: retVal.count+point.count};\n      }\n      break;\n    case \"OpenLayers.Geometry.Polygon\": // only do outer ring\n      var point=geometry.getCentroid();\n      retVal = {sumx: point.x*geometry.components[0].components.length, sumy: point.y*geometry.components[0].components.length, count: geometry.components[0].components.length};\n      break;\n  }\n  return retVal;\n}\ngetCentroid=function(geometry){\n  var oddball=_getCentroid(geometry);\n  return new OpenLayers.Geometry.Point(oddball.sumx/oddball.count, oddball.sumy/oddball.count);\n}\nrecalcNumSites = function(){\n  var sitearray = {};\n  var allFeatures = SiteAreaLayer.features.concat(SitePathLayer.features,SitePointLayer.features);\n  // don't need to consider Label layer...\n  for(var i=0; i< allFeatures.length; i++){\n    if(typeof allFeatures[i].attributes.SiteNum != 'undefined')\n      sitearray['x'+allFeatures[i].attributes.SiteNum.toString()] = true;\n  }\n  var count = 0;\n  for (x in sitearray) count++;\n  jQuery('#dummy-num-sites').val(count);\n};\nrecalcNumSites();\nclearLocation = function(hookArg, clearName){ // clears all the data in the fields.\n  if(clearName === true || (clearName == 'maybe' && jQuery('#" . $options['MainFieldID'] . "').val() != ''))\n    jQuery('" . ($args['locationMode'] != 'multi' ? "#sample-location-name" : "") . ",#location-name').val('');\n  jQuery('#" . $options['MainFieldID'] . ($args['locationMode'] != 'multi' ? ",#sample-location-id" : "") . ",#centroid_sref,#imp-srefX,#imp-srefY,#centroid_geom,#boundary_geom,[name=location\\:comment],[name=location\\:parent_id],#location-code').val('');\n  jQuery('#location-code').attr('dbCode','');\n" . ($args['locationMode'] != 'multi' && $args['siteNameTermListID'] != "" && isset($args['duplicateNameCheck']) && $args['duplicateNameCheck'] == 'enforce' ? "  jQuery('#location-name option').removeAttr('disabled');\n  var nameVal = jQuery('#location-name').val();\n  for(var i=0; i< SiteLabelLayer.features.length; i++){\n    if(typeof SiteLabelLayer.features[i].attributes.SiteNum != 'undefined'){\n      // At the moment the allowable options are integers: if the old data is dodgy it may not hold an integer\n      if(SiteLabelLayer.features[i].style.label == parseInt(SiteLabelLayer.features[i].style.label)){\n\t\tif(SiteLabelLayer.features[i].style.label == nameVal) jQuery('#location-name').val('');\n\t\tjQuery('#location-name').find('option').filter('[value='+SiteLabelLayer.features[i].style.label+']').attr('disabled','disabled');\n      }\n    }\n  }\n" : "") . "  jQuery('#location_location_type_id').val('{$primary}');\n  // first  to remove any hidden multiselect checkbox unclick fields\n  var fullAttrList=jQuery('[name^=locAttr\\:]').not('[name\$=\\:term]');\n  var attrList=jQuery('[name^=locAttr\\:]').not('[name\$=\\:term]').not('.filterFields');\n  fullAttrList.filter('.multiselect').remove();\n  fullAttrList.filter(':checkbox').removeAttr('checked').each(function(idx,elem){\n    var name = jQuery(elem).attr('name').split(':');\n    var value = jQuery(elem).val().split(':');\n    jQuery('[name^=locAttr\\:'+name[1]+'\\:]').filter(':hidden').remove();\n    jQuery(elem).val(value[0]);\n  });\n  // rename\n  fullAttrList.each(function(){\n    var name = jQuery(this).attr('name').split(':');\n    if(name[1].indexOf('[]') > 0) name[1] = name[1].substr(0, name[1].indexOf('[]'));\n    jQuery(this).attr('name', name[0]+':'+name[1]);\n  });\n  // reset values (checkboxes done above).\n  attrList.filter(':radio').removeAttr('checked');\n  attrList.filter(':text').val('');\n  attrList.filter('select').val('');\n  // rename checkboxes to add square brackets\n  attrList.filter(':checkbox').each(function(idx,elem){\n\tvar name = jQuery(elem).attr('name').split(':');\n\tvar similar = jQuery('[name=locAttr\\:'+name[1]+'],[name=locAttr\\:'+name[1]+'\\[\\]]').filter(':checkbox');\n\tif(similar.length > 1) // only do this for checkbox groups.\n\t\tjQuery(this).attr('name', name[0]+':'+name[1]+'[]');\n  });\n  if(typeof hook_set_defaults != 'undefined') hook_set_defaults(hookArg);\n}\nsetPermissions = function(enableItems, disableItems){\n  if(disableItems.length > 0) jQuery(disableItems.join(',')).attr('disabled',true);\n  if(enableItems.length > 0) jQuery(enableItems.join(',')).removeAttr('disabled');\n}\n// sets the permissions when there is nothing selected, and no parent is provided\nsetPermissionsNoParent = function(){\n  setPermissions([],\n                 ['[name=locations_website\\:website_id]',\n                  '#" . $options['MainFieldID'] . "',\n                  '[name=location\\:code]',\n                  '[name=location\\:name]',\n                  '[name=location\\:comment]',\n                  '[name=location\\:location_type_id]',\n                  '[name=location\\:deleted]',\n                  '[name=location\\:parent_id]',\n                  '[name^=locAttr\\:]',\n                  '#dummy-name',\n                  '#imp-sref',\n                  '#imp-geom',\n                  '#imp-boundary-geom']);\n}\nsetPermissionsNoSite = function(){\n  // In filter mode, if parent is in filter options, need it available. Also in that case will need to enter filter options before the main ID becomes available\n  // else when creating a new site, it is possible to select an old site from the drop down, provided there are some to select.\n  var disable = ['[name=locations_website\\:website_id]',\n                  '[name=location\\:code]',\n                  '[name=location\\:name]',\n                  '[name=location\\:comment]',\n                  '[name=location\\:location_type_id]',\n                  '[name=location\\:deleted]',\n                  '[name^=locAttr\\:]',\n                  '#dummy-name',\n                  '#imp-sref',\n                  '#imp-geom',\n                  '#imp-boundary-geom'];\n  if(typeof indiciaData.filterMode == 'undefined'){\n    var enable = ['#" . $options['MainFieldID'] . "']; // can choose site from drop down.\n    disable.push('[name=location\\:parent_id]');\n  } else {\n    disable.push('#" . $options['MainFieldID'] . "');\n    var enable = ['[name=location\\:parent_id]'];\n  }\n  setPermissions(enable,disable);\n}\nsetPermissionsOldEditableSite = function(){\n  setPermissions(['#" . $options['MainFieldID'] . "',\n                  '[name=location\\:code]',\n                  '[name=location\\:name]',\n                  '[name=location\\:comment]',\n                  '[name=location\\:location_type_id]',\n                  '[name=location\\:deleted]',\n                  '[name=location\\:parent_id]',\n                  '[name^=locAttr\\:]',\n                  '#dummy-name',\n                  '#imp-sref',\n                  '#imp-geom',\n                  '#imp-boundary-geom'],\n                 ['[name=locations_website\\:website_id]']);\n}\nsetPermissionsOldReadOnlySite = function(){\n  setPermissions(['#" . $options['MainFieldID'] . "'],\n                 ['[name=locations_website\\:website_id]',\n                  '[name=location\\:code]',\n                  '[name=location\\:name]',\n                  '[name=location\\:comment]',\n                  '[name=location\\:location_type_id]',\n                  '[name=location\\:deleted]',\n                  '[name=location\\:parent_id]',\n                  '[name^=locAttr\\:]',\n                  '#dummy-name',\n                  '#imp-sref',\n                  '#imp-geom',\n                  '#imp-boundary-geom']);\n}\nsetPermissionsNewSite = function(){\n  // when creating a new site, it is possible to select an old site from the drop down, provided there are some to select.\n  var enable = ['[name=locations_website\\:website_id]',\n                '[name=location\\:code]',\n                '[name=location\\:name]',\n                '[name=location\\:comment]',\n                '[name=location\\:location_type_id]',\n                '[name=location\\:parent_id]',\n                '[name^=locAttr\\:]',\n                '#dummy-name',\n                '#imp-sref',\n                '#imp-geom',\n                '#imp-boundary-geom'];\n  var disable = ['[name=location\\:deleted]'];\n  var allFeatures = SiteAreaLayer.features.concat(SitePathLayer.features,SitePointLayer.features);\n  var haveOld=false;\n  for(var i=0; i<allFeatures.length; i++){\n    if(allFeatures[i].attributes['new']==false){\n      haveOld=true;\n    }}\n  if(haveOld){\n    enable.push('#" . $options['MainFieldID'] . "');  // in case we want to change to an existing site.\n  } else {\n    disable.push('#" . $options['MainFieldID'] . "');\n  }\n  setPermissions(enable,disable);\n}\nloadLocation = function(feature){ // loads all the data into the location fields from a feature.\n  if(feature.attributes['new'])\n    setPermissionsNewSite();\n  else if (feature.attributes.canEdit)\n    setPermissionsOldEditableSite();\n  else\n    setPermissionsOldReadOnlySite();\n" . ($args['locationMode'] == 'multi' ? "  var mySelector = '#dummy-name';\n" : "  var mySelector = '#location-name';\n  clearLocation(false, true);\n") . "\n" . ($args['siteNameTermListID'] != "" ? "  jQuery(mySelector).find('option').removeAttr('disabled');\n" : "") . "  // the label is stored in the SiteLabelLayer. For new locations this is the only place the name is stored in the generic module.\n  for(var i=0; i< SiteLabelLayer.features.length; i++){\n    if(typeof SiteLabelLayer.features[i].attributes.SiteNum != 'undefined'){\n      if(feature.attributes.SiteNum == SiteLabelLayer.features[i].attributes.SiteNum){\n        jQuery('#dummy-name').val(SiteLabelLayer.features[i].style.label);\n      }\n" . ($args['siteNameTermListID'] != "" ? "      else {\n        // At the moment the allowable options are integers: if the old data is dodgy it may not hold an integer\n        if(SiteLabelLayer.features[i].style.label == parseInt(SiteLabelLayer.features[i].style.label))\n          jQuery(mySelector).find('option').filter('[value='+SiteLabelLayer.features[i].style.label+']').attr('disabled','disabled');\n      }\n" : "") . "    }\n  }\n" . ($args['locationMode'] == 'multi' ? "" : ";  // main field ID could be a select without an entry for me (in case of a filter) so add one if needed.\n  var amIaSelect = jQuery('#" . $options['MainFieldID'] . "').filter('select');\n  if(amIaSelect.length>0 && amIaSelect.find('[value='+feature.attributes.data.id+']').length==0){\n    amIaSelect.append('<option value=\"'+feature.attributes.data.id+'\">'+feature.attributes.data.name+'</option>');\n  }\n  jQuery(\"#" . $options['MainFieldID'] . ",#sample-location-id\").val(feature.attributes.data.id);\n  // parent_id is left as is in drop down if present. Not multi so must be an existing site.\n  jQuery('#location-name,#sample-location-name').val(feature.attributes.data.name);\n  jQuery('#location_location_type_id').val(feature.attributes.data.location_type_id);\n  if(feature.attributes.data.comment == null) feature.attributes.data.comment='';\n  jQuery('[name=location\\:comment]').val(feature.attributes.data.comment);\n  jQuery('[name=location\\:parent_id],[name=dummy\\:parent_id]').val(feature.attributes.data.parent_id);\n  jQuery('#location-code').val(feature.attributes.data.code).attr('dbCode',feature.attributes.data.code);\n  jQuery('#imp-geom').val(feature.attributes.data.centroid_geom); // this is as stored in the database i.e. 3857/900913 projection, not necessarily the map projection\n  jQuery('#imp-boundary-geom').val(feature.attributes.data.boundary_geom); // this is as stored in the database i.e. 3857/900913 projection, not necessarily the map projection\n  setSref(feature.geometry, feature.attributes.data.centroid_sref);\n  // reset attributes is done by clearLocation above. this clears the values of checkboxes.\n  jQuery.getJSON('" . data_entry_helper::$base_url . "/index.php/services/data/location_attribute_value' +\n            '?mode=json&view=list&auth_token=" . $auth['read']['auth_token'] . "&nonce=" . $auth['read']["nonce"] . "&location_id='+feature.attributes.data.id+'&callback=?', function(data) {\n    if(data instanceof Array && data.length>0){\n      for (var i=0;i<data.length;i++){\n        if (data[i].id) {\n          // no multiselect or boolean checkboxes at the moment so don't code\n          var radiobuttons = jQuery('[name=locAttr\\:'+data[i]['location_attribute_id']+'],[name^=locAttr\\:'+data[i]['location_attribute_id']+'\\:]').filter(':radio');\n          var checkbuttons = jQuery('[name=locAttr\\:'+data[i]['location_attribute_id']+'\\[\\]],[name^=locAttr\\:'+data[i]['location_attribute_id']+'\\:]').filter(':checkbox');\n          if(radiobuttons.length > 0){ // radio buttons all share the same name, only one checked.\n            radiobuttons.attr('name', 'locAttr:'+data[i]['location_attribute_id']+':'+data[i].id)\n                  .filter('[value='+data[i].raw_value+']').attr('checked', 'checked');\n          } else if(checkbuttons.length > 0){ // checkbuttons buttons have different name if selected, any number selected.\n\t\t\tcheckbuttons = checkbuttons.filter('[value='+data[i].raw_value+']')\n\t\t\t\t.attr('name', 'locAttr:'+data[i]['location_attribute_id']+':'+data[i].id).attr('checked', 'checked');\n\t\t\tcheckbuttons.each(function(){\n\t\t\t\tjQuery('<input type=\"hidden\" value=\"\" class=\"multiselect\">').attr('name', jQuery(this).attr('name')).insertBefore(this);\n\t\t\t});\n          } else {\n            jQuery('[name=locAttr\\:'+data[i]['location_attribute_id']+']')\n                      .attr('name', 'locAttr:'+data[i]['location_attribute_id']+':'+data[i].id).val(data[i].raw_value);\n            if(jQuery('[name=locAttr\\:'+data[i]['location_attribute_id']+'\\:term]').length>0){ // autocomplete entries: force a lookup, we are using meaning_id\n              jQuery('[name=locAttr\\:'+data[i]['location_attribute_id']+'\\:term]').val('');\n              jQuery.getJSON('" . data_entry_helper::$base_url . "/index.php/services/data/termlists_term' +\n                '?mode=json&view=detail&auth_token=" . $auth['read']['auth_token'] . "&nonce=" . $auth['read']["nonce"] . "&preferred=t&meaning_id='+data[i].raw_value+'&callback=?', function(tdata) {\n                if(tdata.length>0){\n                  jQuery('[name^=locAttr]').filter('[value='+tdata[0].meaning_id+']').each(function(idx,elem){\n                    var name = jQuery(elem).attr('name').split(':');\n                    jQuery('[name=locAttr\\:'+name[1]+'\\:term]').val(tdata[0].term);\n                  });\n                }\n              });\n            }\n          }\n        }\n      }\n      if(typeof hook_loadFilters != 'undefined')\n        hook_loadFilters(); // can only be done after attributes loaded\n     }});\n") . "\n  if(typeof hook_loadLocation != 'undefined')\n    hook_loadLocation(feature);\n}\ncheckEditable = function(isNew, id){\n  if(isNew) return true; // if I have created a new Site in this session, I can edit it.\n  if(typeof canEditExistingSites != 'undefined') return canEditExistingSites;\n  return(SiteEditable[id]);\n}\nconvertFeature = function(feature, projection){\n  if(feature instanceof Array){\n    if(feature.length == 0) return geom;\n    var newfeatures = [];\n    \$.each(feature, function(idx, featureElem){\n      newfeatures.push(convertFeature(featureElem, projection));\n    });\n    return newfeatures;\n  }\n  feature.geometry = convertGeom(feature.geometry, projection);\n  return feature;\n}\nconvertGeom = function(geom, projection){\n  if (projection.projcode!='EPSG:900913' && projection.projcode!='EPSG:3857') { \n    var cloned = geom.clone();\n    return cloned.transform(new OpenLayers.Projection('EPSG:900913'), projection);\n  }\n  return geom;\n}\nreverseConvertGeom = function(geom, projection){\n  if (projection.projcode!='EPSG:900913' && projection.projcode!='EPSG:3857') {\n    var cloned = geom.clone();\n    return cloned.transform(projection, new OpenLayers.Projection('EPSG:900913'));\n  }\n  return geom;\n}\nzoomToLayerExtent = function(layer){\n  var layerBounds = layer.getDataExtent().clone(); // use a clone\n  var mapBounds = layer.map.getMaxExtent();\n  if(layerBounds.left   < mapBounds.left)   layerBounds.left = mapBounds.left;\n  if(layerBounds.right  > mapBounds.right)  layerBounds.right = mapBounds.right;\n  if(layerBounds.bottom < mapBounds.bottom) layerBounds.bottom = mapBounds.bottom;\n  if(layerBounds.top    > mapBounds.top)    layerBounds.top = mapBounds.top;\n  layer.map.zoomToExtent(layerBounds);\n}\n\nloadFeatures = function(parent_id, child_id, childArgs, loadParent, setSelectOptions, zoomParent, clearLocationFlag, setPermissionState){\n  ParentLocationLayer.destroyFeatures();\n  SiteLabelLayer.destroyFeatures();\n  SiteAreaLayer.destroyFeatures();\n  SitePathLayer.destroyFeatures();\n  SitePointLayer.destroyFeatures();\n  if(setSelectOptions)\n    jQuery('#" . $options['MainFieldID'] . "').find('option').remove();\n" . ($args['locationMode'] != 'multi' && $args['siteNameTermListID'] != "" ? "  jQuery('#location-name').find('option').removeAttr('disabled');\n" : "") . "  if(clearLocationFlag){\n    clearLocation(false, true);\n  }\n  deactivateControls();\n  recalcNumSites();\n  SiteNum=0;\n  if(parent_id != '' && loadParent){\n    jQuery.getJSON(\"" . data_entry_helper::$base_url . "/index.php/services/data/location/\"+parent_id+\"?mode=json&view=detail&auth_token=" . $auth['read']['auth_token'] . "&nonce=" . $auth['read']["nonce"] . "&callback=?\",\n      function(data) {\n       if (data.length>0) {\n         var parser = new OpenLayers.Format.WKT();\n         if(data[0].boundary_geom){ // only one location if any\n           var feature = parser.read(data[0].boundary_geom)\n           feature=convertFeature(feature, \$('#map')[0].map.projection);\n           ParentLocationLayer.addFeatures([feature]);\n           if(zoomParent) {\n             // Parent squares may overlap the edges of the map.\n             zoomToLayerExtent(ParentLocationLayer);\n           }\n         }\n         selectFeature.activate();\n" . ($args['locationMode'] == 'multi' ? "  jQuery('#sample-location-name').val(data[0].name);" : "") . "       }});\n  }\n  if(!loadParent) selectFeature.activate();\n  if(parent_id != '' || loadParent==false){\n    jQuery.getJSON(\"" . data_entry_helper::$base_url . "/index.php/services/data/location?mode=json&view=detail&auth_token=" . $auth['read']['auth_token'] . "&nonce=" . $auth['read']["nonce"] . "&callback=?&orderby=name\"+" . $loctypequery . "+(loadParent ? '&parent_id='+parent_id : ''),\n      function(data) {\n        if (data.length>0) {\n          if(setPermissionState) setPermissionsNoSite();\n          if(child_id=='') selectFeature.activate(); // we have things we can select\n          if(setSelectOptions)\n            jQuery(\"#" . $options['MainFieldID'] . "\").append('<option value=\"\">" . lang::get("LANG_CommonEmptyLocationID") . "</option>');\n          var parser = new OpenLayers.Format.WKT();\n          var locationList = [];\n          for (var i=0;i<data.length;i++){\n            var centreFeature = false;\n            var feature;\n            SiteNum++;\n            if(data[i].boundary_geom){\n              feature = parser.read(data[i].boundary_geom); // assume map projection=900913, if GEOMETRYCOLLECTION this will be an array or its children!\n              var centre = false;\n              if(data[i].centroid_geom) {\n                centreFeature = parser.read(data[i].centroid_geom); // assume map projection=900913\n                centreFeature=convertFeature(centreFeature, \$('#map')[0].map.projection);\n              }\n              var pointFeature = false;\n              var lineFeature = false;\n              var areaFeature = false;\n              if(typeof(feature)=='object'&&(feature instanceof Array)){\n                for(var j=0; j< feature.length; j++){\n                  switch(feature[j].geometry.CLASS_NAME){\n                    case \"OpenLayers.Geometry.Point\":\n                    case \"OpenLayers.Geometry.MultiPoint\":\n                      pointFeature = feature[j];\n                      break;\n                    case \"OpenLayers.Geometry.LineString\":\n                    case \"OpenLayers.Geometry.MultiLineString\":\n                      lineFeature = feature[j];\n                      break;\n                    default:\n                      areaFeature = feature[j];\n                      break;\n                  }\n                }\n              } else {\n                switch(feature.geometry.CLASS_NAME){\n                  case \"OpenLayers.Geometry.Point\":\n                  case \"OpenLayers.Geometry.MultiPoint\":\n                    pointFeature = feature;\n                    break;\n                  case \"OpenLayers.Geometry.LineString\":\n                  case \"OpenLayers.Geometry.MultiLineString\":\n                    lineFeature = feature;\n                    break;\n                  default:\n                    areaFeature = feature;\n                    break;\n                }\n              }\n              if(areaFeature) {\n                areaFeature.attributes = {highlighted: false, 'new': false, canEdit: checkEditable(false, data[i].id), SiteNum: SiteNum, data: data[i]};\n                areaFeature=convertFeature(areaFeature, \$('#map')[0].map.projection);\n                SiteAreaLayer.addFeatures([areaFeature]);\n                if(!centreFeature) centreFeature = new OpenLayers.Feature.Vector(getCentroid(areaFeature.geometry));\n              }\n              if(lineFeature) {\n                lineFeature.attributes = {highlighted: false, 'new': false, canEdit: checkEditable(false, data[i].id), SiteNum: SiteNum, data: data[i]};\n                lineFeature=convertFeature(lineFeature, \$('#map')[0].map.projection);\n                SitePathLayer.addFeatures([lineFeature]);\n                if(!centreFeature) centreFeature = new OpenLayers.Feature.Vector(getCentroid(lineFeature.geometry));\n              }\n              if(pointFeature) {\n                pointFeature.attributes = {highlighted: false, 'new': false, canEdit: checkEditable(false, data[i].id), SiteNum: SiteNum, data: data[i]};\n                pointFeature=convertFeature(pointFeature, \$('#map')[0].map.projection);\n                SitePointLayer.addFeatures([pointFeature]);\n                if(!centreFeature) centreFeature = new OpenLayers.Feature.Vector(getCentroid(pointFeature.geometry));\n              }\n            } else {\n              // no boundary, only a centre point.\n              feature = parser.read(data[i].centroid_geom); // assume map projection=900913\n              feature=convertFeature(feature, \$('#map')[0].map.projection);\n              centreFeature = feature.clone();\n              feature.attributes = {highlighted: false, 'new': false, canEdit: checkEditable(false, data[i].id), SiteNum: SiteNum, data: data[i]};\n              SitePointLayer.addFeatures([feature]);\n            }\n            centreFeature.attributes = {highlighted: false, 'new': false, canEdit: checkEditable(false, data[i].id), SiteNum: SiteNum, data: data[i]};\n" . ($args['SecondaryLocationTypeTerm'] != '' && $options['AdminMode'] ? "            if(data[i].location_type_id == {$secondary}){\n              centreFeature.style = jQuery.extend({}, SiteListSecondaryLabelStyleHash);\n            } else \n  " : "") . "            centreFeature.style = jQuery.extend({}, SiteListPrimaryLabelStyleHash);\n            centreFeature.style.label = data[i].name;\n            SiteLabelLayer.addFeatures([centreFeature]);\n            locationList.push({id : data[i].id, feature : centreFeature});\n            if(setSelectOptions){\n              if(child_id != '' && data[i].id == child_id){\n                jQuery(\"#" . $options['MainFieldID'] . "\").append('<option value=\"'+data[i].id+'\" selected=\"selected\">'+data[i].name+'</option>');\n              } else {\n                jQuery(\"#" . $options['MainFieldID'] . "\").append('<option value=\"'+data[i].id+'\">'+data[i].name+'</option>');\n              }\n            }\n            if(child_id==data[i].id && setPermissionState){\n              if(centreFeature.attributes.canEdit){\n                setPermissionsOldEditableSite();\n              } else {\n                setPermissionsOldReadOnlySite()\n              }\n            }\n            if(typeof hook_ChildFeatureLoad != 'undefined') hook_ChildFeatureLoad(feature, data[i], child_id, childArgs);\n          }\n          recalcNumSites();\n          " . ($args['locationMode'] == 'single' || $args['locationMode'] == 'filtered' ? "" : "if(setSelectOptions) ") . "populateExtensions(locationList);\n        } else if(setSelectOptions){\n          if(setPermissionState) setPermissionsNoParent();\n          jQuery('#" . $options['MainFieldID'] . "').append('<option value=\"\">" . lang::get("LANG_NoSitesInSquare") . "</option>');\n        }\n    });\n  } else {\n    if(setPermissionState) setPermissionsNoParent();\n    if(setSelectOptions)\n      jQuery('#" . $options['MainFieldID'] . "').append('<option value=\"\">" . lang::get("LANG_CommonChooseParentFirst") . "</option>');\n  }\n};\nloadChildFeatures = function(parent_id, setSelectOptions){\n// this is only used when changing the parent: need to keep current highlighted features.\n  SiteNum=1;\n  for(var i=SiteLabelLayer.features.length-1; i >= 0; i--) {\n    if(SiteLabelLayer.features[i].attributes.highlighted == false) {\n      SiteLabelLayer.destroyFeatures([SiteLabelLayer.features[i]]);\n    } else {\n      SiteLabelLayer.features[i].attributes.SiteNum == SiteNum;\n    }\n  }\n  for(var i=SiteAreaLayer.features.length-1; i >= 0; i--) {\n    if(SiteAreaLayer.features[i].attributes.highlighted == false) {\n      SiteAreaLayer.destroyFeatures([SiteAreaLayer.features[i]]);\n    } else {\n      SiteAreaLayer.features[i].attributes.SiteNum == SiteNum;\n    }\n  }\n  for(var i=SitePathLayer.features.length-1; i >= 0; i--) {\n    if(SitePathLayer.features[i].attributes.highlighted == false) {\n      SitePathLayer.destroyFeatures([SitePathLayer.features[i]]);\n    } else {\n      SitePathLayer.features[i].attributes.SiteNum == SiteNum;\n    }\n  }\n  for(var i=SitePointLayer.features.length-1; i >= 0; i--) {\n    if(SitePointLayer.features[i].attributes.highlighted == false) {\n      SitePointLayer.destroyFeatures([SitePointLayer.features[i]]);\n      } else {\n      SitePointLayer.features[i].attributes.SiteNum == SiteNum;\n    }\n  }\n  if(setSelectOptions)\n    jQuery('#" . $options['MainFieldID'] . "').find('option').not(':selected').remove();\n" . ($args['locationMode'] != 'multi' && $args['siteNameTermListID'] != "" ? "  jQuery('#location-name').find('option').removeAttr('disabled');\n" : "") . "  recalcNumSites();\n  jQuery.getJSON(\"" . data_entry_helper::$base_url . "/index.php/services/data/location?mode=json&view=detail&auth_token=" . $auth['read']['auth_token'] . "&nonce=" . $auth['read']["nonce"] . "&callback=?&orderby=name\"+" . $loctypequery . "+'&parent_id='+parent_id,\n      function(data) {\n        if (data.length>0) {\n          if(setSelectOptions)\n            jQuery(\"#" . $options['MainFieldID'] . "\").append('<option value=\"\">" . lang::get("LANG_CommonEmptyLocationID") . "</option>');\n          var parser = new OpenLayers.Format.WKT();\n          var locationList = [];\n          for (var i=0;i<data.length;i++){\n            var centreFeature = false;\n            var feature;\n            SiteNum++;\n            if(data[i].boundary_geom){\n              feature = parser.read(data[i].boundary_geom); // assume map projection=900913, if GEOMETRYCOLLECTION this will be an array or its children!\n              var centre = false;\n              if(data[i].centroid_geom) {\n                centreFeature = parser.read(data[i].centroid_geom); // assume map projection=900913\n                centreFeature=convertFeature(centreFeature, \$('#map')[0].map.projection);\n              }\n              var pointFeature = false;\n              var lineFeature = false;\n              var areaFeature = false;\n              if(typeof(feature)=='object'&&(feature instanceof Array)){\n                for(var j=0; j< feature.length; j++){\n                  switch(feature[j].geometry.CLASS_NAME){\n                    case \"OpenLayers.Geometry.Point\":\n                    case \"OpenLayers.Geometry.MultiPoint\":\n                      pointFeature = feature[j];\n                      break;\n                    case \"OpenLayers.Geometry.LineString\":\n                    case \"OpenLayers.Geometry.MultiLineString\":\n                      lineFeature = feature[j];\n                      break;\n                    default:\n                      areaFeature = feature[j];\n                      break;\n                  }\n                }\n              } else {\n                switch(feature.geometry.CLASS_NAME){\n                  case \"OpenLayers.Geometry.Point\":\n                  case \"OpenLayers.Geometry.MultiPoint\":\n                    pointFeature = feature;\n                    break;\n                  case \"OpenLayers.Geometry.LineString\":\n                  case \"OpenLayers.Geometry.MultiLineString\":\n                    lineFeature = feature;\n                    break;\n                  default:\n                    areaFeature = feature;\n                    break;\n                }\n              }\n              if(areaFeature) {\n                areaFeature.attributes = {highlighted: false, 'new': false, canEdit: checkEditable(false, data[i].id), SiteNum: SiteNum, data: data[i]};\n                areaFeature=convertFeature(areaFeature, \$('#map')[0].map.projection);\n                SiteAreaLayer.addFeatures([areaFeature]);\n                if(!centreFeature) centreFeature = new OpenLayers.Feature.Vector(getCentroid(areaFeature.geometry));\n              }\n              if(lineFeature) {\n                lineFeature.attributes = {highlighted: false, 'new': false, canEdit: checkEditable(false, data[i].id), SiteNum: SiteNum, data: data[i]};\n                lineFeature=convertFeature(lineFeature, \$('#map')[0].map.projection);\n                SitePathLayer.addFeatures([lineFeature]);\n                if(!centreFeature) centreFeature = new OpenLayers.Feature.Vector(getCentroid(lineFeature.geometry));\n              }\n              if(pointFeature) {\n                pointFeature.attributes = {highlighted: false, 'new': false, canEdit: checkEditable(false, data[i].id), SiteNum: SiteNum, data: data[i]};\n                pointFeature=convertFeature(pointFeature, \$('#map')[0].map.projection);\n                SitePointLayer.addFeatures([pointFeature]);\n                if(!centreFeature) centreFeature = new OpenLayers.Feature.Vector(getCentroid(pointFeature.geometry));\n              }\n            } else {\n              // no boundary, only a centre point.\n              feature = parser.read(data[i].centroid_geom); // assume map projection=900913\n              feature=convertFeature(feature, \$('#map')[0].map.projection);\n              centreFeature = feature.clone();\n              feature.attributes = {highlighted: false, 'new': false, canEdit: checkEditable(false, data[i].id), SiteNum: SiteNum, data: data[i]};\n              SitePointLayer.addFeatures([feature]);\n            }\n            centreFeature.attributes = {highlighted: false, 'new': false, canEdit: checkEditable(false, data[i].id), SiteNum: SiteNum, data: data[i]};\n" . ($args['SecondaryLocationTypeTerm'] != '' && $options['AdminMode'] ? "            if(data[i].location_type_id == {$secondary}){\n              centreFeature.style = jQuery.extend({}, SiteListSecondaryLabelStyleHash);\n            } else \n  " : "") . "            centreFeature.style = jQuery.extend({}, SiteListPrimaryLabelStyleHash);\n            centreFeature.style.label = data[i].name;\n            SiteLabelLayer.addFeatures([centreFeature]);\n            locationList.push({id : data[i].id, feature : centreFeature});\n            if(setSelectOptions){\n              jQuery(\"#" . $options['MainFieldID'] . "\").append('<option value=\"'+data[i].id+'\">'+data[i].name+'</option>');\n            }\n            if(typeof hook_ChildFeatureLoad != 'undefined') hook_ChildFeatureLoad(feature, data[i], '', {});\n          }\n          recalcNumSites();\n          " . ($args['locationMode'] == 'single' || $args['locationMode'] == 'filtered' ? "" : "if(setSelectOptions) ") . "populateExtensions(locationList);\n        }\n  });\n};\npopulateExtensions = function(locids){\n// first get the list of attributes, sorted by location_id. Locations are in name order not ID order.\n// rip out the list of attribute captions.\n// loop through list of locations,\n// Binary search attribute list for my locations\n// Run through its attributes and do translate\n";
    if ($args['extendLocationNameTemplate'] != "") {
        data_entry_helper::$javascript .= "  locList = [];\n  for(var i=0;i<locids.length;i++){\n    var template = \"" . $args['extendLocationNameTemplate'] . "\".replace('{name}',locids[i].feature.attributes.data.name);\n    template = template.replace('{code}',locids[i].feature.attributes.data.code==null?'-':locids[i].feature.attributes.data.code);\n    locList.push({id : locids[i].id,\n        feature : locids[i].feature,\n        template : template});\n  }\n  jQuery.getJSON('" . data_entry_helper::$base_url . "/index.php/services/data/location_attribute_value' +\n            '?mode=json&view=list&auth_token=" . $auth['read']['auth_token'] . "&nonce=" . $auth['read']["nonce"] . "&orderby=location_id'+" . $loctypequery . "+'&callback=?', function(data) {\n    if(data instanceof Array && data.length>0){\n      function locBinarySearch(attList, location_id){ // this makes assumptions about the location attribute list contents and order.\n        var startIndex = 0,\n            stopIndex = attList.length - 1;\n        while(startIndex <= stopIndex){\n          var middle = Math.floor((stopIndex + startIndex)/2);\n          if (attList[middle].location_id == location_id) {\n            // there will be more than one attribute per location. Scan back.\n            while(middle > 0 && attList[middle-1].location_id == location_id) middle--;\n            return middle;\n          }\n          //adjust search area\n          if (parseInt(location_id) < parseInt(attList[middle].location_id)){\n            stopIndex = middle - 1;\n          } else {\n            startIndex = middle + 1;\n          }\n        }\n        return -1;\n      }\n      templateReplace = function(template, location_id, attList){\n        var attrid = locBinarySearch(attList, location_id);\n        if(attrid >= 0) {\n          while(attrid < attList.length && attList[attrid].location_id == location_id) {\n            if (attList[attrid].id){\n              template = template.replace('{'+attList[attrid].caption+'}',(attList[attrid].termlist_id != null ? convertTerm(parseInt(attList[attrid].raw_value)) : attList[attrid].value));\n            }\n            attrid++;\n          }\n        }";
        $attrArgs = array('valuetable' => 'location_attribute_value', 'attrtable' => 'location_attribute', 'key' => 'location_id', 'fieldprefix' => 'locAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id']);
        $locationAttributes = data_entry_helper::getAttributes($attrArgs, false);
        foreach ($locationAttributes as $locAttr) {
            data_entry_helper::$javascript .= "\n        template = template.replace('{" . $locAttr["untranslatedCaption"] . "}','-');";
        }
        data_entry_helper::$javascript .= "\n        return template;\n      };\n      for (var j=0;j<locList.length;j++){\n        locList[j].template = templateReplace(locList[j].template, locList[j].id, data);\n        SiteLabelLayer.removeFeatures([locList[j].feature]);\n        locList[j].feature.style.label = locList[j].template;\n        SiteLabelLayer.addFeatures([locList[j].feature]);\n" . ($args['locationMode'] != 'filtered' ? "        var myOption = jQuery(\"#" . $options['MainFieldID'] . "\").find('option').filter('[value='+locList[j].id+']').empty();\n" . ($args['SecondaryLocationTypeTerm'] != '' && $options['AdminMode'] ? "        if(locList[j].feature.attributes.data.location_type_id == {$primary})\n          myOption.css('color','red');\n" : "") . "        myOption.append(locList[j].template);" : "") . "\n      }\n    }});\n";
    }
    data_entry_helper::$javascript .= "\n}\ngetwkt = function(geometry, incFront, incBrackets){\n  var retVal;\n  retVal = '';\n  switch(geometry.CLASS_NAME){\n    case \"OpenLayers.Geometry.Point\":\n      return((incFront!=false ? 'POINT' : '')+(incBrackets!=false ? '(' : '')+geometry.x+' '+geometry.y+(incBrackets!=false ? ')' : ''));\n      break;\n    case \"OpenLayers.Geometry.MultiPoint\":\n      retVal = 'MULTIPOINT(';\n      for(var i=0; i< geometry.components.length; i++)\n        retVal += (i!=0 ? ',':'')+getwkt(geometry.components[i], false, true);\n      retVal += ')';\n      break;\n    case \"OpenLayers.Geometry.LineString\":\n      retVal = (incFront!=false ? 'LINESTRING' : '')+'(';\n      for(var i=0; i< geometry.components.length; i++)\n        retVal += (i!=0 ? ',':'')+getwkt(geometry.components[i], false, false);\n      retVal += ')';\n      break;\n    case \"OpenLayers.Geometry.MultiLineString\":\n      retVal = 'MULTILINESTRING(';\n      for(var i=0; i< geometry.components.length; i++)\n        retVal += (i!=0 ? ',':'')+getwkt(geometry.components[i], false, true);\n      retVal += ')';\n      break;\n    case \"OpenLayers.Geometry.Polygon\": // only do outer ring\n      retVal = (incFront!=false ? 'POLYGON' : '')+'((';\n      for(var i=0; i< geometry.components[0].components.length; i++)\n        retVal += (i!=0 ? ',':'')+getwkt(geometry.components[0].components[i], false, false);\n      retVal += '))';\n      break;\n    case \"OpenLayers.Geometry.MultiPolygon\":\n      retVal = 'MULTIPOLYGON(';\n      for(var i=0; i< geometry.components.length; i++)\n        retVal += (i!=0 ? ',':'')+getwkt(geometry.components[i], false, true);\n      retVal += ')';\n      break;\n    case \"OpenLayers.Geometry.Collection\":\n      retVal = 'GEOMETRYCOLLECTION(';\n      for(var i=0; i< geometry.components.length; i++)\n        retVal += (i!=0 ? ',':'')+getwkt(geometry.components[i], true, true);\n      retVal += ')';\n      break;\n  }\n  return retVal;\n}\nsetGeomFields = function(){\n  // use centre of Area as centroid\n  // Build the combined Geometry, ignore label\n  var geomstack = [];\n  var completeGeom;\n  var centreGeom;\n  var centreSrefGeom;\n  var mySiteNum;\n  var allFeatures = SiteAreaLayer.features.concat(SitePathLayer.features,SitePointLayer.features);\n  for(var i=allFeatures.length-1; i>=0; i--){\n    if(allFeatures[i].attributes.highlighted == true){\n      geomstack.push(allFeatures[i].geometry.clone()); // needs to be a clone as we don't want to transform the original geoms.\n      mySiteNum = allFeatures[i].attributes.SiteNum;\n    }\n  }\n  if(geomstack.length == 0){\n" . ($args['locationMode'] != 'multi' ? "    jQuery(\"#imp-boundary-geom\").val('');\n    jQuery(\"#imp-geom\").val('');\n    jQuery('#imp-sref').val('');\n    jQuery('#imp-srefX').val('');\n    jQuery('#imp-srefY').val('');\n" : "") . "    return;\n  } else if (geomstack.length == 1){\n    completeGeom = geomstack[0];\n  } else {\n    completeGeom = new OpenLayers.Geometry.Collection(geomstack);\n  }\n  centreSrefGeom=getCentroid(completeGeom);\n  // the geometry is in the map projection: if this doesn't match indicia's internal one, then must convert.\n  if (SiteAreaLayer.map.projection.projcode!='EPSG:900913' && SiteAreaLayer.map.projection.projcode!='EPSG:3857') { \n    completeGeom.transform(SiteAreaLayer.map.projection,  new OpenLayers.Projection('EPSG:900913'));\n  }\n  var boundaryWKT = getwkt(completeGeom, true, true);\n  centreGeom=getCentroid(completeGeom);\n  var centreWKT = getwkt(centreGeom, true, true);\n" . ($args['locationMode'] == 'multi' ? "  var highlighted = gethighlight();\n  hook_multisite_setGeomFields(highlighted[0], boundaryWKT, centreWKT);\n" : "  jQuery(\"#imp-boundary-geom\").val(boundaryWKT);\n  jQuery(\"#imp-geom\").val(centreWKT);\n  setSref(centreSrefGeom, 'TBC');  // forces the sref to be generated.\n") . "}\nsetDrawnGeom = function() {\n  // need to leave the location parent id enabled. Don't need to set geometries as we are using an existing location.\n  setPermissionsNewSite();\n  clearLocation(true, 'maybe');\n  if(jQuery('#dummy-parent-id').length>0 && jQuery('[name=location\\:parent_id]').length>0 &&\n      jQuery('#dummy-parent-id').val() != jQuery('[name=location\\:parent_id]').val())\n    jQuery('[name=location\\:parent_id]').val(jQuery('#dummy-parent-id').val()).change();\n" . ($creatorAttr ? "  jQuery('[name=locAttr:" . $creatorAttr . "],[name^=locAttr:" . $creatorAttr . ":]').val('" . $user->name . "');\n" : "") . "};\nremoveDrawnGeom = function(SiteNum){\n  var highlighted=gethighlight();\n  if(highlighted.length > 0 && highlighted[0].attributes.SiteNum == SiteNum) {\n    unhighlightAll();\n  }\n  for(var i=SiteLabelLayer.features.length-1; i>=0; i--)\n    if(SiteLabelLayer.features[i].attributes['new'] == true && SiteLabelLayer.features[i].attributes.SiteNum == SiteNum)\n      SiteLabelLayer.destroyFeatures([SiteLabelLayer.features[i]]);\n  for(var i=SiteAreaLayer.features.length-1; i>=0; i--)\n    if(SiteAreaLayer.features[i].attributes['new'] == true && SiteAreaLayer.features[i].attributes.SiteNum == SiteNum)\n      SiteAreaLayer.destroyFeatures([SiteAreaLayer.features[i]]);\n  for(var i=SitePathLayer.features.length-1; i>=0; i--)\n    if(SitePathLayer.features[i].attributes['new'] == true && SitePathLayer.features[i].attributes.SiteNum == SiteNum)\n      SitePathLayer.destroyFeatures([SitePathLayer.features[i]]);\n  for(var i=SitePointLayer.features.length-1; i>=0; i--)\n    if(SitePointLayer.features[i].attributes['new'] == true && SitePointLayer.features[i].attributes.SiteNum == SiteNum)\n      SitePointLayer.destroyFeatures([SitePointLayer.features[i]]);\n  recalcNumSites();\n}\nresetVertices = function(){\n  var allFeatures = SiteAreaLayer.features.concat(SitePathLayer.features,SitePointLayer.features);\n  for(var i=allFeatures.length-1; i>=0; i--){\n    if(typeof allFeatures[i].attributes['new'] == 'undefined'){ // not one of ours, so must be a vertex\n      var layer= allFeatures[i].layer;\n      layer.removeFeatures([allFeatures[i]]);\n      allFeatures[i].style=dragPointStyleHash;\n      layer.addFeatures([allFeatures[i]]);\n    }\n  }\n  // Oddball case is single points: in this case they use the actual point to drag not a proxy vertex.\n  if(modPointFeature.feature){\n    if(modPointFeature.feature.geometry.CLASS_NAME == \"OpenLayers.Geometry.Point\") {\n      var layer= modPointFeature.feature.layer;\n      layer.removeFeatures([modPointFeature.feature]);\n      modPointFeature.feature.style=dragPointStyleHash;\n      layer.addFeatures([modPointFeature.feature]);\n    }\n  } else {\n    for(var i=SitePointLayer.features.length-1; i>=0; i--){\n      if(SitePointLayer.features[i].style != null){\n        var feature = SitePointLayer.features[i];\n        var layer = feature.layer;\n        layer.removeFeatures([feature]);\n        feature.style=null;\n        layer.addFeatures([feature]);\n      }\n    }\n  }\n  SitePointLayer.redraw();\n}\nreplaceGeom = function(feature, layer, modControl, geom, highlight, setFields){\n  if(modControl.feature)\n    modControl.unselectFeature(modControl.feature);\n  var newfeature = new OpenLayers.Feature.Vector(geom, {});\n  newfeature.attributes = feature.attributes;\n  layer.destroyFeatures([feature]);\n  layer.addFeatures([newfeature]);\n  modControl.selectFeature(newfeature);\n  selectFeature.highlight(newfeature);\n  newfeature.attributes.highlighted=true;\n  resetVertices();\n  if(setFields) setGeomFields();\n}\naddAndSelectNewGeom = function(layer, modControl, geom, highlight){\n  SiteNum++;\n  var feature = new OpenLayers.Feature.Vector(geom, {highlighted: false, 'new': true, canEdit: true, SiteNum: SiteNum});\n  layer.addFeatures([feature]);\n  modControl.selectFeature(feature);\n  feature.attributes.highlighted=true;\n  selectFeature.highlight(feature);\n  resetVertices();\n  setGeomFields();\n  recalcNumSites();\n  return feature;\n}\naddToExistingFeatureSet = function(existingFeatures, layer, modControl, geom, highlight){\n  var feature = new OpenLayers.Feature.Vector(geom, {});\n  feature.attributes = existingFeatures[0].attributes;\n  layer.addFeatures([feature]);\n  modControl.selectFeature(feature);\n  selectFeature.highlight(feature);\n  feature.attributes.highlighted=true;\n  resetVertices();\n  setGeomFields();\n}\nunhighlightAll = function(){\n  if(modAreaFeature.feature) modAreaFeature.unselectFeature(modAreaFeature.feature);\n  if(modPathFeature.feature) modPathFeature.unselectFeature(modPathFeature.feature);\n  if(modPointFeature.feature) modPointFeature.unselectFeature(modPointFeature.feature);\n  var highlighted = gethighlight();\n  for(var i=0; i<highlighted.length; i++) {\n    highlighted[i].attributes.highlighted = false;\n    selectFeature.unhighlight(highlighted[i]);\n  }\n  resetVertices();\n}\nhighlightMe = function(id, SiteNum){\n  var allFeatures = SiteAreaLayer.features.concat(SitePathLayer.features,SitePointLayer.features,SiteLabelLayer.features);\n  for(var i=0; i<allFeatures.length; i++){\n    if((typeof allFeatures[i].attributes.data != 'undefined' &&\n          typeof allFeatures[i].attributes.data.id != 'undefined' &&\n          allFeatures[i].attributes.data.id == id) || \n        (typeof allFeatures[i].attributes.SiteNum != 'undefined' &&\n          allFeatures[i].attributes.SiteNum == SiteNum)){\n      allFeatures[i].attributes.highlighted = true;\n      selectFeature.highlight(allFeatures[i]);\n    }\n  }\n}\ngethighlight = function(){\n  var allFeatures = SiteAreaLayer.features.concat(SitePathLayer.features,SitePointLayer.features,SiteLabelLayer.features);\n  var features=[];\n  for(var i=0; i<allFeatures.length; i++){\n    if(allFeatures[i].attributes.highlighted==true){\n      features.push(allFeatures[i]);\n    }}\n  return features;\n}\n// default is to add a dummy new empty label\nif (typeof hook_new_site_added == 'undefined')\n hook_new_site_added = function(feature, SiteNum) {\n  var centreGeom;\n  var centrefeature;\n  if(!feature){\n    var div = jQuery('#map')[0];\n    var mapCentre = div.map.getCenter();\n    centreGeom = new OpenLayers.Geometry.Point(mapCentre.lon, mapCentre.lat);\n  } else {\n    centreGeom = getCentroid(feature.geometry);\n  }\n  centrefeature = new OpenLayers.Feature.Vector(centreGeom);\n  centrefeature.attributes['new']=true;\n  centrefeature.attributes.highlighted=true;\n  centrefeature.attributes.SiteNum=SiteNum;\n  centrefeature.style = jQuery.extend({}, SiteListPrimaryLabelStyleHash);\n  SiteLabelLayer.addFeatures([centrefeature]);\n  SitePointLayer.redraw();\n};\naddDrawnPointToSelection = function(geometry) {\n  // we assume that we have a point geometry.\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "  if(ParentLocationLayer.features.length == 0) return;\n  if(!ParentLocationLayer.features[0].geometry.intersects(geometry))\n    alert(\"" . lang::get('LANG_PointOutsideParent') . "\");\n" : "") . (isset($args['oneTypeAtATime']) && $args['oneTypeAtATime'] ? "  if(modPathFeature.feature) modPathFeature.unselectFeature(modPathFeature.feature);\n  if(modAreaFeature.feature) modAreaFeature.unselectFeature(modAreaFeature.feature);\n  SitePathLayer.destroyFeatures();\n  SiteAreaLayer.destroyFeatures();\n" : "") . "  var highlightedFeatures = gethighlight();\n" . (!$options['AdminMode'] || isset($args['adminsCanCreate']) && $args['adminsCanCreate'] ? "  if(highlightedFeatures.length == 0){\n    setDrawnGeom();\n    // No currently selected feature. Create a new one.\n    feature = addAndSelectNewGeom(SitePointLayer, modPointFeature, geometry, false);\n    hook_new_site_added(feature, feature.attributes.SiteNum);\n    if(typeof addPGPoint != 'undefined') addPGPoint(geometry);\n    return true;\n  }\n" : "  if(highlightedFeatures.length == 0) return true;\n") . "  var selectedFeature = false;\n  // a site is already selected so the Drawn/Specified state stays unaltered\n  for(var i=0; i<SitePointLayer.features.length; i++){\n    if(SitePointLayer.features[i].attributes.highlighted == true){\n      selectedFeature = SitePointLayer.features[i];\n      break;\n    }}\n  if(highlightedFeatures[0].attributes['new'] == true){\n    if(!selectedFeature) {\n      addToExistingFeatureSet(highlightedFeatures, SitePointLayer, modPointFeature, geometry, false);\n      if(typeof addPGPoint != 'undefined') addPGPoint(geometry);\n      return true;\n    }\n  } else { // highlighted is existing\n    if(highlightedFeatures[0].attributes.canEdit){\n      if(!selectedFeature) {\n        addToExistingFeatureSet(highlightedFeatures, SitePointLayer, modPointFeature, geometry, false);\n        if(typeof addPGPoint != 'undefined') addPGPoint(geometry);\n        return true;\n      }\n    } else {\n      return true;\n    }\n  }\n" . ($args['usePoints'] == 'single' ? "\n  if(typeof clearPGrid != 'undefined') clearPGrid(geometry);\n  replaceGeom(selectedFeature, SitePointLayer, modPointFeature, geometry, false, true);" : "\n  if(typeof addPGPoint != 'undefined') addPGPoint(geometry);\n  if(selectedFeature.geometry.CLASS_NAME == \"OpenLayers.Geometry.MultiPoint\") {\n    modPointFeature.unselectFeature(selectedFeature);\n    selectedFeature.geometry.addPoint(geometry);\n    modPointFeature.selectFeature(selectedFeature);\n    selectFeature.highlight(selectedFeature);\n    selectedFeature.attributes.highlighted = true;\n    resetVertices();\n    setGeomFields();\n  } else { // is OpenLayers.Geometry.Point\n    var CompoundGeom = new OpenLayers.Geometry.MultiPoint([selectedFeature.geometry, geometry]);\n    replaceGeom(selectedFeature, SitePointLayer, modPointFeature, CompoundGeom, false, true);\n  }") . "\n  return true;\n}\naddDrawnLineToSelection = function(geometry) {\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "  if(ParentLocationLayer.features.length == 0) return;\n" : "") . "  var points = geometry.getVertices();\n  if(points.length < 2){\n    alert(\"" . lang::get('LANG_TooFewLinePoints') . "\");\n    return false;\n  }\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "  var centre = getCentroid(geometry);\n  if(!ParentLocationLayer.features[0].geometry.intersects(centre))\n    alert(\"" . lang::get('LANG_LineOutsideParent') . "\");\n" : "") . (isset($args['oneTypeAtATime']) && $args['oneTypeAtATime'] ? "  if(modPointFeature.feature) modPointFeature.unselectFeature(modPointFeature.feature);\n  if(modAreaFeature.feature) modAreaFeature.unselectFeature(modAreaFeature.feature);\n  SitePointLayer.destroyFeatures();\n  SiteAreaLayer.destroyFeatures();\n" : "") . "  var highlightedFeatures = gethighlight();\n" . (!$options['AdminMode'] || isset($args['adminsCanCreate']) && $args['adminsCanCreate'] ? "  if(highlightedFeatures.length == 0){\n    setDrawnGeom();\n    // No currently selected feature. Create a new one.\n    feature = addAndSelectNewGeom(SitePathLayer, modPathFeature, geometry, true);\n    hook_new_site_added(feature, feature.attributes.SiteNum);\n    return true;\n  }\n" : "  if(highlightedFeatures.length == 0) return true;\n") . "\n  var selectedFeature = false;\n  for(var i=0; i<highlightedFeatures.length; i++){\n    if(highlightedFeatures[i].geometry.CLASS_NAME == \"OpenLayers.Geometry.LineString\" ||\n        highlightedFeatures[i].geometry.CLASS_NAME == \"OpenLayers.Geometry.MultiLineString\") {\n      selectedFeature = highlightedFeatures[i];\n      break;\n    }}\n  // a site is already selected so the Drawn/Specified state stays unaltered\n  if(highlightedFeatures[0].attributes['new'] == true){\n    if(!selectedFeature) {\n      addToExistingFeatureSet(highlightedFeatures, SitePathLayer, modPathFeature, geometry, true);\n      return true;\n    }\n  } else { // highlighted is existing\n    if(highlightedFeatures[0].attributes.canEdit){\n      if(!selectedFeature) {\n        addToExistingFeatureSet(highlightedFeatures, SitePathLayer, modPathFeature, geometry, true);\n        return true;\n      }\n    } else {\n      return true;\n    }\n  }\n  " . ($args['useLines'] == 'single' ? "\n  replaceGeom(selectedFeature, SitePathLayer, modPathFeature, geometry, true, true);" : "\n  if(selectedFeature.geometry.CLASS_NAME == \"OpenLayers.Geometry.MultiLineString\") {\n    modPathFeature.unselectFeature(selectedFeature);\n    selectedFeature.geometry.addComponents([geometry]);\n    modPathFeature.selectFeature(selectedFeature);\n    selectFeature.highlight(selectedFeature);\n    selectedFeature.attributes.highlighted = true;\n    resetVertices();\n    setGeomFields();\n  } else { // is OpenLayers.Geometry.LineString\n    var CompoundGeom = new OpenLayers.Geometry.MultiLineString([selectedFeature.geometry, geometry]);\n    replaceGeom(selectedFeature, SitePathLayer, modPathFeature, CompoundGeom, true, true);\n  }") . "\n  return true;\n}\naddDrawnPolygonToSelection = function(geometry) {\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "  if(ParentLocationLayer.features.length == 0) return;\n" : "") . "  var points = geometry.components[0].getVertices();\n  if(points.length < 3){\n    alert(\"" . lang::get('LANG_TooFewPoints') . "\");\n    return false;\n  }\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "  var centre = getCentroid(geometry);\n  if(!ParentLocationLayer.features[0].geometry.intersects(centre))\n    alert(\"" . lang::get('LANG_PolygonOutsideParent') . "\");\n" : "") . (isset($args['oneTypeAtATime']) && $args['oneTypeAtATime'] ? "  if(modPointFeature.feature) modPointFeature.unselectFeature(modPointFeature.feature);\n  if(modPathFeature.feature) modPathFeature.unselectFeature(modPathFeature.feature);\n  SitePointLayer.destroyFeatures();\n  SitePathLayer.destroyFeatures();\n" : "") . "  var highlightedFeatures = gethighlight();\n" . (!$options['AdminMode'] || isset($args['adminsCanCreate']) && $args['adminsCanCreate'] ? "  if(highlightedFeatures.length == 0){\n    setDrawnGeom();\n    // No currently selected feature. Create a new one.\n    feature = addAndSelectNewGeom(SiteAreaLayer, modAreaFeature, geometry, true);\n    hook_new_site_added(feature, feature.attributes.SiteNum);\n    return true;\n  }\n" : "  if(highlightedFeatures.length == 0) return true;\n") . "\n  var selectedFeature = false;\n  for(var i=0; i<highlightedFeatures.length; i++){\n    if(highlightedFeatures[i].geometry.CLASS_NAME == \"OpenLayers.Geometry.Polygon\" ||\n        highlightedFeatures[i].geometry.CLASS_NAME == \"OpenLayers.Geometry.MultiPolygon\") {\n      selectedFeature = highlightedFeatures[i];\n      break;\n    }}\n  // a site is already selected so the Drawn/Specified state stays unaltered\n  if(highlightedFeatures[0].attributes['new'] == true){\n    if(!selectedFeature) {\n      addToExistingFeatureSet(highlightedFeatures, SiteAreaLayer, modAreaFeature, geometry, true);\n      return true;\n    }\n  } else { // highlighted is existing\n    if(highlightedFeatures[0].attributes.canEdit){\n      if(!selectedFeature) {\n        addToExistingFeatureSet(highlightedFeatures, SiteAreaLayer, modAreaFeature, geometry, true);\n        return true;\n      }\n    } else {\n      return true;\n    }\n  }\n  " . ($args['usePolygons'] == 'single' ? "\n  replaceGeom(selectedFeature, SiteAreaLayer, modAreaFeature, geometry, true, true);" : "\n  if(selectedFeature.geometry.CLASS_NAME == \"OpenLayers.Geometry.MultiPolygon\") {\n    modAreaFeature.unselectFeature(selectedFeature);\n    selectedFeature.geometry.addComponents([geometry]);\n    modAreaFeature.selectFeature(selectedFeature);\n    selectFeature.highlight(selectedFeature);\n    selectedFeature.attributes.highlighted = true;\n    resetVertices();\n    setGeomFields();\n  } else { // is OpenLayers.Geometry.Polygon\n    var CompoundGeom = new OpenLayers.Geometry.MultiPolygon([selectedFeature.geometry, geometry]);\n    replaceGeom(selectedFeature, SiteAreaLayer, modAreaFeature, CompoundGeom, true, true);\n  }") . "\n  return true;\n}\nonFeatureModified = function(evt) {\n  var feature = evt.feature;\n  switch(feature.geometry.CLASS_NAME){\n    case \"OpenLayers.Geometry.Point\":\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "      if(!ParentLocationLayer.features[0].geometry.intersects(feature.geometry))\n        alert(\"" . lang::get('LANG_PointOutsideParent') . "\");\n" : "") . "      if(typeof modPGPoint != 'undefined') modPGPoint(feature.geometry);\n      break;\n    case \"OpenLayers.Geometry.MultiPoint\":\n      if(feature.geometry.components.length == 0){\n        modPointFeature.unselectFeature(feature);\n        SitePointLayer.destroyFeatures([feature]);\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "     } else {\n        var centre = getCentroid(feature.geometry);\n        if(!ParentLocationLayer.features[0].geometry.intersects(centre))\n          alert(\"" . lang::get('LANG_PointOutsideParent') . "\");\n" : "") . "      }\n      if(typeof modPGPoint != 'undefined') modPGPoint(feature.geometry);\n      break;\n    case \"OpenLayers.Geometry.LineString\":\n      points = feature.geometry.getVertices();\n      if(points.length < 2){\n        alert(\"" . lang::get('LANG_TooFewLinePoints') . "\");\n        modPathFeature.unselectFeature(feature);\n        SitePathLayer.destroyFeatures([feature]);\n      }\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "      else {\n        var centre = getCentroid(feature.geometry);\n        if(!ParentLocationLayer.features[0].geometry.intersects(centre))\n          alert(\"" . lang::get('LANG_LineOutsideParent') . "\");\n      }\n" : "") . "      break;\n    case \"OpenLayers.Geometry.MultiLineString\":\n      for(i=feature.geometry.components.length-1; i>=0; i--) {\n        points = feature.geometry.components[i].getVertices();\n        if(points.length < 2){\n          alert(\"" . lang::get('LANG_TooFewLinePoints') . "\");\n          var selectedFeature = modPathFeature.feature;\n          modPathFeature.unselectFeature(selectedFeature);\n          selectFeature.unhighlight(selectedFeature);\n          SitePathLayer.removeFeatures([selectedFeature]);\n          selectedFeature.geometry.removeComponents([feature.geometry.components[i]]);\n          SitePathLayer.addFeatures([selectedFeature]);\n          modPathFeature.selectFeature(selectedFeature);\n          selectFeature.highlight(selectedFeature);\n          selectedFeature.attributes.highlighted = true;\n        }\n      }\n      if(feature.geometry.components.length == 0){\n        modPathFeature.unselectFeature(feature);\n        SitePathLayer.destroyFeatures([feature]);\n      }\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "      else {\n        var centre = getCentroid(feature.geometry);\n        if(!ParentLocationLayer.features[0].geometry.intersects(centre))\n          alert(\"" . lang::get('LANG_LineOutsideParent') . "\");\n      }\n" : "") . "      break;\n    case \"OpenLayers.Geometry.Polygon\": // only do outer ring\n      points = feature.geometry.components[0].getVertices();\n      if(points.length < 3){\n        alert(\"" . lang::get('LANG_TooFewPoints') . "\");\n        modAreaFeature.unselectFeature(feature);\n        SiteAreaLayer.destroyFeatures([feature]);\n      }\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "      else {\n        var centre = getCentroid(feature.geometry);\n        if(!ParentLocationLayer.features[0].geometry.intersects(centre))\n          alert(\"" . lang::get('LANG_CentreOutsideParent') . "\");\n      }\n" : "") . "      break;\n    case \"OpenLayers.Geometry.MultiPolygon\":\n      for(i=feature.geometry.components.length-1; i>=0; i--) {\n        points = feature.geometry.components[i].components[0].getVertices();\n        if(points.length < 3){\n          alert(\"" . lang::get('LANG_TooFewPoints') . "\");\n          var selectedFeature = modAreaFeature.feature;\n          modAreaFeature.unselectFeature(selectedFeature);\n          selectFeature.unhighlight(selectedFeature);\n          SiteAreaLayer.removeFeatures([selectedFeature]);\n          selectedFeature.geometry.removeComponents([feature.geometry.components[i]]);\n          SiteAreaLayer.addFeatures([selectedFeature]);\n          modAreaFeature.selectFeature(selectedFeature);\n          selectFeature.highlight(selectedFeature);\n          selectedFeature.attributes.highlighted = true;\n        }\n      }\n      if(feature.geometry.components.length == 0){\n        modAreaFeature.unselectFeature(feature);\n        SiteAreaLayer.destroyFeatures([feature]);\n      }\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "      else {\n        var centre = getCentroid(feature.geometry);\n        if(!ParentLocationLayer.features[0].geometry.intersects(centre))\n          alert(\"" . lang::get('LANG_CentreOutsideParent') . "\");\n      }\n" : "") . "      break;\n  }\n  resetVertices();\n  setGeomFields();\n}\n// TBD should only include next when siteNameTermListID set\nsetNameDropDowns = function(disable, value){\n  jQuery('#dummy-name').find('*').removeAttr('disabled');\n  if(disable === true){\n  \tjQuery('#dummy-name').val('').attr('disabled','disabled');\n  \treturn;\n  }\n  if(disable === false)\n  \tjQuery('#dummy-name').removeAttr('disabled');\n  if(value===false && jQuery('#dummy-name').val() !== '') value=jQuery('#dummy-name').val()\n  if(value !== '')\n    jQuery('#dummy-name').find('option').filter('[value=]').attr('disabled','disabled');\n  jQuery('#dummy-name').find('option').each(function (index, option){\n  // TBD convert this to look at the features.\n      if((value == false || jQuery(option).val() != value) &&\n          jQuery('.cggrid-row,.cgAddedRow').find('.cggrid-name').filter('[value='+jQuery(option).val()+']').length > 0)\n        jQuery(option).attr('disabled','disabled');\n  });\n  if(value!==false) jQuery('#dummy-name').val(value);\n};\n/********************************/\n/* Define Map Control callbacks */\n/********************************/\nCancelSketch = function(layer){\n  for(var i = editControl.controls.length-1; i>=0; i--)\n    if(editControl.controls[i].CLASS_NAME == \"OpenLayers.Control.DrawFeature\" && editControl.controls[i].active)\n      editControl.controls[i].cancel();\n};\nUndoSketchPoint = function(layer){\n  for(var i = editControl.controls.length-1; i>=0; i--)\n    if(editControl.controls[i].CLASS_NAME == \"OpenLayers.Control.DrawFeature\" && editControl.controls[i].active)\n      editControl.controls[i].undo();\n};\nRemoveNewSite = function(){\n  // can only remove the site if highlighted,\n  var highlighted = gethighlight();\n  if(highlighted.length == 0 || !highlighted[0].attributes['new']) return;\n  if(confirm('" . lang::get('LANG_ConfirmRemoveDrawnSite') . "')){\n    if(typeof hook_RemoveNewSite != 'undefined')\n      hook_RemoveNewSite();\n    clearLocation(true, true);\n    removeDrawnGeom(highlighted[0].attributes.SiteNum);\n    recalcNumSites();\n    setGeomFields();\n    if(typeof setNameDropDowns != 'undefined')\n      setNameDropDowns(true, false);\n  }\n};\nStartNewSite = function(){\n  var keepName=false;\n" . ($args['locationMode'] == 'parent' ? "  if(jQuery('#" . $options['ChooseParentFieldID'] . "').val()==''){\n    alert('" . lang::get('LANG_MustSelectParentFirst') . "');\n    return;\n  };" : "") . "\n" . ($args['locationMode'] == 'multi' ? "  unhighlightAll();\n" . (isset($args['siteNameTermListID']) && $args['siteNameTermListID'] != '' ? "  setNameDropDowns(false, '');\n" : "  jQuery('#dummy-name').val('');\n") : "  keepName = jQuery('#" . $options['MainFieldID'] . "').val() == '';\n  // first remove any existing new location.\n  var highlighted = gethighlight();\n  var found=false;\n  // only confirm if have something drawn on map: ie ignore label\n  for(i=0; i<highlighted.length; i++) found = found || (highlighted[i].layer != SiteLabelLayer && highlighted[i].attributes['new']==true)\n  if(found && !confirm('" . lang::get('LANG_ConfirmRemoveDrawnSite') . "')) return false;\n  if(highlighted.length>0 && highlighted[0].attributes['new']==true) removeDrawnGeom(highlighted[0].attributes.SiteNum); // remove label here\n  unhighlightAll();\n  jQuery('#" . $options['MainFieldID'] . ",#sample-location-id').val(''); // reset id field.\n") . "  setPermissionsNewSite(); // need to leave the location parent id enabled.\n  clearLocation(true, !keepName);\n  if(jQuery('#dummy-parent-id').length>0 && jQuery('[name=location\\:parent_id]').length>0 &&\n      jQuery('#dummy-parent-id').val() != jQuery('[name=location\\:parent_id]').val())\n    jQuery('[name=location\\:parent_id]').val(jQuery('#dummy-parent-id').val()).change();\n" . ($creatorAttr ? "  jQuery('[name=locAttr:" . $creatorAttr . "],[name^=locAttr:" . $creatorAttr . ":]').val('" . $user->name . "');\n" : "") . "  // No currently selected feature. Create a dummy label new one.\n  SiteNum++;\n  hook_new_site_added(false, SiteNum);\n  // Programatic activation does not rippleout to deactivate other draw features, so deactivate all first.\n  for(var i=0; i<editControl.controls.length; i++)\n    if(editControl.controls[i].CLASS_NAME == \"OpenLayers.Control.DrawFeature\")\n      editControl.controls[i].deactivate();\n  // we assume there is at least one drawing control: activate the first one.\n  selectFeature.activate();\n  for(var i=0; i<editControl.controls.length; i++){\n    if(editControl.controls[i].CLASS_NAME == \"OpenLayers.Control.DrawFeature\"){\n      selectFeature.deactivate();\n      editControl.controls[i].activate();\n      // new site will have no vertices yet...\n      return;\n    }}\n}\nZoomToFeature = function(feature){\n  var div = jQuery('#map')[0];\n  var bounds=feature.geometry.bounds.clone();\n  // extend the boundary to include a buffer, so the map does not zoom too tight.\n  var dy = (bounds.top-bounds.bottom) * div.settings.maxZoomBuffer;\n  var dx = (bounds.right-bounds.left) * div.settings.maxZoomBuffer;\n  bounds.top = bounds.top + dy;\n  bounds.bottom = bounds.bottom - dy;\n  bounds.right = bounds.right + dx;\n  bounds.left = bounds.left - dx;\n  if (div.map.getZoomForExtent(bounds) > div.settings.maxZoom) {\n    // if showing something small, don't zoom in too far\n    div.map.setCenter(bounds.getCenterLonLat(), div.settings.maxZoom);\n  } else {\n    // Set the default view to show something triple the size of the grid square\n    // Assume this is within the map extent\n    div.map.zoomToExtent(bounds);\n  }\n};\nZoomToSite = function(){\n  var div = jQuery('#map')[0];\n  if(modPointFeature.feature){\n    return ZoomToFeature(modPointFeature.feature);}\n  if(modPathFeature.feature){\n    return ZoomToFeature(modPathFeature.feature);}\n  if(modAreaFeature.feature){\n    return ZoomToFeature(modAreaFeature.feature);}\n  var highlighted = gethighlight();\n  if(highlighted.length>0){\n    var div = jQuery('#map')[0];\n    var bounds=highlighted[0].geometry.bounds.clone();\n    \$.each(highlighted, function(idx, feat){\n      bounds.extend(feat.geometry.bounds);\n    });\n    // extend the boundary to include a buffer, so the map does not zoom too tight.\n    var dy = (bounds.top-bounds.bottom) * div.settings.maxZoomBuffer;\n    var dx = (bounds.right-bounds.left) * div.settings.maxZoomBuffer;\n    bounds.top = bounds.top + dy;\n    bounds.bottom = bounds.bottom - dy;\n    bounds.right = bounds.right + dx;\n    bounds.left = bounds.left - dx;\n    if (div.map.getZoomForExtent(bounds) > div.settings.maxZoom) {\n      // if showing something small, don't zoom in too far\n      div.map.setCenter(bounds.getCenterLonLat(), div.settings.maxZoom);\n    } else {\n      // Set the default view to show something triple the size of the grid square\n      // Assume this is within the map extent\n      div.map.zoomToExtent(bounds);\n    }\n  }\n};\nZoomToParent = function(){\n  if(ParentLocationLayer.features.length > 0)\n    zoomToLayerExtent(ParentLocationLayer);\n};\nZoomToCountry = function(){\n\tvar div = jQuery('#map')[0];\n\tvar center = new OpenLayers.LonLat(" . $args['map_centroid_long'] . "," . $args['map_centroid_lat'] . ");\n\tcenter.transform(div.map.displayProjection, div.map.projection);\n\tdiv.map.setCenter(center, " . (int) $args['map_zoom'] . ");\n}\n/***********************************/\n/* Define Controls for use on Map. */\n/***********************************/\nselectFeatureActivate = function(){\n    if(modAreaFeature.feature) modAreaFeature.unselectFeature(modAreaFeature.feature);\n    if(modPathFeature.feature) modPathFeature.unselectFeature(modPathFeature.feature);\n    if(modPointFeature.feature) modPointFeature.unselectFeature(modPointFeature.feature);\n    modAreaFeature.deactivate();\n    modPathFeature.deactivate();\n    modPointFeature.deactivate();\n    resetVertices();\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "    if(!ParentLocationLayer.features.length) {\n      selectFeature.deactivate();\n      return false;\n    }\n" : "") . "    return true;\n};\npolygonDrawActivate = function(){\n  if(modPointFeature.feature) modPointFeature.unselectFeature(modPointFeature.feature);\n  if(modPathFeature.feature) modPathFeature.unselectFeature(modPathFeature.feature);\n  selectFeature.deactivate();\n  modPointFeature.deactivate();\n  modPathFeature.deactivate();\n  resetVertices();\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "  if(!ParentLocationLayer.features.length) {\n    polygonDraw.deactivate();\n    return false;\n  }\n" : "") . "  highlighted = gethighlight();\n  if(highlighted.length == 0){\n" . (!$options['AdminMode'] || isset($args['adminsCanCreate']) && $args['adminsCanCreate'] ? "    modAreaFeature.activate();\n    return true;\n  }\n  if(highlighted[0].attributes['new'] == true){\n    modAreaFeature.activate();\n    for(var i=0; i<SiteAreaLayer.features.length; i++){\n      if(SiteAreaLayer.features[i].attributes.highlighted == true){\n        modAreaFeature.selectFeature(SiteAreaLayer.features[i]);}}\n    resetVertices();\n    return true;\n" : "    polygonDraw.deactivate();\n    selectFeature.activate();\n    return false;\n") . "  }\n  // highlight feature is an existing one.\n  if(highlighted[0].attributes.canEdit){\n    modAreaFeature.activate();\n    for(var i=0; i<SiteAreaLayer.features.length; i++){\n      if(SiteAreaLayer.features[i].attributes.highlighted == true){\n        modAreaFeature.selectFeature(SiteAreaLayer.features[i]);}}\n    resetVertices();\n    return true;\n  }\n  polygonDraw.deactivate();\n  selectFeature.activate();\n  return false;\n};\nlineDrawActivate = function(){\n  if(modPointFeature.feature) modPointFeature.unselectFeature(modPointFeature.feature);\n  if(modAreaFeature.feature) modAreaFeature.unselectFeature(modAreaFeature.feature);\n  selectFeature.deactivate();\n  modPointFeature.deactivate();\n  modAreaFeature.deactivate();\n  resetVertices();\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "  if(!ParentLocationLayer.features.length) {\n    lineDraw.deactivate();\n    return false;\n  }\n" : "") . "  highlighted = gethighlight();\n  if(highlighted.length == 0){\n" . (!$options['AdminMode'] || isset($args['adminsCanCreate']) && $args['adminsCanCreate'] ? "    modPathFeature.activate();\n    return true;\n  }\n  if(highlighted[0].attributes['new'] == true){\n    modPathFeature.activate();\n    for(var i=0; i<SitePathLayer.features.length; i++){\n      if(SitePathLayer.features[i].attributes.highlighted == true){\n        modPathFeature.selectFeature(SitePathLayer.features[i]);}}\n    resetVertices();\n    return true;\n" : "    lineDraw.deactivate();\n    selectFeature.activate();\n    return false;\n") . "  }\n  // highlight feature is an existing one.\n  if(highlighted[0].attributes.canEdit){\n    modPathFeature.activate();\n    for(var i=0; i<SitePathLayer.features.length; i++){\n      if(SitePathLayer.features[i].attributes.highlighted == true){\n        modPathFeature.selectFeature(SitePathLayer.features[i]);}}\n    resetVertices();\n    return true;\n  }\n  lineDraw.deactivate();\n  selectFeature.activate();\n  return false;\n};\npointDrawDeactivate = function(){\n  if(typeof removePopups != 'undefined') removePopups();\n  jQuery(\"#pointgrid\").hide();\n};\npointDrawActivate = function(){\n  jQuery(\"#pointgrid\").show();\n  if(modAreaFeature.feature) modAreaFeature.unselectFeature(modAreaFeature.feature);\n  if(modPathFeature.feature) modPathFeature.unselectFeature(modPathFeature.feature);\n  selectFeature.deactivate();\n  modAreaFeature.deactivate();\n  modPathFeature.deactivate();\n  resetVertices();\n" . ($args['locationMode'] != 'single' && $args['locationMode'] != 'filtered' ? "  if(!ParentLocationLayer.features.length) {\n    pointDraw.deactivate();\n    return false;\n  }\n" : "") . "  highlighted = gethighlight();\n  if(highlighted.length == 0){\n" . (!$options['AdminMode'] || isset($args['adminsCanCreate']) && $args['adminsCanCreate'] ? "    modPointFeature.activate();\n    return true;\n  }\n  if(highlighted[0].attributes['new'] == true){\n    modPointFeature.activate();\n    for(var i=0; i<SitePointLayer.features.length; i++){\n      if(SitePointLayer.features[i].attributes.highlighted == true){\n        modPointFeature.selectFeature(SitePointLayer.features[i]);\n        resetVertices();}}\n    if(typeof populatePGrid != 'undefined') populatePGrid();\n    return true;\n" : "    pointDraw.deactivate();\n    selectFeature.activate();\n    return false;\n") . "  }\n  // highlight feature is an existing one.\n  if(highlighted[0].attributes.canEdit){\n    modPointFeature.activate();\n    for(var i=0; i<SitePointLayer.features.length; i++){\n      if(SitePointLayer.features[i].attributes.highlighted == true){\n        modPointFeature.selectFeature(SitePointLayer.features[i]);\n        resetVertices();}}\n    if(typeof populatePGrid != 'undefined') populatePGrid();\n    return true;\n  }\n  pointDraw.deactivate();\n  selectFeature.activate();\n  return false;\n};\nMyEditingToolbar=OpenLayers.Class(\n\t\tOpenLayers.Control.Panel,{\n\t\t\tinitialize:function(layer,options){\n\t\t\t\tOpenLayers.Control.Panel.prototype.initialize.apply(this,[options]);\n\t\t\t\tthis.addControls([selectFeature\n" . ($args['usePolygons'] != 'none' ? "\t\t\t\t         ,polygonDraw\n" : '') . ($args['useLines'] != 'none' ? "\t\t\t\t         ,lineDraw\n" : '') . ($args['usePoints'] != 'none' ? "\t\t\t\t         ,pointDraw\n" : '') . ($args['usePolygons'] != 'none' || $args['useLines'] != 'none' ? "\t\t\t\t         ,new OpenLayers.Control.Button({displayClass: \"olControlCancelSketch\", trigger: CancelSketch, title: '" . lang::get('LANG_CancelSketchTooltip') . "'})\n\t\t\t\t         ,new OpenLayers.Control.Button({displayClass: \"olControlUndoSketchPoint\", trigger: UndoSketchPoint, title: '" . lang::get('LANG_UndoSketchPointTooltip') . "'})\n" : '') . (!$options['AdminMode'] || isset($args['adminsCanCreate']) && $args['adminsCanCreate'] ? "\t\t\t\t         ,new OpenLayers.Control.Button({displayClass: \"olControlRemoveNewSite\", trigger: RemoveNewSite, title: '" . lang::get('LANG_RemoveNewSite') . "'})\n\t\t\t\t         ,new OpenLayers.Control.Button({displayClass: \"olControlStartNewSite\", trigger: StartNewSite, title: '" . lang::get('LANG_StartNewSite') . "'})\n" : '') . "\t\t\t\t         ,new OpenLayers.Control.Button({displayClass: \"olControlZoomToSite\", trigger: ZoomToSite, title: '" . lang::get('LANG_ZoomToSite') . "'})\n" . ($args['locationMode'] != 'single' ? "\t\t\t\t         ,new OpenLayers.Control.Button({displayClass: \"olControlZoomToSquare\", trigger: ZoomToParent, title: '" . lang::get('LANG_ZoomToParent') . "'})\n" : '') . "\t\t\t\t         ,new OpenLayers.Control.Button({displayClass: \"olControlZoomToCountry\", trigger: ZoomToCountry, title: '" . lang::get('LANG_ZoomToCountry') . "'})\n\t\t\t\t         ]);\n\t},\n\tCLASS_NAME:\"MyEditingToolbar\"});\ndeactivateControls = function(){\n  if(typeof editControl != 'undefined'){\n    for(var i = editControl.controls.length-1; i>=0; i--){\n      if(editControl.controls[i].CLASS_NAME == \"OpenLayers.Control.DrawFeature\" ||\n         editControl.controls[i].CLASS_NAME == \"OpenLayers.Control.SelectFeature\") {\n        editControl.controls[i].deactivate();\n    }}}\n};\nsetSpecifiedLocation = function() {\n  var highlighted = gethighlight();\n  if(highlighted[0].attributes.canEdit){\n    setPermissionsOldEditableSite(false);\n  } else {\n    // need to leave the location parent id enabled. Don't need to set geometries as we are using an existing location.\n    setPermissionsOldReadOnlySite();\n  }\n}\nonFeatureSelect = function(evt) {\n  var feature = evt.feature;\n  if(feature.attributes.highlighted==true) return false;\n" . ($args['locationMode'] == 'multi' ? "  unhighlightAll();\n" : "  var willRemove = false;\n  var allFeatures = SiteAreaLayer.features.concat(SitePathLayer.features,SitePointLayer.features);\n  for(var i=0; i<allFeatures.length; i++)\n    willRemove = willRemove || (allFeatures[i].attributes['new']==true);\n  if(willRemove && !confirm('" . lang::get('LANG_ConfirmRemoveDrawnSite') . "')) return false;\n  var highlighted = gethighlight();\n  if(highlighted.length > 0 && highlighted[0].attributes['new'])\n    removeDrawnGeom(highlighted[0].attributes.SiteNum);\n  else\n    // Any highlighted existing features should be unhighlighted.\n    unhighlightAll();\n  jQuery(\"#" . $options['MainFieldID'] . ",#sample-location-id\").val(feature.attributes.data.id);\n") . "  ZoomToFeature(feature);\n  // now highlight the new ones\n  highlightMe(false, feature.attributes.SiteNum); // need to fetch SiteNum in case highlight new.\n  loadLocation(feature);\n  return false;\n}\nmodAreaFeature = new OpenLayers.Control.ModifyFeature(SiteAreaLayer,{standalone: true});\nmodPathFeature = new OpenLayers.Control.ModifyFeature(SitePathLayer,{standalone: true});\nmodPointFeature = new OpenLayers.Control.ModifyFeature(SitePointLayer,{standalone: true});\nselectFeature = new OpenLayers.Control.SelectFeature([SiteAreaLayer,SitePathLayer,SitePointLayer,SiteLabelLayer],{'displayClass':'olControlSelectFeature', title: '" . lang::get('LANG_SelectTooltip') . "'});\nselectFeature.events.on({'activate': selectFeatureActivate});\npolygonDraw = new OpenLayers.Control.DrawFeature(SiteAreaLayer,OpenLayers.Handler.Polygon,{'displayClass':'olControlDrawFeaturePolygon', drawFeature: addDrawnPolygonToSelection, title: '" . lang::get('LANG_PolygonTooltip') . "'});\npolygonDraw.events.on({'activate': polygonDrawActivate});\nlineDraw = new OpenLayers.Control.DrawFeature(SitePathLayer,OpenLayers.Handler.Path,{'displayClass':'olControlDrawFeaturePath', drawFeature: addDrawnLineToSelection, title: '" . lang::get('LANG_LineTooltip') . "'});\nlineDraw.events.on({'activate': lineDrawActivate});\npointDraw = new OpenLayers.Control.DrawFeature(SitePointLayer,OpenLayers.Handler.Point,{'displayClass':'olControlDrawFeaturePoint', drawFeature: addDrawnPointToSelection, title: '" . lang::get('LANG_PointTooltip') . "'});\npointDraw.events.on({'activate': pointDrawActivate, 'deactivate': pointDrawDeactivate});\neditControl = new MyEditingToolbar(SiteAreaLayer, {allowDepress: false, 'displayClass':'olControlEditingToolbar'});\n\nmapInitialisationHooks.push(function(mapdiv) {\n\t// try to identify if this map is the main one\n\tif(mapdiv.id=='map'){\n\t\tmapdiv.map.addControl(modAreaFeature);\n\t\tmapdiv.map.addControl(modPathFeature);\n\t\tmapdiv.map.addControl(modPointFeature);\n\t\tmodAreaFeature.deactivate();\n\t\tmodPathFeature.deactivate();\n\t\tmodPointFeature.deactivate();\n\t\tmapdiv.map.addControl(editControl);\n" . (isset($args['mousePosControl']) && $args['mousePosControl'] ? "\t\tjQuery('.olControlEditingToolbar').append('<span id=\"mousePos\"></span>');\n\t\tvar mousePosCtrl = new OpenLayers.Control.MousePosition({\n\t\t  div: document.getElementById('mousePos'),\n\t\t  prefix: 'LUREF:',\n\t\t  displayProjection: new OpenLayers.Projection('EPSG:2169'),\n\t\t  emptyString: '',\n\t\t  numDigits: 0 \n\t\t});\n\t\tmapdiv.map.addControl(mousePosCtrl);\n" : "") . "\t\teditControl.activate();\n\t\tif(SiteAreaLayer.map.editLayer){\n\t\t\tSiteAreaLayer.map.editLayer.clickControl.deactivate();\n\t\t\tSiteAreaLayer.map.editLayer.destroyFeatures();\n\t\t}\n\t\tmapdiv.map.events.on({'zoomend': function(){\n\t\t  if(jQuery('#map')[0].map.zoom >= " . $args['labelZoomLevel'] . "){\n\t\t    if(!SiteLabelLayer.getVisibility())\n\t\t      SiteLabelLayer.setVisibility(true);\n\t\t  } else {\n\t \t   if(SiteLabelLayer.getVisibility())\n\t \t     SiteLabelLayer.setVisibility(false);\n\t \t }\n\t\t}});\n\t\tmapdiv.map.events.triggerEvent('zoomend');\n";
    // If entity to load is set, then we are highlighting an existing location, can't modify, but can start drawing another site.
    if (isset(data_entry_helper::$entity_to_load['location:id'])) {
        switch ($args['locationMode']) {
            // TBD fieldname should be ParentFieldName
            case 'multi':
                data_entry_helper::$javascript .= "\t\tloadFeatures(" . data_entry_helper::$entity_to_load['sample:location_id'] . ",'',{initial: true}, true, true, true, true, true);\n";
                break;
            case 'single':
                data_entry_helper::$javascript .= "\t\tloadFeatures(''," . data_entry_helper::$entity_to_load['location:id'] . ",{initial: true}, false, false, false, false, true);\n";
                break;
            case 'filtered':
                $activeParent = false;
                $filterAttrs = explode(',', $args['filterAttrs']);
                foreach ($filterAttrs as $idx => $filterAttr) {
                    $filterAttr = explode(':', $filterAttr);
                    if ($filterAttr[0] == 'Parent' && $filterAttr[1] == "true") {
                        $activeParent = true;
                    }
                }
                if ($activeParent) {
                    data_entry_helper::$javascript .= "\t\tloadFeatures(" . data_entry_helper::$entity_to_load['location:parent_id'] . "," . data_entry_helper::$entity_to_load['location:id'] . ",{initial: true}, true, false, false, false, true);\n";
                } else {
                    data_entry_helper::$javascript .= "\t\tloadFeatures(''," . data_entry_helper::$entity_to_load['location:id'] . ",{initial: true}, false, false, false, false, true);\n";
                }
                break;
            default:
                // mode = parent
                data_entry_helper::$javascript .= "\t\tloadFeatures(" . data_entry_helper::$entity_to_load['location:parent_id'] . "," . data_entry_helper::$entity_to_load['location:id'] . ",{initial: true}, true, true, false, false, true);\n";
        }
    } else {
        if ($args['locationMode'] == 'single') {
            data_entry_helper::$javascript .= "\t\tloadFeatures('','',{initial: true}, false, false, false, true, true);\n";
        } else {
            if ($args['locationMode'] == 'filtered') {
                $activeParent = false;
                $filterAttrs = explode(',', $args['filterAttrs']);
                foreach ($filterAttrs as $idx => $filterAttr) {
                    $filterAttr = explode(':', $filterAttr);
                    if ($filterAttr[0] == 'Parent' && $filterAttr[1] == "true") {
                        $activeParent = true;
                    }
                }
                if (!$activeParent) {
                    data_entry_helper::$javascript .= "\t\tloadFeatures('','',{initial: true}, false, false, false, true, false);\n";
                }
            } else {
                // either multi, parent with none specified at the moment.
                data_entry_helper::$javascript .= "\t\tsetPermissionsNoParent();\n";
            }
        }
    }
    data_entry_helper::$javascript .= "}});\nSiteLabelLayer.events.on({\n    'beforefeatureselected': onFeatureSelect\n  });\nSiteAreaLayer.events.on({\n    'beforefeatureselected': onFeatureSelect\n    ,'featuremodified': onFeatureModified\n  });\nSitePathLayer.events.on({\n    'beforefeatureselected': onFeatureSelect\n    ,'featuremodified': onFeatureModified\n  });\nSitePointLayer.events.on({\n    'beforefeatureselected': onFeatureSelect\n    ,'featuremodified': onFeatureModified\n  });\n";
    if ($args['locationMode'] != 'multi') {
        data_entry_helper::$javascript .= "\nhook_ChildFeatureLoad = function(feature, data, child_id, childArgs){\n  if(child_id == '' || data.id != child_id){\n";
        if ($args['locationMode'] != 'filtered' && isset($args['duplicateNameCheck']) && $args['duplicateNameCheck'] == 'enforce') {
            data_entry_helper::$javascript .= "    var clearVal = jQuery('#location-name').val() == data.name;\n";
            if ($args['siteNameTermListID'] != "") {
                data_entry_helper::$javascript .= "    jQuery('#location-name').find('option').filter('[value='+data.name+']').attr('disabled','disabled');\n";
            }
            data_entry_helper::$javascript .= "    if(clearVal) jQuery('#location-name').val('');\n";
        }
        data_entry_helper::$javascript .= "    return;\n  }\n  var pointFeature = false;\n  var lineFeature = false;\n  var areaFeature = false;\n  if(typeof(feature)=='object'&&(feature instanceof Array)){\n    for(var j=0; j< feature.length; j++){\n      switch(feature[j].geometry.CLASS_NAME){\n        case \"OpenLayers.Geometry.Point\":\n        case \"OpenLayers.Geometry.MultiPoint\":\n          pointFeature = feature[j];\n          break;\n        case \"OpenLayers.Geometry.LineString\":\n        case \"OpenLayers.Geometry.MultiLineString\":\n          lineFeature = feature[j];\n          break;\n        default:\n          areaFeature = feature[j];\n          break;\n      }\n    }\n  } else {\n    switch(feature.geometry.CLASS_NAME){\n      case \"OpenLayers.Geometry.Point\":\n      case \"OpenLayers.Geometry.MultiPoint\":\n        pointFeature = feature;\n        break;\n      case \"OpenLayers.Geometry.LineString\":\n      case \"OpenLayers.Geometry.MultiLineString\":\n        lineFeature = feature;\n        break;\n      default:\n        areaFeature = feature;\n      break;\n    }\n  }\n  var Zoomed=false;\n  if(areaFeature) {\n    areaFeature.attributes.highlighted=true;\n    selectFeature.highlight(areaFeature);\n    ZoomToFeature(areaFeature);\n    Zoomed=true;\n  }\n  if(lineFeature) {\n    lineFeature.attributes.highlighted=true;\n    selectFeature.highlight(lineFeature);\n    if(!Zoomed) ZoomToFeature(lineFeature);\n    Zoomed=true;\n  }\n  if(pointFeature) {\n    pointFeature.attributes.highlighted=true;\n    selectFeature.highlight(pointFeature);\n    if(!Zoomed) ZoomToFeature(pointFeature);\n  }\n//  setGeomFields();\n};\njQuery('#location-name').change(function(){";
        if ($args['locationMode'] != 'filtered' && isset($args['duplicateNameCheck']) && ($args['duplicateNameCheck'] == true || $args['duplicateNameCheck'] == 'check' || $args['duplicateNameCheck'] == 'enforce')) {
            data_entry_helper::$javascript .= "\n  for(var i=0; i< SiteLabelLayer.features.length; i++){\n    if(SiteLabelLayer.features[i].attributes['new'] == false){\n      if(jQuery(this).val() == SiteLabelLayer.features[i].attributes.data.name){\n        alert(\"" . lang::get('LANG_DuplicateName') . "\");\n" . ($args['duplicateNameCheck'] == 'enforce' ? "\t\t jQuery(this).val('');\n" : "") . "      }\n    }\n  }";
        }
        data_entry_helper::$javascript .= "\n  jQuery('#sample-location-name').val(jQuery(this).val());\n});\njQuery('#location-id').change(function(){\n  jQuery('#sample-location-id').val(jQuery(this).val());\n  });\n//  jQuery(\"#location-name\").val('');\n// In order to change this value, there must be a list of values: therefore the parent has been filled in\n// With a parent filled in, there are 3 states\n// If nothing is selected, then the mod control allows selection of an existing feature, or the draw controls allow the creation of a new site.\n// With a new site in progress, then the mod control allows modification of the new site or selection of an existing feature, or the draw controls allow the additional of elements to the new site.\n// With a existing site selected, then the mod control allows selection of a different existing feature, or the draw controls allow the creation of a new site.\n// the state of the mod and draw controls re enabling stays the same before and afterwards.\nmainFieldChange = function(resetName){\n  // this is only used when not multisite.\n  var highlighted = gethighlight();\n  var found=false;\n  var myVal = jQuery('#" . $options['MainFieldID'] . "').val();\n  // only confirm if have something drawn on map: ie ignore label\n  for(i=0; i<highlighted.length; i++){\n    if(highlighted[i].layer != SiteLabelLayer && highlighted[i].attributes['new']==true)\n      found=true;\n  }\n  if(found){\n    if(!confirm('" . lang::get('LANG_ConfirmRemoveDrawnSite') . "')) return false;\n  }\n  if(highlighted.length>0 && highlighted[0].attributes['new']==true){\n    removeDrawnGeom(highlighted[0].attributes.SiteNum);\n  }\n  jQuery('#sample-location-id').val(myVal);\n  unhighlightAll();\n  pointDraw.deactivate();\n  lineDraw.deactivate();\n  polygonDraw.deactivate();\n  selectFeature.activate();\n  setPermissionsNoSite();\n  if(myVal=='') {\n    clearLocation(true, resetName);\n    return;\n  }\n  // at this point we have selected an existing site.\n  highlightMe(myVal, false);\n  ZoomToSite();\n  var allFeatures = SiteAreaLayer.features.concat(SitePathLayer.features,SitePointLayer.features);\n  for(var i=0; i<allFeatures.length; i++){\n    if(typeof allFeatures[i].attributes.data != 'undefined' &&\n        typeof allFeatures[i].attributes.data.id != 'undefined' &&\n        allFeatures[i].attributes.data.id == myVal){\n      loadLocation(allFeatures[i]); // sets permissions.\n      return;\n    }\n  }\n  clearLocation(true, true);\n}\njQuery('#" . $options['MainFieldID'] . "').change(function(){mainFieldChange(true)});\n";
    }
    if ($args['locationMode'] == 'multi' && isset(data_entry_helper::$entity_to_load["sample:updated_by_id"])) {
        // only set if data loaded from db, not error condition
        iform_mnhnl_set_editable($auth, $args, $node, array(), $options['AdminMode'], $loctypeParam);
        // TBD sort 2169 hardcode
        // this required when adding sites when editting existing samples
        $retVal .= "<input type=\"hidden\" id=\"imp-sref-system\" name=\"location:centroid_sref_system\" value=\"2169\" >";
        // multiple site: parent sample points to parent location in location_id, not parent_id. Each site has own subsample.
        // can not change the (parent) location of the main sample, as this will reset all the attached samples and sites, so rendering entered data useless. Just delete.
        return $retVal . "\n<input type=\"hidden\" name =\"sample:location_id\" value=\"" . data_entry_helper::$entity_to_load["sample:location_id"] . "\" >\n  <p>" . $options['ParentLabel'] . ' : ' . data_entry_helper::$entity_to_load["location:name"] . '</p>
' . ($args['includeNumSites'] ? "<label for=\"dummy-num-sites\" class=\"auto-width\">" . lang::get('LANG_NumSites') . ":</label> <input id=\"dummy-num-sites\" name=\"dummy:num-sites\" class=\"checkNumSites narrow\" readonly=\"readonly\"><br />\n" : '') . "<p>" . $options['Instructions2'] . "</p>\n" . ($options['AdminMode'] && (!isset($args['adminsCanCreate']) || !$args['adminsCanCreate']) ? '<p>' . lang::get('LANG_LocModTool_CantCreate') . '</p>' : '') . ($args['siteNameTermListID'] == '' ? "<label for=\"dummy-name\">" . $options['NameLabel'] . ":</label> <input id=\"dummy-name\" name=\"dummy:name\" class='wide required'><br />\n" : data_entry_helper::select(array('label' => $options['NameLabel'], 'id' => 'dummy-name', 'fieldname' => 'dummy:name', 'table' => 'termlists_term', 'captionField' => 'term', 'valueField' => 'term', 'blankText' => '', 'class' => 'checkGrid', 'extraParams' => $auth['read'] + array('termlist_id' => $args['siteNameTermListID'], 'orderby' => 'id'))));
    }
    $retVal .= "<input type='hidden' id=\"sample-location-name\" name=\"sample:location_name\" value=\"" . htmlspecialchars(data_entry_helper::$entity_to_load['sample:location_name']) . "\" />";
    if ($args['includeLocTools'] && function_exists('iform_loctools_listlocations')) {
        $locations = iform_loctools_listlocations($node);
    } else {
        $locations = 'all';
    }
    if ($args['locationMode'] == 'parent' || $args['locationMode'] == 'multi') {
        if (!isset($args['loctoolsLocTypeID'])) {
            return "locationMode == parent, loctoolsLocTypeID not set.";
        }
        iform_mnhnl_set_editable($auth, $args, $node, array(), $args['locationMode'] == 'parent' ? "conditional" : $options['AdminMode'], $loctypeParam);
        $locOptions = array('validation' => array('required'), 'label' => $options['ChooseParentLabel'], 'id' => $options['ChooseParentFieldID'], 'table' => 'location', 'fieldname' => $options['ChooseParentFieldName'], 'valueField' => 'id', 'captionField' => 'name', 'template' => 'select', 'itemTemplate' => 'select_item', 'columns' => 'id,name', 'extraParams' => array_merge($auth['read'], array('parent_id' => 'NULL', 'view' => 'detail', 'orderby' => 'name', 'location_type_id' => $args['loctoolsLocTypeID'], 'deleted' => 'f')));
        $locResponse = data_entry_helper::get_population_data($locOptions);
        if (isset($locResponse['error'])) {
            return "PARENT LOOKUP ERROR:  " . $locResponse['error'];
        }
        $opts = "";
        if (!isset(data_entry_helper::$entity_to_load[$options['ParentFieldName']])) {
            $opts = str_replace(array('{value}', '{caption}', '{selected}'), array('', htmlentities(lang::get('LANG_CommonParentBlank')), ''), $indicia_templates[$locOptions['itemTemplate']]);
        }
        foreach ($locResponse as $record) {
            $include = false;
            if ($locations == 'all') {
                $include = true;
            } else {
                if (in_array($record["id"], $locations)) {
                    $include = true;
                }
            }
            if ($include == true) {
                $opts .= str_replace(array('{value}', '{caption}', '{selected}'), array($record[$locOptions['valueField']], htmlentities($record[$locOptions['captionField']]), isset(data_entry_helper::$entity_to_load[$options['ParentFieldName']]) ? data_entry_helper::$entity_to_load[$options['ParentFieldName']] == $record[$locOptions['valueField']] ? 'selected=selected' : '' : ''), $indicia_templates[$locOptions['itemTemplate']]);
            }
        }
        $locOptions['items'] = $opts;
        $retVal .= '<p>' . $options['Instructions1'] . '</p>' . data_entry_helper::apply_template($locOptions['template'], $locOptions) . ($args['includeNumSites'] ? '<label for="dummy-num-sites" class="auto-width">' . lang::get('LANG_NumSites') . ':</label> <input id="dummy-num-sites" name="dummy:num-sites" class="checkNumSites narrow" readonly="readonly"><br />
' : '') . '<p>' . $options['Instructions2'] . '</p>' . ($options['AdminMode'] && (!isset($args['adminsCanCreate']) || !$args['adminsCanCreate']) ? '<p>' . lang::get('LANG_LocModTool_CantCreate') . '</p>' : '');
    }
    if ($args['locationMode'] == 'parent') {
        $retVal .= "<input type='hidden' id=\"sample-location-id\" name=\"sample:location_id\" value='" . data_entry_helper::$entity_to_load['sample:location_id'] . "' />";
        data_entry_helper::$javascript .= "\njQuery(\"#" . $options['ChooseParentFieldID'] . "\").change(function(){\n  jQuery(\"#imp-geom,#imp-boundary-geom,#imp-sref,#imp-srefX,#imp-srefY,#" . $options['MainFieldID'] . ",#" . $options['ParentFieldID'] . ",#sample-location-id,#location-name,#sample-location-name\").val('');\n  jQuery(\"#location_location_type_id\").val('{$primary}');\n  loadFeatures(this.value, '', {initial: false}, true, true, true, true, true);\n  if(typeof hook_mnhnl_parent_changed != 'undefined')\n    hook_mnhnl_parent_changed();\n});\njQuery(\"#" . $options['ParentFieldID'] . "\").change(function(){\n  if(jQuery(this).val() != '') {\n    // we have a new parent location, so draw boundary\n    jQuery.getJSON(\"" . data_entry_helper::$base_url . "/index.php/services/data/location/\"+jQuery(this).val()+\"?mode=json&view=detail&auth_token=" . $auth['read']['auth_token'] . "&nonce=" . $auth['read']["nonce"] . "&callback=?\",\n      function(data) {\n       if (data.length>0) {\n         var parser = new OpenLayers.Format.WKT();\n         if(data[0].boundary_geom){ // only one location if any\n           var feature = parser.read(data[0].boundary_geom)\n           feature=convertFeature(feature, \$('#map')[0].map.projection);\n           ParentLocationLayer.destroyFeatures();\n           ParentLocationLayer.addFeatures([feature]);\n           zoomToLayerExtent(ParentLocationLayer);\n         }\n       }});\n" . ($options['AdminMode'] ? "    // in admin mode we have to reset the location name drop downs.\n    jQuery('#location-name').find('option').removeAttr('disabled');\n" . (isset($args['duplicateNameCheck']) && ($args['duplicateNameCheck'] == true || $args['duplicateNameCheck'] == 'check' || $args['duplicateNameCheck'] == 'enforce') ? "    jQuery.getJSON(\"" . data_entry_helper::$base_url . "/index.php/services/data/location?parent_id=\"+jQuery(this).val()+\"&location_type_id" . $primary . "&mode=json&view=detail&auth_token=" . $auth['read']['auth_token'] . "&nonce=" . $auth['read']["nonce"] . "&callback=?\",\n      function(data) {\n        if (data.length>0) {\n          var currentName = jQuery('#location-name').val();\n          var currentID = jQuery('#" . $options['MainFieldID'] . "').val();\n          // first check if there is a clash and give a warning\n          for(var di=0; di<data.length; di++){\n            if(currentName == data[di].name && currentID != data[di].id && currentID != ''){\n              alert(\"" . lang::get('This site name is already in use in the new square. Please choose another.') . "\");\n              break; // only display one message\n            }\n          }\n" . ($args['duplicateNameCheck'] == 'enforce' ? "          // if enforce, disable all options for existing and reset the name value if needed.\n          for(var di=0; di<data.length; di++){\n            if(data[di].name == parseInt(data[di].name) && currentID != data[di].id)\n              // only disable fields for existing locations for numeric names and which are not me. \n              jQuery('#location-name').find('option').filter('[value='+data[di].name+']').attr('disabled','disabled');\n          }\n          // finally if enforce and there is a clash, reset the value. This will then automatically take first available.\n          for(var di=0; di<data.length; di++){\n            if(currentName == data[di].name && currentID != data[di].id)\n              jQuery('#location-name').val('');\n          }\n" : "") . "\n       }});\n" : "") : "") . "  } else\n    ParentLocationLayer.destroyFeatures();\n});\n";
        // choose a single site from a parent, so built site selector drop down.
        // parent uses ID locModTool
        $opts = "";
        $locOptions = array('label' => $options['MainFieldLabel'], 'id' => $options['MainFieldID'], 'table' => 'location', 'fieldname' => $options['MainFieldName'], 'valueField' => 'id', 'captionField' => 'name', 'template' => 'select', 'itemTemplate' => 'select_item', 'nocache' => true, 'extraParams' => array_merge($auth['read'], array('parent_id' => data_entry_helper::$entity_to_load["location:parent_id"], 'view' => 'detail', 'orderby' => 'name', 'location_type_id' => $loctypeParam, 'deleted' => 'f')));
        if (isset(data_entry_helper::$entity_to_load["sample:id"])) {
            // if preloaded, then drop down is dependant on value in parent field: if not then get user to enter parent first
            $response = data_entry_helper::get_population_data($locOptions);
            // OK as parent_id filled in: not likely to be large number.
            if (isset($response['error'])) {
                return "CHILD LOOKUP ERROR:  " . $response['error'];
            }
            $opts .= str_replace(array('{value}', '{caption}', '{selected}'), array('', htmlentities(lang::get('LANG_CommonEmptyLocationID')), ''), $indicia_templates[$locOptions['itemTemplate']]);
            foreach ($response as $record) {
                $caption = htmlspecialchars($record[$locOptions['captionField']]);
                // it will be extended using a attribute template by JS
                $opts .= str_replace(array('{value}', '{caption}', '{selected}'), array($record[$locOptions['valueField']], htmlentities($caption), isset(data_entry_helper::$entity_to_load['location:id']) ? data_entry_helper::$entity_to_load['sample:location_id'] == $record[$locOptions['valueField']] ? 'selected=selected' : '' : ''), $indicia_templates[$locOptions['itemTemplate']]);
            }
        } else {
            $opts = "<option >" . lang::get("LANG_CommonChooseParentFirst") . "</option>";
        }
        $locOptions['items'] = $opts;
        // single site requires all location data in main form. Mult site must have array: depends on implementation so left to actual form.
        $retVal .= data_entry_helper::apply_template($locOptions['template'], $locOptions) . "<br />";
        if ($options['AdminMode']) {
            $locOptions = array('validation' => array('required'), 'label' => $options['ParentLabel'], 'id' => $options['ParentFieldID'], 'fieldname' => $options['ParentFieldName'], 'valueField' => 'id', 'captionField' => 'name', 'template' => 'select', 'itemTemplate' => 'select_item');
            $opts = str_replace(array('{value}', '{caption}', '{selected}'), array('', '', ''), $indicia_templates[$locOptions['itemTemplate']]);
            foreach ($locResponse as $record) {
                $include = false;
                if ($locations == 'all') {
                    $include = true;
                } else {
                    if (in_array($record["id"], $locations)) {
                        $include = true;
                    }
                }
                if ($include == true) {
                    $opts .= str_replace(array('{value}', '{caption}', '{selected}'), array($record[$locOptions['valueField']], htmlentities($record[$locOptions['captionField']]), isset(data_entry_helper::$entity_to_load[$options['ParentFieldName']]) ? data_entry_helper::$entity_to_load[$options['ParentFieldName']] == $record[$locOptions['valueField']] ? 'selected=selected' : '' : ''), $indicia_templates[$locOptions['itemTemplate']]);
                }
            }
            $locOptions['items'] = $opts;
            $retVal .= data_entry_helper::apply_template($locOptions['template'], $locOptions);
        } else {
            $retVal .= "<input type='hidden' id=\"" . $options['ParentFieldID'] . "\" name=\"" . $options['ParentFieldName'] . "\" value=\"" . (isset(data_entry_helper::$entity_to_load[$options['ParentFieldName']]) ? data_entry_helper::$entity_to_load[$options['ParentFieldName']] : "") . "\" />";
        }
        if ($args['siteNameTermListID'] == '') {
            $retVal .= "<label for=\"location-name\">" . $options['NameLabel'] . ":</label> <input type='text' id=\"location-name\" name=\"location:name\" class='required wide' value=\"" . htmlspecialchars(data_entry_helper::$entity_to_load['location:name']) . "\" /><span class='deh-required'>*</span><br/>";
        } else {
            $retVal .= data_entry_helper::select(array('label' => $options['NameLabel'], 'id' => 'location-name', 'fieldname' => 'location:name', 'table' => 'termlists_term', 'captionField' => 'term', 'valueField' => 'term', 'extraParams' => $auth['read'] + array('termlist_id' => $args['siteNameTermListID'], 'orderby' => 'id')));
        }
    } else {
        if ($args['locationMode'] == 'multi') {
            //TBD sort 2169 hardcode
            $retVal .= "<input type=\"hidden\" id=\"imp-sref-system\" name=\"location:centroid_sref_system\" value=\"2169\" >";
            // multiSite needs the location name.
            if ($args['siteNameTermListID'] == '') {
                $retVal .= "<label for=\"dummy-name\">" . $options['NameLabel'] . ":</label> <input type='text' id=\"dummy-name\" name=\"dummy:name\" class='wide' value=\"" . htmlspecialchars(data_entry_helper::$entity_to_load['location:name']) . "\" /><span class='deh-required'>*</span><br/>";
            } else {
                $retVal .= data_entry_helper::select(array('label' => $options['NameLabel'], 'id' => 'dummy-name', 'fieldname' => 'dummy:name', 'table' => 'termlists_term', 'captionField' => 'term', 'valueField' => 'term', 'blankText' => '', 'class' => 'checkGrid', 'extraParams' => $auth['read'] + array('termlist_id' => $args['siteNameTermListID'], 'orderby' => 'id')));
            }
            data_entry_helper::$javascript .= "\njQuery(\"#" . $options['ChooseParentFieldID'] . "\").change(function(){\n  if(typeof hook_mnhnl_parent_changed != 'undefined')\n    hook_mnhnl_parent_changed();\n  loadFeatures(this.value, '', {initial : false}, true, true, true, true, true);\n});\n";
        } else {
            if ($args['locationMode'] == 'single') {
                // no parent look up: actual name is a text entry field.
                $location_list_args = array('nocache' => true, 'includeCodeField' => true, 'label' => lang::get('LANG_CommonLocationNameLabel'), 'NameBlankText' => lang::get('LANG_Location_Name_Blank_Text'), 'fieldname' => 'location:id', 'id' => $options['MainFieldID'], 'columns' => 'id,name,code,location_type_id', 'extraParams' => array_merge(array('view' => 'detail', 'orderby' => 'name', 'website_id' => $args['website_id'], 'location_type_id' => $loctypeParam), $auth['read']), 'table' => 'location', 'template' => 'select', 'itemTemplate' => 'select_item', 'filterField' => 'parent_id', 'size' => 3);
                // Idea here is to get a list of all locations in order to build drop downs.
                $responseRecords = data_entry_helper::get_population_data($location_list_args);
                if (isset($responseRecords['error'])) {
                    return $responseRecords['error'];
                }
                iform_mnhnl_set_editable($auth, $args, $node, $responseRecords, 'conditional', $loctypeParam);
                $usedCodes = array();
                $maxCode = 0;
                $NameOpts = '';
                foreach ($responseRecords as $record) {
                    if ($record['name'] != '') {
                        $item = array('selected' => data_entry_helper::$entity_to_load['location:id'] == $record['id'] ? 'selected=\\"selected\\"' : '', 'value' => $record['id'], 'caption' => htmlspecialchars(utf8_decode($record['name'])));
                        $NameOpts .= data_entry_helper::mergeParamsIntoTemplate($item, $location_list_args['itemTemplate']);
                        if ($record['code'] != '') {
                            $usedCodes[] = "\"" . $record['code'] . "\"";
                            if ($maxCode < $record['code']) {
                                $maxCode = $record['code'];
                            }
                        }
                    }
                }
                data_entry_helper::$javascript .= "\nvar usedCodes = [" . implode(',', $usedCodes) . "];\nvar defaultCode = " . ($maxCode + 1) . ";\n";
                $retVal .= '<p>' . $options['Instructions2'] . '</p>' . ($options['AdminMode'] && (!isset($args['adminsCanCreate']) || !$args['adminsCanCreate']) ? '<p>' . lang::get('LANG_LocModTool_CantCreate') . '</p>' : '') . '<fieldset><legend>' . lang::get('Existing locations') . '</legend>';
                if ($NameOpts != '') {
                    $location_list_args['items'] = str_replace(array('{value}', '{caption}', '{selected}'), array('', htmlentities($location_list_args['NameBlankText']), ''), $indicia_templates[$location_list_args['itemTemplate']]) . $NameOpts;
                    $retVal .= data_entry_helper::apply_template($location_list_args['template'], $location_list_args);
                    if ($args['SecondaryLocationTypeTerm'] != '' && $options['AdminMode']) {
                        $retVal .= '<p>' . lang::get("LANG_Multiple_Location_Types") . '</p>';
                    }
                } else {
                    $retVal .= '<p>' . lang::get("LANG_NoSites") . '</p>';
                }
                $retVal .= "</fieldset><label for=\"location-name\">" . $options['NameLabel'] . ":</label> <input id=\"location-name\" name=\"location:name\" class='wide required' value=\"" . htmlspecialchars(data_entry_helper::$entity_to_load['location:name']) . "\"><span class=\"deh-required\">*</span><br />\n      <input type='hidden' id=\"sample-location-id\" name=\"sample:location_id\" value='" . data_entry_helper::$entity_to_load['sample:location_id'] . "' />";
            } else {
                // single location, filtered.
                data_entry_helper::$javascript .= "indiciaData.filterMode=true;\n";
                iform_mnhnl_set_editable($auth, $args, $node, array(), 'conditional', $loctypeParam);
                $retVal .= '<p>' . $options['Instructions2'] . '</p>' . ($options['AdminMode'] && (!isset($args['adminsCanCreate']) || !$args['adminsCanCreate']) ? '<p>' . lang::get('LANG_LocModTool_CantCreate') . '</p>' : '');
                $filterAttrs = explode(',', $args['filterAttrs']);
                // filter attributes are assumed to be text (could extend later)
                $attrArgs = array('valuetable' => 'location_attribute_value', 'attrtable' => 'location_attribute', 'key' => 'location_id', 'fieldprefix' => 'locAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id']);
                if (array_key_exists('location:id', data_entry_helper::$entity_to_load) && data_entry_helper::$entity_to_load['location:id'] != "") {
                    // if we have location Id to load, use it to get attribute values
                    $attrArgs['id'] = data_entry_helper::$entity_to_load['location:id'];
                }
                $locationAttributes = data_entry_helper::getAttributes($attrArgs, false);
                if ($args['LocationTypeTerm'] == '' && isset($args['loctoolsLocTypeID'])) {
                    $args['LocationTypeTerm'] = $args['loctoolsLocTypeID'];
                }
                $primary = iform_mnhnl_getTermID($auth, 'indicia:location_types', $args['LocationTypeTerm']);
                $filterAttrs[] = "Name";
                // always add the location name special case to the filter list.
                $defaultsFunction = "";
                $loadFunction = "hook_loadFilters = function(){\n";
                $initFunctions = "";
                $prevAttr = null;
                $prevFilterAttr = null;
                $prevIdx = null;
                $attrList = array();
                $includeCommune = true;
                $location_list_args = array('nocache' => true, 'extraParams' => array_merge(array('orderby' => 'id', 'view' => 'detail', 'website_id' => $args['website_id'], 'location_type_id' => $primary), $auth['read']), 'columns' => 'id,name,parent_id', 'table' => 'location');
                $locList = data_entry_helper::get_population_data($location_list_args);
                if (isset($locList['error'])) {
                    return $locList['error'];
                }
                $location_attr_list_args = array('nocache' => true, 'extraParams' => array_merge(array('orderby' => 'location_id', 'view' => 'list', 'website_id' => $args['website_id'], 'location_type_id' => $primary), $auth['read']), 'table' => 'location_attribute_value');
                $locAttrList = data_entry_helper::get_population_data($location_attr_list_args);
                if (isset($locAttrList['error'])) {
                    return $locAttrList['error'];
                }
                $locTextList = array();
                $locListCount = count($locList);
                $locAttrListCount = count($locAttrList);
                for ($i = 0, $j = 0; $i < $locListCount; $i++) {
                    while ($j < $locAttrListCount && $locAttrList[$j]['location_id'] < $locList[$i]['id']) {
                        $j++;
                    }
                    $locAttrTextList = array();
                    while ($j < $locAttrListCount && $locAttrList[$j]['location_id'] == $locList[$i]['id']) {
                        $locAttrTextList[] = '"' . $locAttrList[$j]['location_attribute_id'] . '":"' . $locAttrList[$j]['raw_value'] . '"';
                        $j++;
                    }
                    $locTextList[] = "{'id':" . $locList[$i]['id'] . ", 'name':\"" . $locList[$i]['name'] . "\", 'parent_id':\"" . $locList[$i]['parent_id'] . "\", 'attrs': {" . implode(",", $locAttrTextList) . "}}";
                }
                data_entry_helper::$javascript .= "\nvar locations = [\n" . implode(",\n", $locTextList) . "];\n";
                foreach ($filterAttrs as $idx => $filterAttr) {
                    $filterAttr = explode(':', $filterAttr);
                    $attr = "";
                    if ($filterAttr[0] != "Name" && $filterAttr[0] != "Parent") {
                        foreach ($locationAttributes as $locationAttribute) {
                            if ($locationAttribute['untranslatedCaption'] == $filterAttr[0] || $filterAttr[0] == "Shape" && $locationAttribute['untranslatedCaption'] == $filterAttr[1]) {
                                $attr = $locationAttribute;
                            }
                        }
                        if ($attr == "") {
                            return '<p>' . lang::get("Location Module: Could not find attribute ") . $filterAttr[$filterAttr[0] == "Shape" ? 1 : 0] . '</p>';
                        }
                    }
                    $nextIdx = $idx + 1;
                    while ($nextIdx < count($filterAttrs)) {
                        $fparts = explode(':', $filterAttrs[$nextIdx]);
                        if ($fparts[0] != 'Parent' || $fparts[1] == "true") {
                            break;
                        }
                        $nextIdx++;
                    }
                    // need to add functionality to tie locations to a square, even if not in use (for sites form)
                    // also this form must fill in a hidden commune field.
                    switch ($filterAttr[0]) {
                        case "Parent":
                            //special case, assume only one of these in a form. Not required
                            // field 1: editable true or false
                            // field 2: display warning if outside true or false
                            // field 3: location_type term
                            $parentLocTypeID = iform_mnhnl_getTermID($auth, 'indicia:location_types', $filterAttr[3]);
                            // proxiedurl,featurePrefix,featureType,[geometryName],featureNS,srsName[,propertyNames]
                            $protocol = explode(',', $args['locationLayerLookup']);
                            data_entry_helper::$javascript .= "\nhook_setSref_" . $idx . " = function(geom){ // map projection\n  // srsName should be in map projection.\n  var protocol = new OpenLayers.Protocol.WFS({\n      url:  '" . $protocol[0] . "',featurePrefix: '" . $protocol[1] . "',featureType: '" . $protocol[2] . "',geometryName:'boundary_geom',featureNS: '" . $protocol[3] . "',srsName: '" . $protocol[4] . "',version: '1.1.0',propertyNames: ['boundary_geom','name']\n     ,callback: function(a1){\n        if(a1.error && (typeof a1.error.success == 'undefined' || a1.error.success == false)){\n          alert(\"" . lang::get('LANG_ParentLookUpFailed') . "\");\n          return;\n        }\n        if(a1.features.length > 0) {\n            var id = a1.features[0].fid.slice(" . (strlen($protocol[2]) + 1) . ")\n";
                            if ($filterAttr[1] == "true") {
                                data_entry_helper::$javascript .= "          if(jQuery('#filterSelect" . $idx . "').val() == '' || // not currently filled in\n              (jQuery('#filterSelect" . $idx . "').val() != id && confirm(\"" . lang::get('LANG_PositionInDifferentParent') . "\"))) {\n            ParentLocationLayer.destroyFeatures();\n            ParentLocationLayer.addFeatures(a1.features); // TBD check geometry system - convert?\n            jQuery('#filterSelect" . $idx . "').val(id);\n            jQuery('#" . $options['ParentFieldID'] . "').val(id);\n";
                                foreach ($filterAttrs as $idx1 => $filterAttr1) {
                                    // just need index, so don't explode
                                    if ($idx1 > $idx && $idx1 < count($filterAttrs) - 1) {
                                        // don't do name
                                        data_entry_helper::$javascript .= "            filterLoad" . $idx1 . "();\n";
                                    }
                                }
                                // update drop downs, but leave values as they are.
                                data_entry_helper::$javascript .= "          }\n";
                            } else {
                                data_entry_helper::$javascript .= "          jQuery('#" . $options['ParentFieldID'] . "').val(id);\n          jQuery('#" . $options['ChooseParentFieldID'] . "').val(a1.features[0].attributes['name']);\n";
                            }
                            data_entry_helper::$javascript .= "\n          loadChildFeatures(id, true); // load in children onto map\n        } else {\n" . ($filterAttr[2] == 'true' ? "        alert(\"" . lang::get('LANG_PositionOutsideParent') . "\");\n" : '') . "          jQuery('#" . $options['ParentFieldID'] . "').val('');\n          jQuery('#" . ($filterAttr[1] == "true" ? "filterSelect" . $idx : $options['ChooseParentFieldID']) . "').val('');\n        }\n      }\n    });\n  filter = new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND, filters:[\n  \t\t\tnew OpenLayers.Filter.Spatial({type: OpenLayers.Filter.Spatial.CONTAINS,property: 'boundary_geom',value: geom}),\n  \t\t\tnew OpenLayers.Filter.Comparison({type: OpenLayers.Filter.Comparison.EQUAL_TO, property: 'location_type_id', value: '" . $parentLocTypeID . "'})]});\n  protocol.read({filter: filter});\n};\n";
                            if ($filterAttr[1] == "true") {
                                // filterable.
                                // set up the parent list, cacheable
                                $locOptions = array('label' => lang::get('LANG_CommonParentLabel'), 'id' => 'filterSelect' . $idx, 'table' => 'location', 'fieldname' => $options['ChooseParentFieldName'], 'valueField' => 'id', 'captionField' => 'name', 'template' => 'select', 'itemTemplate' => 'select_item', 'validation' => array('required'), 'columns' => 'id,name', 'extraParams' => array_merge($auth['read'], array('parent_id' => 'NULL', 'view' => 'detail', 'orderby' => 'name', 'location_type_id' => $parentLocTypeID, 'deleted' => 'f')));
                                $locResponse = data_entry_helper::get_population_data($locOptions);
                                if (isset($locResponse['error'])) {
                                    return "PARENT LOOKUP ERROR:  " . $locResponse['error'];
                                }
                                $opts = str_replace(array('{value}', '{caption}', '{selected}'), array('', lang::get('LANG_FirstChooseParentFilter'), ''), $indicia_templates[$locOptions['itemTemplate']]);
                                foreach ($locResponse as $record) {
                                    $include = false;
                                    if ($locations == 'all') {
                                        $include = true;
                                    } else {
                                        if (in_array($record["id"], $locations)) {
                                            $include = true;
                                        }
                                    }
                                    if ($include == true) {
                                        $opts .= str_replace(array('{value}', '{caption}', '{selected}'), array($record[$locOptions['valueField']], htmlentities($record[$locOptions['captionField']]), isset(data_entry_helper::$entity_to_load[$options['ParentFieldName']]) ? data_entry_helper::$entity_to_load[$options['ParentFieldName']] == $record[$locOptions['valueField']] ? 'selected=selected' : '' : ''), $indicia_templates[$locOptions['itemTemplate']]);
                                    }
                                }
                                $locOptions['items'] = $opts;
                                $retVal .= data_entry_helper::apply_template($locOptions['template'], $locOptions);
                                if ($options['AdminMode']) {
                                    // In admin mode assume can reassign to any location: admins should have access to all squares.
                                    $location_list_args = array('view' => 'detail', 'extraParams' => array_merge(array('orderby' => 'name', 'website_id' => $args['website_id']), $auth['read']), 'location_type_id' => $parentLocTypeID, 'default' => data_entry_helper::$entity_to_load[$options['ParentFieldName']], 'validation' => array('required'), 'label' => $options['ParentLabel'], 'id' => $options['ParentFieldID'], 'fieldname' => $options['ParentFieldName'], 'blankText' => '');
                                    $retVal .= data_entry_helper::location_select($location_list_args);
                                } else {
                                    $retVal .= "<input type='hidden' id='" . $options['ParentFieldID'] . "' name='" . $options['ParentFieldName'] . "' value='" . (isset(data_entry_helper::$entity_to_load[$options['ParentFieldName']]) ? data_entry_helper::$entity_to_load[$options['ParentFieldName']] : "") . "' />";
                                }
                                data_entry_helper::$javascript .= "indiciaData.filterParent=true;\n// load the counts to the end of the parent drop down list. Do only once. Equivalent to filterLoad" . $idx . "\njQuery('#filterSelect" . $idx . " option').each(function(idx, elem){\n  if(elem.value=='') return;\n  for(i=0, j=0; i< locations.length; i++){\n    if(locations[i]['parent_id']==elem.value) j++;\n  }\n  if(j) elem.text=elem.text+' ('+j+')';\n});\ndisplayParent = function(zoom){\n  var parent_id = jQuery('#filterSelect" . $idx . "').val();\n  loadFeatures(parent_id, '', {initial : false}, true, false, zoom, false, false);\n}\njQuery('#filterSelect" . $idx . "').change(function(){\n  jQuery('#" . $options['ParentFieldID'] . "').val(jQuery(this).val());\n  SetFilterNewLocation();\n";
                                foreach ($filterAttrs as $idx1 => $filterAttr1) {
                                    if ($idx1 > $idx) {
                                        data_entry_helper::$javascript .= "  filterReset" . $idx1 . "();\n";
                                    }
                                }
                                data_entry_helper::$javascript .= "  if(jQuery(this).val()!=''){\n";
                                foreach ($filterAttrs as $idx1 => $filterAttr1) {
                                    if ($idx1 > $idx) {
                                        data_entry_helper::$javascript .= "    filterLoad" . $idx1 . "();\n";
                                    }
                                }
                                data_entry_helper::$javascript .= "  }\n  displayParent(true);\n});\n";
                                $defaultsFunction .= "  if(keepFilter){\n    jQuery('#" . $options['ParentFieldID'] . "').val(jQuery('#filterSelect" . $idx . "').val());\n  } else {\n    jQuery('#filterSelect" . $idx . "').val('');\n  }\n";
                                $prevFilterAttr = $filterAttr;
                                $prevAttr = $attr;
                                $prevIdx = $idx;
                            } else {
                                // not filterable: just readonly field
                                $retVal .= '<input id="' . $options['ParentFieldID'] . '" name="' . $options['ParentFieldName'] . '" type="hidden" value="' . (isset(data_entry_helper::$entity_to_load[$options['ParentFieldName']]) && data_entry_helper::$entity_to_load[$options['ParentFieldName']] != "" && data_entry_helper::$entity_to_load[$options['ParentFieldName']] != null ? data_entry_helper::$entity_to_load[$options['ParentFieldName']] : '') . '">' . '<input id="' . $options['ChooseParentFieldID'] . '" name="dummy" value="" disabled="disabled" >';
                                $loadFunction .= "  populate" . $idx . "();\n";
                                data_entry_helper::$javascript .= "\n\$('#sample-location-id').before('<label>" . lang::get('LANG_CommonParentLabel') . ":</label> ');\n\$('#" . $options['ChooseParentFieldID'] . "').insertBefore('#sample-location-id');\n\$('#sample-location-id').before('<br/>');\npopulate" . $idx . " = function(){\n  jQuery('#" . $options['ChooseParentFieldID'] . "').val('');\n  if(jQuery('#" . $options['ParentFieldID'] . "').val()!='' && jQuery('#" . $options['ParentFieldID'] . "').val() != null){\n    var protocol = new OpenLayers.Protocol.WFS({\n        url:  '" . $protocol[0] . "',featurePrefix: '" . $protocol[1] . "',featureType: '" . $protocol[2] . "',geometryName:'boundary_geom',featureNS: '" . $protocol[3] . "',srsName: '" . $protocol[4] . "',version: '1.1.0',propertyNames: ['boundary_geom','name']\n       ,callback: function(a1){\n          if(a1.error && (typeof a1.error.success == 'undefined' || a1.error.success == false)){\n            alert(\"" . lang::get('LANG_ParentLookUpFailed') . "\");\n          } else if(a1.features.length > 0) {\n            jQuery('#" . $options['ChooseParentFieldID'] . "').val(a1.features[0].attributes['name']);\n        }}});\n    var filter = new OpenLayers.Filter.FeatureId({fids: ['" . $protocol[2] . ".'+jQuery('#" . $options['ParentFieldID'] . "').val()]});\n    protocol.read({filter: filter});\n  }\n};\nfilterLoad" . $idx . " = function(){\n  populate" . $idx . "();\n};\npopulate" . $idx . "();\nfilterReset" . $idx . " = function(){\n  jQuery('#" . $options['ChooseParentFieldID'] . "').val('');\n};";
                            }
                            // have to extract id from fid.
                            break;
                        case "Shape":
                            //special case: geoserver shape file look up, assume only one of these in a form.
                            // 0 = "Shape"
                            // 1 = Attribute Caption, e.g. "Commune"
                            // 2 = display warning if outside list (will be set to blank)
                            // 3 = optional location type term filter
                            // 4 = buffer
                            // Note that for Commune readonly displays, the normal Commune functionality is used, e.g. in the Amphibians Squares where the Commune must be kept in line so the Amphibian Sites can use it.
                            $parentLocTypeID = $filterAttr[3] != '' ? iform_mnhnl_getTermID($auth, 'indicia:location_types', $filterAttr[3]) : -1;
                            // proxiedurl,featurePrefix,featureType,geometryName,featureNS,srsName,propertyNames
                            if ($filterAttr[1] == "Commune") {
                                $includeCommune = false;
                            }
                            $protocol = explode(',', $filterAttr[1] == "Commune" ? $args['communeLayerLookup'] : $args['locationLayerLookup']);
                            $retVal .= '<input id="' . $attr['id'] . '" class="filterFields" name="' . $attr['fieldname'] . '" type="hidden" value="' . $attr['default'] . '"><label>' . $attr['caption'] . ':</label> <select class="required" id="filterSelect' . $idx . '"></select><span class="deh-required">*</span><br/>';
                            $attrList[] = array('id' => $attr['attributeId'], 'shape' => true);
                            data_entry_helper::$javascript .= "\ndisplayShape = function(zoom){\n  ParentLocationLayer.destroyFeatures();\n  if(jQuery('#filterSelect" . $idx . "').val()=='') return;\n  var protocol = new OpenLayers.Protocol.WFS({ // WFS request is to be made in the map projection\n    url:  '" . $protocol[0] . "',featurePrefix: '" . $protocol[1] . "',featureType: '" . $protocol[2] . "',geometryName: '" . $protocol[3] . "',featureNS: '" . $protocol[4] . "',srsName: '" . $protocol[5] . "',version: '1.1.0',propertyNames: ['" . $protocol[6] . "','" . $protocol[3] . "']\n   ,callback:function(data){\n      if(data.features.length>0){ // feature is in map projection\n        ParentLocationLayer.addFeatures(data.features); // TBD check geometry system - convert?\n        if(zoom) ZoomToParent();\n      }}});\n  var filter = new OpenLayers.Filter.Comparison({type: OpenLayers.Filter.Comparison.EQUAL_TO, property: '" . $protocol[6] . "', value: jQuery('#filterSelect" . $idx . "').val()});\n" . ($filterAttr[3] != '' ? "  filter = new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND, filters:[filter, new OpenLayers.Filter.Comparison({type: OpenLayers.Filter.Comparison.EQUAL_TO, property: 'location_type_id', value: '" . $parentLocTypeID . "'})]});\n" : '') . "  protocol.read({filter: filter});\n}\nfilterLoad" . $idx . " = function(){\n  var protocol = new OpenLayers.Protocol.WFS({\n    url:  '" . $protocol[0] . "',featurePrefix: '" . $protocol[1] . "',featureType: '" . $protocol[2] . "',geometryName: '" . $protocol[3] . "',featureNS: '" . $protocol[4] . "',srsName: '" . $protocol[5] . "',version: '1.1.0',sortBy: '" . $protocol[6] . "',propertyNames: ['" . $protocol[6] . ($filterAttr[3] != '' ? "','location_type_id" : '') . "']\n    ,callback:function(data){\n      jQuery('#filterSelect" . $idx . "').empty().append('<option value=\"\">" . lang::get("Please select...") . "</option>');\n      var names=[];\n      for(var i=0; i<data.features.length; i++) names.push(data.features[i].attributes['" . $protocol[6] . "']);\n      names.sort(); // the sort WFS does not work...\n      for(var i=0; i<names.length; i++) {\n        for(j=0, count=0; j< locations.length; j++){\n          if(locations[j].attrs['" . $attr['attributeId'] . "']==names[i]) {\n            count++;\n            locations[j].shapeFound=true;\n          }\n        }\n        jQuery('#filterSelect" . $idx . "').append('<option value=\"'+names[i]+'\">'+names[i]+(count?' ('+count+')':'')+'</option>');\n      }\n      for(j=0; j< locations.length; j++){ // add any communes which are in the locations but not in the shape file.\n        if(typeof locations[j].shapeFound == 'undefined'){\n          for(i=0, count=0; i< locations.length; i++){\n            if(locations[j].attrs['" . $attr['attributeId'] . "']==locations[i].attrs['" . $attr['attributeId'] . "']) {\n              count++;\n              locations[i].shapeFound=true;\n            }\n          }\n          jQuery('#filterSelect" . $idx . "').append('<option value=\"'+locations[j].attrs['" . $attr['attributeId'] . "']+'\">'+locations[j].attrs['" . $attr['attributeId'] . "']+' ('+count+')'+'</option>');\n        }\n      }\n      if(jQuery('#locAttr\\\\:" . $attr['attributeId'] . "').val()!=''){\n        jQuery('#filterSelect" . $idx . "').val(jQuery('#locAttr\\\\:" . $attr['attributeId'] . "').val());\n        displayShape(false);\n      }\n  }});\n  protocol.read(" . ($filterAttr[3] != '' ? "{filter: new OpenLayers.Filter.Comparison({type: OpenLayers.Filter.Comparison.EQUAL_TO, property: 'location_type_id', value: '" . $parentLocTypeID . "'})}" : '') . ");\n}\n// this is only done once\nfilterLoad" . $idx . "();\nhook_setSref_" . $idx . " = function(geom){ // map projection\n  // srsName should be in map projection.\n  var protocol = new OpenLayers.Protocol.WFS({\n      url:  '" . $protocol[0] . "',featurePrefix: '" . $protocol[1] . "',featureType: '" . $protocol[2] . "',geometryName:'" . $protocol[3] . "',featureNS: '" . $protocol[4] . "',srsName: '" . $protocol[5] . "',version: '1.1.0',propertyNames: [\"" . $protocol[6] . "\",'" . $protocol[3] . "']\n     ,callback: function(a1){\n        if(a1.error && (typeof a1.error.success == 'undefined' || a1.error.success == false)){\n          alert(\"" . lang::get('LANG_' . $filterAttr[1] . 'LookUpFailed') . "\");\n          return;\n        }\n        if(a1.features.length > 0) {\n          if(jQuery('#filterSelect" . $idx . "').val() == '' || // not currently filled in\n              (jQuery('#filterSelect" . $idx . "').val() != a1.features[0].attributes[\"" . $protocol[6] . "\"] && confirm(\"" . lang::get('LANG_PositionInDifferent' . $filterAttr[1]) . "\"))) {\n            ParentLocationLayer.destroyFeatures();\n            ParentLocationLayer.addFeatures(a1.features); // feature should be in map projection\n            jQuery('#filterSelect" . $idx . "').val(a1.features[0].attributes[\"" . $protocol[6] . "\"]);\n            jQuery('#locAttr\\\\:" . $attr['attributeId'] . "').val(a1.features[0].attributes[\"" . $protocol[6] . "\"]);\n";
                            foreach ($filterAttrs as $idx1 => $filterAttr1) {
                                // just need index, so don't explode
                                if ($idx1 > $idx && $idx1 < count($filterAttrs) - 1) {
                                    // don't do name
                                    data_entry_helper::$javascript .= "            filterLoad" . $idx1 . "();\n";
                                }
                            }
                            data_entry_helper::$javascript .= "          } // else user choose not to change\n        } else {\n";
                            if (!isset($args['communeLayerBuffer']) || $args['communeLayerBuffer'] == "") {
                                // No buffer in definition
                                data_entry_helper::$javascript .= "          if(jQuery('#filterSelect" . $idx . "').val() == '') { // not currently filled in\n            alert(\"" . lang::get('LANG_PositionOutside' . $filterAttr[1] . "_1") . "\");\n          } else if(!confirm(\"" . lang::get('LANG_PositionOutside' . $filterAttr[1] . "_2") . "\")) {\n            jQuery('#locAttr\\\\:" . $attr['attributeId'] . "').val('');\n            jQuery('#filterSelect" . $idx . "').val('');\n            ParentLocationLayer.destroyFeatures();\n          }\n";
                            } else {
                                // buffer set
                                data_entry_helper::$javascript .= "          //  Get list of communes within buffer of geom\n          var protocol = new OpenLayers.Protocol.WFS({\n              url:  '" . $protocol[0] . "',featurePrefix: '" . $protocol[1] . "',featureType: '" . $protocol[2] . "',geometryName:'" . $protocol[3] . "',featureNS: '" . $protocol[4] . "',srsName: '" . $protocol[5] . "',version: '1.1.0',propertyNames: [\"" . $protocol[6] . "\",'" . $protocol[3] . "']\n             ,callback: function(a1){\n                var replace = false,\n                    reset = false;\n                if(a1.error && (typeof a1.error.success == 'undefined' || a1.error.success == false)){\n                  alert(\"" . lang::get('LANG_' . $filterAttr[1] . 'LookUpFailed') . "\");\n                  return;\n                }\n                if(a1.features.length == 0) {\n                  if(jQuery('#filterSelect" . $idx . "').val() == '') { // not currently filled in\n                    alert(\"" . str_replace('{DISTANCE}', $args['communeLayerBuffer'], lang::get('LANG_PositionOutside' . $filterAttr[1] . "_3")) . "\");\n                  } else if(!confirm(\"" . str_replace('{DISTANCE}', $args['communeLayerBuffer'], lang::get('LANG_PositionOutside' . $filterAttr[1] . "_4")) . "\")) {\n                    reset = true;\n                  }\n                } else {\n                  var closest = 0;\n                  if(a1.features.length >= 0) {\n                    for(var i=0; i< a1.features.length; i++){\n                      var distance, thisDistance = geom.distanceTo(a1.features[i].geometry, {});\n                      if(i==0 || thisDistance<distance){\n                        closest=i;\n                        distance=thisDistance;\n                      }\n                    }\n                  }\n                  if(jQuery('#filterSelect" . $idx . "').val() == '') { // not currently filled in\n                    if(confirm(\"" . lang::get('LANG_PositionOutside' . $filterAttr[1] . "_5") . "\".replace(/SHAPE/g, a1.features[closest].attributes['" . $protocol[6] . "']))){\n                      replace = true;\n                    }\n                  } else if(jQuery('#filterSelect" . $idx . "').val() == a1.features[closest].attributes[\"" . $protocol[6] . "\"]){\n                    if(confirm(\"" . lang::get('LANG_PositionOutside' . $filterAttr[1] . "_6") . "\".replace(/SHAPE/g, a1.features[closest].attributes['" . $protocol[6] . "']))){\n                      replace = true;\n                    } else {\n                      reset = true;\n                    }\n                  } else { // doesn't match\n                    if(confirm(\"" . lang::get('LANG_PositionOutside' . $filterAttr[1] . "_7") . "\".replace(/SHAPE/g, a1.features[closest].attributes['" . $protocol[6] . "']).replace(/OLD/g, jQuery('#filterSelect" . $idx . "').val()))){\n                      replace = true;\n                    }\n                  }\n                }\n                if(reset) {\n                  jQuery('#locAttr\\\\:" . $attr['attributeId'] . "').val('');\n                  jQuery('#filterSelect" . $idx . "').val('');\n                  ParentLocationLayer.destroyFeatures();\n                } else if(replace){\n                  ParentLocationLayer.destroyFeatures();\n                  ParentLocationLayer.addFeatures([a1.features[closest]]); // feature should be in map projection\n                  jQuery('#filterSelect" . $idx . "').val(a1.features[closest].attributes['" . $protocol[6] . "']);\n                  jQuery('#locAttr\\\\:" . $attr['attributeId'] . "').val(a1.features[closest].attributes['" . $protocol[6] . "']);\n";
                                foreach ($filterAttrs as $idx1 => $filterAttr1) {
                                    // just need index, so don't explode
                                    if ($idx1 > $idx && $idx1 < count($filterAttrs) - 1) {
                                        // don't do name
                                        data_entry_helper::$javascript .= "                  filterLoad" . $idx1 . "();\n";
                                    }
                                }
                                data_entry_helper::$javascript .= "\n                }\n              }\n          });\n          var filter = new OpenLayers.Filter.Spatial({type: OpenLayers.Filter.Spatial.DWITHIN, property: '" . $protocol[3] . "', value: geom, distance: '" . $args['communeLayerBuffer'] . "'});\n" . ($filterAttr[3] != '' ? "          filter = new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND,\n               filters:[filter,\n\t\t                new OpenLayers.Filter.Comparison({type: OpenLayers.Filter.Comparison.EQUAL_TO, property: 'location_type_id', value: '" . $parentLocTypeID . "'})]});\n" : '') . "          protocol.read({filter: filter});\n";
                            }
                            data_entry_helper::$javascript .= "        }\n      }\n  });\n  var filter = new OpenLayers.Filter.Spatial({type: OpenLayers.Filter.Spatial.CONTAINS,property: '" . $protocol[3] . "',value: geom});\n" . ($filterAttr[3] != '' ? "  filter = new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND, filters:[filter, new OpenLayers.Filter.Comparison({type: OpenLayers.Filter.Comparison.EQUAL_TO, property: 'location_type_id', value: '" . $parentLocTypeID . "'})]});\n" : '') . "  protocol.read({filter: filter});\n};\njQuery('#filterSelect" . $idx . "').change(function(){\n  jQuery('#locAttr\\\\:" . $attr['attributeId'] . "').val(jQuery('#filterSelect" . $idx . "').val());\n  SetFilterNewLocation();\n";
                            foreach ($filterAttrs as $idx1 => $filterAttr1) {
                                if ($idx1 > $idx) {
                                    data_entry_helper::$javascript .= "    filterReset" . $idx1 . "();\n";
                                }
                            }
                            data_entry_helper::$javascript .= "  if(jQuery(this).val()!=''){\n";
                            foreach ($filterAttrs as $idx1 => $filterAttr1) {
                                if ($idx1 > $idx) {
                                    data_entry_helper::$javascript .= "    filterLoad" . $idx1 . "();\n";
                                }
                            }
                            data_entry_helper::$javascript .= "  }\n  displayShape(true);\n});\n";
                            $defaultsFunction .= "  if(keepFilter){\n    jQuery('#locAttr\\\\:" . $attr['attributeId'] . "').val(jQuery('#filterSelect" . $idx . "').val());\n  } else {\n    jQuery('#filterSelect" . $idx . "').val('');\n  }\n";
                            $loadFunction .= "  jQuery('#filterSelect" . $idx . "').val(jQuery('#locAttr\\\\:" . $attr['attributeId'] . "').val());\ndisplayShape(false);\n";
                            $prevFilterAttr = $filterAttr;
                            $prevAttr = $attr;
                            $prevIdx = $idx;
                            break;
                        case "Name":
                            //special case:
                            $retVal .= '<fieldset><legend>' . lang::get('Existing locations') . '</legend><label>' . $options['FilterNameLabel'] . ':</label> ' . '<select id="' . $options['MainFieldID'] . '" name="' . $options['MainFieldName'] . '" disabled="disabled">' . '<option value="">' . lang::get("None") . '</option>' . (array_key_exists($options['MainFieldName'], data_entry_helper::$entity_to_load) && data_entry_helper::$entity_to_load[$options['MainFieldName']] != "" ? '<option value="' . data_entry_helper::$entity_to_load[$options['MainFieldName']] . '" selected="selected">' . data_entry_helper::$entity_to_load['location:name'] . '</option>' : '') . '</select><br/></fieldset>';
                            // when a field is changed on the drop down, all following ones are reset.
                            // filterLoad function creates the drop down, based on filters. Assumes all filters are filled in - if not then sets to current value.
                            // the existing locations filter drop down runs the location ID. the site name is the location name.
                            data_entry_helper::$javascript .= "\n// when " . $options['MainFieldID'] . " changes the location will be loaded, including " . $options['MainFieldName'] . "\nfilterLoad" . $idx . " = function(){\n  jQuery('#location-name').data('newValue','');\n  if(jQuery('#" . $options['MainFieldID'] . "').val() != '' && jQuery('#" . $options['MainFieldID'] . "').val() != null)\n    jQuery('#" . $options['MainFieldID'] . "').data('storedValue',jQuery('#" . $options['MainFieldID'] . "').val())\n      .data('storedCaption',jQuery('#" . $options['MainFieldID'] . "').find(':selected')[0].text);\n  else\n    jQuery('#" . $options['MainFieldID'] . "').data('storedValue','').data('storedCaption','ERROR');\n  if(";
                            $condition = '';
                            foreach ($filterAttrs as $idx1 => $filterAttr1) {
                                if ($idx1 >= $idx) {
                                    continue;
                                }
                                $filterAttr1 = explode(':', $filterAttr1);
                                foreach ($locationAttributes as $locationAttribute1) {
                                    if ($filterAttr1[0] == "Parent") {
                                        if ($filterAttr1[1] == "true") {
                                            $condition .= ($condition == '' ? '' : ' || ') . "jQuery('#location\\\\:parent_id').val()== ''";
                                        }
                                    } else {
                                        if ($locationAttribute1['untranslatedCaption'] == ($filterAttr1[0] == "Shape" ? $filterAttr1[1] : $filterAttr1[0])) {
                                            $condition .= ($condition == '' ? '' : ' || ') . "jQuery('#locAttr\\\\:" . $locationAttribute1['attributeId'] . "').val()== ''";
                                        }
                                    }
                                }
                            }
                            data_entry_helper::$javascript .= $condition . "){\n\tif(jQuery('#" . $options['MainFieldID'] . "').data('storedValue')==null || jQuery('#" . $options['MainFieldID'] . "').data('storedValue')=='')\n      jQuery('#" . $options['MainFieldID'] . "').empty().attr('disabled','disabled').append('<option value=\"\">" . lang::get("First fill in filter options above") . "</option>');\n    else\n      jQuery('#" . $options['MainFieldID'] . "').empty().append('<option selected=\"selected\" value=\"'+jQuery('#" . $options['MainFieldID'] . "').data('storedValue')+'\">'+jQuery('#" . $options['MainFieldID'] . "').data('storedCaption')+'</option>');\n    return;\n  }\n  parent_id=jQuery('[name=location\\\\:parent_id]');\n  if(parent_id.length!=0) parent_id=parent_id.val();\n  // work out new name value: ignores shape attribute and parent_id. options for drop down\n  for(i=0, newName = 1, results=[]; i<locations.length; i++){\n    match=true;\n    for(j=0; j<location_attrs.length; j++)\n      if(jQuery('#locAttr\\\\:'+location_attrs[j].id).val()!=locations[i].attrs[location_attrs[j].id]) match=false;\n    if(match && parseInt(locations[i].name)>=newName) newName=parseInt(locations[i].name)+1;\n    if(typeof indiciaData.filterParent != 'undefined' && locations[i].parent_id!=parent_id) match=false;\n    if(match) results.push(locations[i]);\n  }\n  jQuery('#location-name').data('newValue',newName);\n  if(jQuery('#location-name').val()=='' && (jQuery('#location-id').val()=='' || jQuery('#location-id').val()==null)) jQuery('#location-name').val(newName);\n  // next work out existing sites list\n  jQuery('#" . $options['MainFieldID'] . "').empty(); // clear list\n  var stored = jQuery('#" . $options['MainFieldID'] . "').data('storedValue');\n  if(results.length>0) {\n    jQuery('#" . $options['MainFieldID'] . "').removeAttr('disabled').append('<option value=\"\">" . lang::get("Please select...") . "</option>');\n    for (var i=0;i<results.length;i++)\n      jQuery('#" . $options['MainFieldID'] . "').append('<option value=\"'+results[i].id+'\">'+results[i].name+'</option>');\n    if(stored!=null && stored!=''){\n      if(jQuery('#" . $options['MainFieldID'] . "').find('option').filter('[value='+stored+']').length>0){\n        jQuery('#" . $options['MainFieldID'] . "').val(stored);\n      } else {\n        jQuery('#" . $options['MainFieldID'] . "').prepend('<option selected=\"selected\" value=\"'+stored+'\">'+jQuery('#" . $options['MainFieldID'] . "').data('storedCaption')+'</option>');\n      }\n    }\n  } else {\n    if(stored!=null && stored!='')\n      jQuery('#" . $options['MainFieldID'] . "').prepend('<option selected=\"selected\" value=\"'+stored+'\">'+jQuery('#" . $options['MainFieldID'] . "').data('storedCaption')+'</option>');\n    else\n      jQuery('#" . $options['MainFieldID'] . "').attr('disabled','disabled').empty().append('<option value=\"\">" . lang::get("None available") . "</option>');\n  }\n  var options=\$('#location-name option');\n  if(options.length>0){\n    options.removeAttr('disabled');\n    options.not(':selected').each(function(idx,elem){\n      if(results.length>0) {\n        for (var i=0;i<results.length;i++){\n          if(results[i].name == elem.value) \$(elem).attr('disabled','disabled');\n        }\n      }});\n  }\n};\nfilterReset" . $idx . " = function(){\n  // filterResets also clear the main field. \n  jQuery('#" . $options['MainFieldID'] . "').empty().attr('disabled','disabled').append('<option value=\"\">" . lang::get("First fill in filter options above") . "</option>');\n  jQuery('#location-name').data('newValue','');\n};";
                            if (array_key_exists('location:id', data_entry_helper::$entity_to_load) && data_entry_helper::$entity_to_load['location:id'] != "") {
                                $initFunctions .= "\nfilterLoad" . $idx . "(true);";
                            } else {
                                $initFunctions .= "\nfilterReset" . $idx . "();";
                            }
                            // $defaultsFunction .= "  jQuery('#location-name').val(jQuery('#location-name').data('newValue'));\n";
                            $defaultsFunction .= "  filterLoad" . $idx . "(true)\n";
                            $loadFunction .= "  filterLoad" . $idx . "(true);\n";
                            break;
                        default:
                            $attr['class'] = (isset($attr['class']) ? $attr['class'] . " " : "") . "filterFields";
                            $ctrl = data_entry_helper::outputAttribute($attr, array('class' => "filterFields")) . '<span id="filter' . $idx . '"><label class="auto-width">' . lang::get("or pick one previously used") . ':</label> ' . '<select id="filterSelect' . $idx . '" ></select></span>';
                            $retVal .= str_replace('<br/>', '', $ctrl) . '<br />';
                            $attrList[] = array('id' => $attr['attributeId'], 'shape' => false);
                            if (count($filterAttr) > 1) {
                                data_entry_helper::add_resource('json');
                                data_entry_helper::add_resource('autocomplete');
                                data_entry_helper::$javascript .= "\njQuery('#locAttr\\\\:" . $attr['attributeId'] . "').autocomplete('" . data_entry_helper::$base_url . "/index.php/services/data/termlists_term', {\n      extraParams : {\n        view : 'detail',\n        orderby : 'term',\n        mode : 'json',\n        qfield : 'term',\n        auth_token: '" . $auth['read']['auth_token'] . "',\n        nonce: '" . $auth['read']['nonce'] . "',\n        termlist_id: '" . $filterAttr[1] . "'\n      },\n      max: 10000,\n      mustMatch : true,\n      parse: function(data) {\n        var results = [];\n        jQuery.each(data, function(i, item) {\n          results[results.length] = {'data' : item,'result' : item.term,'value' : item.term};\n        });\n        return results;\n      },\n      formatItem: function(item) {return item.term;}\n  });\njQuery('#locAttr\\\\:" . $attr['attributeId'] . "').result(function(data,value){\n  jQuery(this).change();\n});";
                            }
                            data_entry_helper::$javascript .= "\njQuery('#filterSelect" . $idx . "').change(function(){\n  jQuery('#locAttr\\\\:" . $attr['attributeId'] . "').data('store',jQuery('#filterSelect" . $idx . "').val()).val(jQuery('#filterSelect" . $idx . "').val());\n  SetFilterNewLocation();\n  if(jQuery(this).val()==''){\n";
                            foreach ($filterAttrs as $idx1 => $filterAttr1) {
                                if ($idx1 > $idx) {
                                    data_entry_helper::$javascript .= "    filterReset" . $idx1 . "();\n";
                                }
                            }
                            data_entry_helper::$javascript .= "  } else {\n";
                            foreach ($filterAttrs as $idx1 => $filterAttr1) {
                                if ($idx1 > $idx) {
                                    data_entry_helper::$javascript .= "    filterLoad" . $idx1 . "();\n";
                                }
                            }
                            data_entry_helper::$javascript .= "  }});\n\njQuery('#locAttr\\\\:" . $attr['attributeId'] . "').data('store',jQuery('#locAttr\\\\:" . $attr['attributeId'] . "').val()).change(function(){\n  jQuery(this).data('store',jQuery(this).val());\n  if(jQuery(this).val()=='') {\n    jQuery('#filterSelect" . $idx . "').val('');\n";
                            foreach ($filterAttrs as $idx1 => $filterAttr1) {
                                if ($idx1 > $idx) {
                                    data_entry_helper::$javascript .= "    filterReset" . $idx1 . "();\n";
                                }
                            }
                            data_entry_helper::$javascript .= "    } else {\n    if(jQuery('#filterSelect" . $idx . "').find('option').filter('[value='+jQuery(this).val()+']').length>0)\n      jQuery('#filterSelect" . $idx . "').val(jQuery(this).val());\n    else\n      jQuery('#filterSelect" . $idx . "').val('');\n";
                            foreach ($filterAttrs as $idx1 => $filterAttr1) {
                                if ($idx1 > $idx) {
                                    data_entry_helper::$javascript .= "    filterLoad" . $idx1 . "();\n";
                                }
                            }
                            data_entry_helper::$javascript .= "  }});\n\n// loads in the drop down list for a filter attribute.\n// Triggered in several places: when the filter above changes value\nfilterLoad" . $idx . " = function(){\n  var match, results, results1;\n  var id=jQuery('#" . $options['MainFieldID'] . "').val();\n  if(checkEditable(id=='',id))\n    jQuery('#locAttr\\\\:" . $attr['attributeId'] . "').removeAttr('disabled');\n  parent_id=jQuery('[name=location\\\\:parent_id]');\n  if(parent_id.length!=0) parent_id=parent_id.val();\n  for(i=0, results=[]; i<locations.length; i++){\n    match=true;\n    if(typeof indiciaData.filterParent != 'undefined' && locations[i].parent_id!=parent_id) match=false;\n    for(j=0; j<location_attrs.length; j++) {\n      if(location_attrs[j].id==" . $attr['attributeId'] . ") break;\n      if(jQuery('#locAttr\\\\:'+location_attrs[j].id).val()!=locations[i].attrs[location_attrs[j].id]) match=false;\n    }\n    if(match) results.push(locations[i].attrs[\"" . $attr['attributeId'] . "\"]);\n  }\n  jQuery('#filterSelect" . $idx . "').empty();\n  if(results.length>0) {\n    results.sort();\n    for(i=1, results1=[results[0]]; i<results.length; i++)\n      if(results[i]!=results[i-1]) results1.push(results[i]);\n    jQuery('#filter" . $idx . "').show();\n    jQuery('#filterSelect" . $idx . "').append('<option value=\"\">" . lang::get("Please select...") . "</option>');\n    for (var i=0;i<results1.length;i++){\n      // for each results, need to work out count of matching locations.\n      for(var k=0, count=0; k<locations.length; k++){\n        match=true;\n        if(typeof indiciaData.filterParent != 'undefined' && locations[k].parent_id!=parent_id) match=false;\n        for(var j=0; j<location_attrs.length; j++) {\n          if(location_attrs[j].id==" . $attr['attributeId'] . ") {\n            if(locations[k].attrs[location_attrs[j].id]!=results1[i]) match=false;\n            break;\n          }\n          if(jQuery('#locAttr\\\\:'+location_attrs[j].id).val()!=locations[k].attrs[location_attrs[j].id]) match=false;\n        }\n        if(match) count++;\n      }\n      jQuery('#filterSelect" . $idx . "').append('<option value=\"'+results1[i]+'\" '+(results1[i] == jQuery('#locAttr\\\\:" . $attr['attributeId'] . "').val() ? 'selected=\"selected\"' : '')+'>'+results1[i]+' ('+count+')'+'</option>');\n    }\n  } else\n    jQuery('#filter" . $idx . "').hide();\n};\nfilterReset" . $idx . " = function(){\n  jQuery('#locAttr\\\\:" . $attr['attributeId'] . "').val('');\n  filterLoad" . $idx . "();\n};";
                            if (array_key_exists('location:id', data_entry_helper::$entity_to_load) && data_entry_helper::$entity_to_load['location:id'] != "") {
                                $initFunctions .= "\nfilterLoad" . $idx . "();";
                            } else {
                                $initFunctions .= "\nfilterReset" . $idx . "();";
                            }
                            $defaultsFunction .= "  filterLoad" . $idx . "();\n";
                            $loadFunction .= "  filterLoad" . $idx . "();\n";
                            $prevFilterAttr = $filterAttr;
                            $prevAttr = $attr;
                            $prevIdx = $idx;
                            break;
                    }
                }
                $creatorAttr = iform_mnhnl_getAttrID($auth, $args, 'location', 'Creator');
                global $user;
                if ($creatorAttr) {
                    $defaultsFunction .= "  jQuery('#locAttr\\:" . $creatorAttr . "').val('" . $user->name . "');\n";
                }
                $communeAttr = iform_mnhnl_getAttrID($auth, $args, 'location', 'Commune');
                if (!(isset($args['communeLayerLookup']) && $args['communeLayerLookup'] != '') || !$communeAttr) {
                    $includeCommune = false;
                } else {
                    $parts = explode(',', $args['communeLayerLookup']);
                }
                data_entry_helper::$javascript .= "\nSetFilterNewLocation = function(){\n  var id=jQuery('#" . $options['MainFieldID'] . "').val();\n  if(checkEditable(id=='',id)) return;\n  setPermissionsNewSite();\n  clearLocation(true,'maybe');\n};\nhook_set_defaults = function(keepFilter){\n" . $defaultsFunction . "\n};\n" . $loadFunction . "\n};\nhook_setSref = function(geom){ // geom is in map projection.\n  jQuery('#map').ajaxStop(function(event){\n";
                if ($includeCommune) {
                    data_entry_helper::$javascript .= "\n  jQuery('[name=locAttr\\:{$communeAttr}],[name^=locAttr\\:{$communeAttr}\\:]').val('');\n  var communeProtocol = new OpenLayers.Protocol.WFS({\n      url:  '" . str_replace("{HOST}", $_SERVER['HTTP_HOST'], $parts[0]) . "',\n      featurePrefix: '" . $parts[1] . "',\n      featureType: '" . $parts[2] . "',\n      geometryName:'" . $parts[3] . "',\n      featureNS: '" . $parts[4] . "',\n      srsName: '" . $parts[5] . "',\n      version: '1.1.0',\n      propertyNames: ['" . $parts[6] . "']\n     ,callback: function(a1){\n        if(a1.error && (typeof a1.error.success == 'undefined' || a1.error.success == false)){\n          alert(\"" . lang::get('LANG_CommuneLookUpFailed') . "\");\n          return;\n        }\n        if(a1.features.length > 0) {\n          jQuery('[name=locAttr\\:{$communeAttr}],[name^=locAttr\\:{$communeAttr}\\:]').val(a1.features[0].attributes[\"" . $parts[6] . "\"]);\n        } else {\n";
                    if (!isset($args['communeLayerBuffer']) || $args['communeLayerBuffer'] == "") {
                        // No buffer in definition
                        data_entry_helper::$javascript .= "          alert(\"" . lang::get('LANG_PositionOutsideCommune_1') . "\");\n";
                    } else {
                        // buffer set
                        data_entry_helper::$javascript .= "          //  Get list of communes within buffer of geom\n          var protocol = new OpenLayers.Protocol.WFS({\n              url:  '" . $parts[0] . "',featurePrefix: '" . $parts[1] . "',featureType: '" . $parts[2] . "',geometryName:'" . $parts[3] . "',featureNS: '" . $parts[4] . "',srsName: '" . $parts[5] . "',version: '1.1.0',propertyNames: [\"" . $parts[6] . "\"]\n             ,callback: function(a1){\n                var replace = false,\n                    reset = false;\n                if(a1.error && (typeof a1.error.success == 'undefined' || a1.error.success == false)){\n                  alert(\"" . lang::get('LANG_CommuneLookUpFailed') . "\");\n                  return;\n                }\n                if(a1.features.length == 0) {\n                  alert(\"" . str_replace('{DISTANCE}', $args['communeLayerBuffer'], lang::get('LANG_PositionOutsideCommune_3')) . "\");\n                } else {\n                  var closest = 0;\n                  if(a1.features.length >= 0) {\n                    for(var i=0; i< a1.features.length; i++){\n                      var distance, thisDistance = geom.distanceTo(a1.features[i].geometry, {});\n                      if(i==0 || thisDistance<distance){\n                        closest=i;\n                        distance=thisDistance;\n                      }\n                    }\n                  }\n                  alert(\"" . lang::get('LANG_PositionOutside' . $filterAttr[1] . "_5A") . "\".replace(/SHAPE/g, a1.features[closest].attributes['" . $parts[6] . "']));\n                  jQuery('[name=locAttr\\:{$communeAttr}],[name^=locAttr\\:{$communeAttr}\\:]').val(a1.features[closest].attributes[\"" . $parts[6] . "\"]);\n                }\n              }\n          });\n          var filter = new OpenLayers.Filter.Spatial({type: OpenLayers.Filter.Spatial.DWITHIN, property: '" . $parts[3] . "', value: geom, distance: '" . $args['communeLayerBuffer'] . "'});\n          protocol.read({filter: filter});\n";
                    }
                    data_entry_helper::$javascript .= "        }\n      }\n  });\n  var filter = new OpenLayers.Filter.Spatial({type: OpenLayers.Filter.Spatial.CONTAINS,property: '" . $parts[3] . "',value: geom});\n  communeProtocol.read({filter: filter});\n";
                }
                foreach ($filterAttrs as $idx => $filterAttr) {
                    $filterAttr = explode(':', $filterAttr);
                    if ($filterAttr[0] == "Parent" || $filterAttr[0] == "Shape") {
                        data_entry_helper::$javascript .= "    hook_setSref_" . $idx . "(geom);\n";
                    }
                    // map projection
                }
                $locAttrText = array();
                foreach ($attrList as $filterAttr) {
                    $locAttrText[] = "  {'id':'" . $filterAttr['id'] . "', 'shape':" . ($filterAttr['shape'] ? 'true' : 'false') . "}";
                }
                data_entry_helper::$javascript .= "    \$(this).unbind(event);\n  });\n};\nlocation_attrs = [" . implode(",\n", $locAttrText) . "];";
                if ($includeCommune) {
                    data_entry_helper::$javascript .= "jQuery('[name=locAttr\\:{$communeAttr}],[name^=locAttr\\:{$communeAttr}\\:]').attr('readonly','readonly');\n";
                }
                if (isset($args['autoGenSiteName']) && $args['autoGenSiteName']) {
                    $retVal .= "<label for=\"location-name\">" . $options['NameLabel'] . ":</label> <input type='text' id=\"location-name\" name=\"location:name\" " . ($options['AdminMode'] ? "class='required integer' min='1'" : "class='required' readonly='readonly'") . " value=\"" . htmlspecialchars(data_entry_helper::$entity_to_load['location:name']) . "\" /><span class='deh-required'>*</span><br/>";
                } else {
                    if ($args['siteNameTermListID'] == '') {
                        $retVal .= "<label for=\"location-name\">" . $options['NameLabel'] . ":</label> <input type='text' id=\"location-name\" name=\"location:name\" class='wide required' value=\"" . htmlspecialchars(data_entry_helper::$entity_to_load['location:name']) . "\" /><span class='deh-required'>*</span><br/>";
                    } else {
                        $retVal .= data_entry_helper::select(array('label' => $options['NameLabel'], 'id' => 'location-name', 'fieldname' => 'location:name', 'table' => 'termlists_term', 'captionField' => 'term', 'valueField' => 'term', 'blankText' => '', 'validation' => array('required'), 'extraParams' => $auth['read'] + array('termlist_id' => $args['siteNameTermListID'], 'orderby' => 'id')));
                    }
                }
                data_entry_helper::$javascript .= $initFunctions;
                $retVal .= "<input type='hidden' id=\"sample-location-id\" name=\"sample:location_id\" value='" . data_entry_helper::$entity_to_load['sample:location_id'] . "' />";
            }
        }
    }
    if (isset($args['includeLocationCode']) && $args['includeLocationCode']) {
        $retVal .= "<label for=\"location-code\">" . $options['CodeLabel'] . ":</label> <input id=\"location-code\" class=\"integer\" min=1 name=\"location:code\" value=\"" . htmlspecialchars(data_entry_helper::$entity_to_load['location:code']) . "\" dbCode=\"" . htmlspecialchars(data_entry_helper::$entity_to_load['location:code']) . "\"><br />";
    }
    // Move any Attribute fields side by side.
    if (isset($args['removeBreakLocAttrIDs']) && $args['removeBreakLocAttrIDs'] != "") {
        $removeBreakLocAttrIDs = explode(':', $args['removeBreakLocAttrIDs']);
        foreach ($removeBreakLocAttrIDs as $removeBreakLocAttrID) {
            data_entry_helper::$javascript .= "\njQuery('[name=locAttr\\:" . $removeBreakLocAttrID . "],[name^=locAttr\\:" . $removeBreakLocAttrID . "\\:]').css('margin-right', '20px').nextAll('br').eq(0).remove();";
        }
    }
    return $retVal;
}
   /**
    * Return the generated form output.
    * @return Form HTML.
    */
   public static function get_form($args, $node, $response = null)
   {
       global $user;
       global $custom_terms;
       $logged_in = $user->uid > 0;
       $r = '';
       // Get authorisation tokens to update and read from the Warehouse.
       $auth = data_entry_helper::get_read_write_auth($args['website_id'], $args['password']);
       $readAuth = $auth['read'];
       $svcUrl = data_entry_helper::$base_url . '/index.php/services';
       drupal_add_js(drupal_get_path('module', 'iform') . '/media/js/jquery.form.js', 'module');
       data_entry_helper::link_default_stylesheet();
       data_entry_helper::add_resource('jquery_ui');
       $language = iform_lang_iso_639_2($args['language']);
       if ($args['language'] != 'en') {
           data_entry_helper::add_resource('jquery_ui_' . $args['language']);
       }
       // If not logged in: Display an information message.
       // This form should only be called in POST mode when setting the location allocation.
       //  All other posting is now done via AJAX.
       // When invoked by GET there are the following modes:
       // No additional arguments: mode 0.
       // Additional argument - new : mode 1.
       // Additional argument - sample_id=<id> : mode 2.
       // Additional argument - occurrence_id=<id> : mode 3.
       // Additional arguments - merge_sample_id1=<id>&merge_sample_id2=<id> : mode 2.1
       $mode = 0;
       // default mode : output survey selector
       // mode 1: output the main Data Entry page: occurrence list or add/edit occurrence tabs hidden. "Survey" tab active
       // mode 2: output the main Data Entry page, display existing sample. Active tab determined by iform params. No occurence details filled in.
       // mode 2.1: sample 2 has all its occurrences merged into sample 1. sample 2 is then flagged as deleted. sample 1 is then viewed as in normal mode 2.
       // mode 3: output the main Data Entry page, display existing occurrence. "Edit Occurrence" tab active. Occurence details filled in.
       $surveyReadOnly = false;
       // On top of this, things can be flagged as readonly. RO mode 2+4 means no Add Occurrence tab.
       if (!$logged_in) {
           return lang::get('LANG_not_logged_in');
       }
       $parentSample = array();
       $parentLoadID = null;
       $childSample = array();
       $childLoadID = null;
       $thisOccID = -1;
       // IDs have to be >0, so this is outside the valid range
       // Load up attribute details
       $sample_walk_direction_id = self::getAttrID($auth, $args, 'sample', self::ATTR_WALK);
       $sample_reliability_id = self::getAttrID($auth, $args, 'sample', self::ATTR_RELIABILITY);
       $sample_visit_number_id = self::getAttrID($auth, $args, 'sample', self::ATTR_VISIT);
       $sample_wind_id = self::getAttrID($auth, $args, 'sample', self::ATTR_WIND);
       $sample_precipitation_id = self::getAttrID($auth, $args, 'sample', self::ATTR_RAIN);
       $sample_temperature_id = self::getAttrID($auth, $args, 'sample', self::ATTR_TEMP);
       $sample_cloud_id = self::getAttrID($auth, $args, 'sample', self::ATTR_CLOUD);
       $sample_start_time_id = self::getAttrID($auth, $args, 'sample', self::ATTR_START_TIME);
       $sample_end_time_id = self::getAttrID($auth, $args, 'sample', self::ATTR_END_TIME);
       $sample_closure_id = self::getAttrID($auth, $args, 'sample', self::ATTR_CLOSED);
       $uid_attr_id = self::getAttrID($auth, $args, 'sample', self::ATTR_UID);
       $email_attr_id = self::getAttrID($auth, $args, 'sample', self::ATTR_EMAIL);
       $username_attr_id = self::getAttrID($auth, $args, 'sample', self::ATTR_USERNAME);
       $occurrence_confidence_id = self::getAttrID($auth, $args, 'occurrence', self::ATTR_CONFIDENCE);
       $occurrence_count_id = self::getAttrID($auth, $args, 'occurrence', self::ATTR_COUNT);
       $occurrence_approximation_id = self::getAttrID($auth, $args, 'occurrence', self::ATTR_APPROXIMATION);
       $occurrence_territorial_id = self::getAttrID($auth, $args, 'occurrence', self::ATTR_TERRITORIAL);
       $occurrence_atlas_code_id = self::getAttrID($auth, $args, 'occurrence', self::ATTR_ATLAS_CODE);
       $occurrence_overflying_id = self::getAttrID($auth, $args, 'occurrence', self::ATTR_OVERFLYING);
       if (!$sample_closure_id) {
           return '<p>This form must be used with a survey which has the "' . self::ATTR_CLOSED . '" sample attribute allocated to it. Survey_id = ' . $args['survey_id'];
       }
       if (!$uid_attr_id) {
           return '<p>This form must be used with a survey which has the "' . self::ATTR_UID . '" sample attribute allocated to it. Survey_id = ' . $args['survey_id'];
       }
       if (!$email_attr_id) {
           return '<p>This form must be used with a survey which has the "' . self::ATTR_EMAIL . '" sample attribute allocated to it. Survey_id = ' . $args['survey_id'];
       }
       if (!$username_attr_id) {
           return '<p>This form must be used with a survey which has the "' . self::ATTR_USERNAME . '" sample attribute allocated to it. Survey_id = ' . $args['survey_id'];
       }
       if (!$sample_walk_direction_id) {
           return '<p>This form must be used with a survey which has the "' . self::ATTR_WALK . '" sample attribute allocated to it. Survey_id = ' . $args['survey_id'];
       }
       if (!$sample_visit_number_id) {
           return '<p>This form must be used with a survey which has the "' . self::ATTR_VISIT . '" sample attribute allocated to it. Survey_id = ' . $args['survey_id'];
       }
       if (!$occurrence_count_id) {
           return '<p>This form must be used with a survey which has the "' . self::ATTR_COUNT . '" occurrence attribute allocated to it. Survey_id = ' . $args['survey_id'];
       }
       if (!$occurrence_territorial_id) {
           return '<p>This form must be used with a survey which has the "' . self::ATTR_TERRITORIAL . '" occurrence attribute allocated to it. Survey_id = ' . $args['survey_id'];
       }
       if (!$occurrence_atlas_code_id) {
           return '<p>This form must be used with a survey which has the "' . self::ATTR_ATLAS_CODE . '" occurrence attribute allocated to it. Survey_id = ' . $args['survey_id'];
       }
       if ($_POST) {
           if (!array_key_exists('website_id', $_POST)) {
               // non Indicia POST, in this case must be the location allocations. add check to ensure we don't corrept the data by accident
               if (iform_loctools_checkaccess($node, 'admin') && array_key_exists('mnhnlbtw', $_POST)) {
                   iform_loctools_deletelocations($node);
                   foreach ($_POST as $key => $value) {
                       $parts = explode(':', $key);
                       if ($parts[0] == 'location' && $value) {
                           iform_loctools_insertlocation($node, $value, $parts[1]);
                       }
                   }
               }
           }
       } else {
           if (array_key_exists('merge_sample_id1', $_GET) && array_key_exists('merge_sample_id2', $_GET) && user_access($args['edit_permission'])) {
               $mode = 2;
               // first check can access the 2 samples given
               $parentLoadID = $_GET['merge_sample_id1'];
               $url = $svcUrl . '/data/sample/' . $parentLoadID . "?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"];
               $session = curl_init($url);
               curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
               $entity = json_decode(curl_exec($session), true);
               if (count($entity) == 0 || $entity[0]["parent_id"]) {
                   return '<p>' . lang::get('LANG_No_Access_To_Sample') . ' ' . $parentLoadID . '</p>';
               }
               // The check for id2 is slightly different: there is the possiblity that someone will F5/refresh their browser, after the transfer and delete have taken place.
               // In this case we carry on, but do not do the transfer and delete.
               $url = $svcUrl . '/data/sample/' . $_GET['merge_sample_id2'] . "?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"];
               $session = curl_init($url);
               curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
               $entity = json_decode(curl_exec($session), true);
               if (count($entity) > 0 && !$entity[0]["parent_id"]) {
                   // now get child samples and point to new parent.
                   $url = $svcUrl . '/data/sample?mode=json&view=detail&auth_token=' . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"] . '&parent_id=' . $_GET['merge_sample_id2'];
                   $session = curl_init($url);
                   curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
                   $entities = json_decode(curl_exec($session), true);
                   if (count($entities) > 0) {
                       foreach ($entities as $entity) {
                           $Model = data_entry_helper::wrap(array('id' => $entity['id'], 'parent_id' => $_GET['merge_sample_id1']), 'sample');
                           $request = data_entry_helper::$base_url . "/index.php/services/data/save";
                           $postargs = 'submission=' . json_encode($Model) . '&auth_token=' . $auth['write_tokens']['auth_token'] . '&nonce=' . $auth['write_tokens']['nonce'] . '&persist_auth=true';
                           $postresponse = data_entry_helper::http_post($request, $postargs, false);
                           // the response array will always feature an output, which is the actual response or error message. if it is not json format, assume error text, and json encode that.
                           $response = $postresponse['output'];
                           if (!json_decode($response, true)) {
                               return "<p>" . lang::get('LANG_Error_When_Moving_Sample') . ": id " . $entity['id'] . " : " . $response;
                           }
                       }
                   }
                   // finally delete the no longer used sample
                   $Model = data_entry_helper::wrap(array('id' => $_GET['merge_sample_id2'], 'deleted' => 'true'), 'sample');
                   $request = data_entry_helper::$base_url . "/index.php/services/data/save";
                   $postargs = 'submission=' . json_encode($Model) . '&auth_token=' . $auth['write_tokens']['auth_token'] . '&nonce=' . $auth['write_tokens']['nonce'] . '&persist_auth=true';
                   $postresponse = data_entry_helper::http_post($request, $postargs, false);
                   // the response array will always feature an output, which is the actual response or error message. if it is not json format, assume error text, and json encode that.
                   $response = $postresponse['output'];
                   if (!json_decode($response, true)) {
                       return "<p>" . lang::get('LANG_Error_When_Deleting_Sample') . ": id " . $entity['id'] . " : " . $response;
                   }
               }
           } else {
               if (array_key_exists('sample_id', $_GET)) {
                   $mode = 2;
                   $parentLoadID = $_GET['sample_id'];
               } else {
                   if (array_key_exists('occurrence_id', $_GET)) {
                       $mode = 3;
                       $childLoadID = $_GET['occurrence_id'];
                       $thisOccID = $childLoadID;
                   } else {
                       if (array_key_exists('new', $_GET)) {
                           $mode = 1;
                       }
                   }
               }
           }
           // else default to mode 0
       }
       // define language strings so they can be used for validation translation.
       data_entry_helper::$javascript .= "var translations = [\n";
       foreach ($custom_terms as $key => $value) {
           if (substr($key, 0, 4) != "LANG") {
               data_entry_helper::$javascript .= "  {key: \"" . $key . "\", translated: \"" . $value . "\"},\n";
           }
       }
       data_entry_helper::$javascript .= "];\n";
       // define layers for all maps.
       // each argument is a comma separated list eg:
       // "Name:Lux Outline,URL:http://localhost/geoserver/wms,LAYERS:indicia:nation2,SRS:EPSG:2169,FORMAT:image/png,minScale:0,maxScale:1000000,units:m";
       $optionsArray_Location = array();
       $options = explode(',', $args['locationLayer']);
       foreach ($options as $option) {
           $parts = explode(':', $option);
           $optionName = $parts[0];
           unset($parts[0]);
           $optionsArray_Location[$optionName] = implode(':', $parts);
       }
       // Work out list of locations this user can see.
       $locations = iform_loctools_listlocations($node);
       if ($locations != 'all') {
           data_entry_helper::$javascript .= "var locationList = [" . implode(',', $locations) . "];\n";
       }
       drupal_add_js(drupal_get_path('module', 'iform') . '/media/js/hasharray.js', 'module');
       drupal_add_js(drupal_get_path('module', 'iform') . '/media/js/jquery.datagrid.js', 'module');
       if (method_exists(get_called_class(), 'getHeaderHTML')) {
           $r .= call_user_func(array(get_called_class(), 'getHeaderHTML'), $args);
       }
       // Work out list of locations this user can see.
       // $locations = iform_loctools_listlocations($node);
       ///////////////////////////////////////////////////////////////////
       // default mode 0 : display a page with tabs for survey selector,
       // locations allocator and reports (last two require permissions)
       ///////////////////////////////////////////////////////////////////
       if ($mode == 0) {
           // If the user has permissions, add tabs so can choose to see
           // locations allocator
           $tabs = array('#surveyList' => lang::get('LANG_Surveys'));
           if (iform_loctools_checkaccess($node, 'admin')) {
               $tabs['#setLocations'] = lang::get('LANG_Allocate_Locations');
           }
           if (iform_loctools_checkaccess($node, 'superuser')) {
               $tabs['#downloads'] = lang::get('LANG_Download');
           }
           if (count($tabs) > 1) {
               $r .= "<div id=\"controls\">" . data_entry_helper::enable_tabs(array('divId' => 'controls', 'active' => '#surveyList')) . "<div id=\"temp\"></div>";
               $r .= data_entry_helper::tab_header(array('tabs' => $tabs));
           }
           if ($locations == 'all') {
               $useloclist = 'NO';
               $loclist = '-1';
           } else {
               // an empty list will cause an sql error, lids must be > 0, so push a -1 to prevent the error.
               if (empty($locations)) {
                   $locations[] = -1;
               }
               $useloclist = 'YES';
               $loclist = implode(',', $locations);
           }
           // Create the Survey list datagrid for this user.
           drupal_add_js("jQuery(document).ready(function(){\n  \$('div#smp_grid').indiciaDataGrid('rpt:reports_for_prebuilt_forms/MNHNL/mnhnl_btw_list_samples', {\n    indiciaSvc: '" . $svcUrl . "',\n    dataColumns: ['location_name', 'date', 'num_visit', 'num_occurrences', 'num_taxa'],\n    reportColumnTitles: {location_name : '" . lang::get('LANG_Transect') . "', date : '" . lang::get('LANG_Date') . "', num_visit : '" . lang::get('LANG_Visit_No') . "', num_occurrences : '" . lang::get('LANG_Num_Occurrences') . "', num_taxa : '" . lang::get('LANG_Num_Species') . "'},\n    actionColumns: {" . lang::get('LANG_Show') . " : \"" . url('node/' . $node->nid, array('query' => 'sample_id=£id£')) . "\"},\n    auth : { nonce : '" . $readAuth['nonce'] . "', auth_token : '" . $readAuth['auth_token'] . "'},\n    parameters : { survey_id : '" . $args['survey_id'] . "', visit_attr_id : '" . $sample_visit_number_id . "', closed_attr_id : '" . $sample_closure_id . "', use_location_list : '" . $useloclist . "', locations : '" . $loclist . "'},\n    itemsPerPage : 12,\n    condCss : {field : 'closed', value : '0', css: 'mnhnl-btw-highlight'},\n    cssOdd : ''\n  });\n});\n      ", 'inline');
           data_entry_helper::$javascript .= "\n// Create Layers.\nvar locationListLayer;\nmapInitialisationHooks.push(function (div) {\n      \"use strict\";";
           if ($locations == 'all' || $loclist != '-1') {
               data_entry_helper::$javascript .= "\n  var WMSoptions = {SERVICE: 'WMS', VERSION: '1.1.0', STYLES: '',\n        SRS: div.map.projection.proj.srsCode, /* Now takes it from map */\n        FORMAT: '" . $optionsArray_Location['FORMAT'] . "',\n        TRANSPARENT: 'true', ";
               if ($locations != 'all') {
                   // when given a restricted feature list we have to use the feature id to filter in order to not go over 2000 char limit on the URL
                   // Can only generate the feature id if we access a table directly, not through a view. Go direct to the locations table.
                   // don't need to worry about parent_id in this case as we know exactly which features we want.
                   // need to use btw_transects view for unrestricted so we can filter by parent_id=NULL.
                   $locFeatures = array();
                   foreach ($locations as $location) {
                       $locFeatures[] = "locations." . $location;
                   }
                   data_entry_helper::$javascript .= "\n        LAYERS: 'indicia:locations',\n        FEATUREID: '" . implode(',', $locFeatures) . "'";
               } else {
                   data_entry_helper::$javascript .= " LAYERS: '" . $optionsArray_Location['LAYERS'] . "', CQL_FILTER: 'website_id=" . $args['website_id'] . "'";
               }
               data_entry_helper::$javascript .= "\n  };\n  locationListLayer = new OpenLayers.Layer.WMS('" . $optionsArray_Location['Name'] . "',\n        '" . (function_exists(iform_proxy_url) ? iform_proxy_url($optionsArray_Location['URL']) : $optionsArray_Location['URL']) . "',\n        WMSoptions, {\n        minScale: " . $optionsArray_Location['minScale'] . ",\n        maxScale: " . $optionsArray_Location['maxScale'] . ",\n        units: '" . $optionsArray_Location['units'] . "',\n        isBaseLayer: false,\n        singleTile: true\n  });\n  div.map.addLayer(locationListLayer);\n});\n";
           }
           $r .= '
 <div id="surveyList" class="mnhnl-btw-datapanel"><div id="smp_grid"></div>
   <form><input type="button" value="' . lang::get('LANG_Add_Survey') . '" onclick="window.location.href=\'' . url('node/' . $node->nid, array('query' => 'new')) . '\'"></form></div>';
           // Add the locations allocator if user has admin rights.
           if (iform_loctools_checkaccess($node, 'admin')) {
               $r .= '
 <div id="setLocations" class="mnhnl-btw-datapanel">
   <form method="post">
     <input type="hidden" id="mnhnlbtw" name="mnhnlbtw" value="mnhnlbtw" />';
               $url = $svcUrl . '/data/location?mode=json&view=detail&auth_token=' . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"] . "&parent_id=NULL&orderby=name&columns=id,name,parent_id";
               $session = curl_init($url);
               curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
               $entities = json_decode(curl_exec($session), true);
               $userlist = iform_loctools_listusers($node);
               if (!empty($entities)) {
                   foreach ($entities as $entity) {
                       if (!$entity["parent_id"]) {
                           // only assign parent locations.
                           $r .= "\n<label for=\"location:" . $entity["id"] . "\">" . $entity["name"] . ":</label><select id=\"location:" . $entity["id"] . "\" name=\"location:" . $entity["id"] . "\"><option value=\"\" >&lt;" . lang::get('LANG_Not_Allocated') . "&gt;</option>";
                           $defaultuserid = iform_loctools_getuser($node, $entity["id"]);
                           foreach ($userlist as $uid => $a_user) {
                               $r .= "<option value=\"" . $uid . "\" " . ($uid == $defaultuserid ? 'selected="selected" ' : '') . ">" . $a_user->name . "</option>";
                           }
                           $r .= "</select>";
                       }
                   }
               }
               $r .= "\n      <input type=\"submit\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('Save Location Allocations') . "\" />\n    </form>\n  </div>";
           }
           // Add the downloader if user has manager (superuser) rights.
           if (iform_loctools_checkaccess($node, 'superuser')) {
               $r .= '
 <div id="downloads" class="mnhnl-btw-datapanel">
   <form method="post" action="' . data_entry_helper::$base_url . '/index.php/services/report/requestReport?report=reports_for_prebuilt_forms/MNHNL/mnhnl_btw_transect_direction_report.xml&reportSource=local&auth_token=' . $readAuth['auth_token'] . '&nonce=' . $readAuth['nonce'] . '&mode=csv">
     <p>' . lang::get('LANG_Direction_Report') . '</p>
     <input type="hidden" name="params" value=\'{"survey_id":' . $args['survey_id'] . ', "direction_attr_id":' . $sample_walk_direction_id . ', "closed_attr_id":' . $sample_closure_id . '}\' />
     <input type="submit" class="ui-state-default ui-corner-all" value="' . lang::get('LANG_Direction_Report_Button') . '">
   </form>
   <form method="post" action="' . data_entry_helper::$base_url . '/index.php/services/report/requestReport?report=reports_for_prebuilt_forms/MNHNL/mnhnl_btw_verified_data_report.xml&reportSource=local&auth_token=' . $readAuth['auth_token'] . '&nonce=' . $readAuth['nonce'] . '&mode=csv">
     <p>' . lang::get('LANG_Verified_Data_Report') . '</p>
     <input type="hidden" name="params" value=\'{"survey_id":' . $args['survey_id'] . '}\' />
     <input type="submit" class="ui-state-default ui-corner-all" value="' . lang::get('LANG_Verified_Data_Report_Button') . '">
   </form>
   <form method="post" action="' . data_entry_helper::$base_url . '/index.php/services/report/requestReport?report=reports_for_prebuilt_forms/MNHNL/mnhnl_btw_download_report_2.xml&reportSource=local&auth_token=' . $readAuth['auth_token'] . '&nonce=' . $readAuth['nonce'] . '&mode=csv">
     <p>' . lang::get('LANG_Initial_Download') . '</p>
     <input type="hidden" name="params" value=\'{"survey_id":' . $args['survey_id'] . ', "closed_attr_id":' . $sample_closure_id . ', "download": "INITIAL", "quality": "!R", "occattrs": "' . $occurrence_confidence_id . ',' . $occurrence_count_id . ',' . $occurrence_approximation_id . ',' . $occurrence_territorial_id . ',' . $occurrence_atlas_code_id . ',' . $occurrence_overflying_id . '", "smpattrs" : "' . $sample_walk_direction_id . ',' . $sample_reliability_id . ',' . $sample_visit_number_id . ',' . $sample_wind_id . ',' . $sample_precipitation_id . ',' . $sample_temperature_id . ',' . $sample_cloud_id . ',' . $sample_start_time_id . ',' . $sample_end_time_id . ',' . $sample_closure_id . ',' . $uid_attr_id . ',' . $email_attr_id . ',' . $username_attr_id . '"}\' />
     <input type="submit" class="ui-state-default ui-corner-all" value="' . lang::get('LANG_Initial_Download_Button') . '">
   </form>
   <form method="post" action="' . data_entry_helper::$base_url . '/index.php/services/report/requestReport?report=reports_for_prebuilt_forms/MNHNL/mnhnl_btw_download_report_2.xml&reportSource=local&auth_token=' . $readAuth['auth_token'] . '&nonce=' . $readAuth['nonce'] . '&mode=csv">
     <p>' . lang::get('LANG_Confirm_Download') . '</p>
     <input type="hidden" name="params" value=\'{"survey_id":' . $args['survey_id'] . ', "closed_attr_id":' . $sample_closure_id . ', "download": "CONFIRM", "quality": "V", "occattrs": "' . $occurrence_confidence_id . ',' . $occurrence_count_id . ',' . $occurrence_approximation_id . ',' . $occurrence_territorial_id . ',' . $occurrence_atlas_code_id . ',' . $occurrence_overflying_id . '", "smpattrs" : "' . $sample_walk_direction_id . ',' . $sample_reliability_id . ',' . $sample_visit_number_id . ',' . $sample_wind_id . ',' . $sample_precipitation_id . ',' . $sample_temperature_id . ',' . $sample_cloud_id . ',' . $sample_start_time_id . ',' . $sample_end_time_id . ',' . $sample_closure_id . ',' . $uid_attr_id . ',' . $email_attr_id . ',' . $username_attr_id . '"}\' />
     <input type="submit" class="ui-state-default ui-corner-all" value="' . lang::get('LANG_Confirm_Download_Button') . '">
   </form>
   <form method="post" action="' . data_entry_helper::$base_url . '/index.php/services/report/requestReport?report=reports_for_prebuilt_forms/MNHNL/mnhnl_btw_download_report_2.xml&reportSource=local&auth_token=' . $readAuth['auth_token'] . '&nonce=' . $readAuth['nonce'] . '&mode=csv">
     <p>' . lang::get('LANG_Final_Download') . '</p>
     <input type="hidden" name="params" value=\'{"survey_id":' . $args['survey_id'] . ', "closed_attr_id":' . $sample_closure_id . ', "download": "FINAL", "quality": "V", "occattrs": "' . $occurrence_confidence_id . ',' . $occurrence_count_id . ',' . $occurrence_approximation_id . ',' . $occurrence_territorial_id . ',' . $occurrence_atlas_code_id . ',' . $occurrence_overflying_id . '", "smpattrs" : "' . $sample_walk_direction_id . ',' . $sample_reliability_id . ',' . $sample_visit_number_id . ',' . $sample_wind_id . ',' . $sample_precipitation_id . ',' . $sample_temperature_id . ',' . $sample_cloud_id . ',' . $sample_start_time_id . ',' . $sample_end_time_id . ',' . $sample_closure_id . ',' . $uid_attr_id . ',' . $email_attr_id . ',' . $username_attr_id . '"}\' />
     <input type="submit" class="ui-state-default ui-corner-all" value="' . lang::get('LANG_Final_Download_Button') . '">
   </form>
   <form method="post" action="' . data_entry_helper::$base_url . '/index.php/services/report/requestReport?report=reports_for_prebuilt_forms/MNHNL/mnhnl_btw_download_report_2.xml&reportSource=local&auth_token=' . $readAuth['auth_token'] . '&nonce=' . $readAuth['nonce'] . '&mode=csv">
     <p>' . lang::get('LANG_Complete_Final_Download') . '</p>
     <input type="hidden" name="params" value=\'{"survey_id":' . $args['survey_id'] . ', "closed_attr_id":' . $sample_closure_id . ', "download": "OFF", "quality": "NA", "occattrs": "' . $occurrence_confidence_id . ',' . $occurrence_count_id . ',' . $occurrence_approximation_id . ',' . $occurrence_territorial_id . ',' . $occurrence_atlas_code_id . ',' . $occurrence_overflying_id . '", "smpattrs" : "' . $sample_walk_direction_id . ',' . $sample_reliability_id . ',' . $sample_visit_number_id . ',' . $sample_wind_id . ',' . $sample_precipitation_id . ',' . $sample_temperature_id . ',' . $sample_cloud_id . ',' . $sample_start_time_id . ',' . $sample_end_time_id . ',' . $sample_closure_id . ',' . $uid_attr_id . ',' . $email_attr_id . ',' . $username_attr_id . '"}\' />
     <input type="submit" class="ui-state-default ui-corner-all" value="' . lang::get('LANG_Complete_Final_Download_Button') . '">
   </form>
 </div>';
           }
           // Create Map
           $options = iform_map_get_map_options($args, $readAuth);
           $olOptions = iform_map_get_ol_options($args);
           //      if($locations == 'all' || $loclist != '-1')
           //        $options['layers'] = array('locationListLayer');
           $options['searchLayer'] = 'false';
           $options['editLayer'] = 'false';
           $options['initialFeatureWkt'] = null;
           $options['proxy'] = '';
           $options['scroll_wheel_zoom'] = false;
           $options['width'] = 'auto';
           // TBD remove from arglist
           $r .= "<div class=\"mnhnl-btw-mappanel\">\n" . data_entry_helper::map_panel($options, $olOptions) . "</div>\n";
           data_entry_helper::$javascript .= "\n\$('#controls').bind('tabsshow', function(event, ui) {\n  var y = \$('.mnhnl-btw-datapanel:visible').outerHeight(true) + \$('.mnhnl-btw-datapanel:visible').position().top;\n  if(y < \$('.mnhnl-btw-mappanel').outerHeight(true)+ \$('.mnhnl-btw-mappanel').position().top){\n    y = \$('.mnhnl-btw-mappanel').outerHeight(true)+ \$('.mnhnl-btw-mappanel').position().top;\n  }\n  \$('#controls').height(y - \$('#controls').position().top);\n});\n";
           if (count($tabs) > 1) {
               // close tabs div if present
               $r .= "</div>";
           }
           if (method_exists(get_called_class(), 'getTrailerHTML')) {
               $r .= call_user_func(array(get_called_class(), 'getTrailerHTML'), $args);
           }
           return $r;
       }
       ///////////////////////////////////////////////////////////////////
       // At this point there are 3 modes:
       // Adding a new survey
       // editing/showing an existing survey
       // editing/showing an existing occurrence
       // First load the occurrence (and its position sample) if provided
       // Then load the parent sample if provided, or derived from occurrence.
       // $occReadOnly is set if the occurrence has been downloaded. Not even an admin user can modify it in this case.
       data_entry_helper::$javascript .= "\n// Create Layers.\nvar locationLayer, occListLayer, control;\nmapInitialisationHooks.push(function (div) {\n  \"use strict\";\n  // Create vector layers: one to display the location onto, and another for the occurrence list\n  // the default edit layer is used for the occurrences themselves\n  var locStyleMap = new OpenLayers.StyleMap({\n      'default': new OpenLayers.Style({\n        fillColor: 'Green',\n        strokeColor: 'Black',\n        fillOpacity: 0.2,\n        strokeWidth: 1\n  })});\n  locationLayer = new OpenLayers.Layer.Vector('" . lang::get("LANG_Location_Layer") . "', {styleMap: locStyleMap});\n  var occStyleMap = new OpenLayers.StyleMap({\n      'default': new OpenLayers.Style({\n        pointRadius: 3,\n        fillColor: 'Red',\n        fillOpacity: 0.3,\n        strokeColor: 'Red',\n        strokeWidth: 1\n  })});\n  occListLayer = new OpenLayers.Layer.Vector(\"" . lang::get("LANG_Occurrence_List_Layer") . "\", {styleMap: occStyleMap});\n  div.map.addLayer(locationLayer);\n  div.map.addLayer(occListLayer);\n  var control = new OpenLayers.Control.SelectFeature(occListLayer);\n  occListLayer.map.addControl(control);\n  function onPopupClose(evt) {\n    // 'this' is the popup.\n    control.unselect(this.feature);\n  }\n  function onFeatureSelect(evt) {\n    feature = evt.feature;\n    popup = new OpenLayers.Popup.FramedCloud(\"featurePopup\",\n               feature.geometry.getBounds().getCenterLonLat(),\n                             new OpenLayers.Size(100,100),\n                             feature.attributes.taxon + \" (\" + feature.attributes.count + \")\",\n                             null, true, onPopupClose);\n    feature.popup = popup;\n    popup.feature = feature;\n    feature.layer.map.addPopup(popup);\n  }\n  function onFeatureUnselect(evt) {\n    feature = evt.feature;\n    if (feature.popup) {\n        popup.feature = null;\n        feature.layer.map.removePopup(feature.popup);\n        feature.popup.destroy();\n        feature.popup = null;\n    }\n  }\n  occListLayer.events.on({\n    'featureselected': onFeatureSelect,\n    'featureunselected': onFeatureUnselect\n  });\n  control.activate();\n});\n";
       $occReadOnly = false;
       $childSample = array();
       if ($childLoadID) {
           // load the occurrence and its associated sample (which holds the position)
           $url = $svcUrl . '/data/occurrence/' . $childLoadID;
           $url .= "?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"];
           $session = curl_init($url);
           curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
           $entity = json_decode(curl_exec($session), true);
           if (count($entity) == 0) {
               return '<p>' . lang::get('LANG_No_Access_To_Occurrence') . '</p>';
           }
           foreach ($entity[0] as $key => $value) {
               $childSample['occurrence:' . $key] = $value;
           }
           if ($entity[0]['downloaded_flag'] == 'F') {
               // Final download complete, now readonly
               $occReadOnly = true;
           }
           $url = $svcUrl . '/data/sample/' . $childSample['occurrence:sample_id'];
           $url .= "?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"];
           $session = curl_init($url);
           curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
           $entity = json_decode(curl_exec($session), true);
           if (count($entity) == 0) {
               return '<p>' . lang::get('LANG_No_Access_To_Occurrence') . '</p>';
           }
           foreach ($entity[0] as $key => $value) {
               $childSample['sample:' . $key] = $value;
           }
           $childSample['sample:geom'] = '';
           // value received from db is not WKT, which is assumed by all the code.
           $childSample['taxon'] = $childSample['occurrence:taxon'];
           $parentLoadID = $childSample['sample:parent_id'];
       }
       $parentSample = array();
       if ($parentLoadID) {
           // load the container master sample
           $url = $svcUrl . '/data/sample/' . $parentLoadID;
           $url .= "?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"];
           $session = curl_init($url);
           curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
           $entity = json_decode(curl_exec($session), true);
           if (count($entity) == 0) {
               return '<p>' . lang::get('LANG_No_Access_To_Sample') . '</p>';
           }
           foreach ($entity[0] as $key => $value) {
               $parentSample['sample:' . $key] = $value;
           }
           if (is_array($locations) && !in_array($entity[0]["location_id"], $locations)) {
               return '<p>' . lang::get('LANG_No_Access_To_Location') . '</p>';
           }
           if ($entity[0]["parent_id"]) {
               return '<p>' . lang::get('LANG_No_Access_To_Sample') . '</p>';
           }
           $parentSample['sample:date'] = $parentSample['sample:date_start'];
           // bit of a bodge
           $childSample['sample:date'] = $parentSample['sample:date'];
           // enforce a match between child and parent sample dates
           // default values for attributes from DB are picked up automatically.
       }
       data_entry_helper::$entity_to_load = $parentSample;
       $attributes = data_entry_helper::getAttributes(array('id' => data_entry_helper::$entity_to_load['sample:id'], 'valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'fieldprefix' => 'smpAttr', 'extraParams' => $readAuth));
       $closedFieldName = $attributes[$sample_closure_id]['fieldname'];
       $closedFieldValue = data_entry_helper::check_default_value($closedFieldName, array_key_exists('default', $attributes[$sample_closure_id]) ? $attributes[$sample_closure_id]['default'] : '0');
       // default is not closed
       if ($closedFieldValue == '') {
           $closedFieldValue = '0';
       }
       if ($closedFieldValue == '1' && !user_access($args['edit_permission'])) {
           // sample has been closed, no admin perms. Everything now set to read only.
           $surveyReadOnly = true;
           $disabledText = "disabled=\"disabled\"";
           $defAttrOptions = array('extraParams' => $readAuth, 'disabled' => $disabledText);
       } else {
           // sample editable. Admin users can modify closed samples.
           $disabledText = "";
           $defAttrOptions = array('extraParams' => $readAuth);
       }
       // with the AJAX code, we deal with the validation semi manually: Form name is meant be invalid as we only want code included.
       data_entry_helper::enable_validation(null);
       $r .= "<div id=\"controls\">\n";
       $activeTab = 'survey';
       // mode 1 = new Sample, display sample.
       if ($mode == 2) {
           // have specified a sample ID
           if ($args["on_edit_survey_nav"] == "survey") {
               $activeTab = 'survey';
           } else {
               if ($surveyReadOnly || $args["on_edit_survey_nav"] == "list") {
                   $activeTab = 'occurrenceList';
               } else {
                   $activeTab = 'occurrence';
               }
           }
           if ($surveyReadOnly) {
               data_entry_helper::$javascript .= "jQuery('#occ-form').hide();";
           }
       } else {
           if ($mode == 3) {
               // have specified an occurrence ID
               $activeTab = 'occurrence';
           }
       }
       // Set Up form tabs.
       $r .= data_entry_helper::enable_tabs(array('divId' => 'controls', 'active' => $activeTab));
       $r .= "<div id=\"temp\"></div>";
       $r .= data_entry_helper::tab_header(array('tabs' => array('#survey' => lang::get('LANG_Survey'), '#occurrence' => lang::get($surveyReadOnly || $occReadOnly ? 'LANG_Show_Occurrence' : (isset($childSample['sample:id']) ? 'LANG_Edit_Occurrence' : 'LANG_Add_Occurrence')), '#occurrenceList' => lang::get('LANG_Occurrence_List'))));
       // Set up main Survey Form.
       $r .= "<div id=\"survey\" class=\"mnhnl-btw-datapanel\">\n  <p id=\"read-only-survey\"><strong>" . lang::get('LANG_Read_Only_Survey') . "</strong></p>";
       if (user_access($args['edit_permission']) && array_key_exists('sample:id', data_entry_helper::$entity_to_load)) {
           // check for other surveys of same date/transect: only if admin user.
           $url = $svcUrl . '/data/sample?mode=json&view=detail&auth_token=' . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"] . "&date_start=" . $parentSample['sample:date_start'] . "&location_id=" . $parentSample['sample:location_id'];
           $session = curl_init($url);
           curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
           $entity = json_decode(curl_exec($session), true);
           if (count($entity) > 1) {
               // ignore ourselves!
               $r .= "<div id=\"mergeSurveys\"><p><strong>" . lang::get('LANG_Found_Mergable_Surveys') . "</strong></p>";
               foreach ($entity as $survey) {
                   if ($survey['id'] != $parentSample['sample:id']) {
                       $r .= "<form action=\"" . url('node/' . $node->nid, array()) . "\" method=\"get\"><input type=\"submit\" value=\"" . lang::get('LANG_Merge_With_ID') . " " . $survey['id'] . "\"><input type=\"hidden\" name=\"merge_sample_id1\" value=\"" . $parentSample['sample:id'] . "\" /><input type=\"hidden\" name=\"merge_sample_id2\" value=\"" . $survey['id'] . "\" /></form>";
                   }
               }
               $r .= "</div>";
           }
       }
       $r .= "<form id=\"SurveyForm\" action=\"" . iform_ajaxproxy_url($node, 'sample') . "\" method=\"post\">\n    <input type=\"hidden\" id=\"website_id\" name=\"website_id\" value=\"" . $args['website_id'] . "\" />\n    <input type=\"hidden\" id=\"sample:survey_id\" name=\"sample:survey_id\" value=\"" . $args['survey_id'] . "\" />";
       if (array_key_exists('sample:id', data_entry_helper::$entity_to_load)) {
           $r .= "<input type=\"hidden\" id=\"sample:id\" name=\"sample:id\" value=\"" . data_entry_helper::$entity_to_load['sample:id'] . "\" />\n";
       } else {
           $r .= "<input type=\"hidden\" id=\"sample:id\" name=\"sample:id\" value=\"\" disabled=\"disabled\" />\n";
           // GvB 19/Nov/2012 : change to user detail defaults
           // logic is now much simpler, and they are only included/created if the sample is new.
           $fieldName = $attributes[$uid_attr_id]['fieldname'];
           $fieldValue = data_entry_helper::check_default_value($fieldName, $user->uid);
           $r .= "<input type=\"hidden\" name=\"" . $fieldName . "\" value=\"" . $fieldValue . "\" />\n";
           $fieldName = $attributes[$email_attr_id]['fieldname'];
           $fieldValue = data_entry_helper::check_default_value($fieldName, $user->mail);
           $r .= "<input type=\"hidden\" name=\"" . $fieldName . "\" value=\"" . $fieldValue . "\" />\n";
           $fieldName = $attributes[$username_attr_id]['fieldname'];
           $fieldValue = data_entry_helper::check_default_value($fieldName, $user->name);
           $r .= "<input type=\"hidden\" name=\"" . $fieldName . "\" value=\"" . $fieldValue . "\" />\n";
       }
       $defAttrOptions['validation'] = array('required');
       if ($locations == 'all') {
           $locOptions = array_merge(array('label' => lang::get('LANG_Transect')), $defAttrOptions);
           $locOptions['extraParams'] = array_merge(array('parent_id' => 'NULL', 'view' => 'detail', 'orderby' => 'name'), $locOptions['extraParams']);
           $r .= data_entry_helper::location_select($locOptions);
       } else {
           // can't use location select due to location filtering.
           $r .= "<label for=\"imp-location\">" . lang::get('LANG_Transect') . ":</label>\n<select id=\"imp-location\" name=\"sample:location_id\" " . $disabled_text . " class=\" \"  >";
           $url = $svcUrl . '/data/location?mode=json&view=detail&parent_id=NULL&orderby=name&auth_token=' . $readAuth['auth_token'] . '&nonce=' . $readAuth["nonce"];
           $session = curl_init($url);
           curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
           $entities = json_decode(curl_exec($session), true);
           if (!empty($entities)) {
               foreach ($entities as $entity) {
                   if (in_array($entity["id"], $locations)) {
                       if ($entity["id"] == data_entry_helper::$entity_to_load['sample:location_id']) {
                           $selected = 'selected="selected"';
                       } else {
                           $selected = '';
                       }
                       $r .= "<option value=\"" . $entity["id"] . "\" " . $selected . ">" . $entity["name"] . "</option>";
                   }
               }
           }
           $r .= "</select><span class=\"deh-required\">*</span><br />";
       }
       $languageFilteredAttrOptions = $defAttrOptions + array('language' => iform_lang_iso_639_2($args['language']));
       $r .= data_entry_helper::outputAttribute($attributes[$sample_walk_direction_id], $languageFilteredAttrOptions) . ($sample_reliability_id ? data_entry_helper::outputAttribute($attributes[$sample_reliability_id], $languageFilteredAttrOptions) : "<span style=\"display: none;\">Sample attribute '" . self::ATTR_RELIABILITY . "' not assigned to this survey</span>") . data_entry_helper::outputAttribute($attributes[$sample_visit_number_id], array_merge($languageFilteredAttrOptions, array('default' => 1, 'noBlankText' => true)));
       if (isset(data_entry_helper::$entity_to_load['sample:date']) && preg_match('/^(\\d{4})/', data_entry_helper::$entity_to_load['sample:date'])) {
           // Date has 4 digit year first (ISO style) - convert date to expected output format
           $d = new DateTime(data_entry_helper::$entity_to_load['sample:date']);
           data_entry_helper::$entity_to_load['sample:date'] = $d->format('d/m/Y');
       }
       if ($args['language'] != 'en') {
           data_entry_helper::add_resource('jquery_ui_' . $args['language']);
       }
       // this will autoload the jquery_ui resource. The date_picker does not have access to the args.
       if ($surveyReadOnly) {
           $r .= data_entry_helper::text_input(array_merge($defAttrOptions, array('label' => lang::get('LANG_Date'), 'fieldname' => 'sample:date', 'disabled' => $disabledText)));
       } else {
           $r .= data_entry_helper::date_picker(array('label' => lang::get('LANG_Date'), 'fieldname' => 'sample:date', 'class' => 'vague-date-picker'));
       }
       $r .= ($sample_wind_id ? data_entry_helper::outputAttribute($attributes[$sample_wind_id], $languageFilteredAttrOptions) : "<span style=\"display: none;\">Sample attribute '" . self::ATTR_WIND . "' not assigned to this survey</span>") . ($sample_precipitation_id ? data_entry_helper::outputAttribute($attributes[$sample_precipitation_id], $languageFilteredAttrOptions) : "<span style=\"display: none;\">Sample attribute '" . self::ATTR_RAIN . "' not assigned to this survey</span>") . ($sample_temperature_id ? data_entry_helper::outputAttribute($attributes[$sample_temperature_id], array_merge($defAttrOptions, array('suffixTemplate' => 'nosuffix'))) . "<span class=\"attr-trailer\"> &deg;C</span><br />" : "<span style=\"display: none;\">Sample attribute '" . self::ATTR_TEMP . "' not assigned to this survey</span>") . ($sample_cloud_id ? data_entry_helper::outputAttribute($attributes[$sample_cloud_id], $defAttrOptions) : "<span style=\"display: none;\">Sample attribute '" . self::ATTR_CLOUD . "' not assigned to this survey</span>") . ($sample_start_time_id ? data_entry_helper::outputAttribute($attributes[$sample_start_time_id], array_merge($defAttrOptions, array('suffixTemplate' => 'nosuffix'))) . "<span class=\"attr-trailer\"> hh:mm</span><br />" : "<span style=\"display: none;\">Sample attribute '" . self::ATTR_START_TIME . "' not assigned to this survey</span>") . ($sample_end_time_id ? data_entry_helper::outputAttribute($attributes[$sample_end_time_id], array_merge($defAttrOptions, array('suffixTemplate' => 'nosuffix'))) . "<span class=\"attr-trailer\"> hh:mm</span><br />" : "<span style=\"display: none;\">Sample attribute '" . self::ATTR_END_TIME . "' not assigned to this survey</span>");
       data_entry_helper::$javascript .= "\njQuery('.attr-trailer').prev('br').remove();\n";
       unset($defAttrOptions['suffixTemplate']);
       unset($defAttrOptions['validation']);
       if (user_access($args['edit_permission'])) {
           //  users with admin permissions can override the closing of the
           // sample by unchecking the checkbox.
           // Because this is attached to the sample, we have to include the sample required fields in the
           // the post. This means they can't be disabled, so we enable all fields in this case.
           // Normal users can only set this to closed, and they do this using a button/hidden field.
           $r .= data_entry_helper::outputAttribute($attributes[$sample_closure_id], $defAttrOptions);
           // In addition admin users can delete a survey/sample.
           $r .= data_entry_helper::checkbox(array('label' => lang::get('Deleted'), 'fieldname' => 'sample:deleted', 'id' => 'main-sample-deleted'));
       } else {
           // hidden closed
           $r .= "<input type=\"hidden\" id=\"main-sample-closed\" name=\"" . $closedFieldName . "\" value=\"" . $closedFieldValue . "\" />\n";
       }
       data_entry_helper::$javascript .= "\n\$.validator.messages.required = \"" . lang::get('validation_required') . "\";\n\$.validator.defaults.onsubmit = false; // override default - so that we handle all submission validation.\n";
       if (!$surveyReadOnly) {
           // NB that we don't even include the buttons when readonly.
           data_entry_helper::$javascript .= "\njQuery('#read-only-survey').hide();\njQuery('#ro-sur-occ-warn').hide();\n";
           $r .= "<input type=button id=\"close1\" class=\"ui-state-default ui-corner-all \" value=\"" . lang::get('LANG_Save_Survey_Details') . "\";\n        onclick=\"var result = \$('#SurveyForm input').valid();\n          var result2 = \$('#SurveyForm select').valid();\n          if (!result || !result2) {\n              return;\n            }\n            jQuery('#close1').addClass('loading-button');\n            jQuery('#SurveyForm').submit();\">\n";
           if (!user_access($args['edit_permission'])) {
               if ($mode == 1) {
                   data_entry_helper::$javascript .= "jQuery('#close2').hide();\n";
               }
               $r .= "<input type=button id=\"close2\" class=\"ui-state-default ui-corner-all \" value=\"" . lang::get('LANG_Save_Survey_And_Close') . "\"\n        onclick=\"if(confirm('" . lang::get('LANG_Close_Survey_Confirm') . "')){\n          var result = \$('#SurveyForm input').valid();\n          var result2 = \$('#SurveyForm select').valid();\n          if (!result || !result2) {\n              return;\n            }\n            jQuery('#main-sample-closed').val('1');\n            jQuery('#close2').addClass('loading-button');\n            jQuery('#SurveyForm').submit();\n          };\">\n";
           }
       }
       $r .= "</form></div>\n";
       data_entry_helper::$javascript .= "\nalertIndiciaError = function(data){\n\tvar errorString = \"" . lang::get('LANG_Indicia_Warehouse_Error') . "\";\n\tif(data.error){\terrorString = errorString + ' : ' + data.error;\t}\n\tif(data.errors){\n\t\tfor (var i in data.errors){\n\t\t\terrorString = errorString + ' : ' + data.errors[i];\n\t\t}\n\t}\n\talert(errorString);\n\t// the most likely cause is authentication failure - eg the read authentication has timed out.\n\t// prevent further use of the form:\n\t\$('.loading-panel').remove();\n\t\$('.loading-hide').removeClass('loading-hide');\n};\nerrorPos = null;\nclearErrors = function(formSel) {\n\tjQuery(formSel).find('.inline-error').remove();\n\terrorPos = null;\n};\nmyScrollTo = function(selector){\n\tjQuery(selector).filter(':visible').each(function(){\n\t\tif(errorPos == null || jQuery(this).offset().top < errorPos){\n\t\t\terrorPos = jQuery(this).offset().top;\n\t\t\twindow.scroll(0,errorPos);\n\t\t}\n\t});\n};\nmyScrollToError = function(){\n\tjQuery('.inline-error,.error').filter(':visible').prev().each(function(){\n\t\tif(errorPos == null || jQuery(this).offset().top < errorPos){\n\t\t\terrorPos = jQuery(this).offset().top;\n\t\t\twindow.scroll(0,errorPos);\n\t\t}\n\t});\n};\njQuery('#SurveyForm').ajaxForm({\n\tasync: false,\n\tdataType:  'json',\n    beforeSubmit:   function(data, obj, options){\n    \tvar valid = true;\n    \tclearErrors('form#SurveyForm');\n    \tif (!jQuery('form#SurveyForm > input').valid()) {\n\t\t\tmyScrollToError();\n  \t\t\tjQuery('.loading-button').removeClass('loading-button');\n\t\t\treturn false;\n  \t\t};\n  \t\tSurveyFormRetVal = true;\n  \t\tif(jQuery('#main-sample-deleted:checked').length == 0){ // only do check if not deleting\n          jQuery.ajax({ // now check if there are any other samples with this combination of date and location\n            type: 'GET',\n            url: \"" . $svcUrl . "/data/sample?mode=json&view=detail\" +\n                \"&nonce=" . $readAuth['nonce'] . "&auth_token=" . $readAuth['auth_token'] . "\" +\n                \"&orderby=id&callback=?&location_id=\"+jQuery('#imp-location').val()+\"&date_start=\"+jQuery('#SurveyForm [name=sample\\:date]').val(),\n            data: {},\n            success: function(detData) {\n              for(i=0, j=0; i< detData.length; i++){\n                if(detData[i].id != jQuery('#SurveyForm [name=sample\\:id]').val()) j++;\n              }\n              if(j) {\n              \tSurveyFormRetVal = confirm(\"" . lang::get('LANG_Survey_Already_Exists') . "\");\n              }\n            },\n            dataType: 'json',\n            async: false\n          });\n        }\n\t\treturn SurveyFormRetVal;\n\t},\n    success:   function(data){\n       // this will leave all the fields populated.\n       \tif(data.success == 'multiple records' && data.outer_table == 'sample'){\n          jQuery('#occ-form').show();\n          jQuery('#na-occ-warn,#mergeSurveys').hide();";
       if (!user_access($args['edit_permission'])) {
           // don't need to worry about record_status value for non admins as they can't modify when closed.
           data_entry_helper::$javascript .= "\n          if(jQuery('#main-sample-closed').val() == '1'){\n            jQuery('#read-only-survey,#ro-sur-occ-warn').show();\n            jQuery('#close1,#close2,#occ-form').hide(); //can't enter any more occurrences\n            jQuery('#SurveyForm').children().attr('disabled','disabled');\n          };\n";
       } else {
           data_entry_helper::$javascript .= "\n          jQuery('#occurrence\\\\:record_status').val(jQuery('#smpAttr\\\\:" . $attributes[$sample_closure_id]['attributeId'] . ":checked').length > 0 ? 'C' : 'I');\n          if(jQuery('#main-sample-deleted:checked').length > 0){\n            jQuery('#return-to-main').click();\n            return;\n          };\n";
       }
       data_entry_helper::$javascript .= "// If sample_id filled in -> we have a previously saved collection, so possibly have subsamples.\nif(jQuery('#SurveyForm > input[name=sample\\:id]').val() != ''){\n    // Put up warning dialogue that we are checking the subsamples: include a progress bar: set to zero%.\n    var dialog = \$('<span id=\"subsample-progress-span\"><p>'+\"" . lang::get('Please wait whilst some data integrity checks are carried out.') . "\"+'</p><div id=\"subsample-progress\"></div></span>').dialog({ title: \"" . lang::get('Checks') . "\", zIndex: 4000 });\n    jQuery('#subsample-progress').progressbar({value: 0});\n    jQuery.ajax({ // get all subsamples/occurrences to check if the dates match\n            type: 'GET',\n            url: \"" . $svcUrl . "/report/requestReport?report=library/occurrences/occurrences_list_for_parent_sample.xml&reportSource=local&mode=json&nonce=" . $readAuth['nonce'] . "&auth_token=" . $readAuth['auth_token'] . "\" +\n                \"&callback=?&sample_id=\"+data.outer_id+\"&survey_id=&date_from=&date_to=&taxon_group_id=&smpattrs=&occattrs=\",\n            data: {},\n            success: function(subData) {\n              jQuery('#subsample-progress').data('max',subData.length+1);\n              var mainDate = \$.datepicker.formatDate('yy-mm-dd', jQuery('#SurveyForm > input[name=sample\\:date]').datepicker(\"getDate\"));\n              for(i=0; i< subData.length; i++){ // loop through all subsamples\n                jQuery('#subsample-progress').progressbar('option','value',(i+1)*100/jQuery('#subsample-progress').data('max'));\n                var values = {};\n                var url = '';\n                // Check if date on subsamples matches supersample date: if not set up a post array for the sample, with correct date.\n                if(subData[i].date_start != mainDate){\n                  values['sample:id']=subData[i].sample_id;\n                  values['sample:date']=mainDate;\n                  url=\"" . iform_ajaxproxy_url($node, 'sample') . "\";\n                }\n";
       // Send AJAX request to set occurrence to 'C' if closed : use sync
       if (!user_access($args['edit_permission'])) {
           data_entry_helper::$javascript .= "                if(jQuery('#main-sample-closed').val() == '1'){\n";
       } else {
           data_entry_helper::$javascript .= "                if(jQuery('#smpAttr\\\\:" . $attributes[$sample_closure_id]['attributeId'] . ":checked').length > 0){\n";
       }
       // If records are already verified, they are left verified, as if the records themselves are saved
       // they will flagged as no longer verified: But have to force a re verification if date is changed.
       data_entry_helper::$javascript .= "\n                  if(subData[i].record_status == 'I' || typeof values['sample:id'] != 'undefined'){\n                    values['occurrence:id']=subData[i].occurrence_id;\n                    values['occurrence:record_status']='C';\n                    url=(url == '' ? \"" . iform_ajaxproxy_url($node, 'occurrence') . "\" : \"" . iform_ajaxproxy_url($node, 'smp-occ') . "\");\n                  }\n                } else { // any occurrences on unclosed collections must be flagged as 'I' - reopening unverifies.\n                  if(subData[i].record_status != 'I'){\n                    values['occurrence:id']=subData[i].occurrence_id;\n                    values['occurrence:record_status']='I';\n                    url=(url == '' ? \"" . iform_ajaxproxy_url($node, 'occurrence') . "\" : \"" . iform_ajaxproxy_url($node, 'smp-occ') . "\");\n                  }\n                }\n                if(url!=''){\n                  values['website_id']=" . $args['website_id'] . ";\n                  jQuery.ajax({ type: 'POST', url: url, data: values, dataType: 'json', async: false});\n                }\n              }\n            },\n            dataType: 'json',\n            async: false\n    });\n    dialog.dialog('close');\n    dialog.dialog('destroy');\n    jQuery('#subsample-progress-span').remove();\n}\n\n\t\t\twindow.scroll(0,0);\n            jQuery('#SurveyForm > input[name=sample\\:id]').removeAttr('disabled').val(data.outer_id);\n            jQuery('#occ-form > input[name=sample\\:parent_id]').val(data.outer_id);\n            jQuery('#occ-form > input[name=sample\\:date]').val(jQuery('#SurveyForm > input[name=sample\\:date]').val());\n            loadAttributes('sample_attribute_value', 'sample_attribute_id', 'sample_id', data.outer_id, 'smpAttr');\n            switch(\"" . $args["on_save_survey_nav"] . "\"){\n\t\t\t\tcase \"list\":\n\t\t\t\t\tvar a = \$('ul.ui-tabs-nav a')[2];\n\t\t\t\t\t\$(a).click();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"survey\":\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:";
       if (!user_access($args['edit_permission'])) {
           data_entry_helper::$javascript .= "\n\t\t\t\t\tif(jQuery('#main-sample-closed').val() == 0){\n\t\t\t\t\t\tvar a = \$('ul.ui-tabs-nav a')[1];\n\t\t\t\t\t\t\$(a).click();\n\t\t\t\t\t};";
       } else {
           data_entry_helper::$javascript .= "\n\t\t\t\t\tvar a = \$('ul.ui-tabs-nav a')[1];\n\t\t\t\t\t\$(a).click();";
       }
       data_entry_helper::$javascript .= "\n\t\t\t\t\tbreak;\n\t\t\t}\n        } else {\n\t\t\tif(data.error){\n\t\t\t\tvar lastIndex = data.error.lastIndexOf('Validation error');\n    \t\t\tif (lastIndex != -1 && lastIndex  == (data.error.length - 16)){\n\t\t\t\t\tif(data.errors){\n\t\t\t\t\t\t// TODO translation\n\t\t\t\t\t\tfor (i in data.errors){\n\t\t\t\t\t\t\tvar label = \$('<p/>').addClass('inline-error').html(data.errors[i]);\n\t\t\t\t\t\t\tlabel.insertAfter('[name='+i+']');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmyScrollToError();\n\t\t\t\t\t\treturn;\n  \t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\talertIndiciaError(data);\n        }\n\t},\n    complete: function (){\n  \t\tjQuery('.loading-button').removeClass('loading-button');\n  \t}\n});\n// In this case, all the samples attributes are on the survey tab, and all the occurrence attributes are on the occurrence tab. No need to worry about getting the correct form.\nloadAttributes = function(attributeTable, attributeKey, key, keyValue, prefix){\n    jQuery.ajax({\n        type: \"GET\",\n        url: \"" . $svcUrl . "/data/\" + attributeTable + \"?mode=json&view=list\" +\n        \t\"&reset_timeout=true&nonce=" . $readAuth['nonce'] . "&auth_token=" . $readAuth['auth_token'] . "\" +\n   \t\t\t\"&\" + key + \"=\" + keyValue + \"&callback=?\",\n        data: {},\n        success: (function(attrPrefix, attrKey) {\n          var retVal = function(attrdata) {\n            if(!(attrdata instanceof Array)){\n              alertIndiciaError(attrdata);\n            } else if (attrdata.length>0) {\n              for (var i=0;i<attrdata.length;i++){\n                // in all cases if the attribute already has the <prefix>:<X>:<Y> format name we leave. Other wise we update <prefix>:<X> to <prefix>:<X>:<Y>\n                // We leave all values unchanged.\n                // need to be careful about Cloud: this is a drop down, but it is not language specific: the termlist is\n                // always in english, so the iso won't match.\n                if (attrdata[i].id){\n                  if (attrdata[i].iso == null || attrdata[i].iso == '') // no iso - not a look up.\n                    jQuery('[name='+attrPrefix+'\\:'+attrdata[i][attrKey]+']').attr('name', attrPrefix+':'+attrdata[i][attrKey]+':'+attrdata[i].id);\n                  else {\n                    if (attrdata[i].iso == '" . $language . "') // this is our actual language so OK\n                      jQuery('[name='+attrPrefix+'\\:'+attrdata[i][attrKey]+']').attr('name', attrPrefix+':'+attrdata[i][attrKey]+':'+attrdata[i].id);\n                    else {// not our language: look up all the other attrs, and if we don't find one of this id for our language, use this one.\n                      var found = false;\n                      for (var j=0;j<attrdata.length;j++)\n                        found = found || (i!=j && attrdata[i][attrKey] == attrdata[j][attrKey] && attrdata[j].iso == '" . $language . "');\n                      if(!found)\n                        jQuery('[name='+attrPrefix+'\\:'+attrdata[i][attrKey]+']').attr('name', attrPrefix+':'+attrdata[i][attrKey]+':'+attrdata[i].id);\n                    }\n                  }\n                }\n              }\n            }};\n          return retVal;\n          })(prefix, attributeKey),\n\t\tdataType: 'json',\n\t    async: false\n\t});\n}";
       // Set up Occurrence List tab: don't include when creating a new sample as it will have no occurrences
       // Grid populated at a later point
       $r .= "<div id=\"occurrenceList\" class=\"mnhnl-btw-datapanel\"><div id=\"occ_grid\"></div>\n  <form method=\"post\" action=\"" . data_entry_helper::$base_url . "/index.php/services/report/requestReport?report=reports_for_prebuilt_forms/MNHNL/mnhnl_btw_occurrences_report.xml&reportSource=local&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth['nonce'] . "&mode=csv\">\n    <input type=\"hidden\" id=\"params\" name=\"params\" value='{\"survey_id\":" . $args['survey_id'] . ", \"sample_id\":" . data_entry_helper::$entity_to_load['sample:id'] . "}' />\n    <input type=\"submit\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Download_Occurrences') . "\">\n  </form></div>";
       if ($occReadOnly) {
           // NB that we don't even include the buttons when readonly.
           data_entry_helper::$javascript .= "\njQuery('#ro-occ-occ-warn').show();\njQuery('#ro-sur-occ-warn').hide();\n";
       } else {
           data_entry_helper::$javascript .= "\njQuery('#ro-occ-occ-warn').hide();\n";
       }
       if ($mode == 1) {
           data_entry_helper::$javascript .= "jQuery('#occ-form').hide();";
       } else {
           data_entry_helper::$javascript .= "jQuery('#na-occ-warn').hide();";
       }
       // Set up Occurrence tab: don't allow entry of a new occurrence until after top level sample is saved.
       data_entry_helper::$entity_to_load = $childSample;
       $attributes = data_entry_helper::getAttributes(array('id' => data_entry_helper::$entity_to_load['occurrence:id'], 'valuetable' => 'occurrence_attribute_value', 'attrtable' => 'occurrence_attribute', 'key' => 'occurrence_id', 'fieldprefix' => 'occAttr', 'extraParams' => $readAuth));
       $extraParams = $readAuth + array('taxon_list_id' => $args['list_id'], 'view' => 'detail', 'query' => urlencode(json_encode(array('in' => array('language_iso', array('lat', iform_lang_iso_639_2($args['language'])))))));
       if ($occReadOnly) {
           // if the occurrence has been downloaded, no one can modify it.
           $disabledText = "disabled=\"disabled\"";
           $defAttrOptions['disabled'] = $disabledText;
       }
       $species_ctrl_args = array('label' => lang::get('LANG_Species'), 'fieldname' => 'occurrence:taxa_taxon_list_id', 'table' => 'taxa_taxon_list', 'captionField' => 'taxon', 'valueField' => 'id', 'columns' => 2, 'extraParams' => $extraParams, 'disabled' => $disabledText, 'defaultCaption' => data_entry_helper::$entity_to_load['occurrence:taxon']);
       $r .= "  <div id=\"occurrence\" class=\"mnhnl-btw-datapanel\">\n    <p id=\"ro-occ-occ-warn\"><strong>" . lang::get('LANG_Read_Only_Occurrence') . "</strong></p>\n    <p id=\"ro-sur-occ-warn\"><strong>" . lang::get('LANG_Read_Only_Survey') . "</strong></p>\n    <p id=\"na-occ-warn\"><strong>" . lang::get('LANG_Page_Not_Available') . "</strong></p>\n    <form method=\"post\" id=\"occ-form\" action=\"" . iform_ajaxproxy_url($node, 'smp-occ') . "\" >\n    <input type=\"hidden\" id=\"website_id\" name=\"website_id\" value=\"" . $args['website_id'] . "\" />\n    <input type=\"hidden\" id=\"sample:survey_id\" name=\"sample:survey_id\" value=\"" . $args['survey_id'] . "\" />\n    <input type=\"hidden\" id=\"sample:parent_id\" name=\"sample:parent_id\" value=\"" . $parentSample['sample:id'] . "\" />\n    <input type=\"hidden\" id=\"sample:date\" name=\"sample:date\" value=\"" . data_entry_helper::$entity_to_load['sample:date'] . "\" />\n    <input type=\"hidden\" id=\"sample:id\" name=\"sample:id\" value=\"" . data_entry_helper::$entity_to_load['sample:id'] . "\" />\n    <input type=\"hidden\" id=\"occurrence:id\" name=\"occurrence:id\" value=\"" . data_entry_helper::$entity_to_load['occurrence:id'] . "\" />\n    <input type=\"hidden\" id=\"occurrence:record_status\" name=\"occurrence:record_status\" value=\"" . ($closedFieldValue == '0' ? 'I' : 'C') . "\" />\n    <input type=\"hidden\" id=\"occurrence:downloaded_flag\" name=\"occurrence:downloaded_flag\" value=\"N\" />\n    " . data_entry_helper::autocomplete($species_ctrl_args) . "\n    " . ($occurrence_confidence_id ? data_entry_helper::outputAttribute($attributes[$occurrence_confidence_id], array_merge($languageFilteredAttrOptions, array('noBlankText' => ''))) : "<span style=\"display: none;\">Occurrence attribute '" . self::ATTR_CONFIDENCE . "' not assigned to this survey</span>") . "\n    " . data_entry_helper::sref_and_system(array('label' => lang::get('LANG_Spatial_ref'), 'systems' => array('2169' => 'Luref (Gauss Luxembourg)'))) . "\n    <p>" . lang::get('LANG_Click_on_map') . "</p>\n    " . data_entry_helper::outputAttribute($attributes[$occurrence_count_id], array_merge($defAttrOptions, array('default' => 1))) . "\n    " . ($occurrence_approximation_id ? data_entry_helper::outputAttribute($attributes[$occurrence_approximation_id], $defAttrOptions) : "<span style=\"display: none;\">Occurrence attribute '" . self::ATTR_APPROXIMATION . "' not assigned to this survey</span>") . "\n    " . data_entry_helper::outputAttribute($attributes[$occurrence_territorial_id], array_merge($defAttrOptions, array('default' => 1, 'id' => 'occ-territorial'))) . "\n    " . data_entry_helper::outputAttribute($attributes[$occurrence_atlas_code_id], $languageFilteredAttrOptions) . "\n    " . ($occurrence_overflying_id ? data_entry_helper::outputAttribute($attributes[$occurrence_overflying_id], $defAttrOptions) : "<span style=\"display: none;\">Occurrence attribute '" . self::ATTR_OVERFLYING . "' not assigned to this survey</span>") . "\n    " . data_entry_helper::textarea(array('label' => lang::get('LANG_Comment'), 'fieldname' => 'occurrence:comment', 'disabled' => $disabledText));
       if (!$surveyReadOnly && !$occReadOnly) {
           if ($mode == 3) {
               $r .= data_entry_helper::checkbox(array('label' => lang::get('Delete'), 'fieldname' => 'sample:deleted', 'id' => 'occ-sample-deleted'));
           }
           $r .= "<input type=\"submit\" id=\"occ-submit\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Save_Occurrence_Details') . "\" />";
       }
       $r .= "  </form>\n";
       data_entry_helper::$javascript .= "\n// because of ID tracking it is easier to rebuild entire list etc.\nretriggerGrid = function(){\n  \$('div#occ_grid').empty();\n  occListLayer.destroyFeatures();\n  activateAddList = 1;\n  thisOccID = -1;\n  \$('div#occ_grid').indiciaDataGrid('rpt:reports_for_prebuilt_forms/MNHNL/mnhnl_btw_list_occurrences', {\n    indiciaSvc: '" . $svcUrl . "',\n    dataColumns: ['taxon', 'territorial', 'count'],\n    reportColumnTitles: {taxon : '" . lang::get('LANG_Species') . "', territorial : '" . lang::get('LANG_Territorial') . "', count : '" . lang::get('LANG_Count') . "'},\n    actionColumns: {'" . lang::get('LANG_Show') . "' : \"" . url('node/' . $node->nid, array('query' => 'occurrence_id=£id£')) . "\",\n            '" . lang::get('LANG_Highlight') . "' : \"script:highlight(£id£);\"},\n    auth : { nonce : '" . $readAuth['nonce'] . "', auth_token : '" . $readAuth['auth_token'] . "'},\n    parameters : { survey_id : '" . $args['survey_id'] . "',\n            parent_id : jQuery('#SurveyForm [name=sample\\:id]').val(),\n            territorial_attr_id : '" . $occurrence_territorial_id . "',\n            count_attr_id : '" . $occurrence_count_id . "'},\n    itemsPerPage : 12,\n    callback : addListFeature ,\n    cssOdd : ''\n  });\n}\n\njQuery('#occ-form').ajaxForm({\n\tasync: false,\n\tdataType:  'json',\n    beforeSubmit:   function(data, obj, options){\n    \tvar valid = true;\n    \tclearErrors('form#occ-form');\n    \tif (!jQuery('form#occ-form > input').valid()) { valid = false; }\n    \tif (!jQuery('form#occ-form > select').valid()) { valid = false; }\n    \tif(!valid) {\n\t\t\tmyScrollToError();\n\t\t\treturn false;\n\t\t};\n\t\tjQuery('#occ-submit').addClass('loading-button');\n\t\treturn true;\n\t},\n    success:   function(data){\n       // this will leave all the fields populated.\n       \tif(data.success == 'multiple records' && data.outer_table == 'sample'){\n\t\t\twindow.scroll(0,0);\n\t\t\t// cant use reset form, as returns it to original values: if this was called with occurrence_id =<x> then it would repopulate with original occurrence's values\n\t\t\t// website_id, survey_id, record_status, downloaded_flag, sample:entered_sref_system are constants and are left alone. parent_id, date are only set referring to parent sample.\n\t\t\tjQuery('form#occ-form').find('[name^=occAttr\\:]').each(function(){\n\t\t\t\tvar name = jQuery(this).attr('name').split(':');\n\t\t\t\tjQuery(this).attr('name', name[0]+':'+name[1]);\n\t\t\t});\n\t\t\tjQuery('form#occ-form').find('[name=occurrence\\:id],[name=sample\\:id]').val('').attr('disabled', 'disabled');\n\t\t\tjQuery('form#occ-form').find('[name=occurrence\\:taxa_taxon_list_id],[name=occurrence\\:taxa_taxon_list_id\\:taxon],[name=sample\\:entered_sref],[name=sample\\:geom],[name=occurrence\\:comment]').val('');\n\t\t\tjQuery('form#occ-form').find('[name=occAttr\\:" . $occurrence_confidence_id . "]').find('option').removeAttr('selected');\n\t\t\tjQuery('form#occ-form').find('[name=occAttr\\:" . $occurrence_count_id . "]').val('1');\n\t\t\tjQuery('form#occ-form').find('input[name=occAttr\\:" . $occurrence_approximation_id . "],input[name=occAttr\\:" . $occurrence_overflying_id . "]').removeAttr('checked','checked');\n\t\t\tjQuery('form#occ-form').find('#occ-territorial').attr('checked','checked');\n\t\t\tjQuery('label[for=occ-sample-deleted]').remove(); // sample deleted only applicable when editing an existing occurrence. After saving reverts to Add Occurreence: no delete. Remove label then actual checkbox\n\t\t\tjQuery('form#occ-form').find('[name=sample\\:deleted]').remove(); // This removes both parts of the checkbox.\n\t\t\tsetAtlasStatus();\n\t\t\tretriggerGrid();\n\t\t\tlocationLayer.map.editLayer.destroyFeatures();\n\t\t\tvar a = \$('ul.ui-tabs-nav a')[1];\n\t\t\t\$(a).empty().html('<span>" . lang::get('LANG_Add_Occurrence') . "</span>');\n\t\t\tswitch(\"" . $args["on_save_occurrence_nav"] . "\"){\n\t\t\t\tcase \"list\":\n\t\t\t\t\ta = \$('ul.ui-tabs-nav a')[2];\n\t\t\t\t\t\$(a).click();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"survey\":\n\t\t\t\t\ta = \$('ul.ui-tabs-nav a')[0];\n\t\t\t\t\t\$(a).click();\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n        } else {\n\t\t\tif(data.error){\n\t\t\t\tvar lastIndex = data.error.lastIndexOf('Validation error');\n    \t\t\tif (lastIndex != -1 && lastIndex  == (data.error.length - 16)){\n\t\t\t\t\tif(data.errors){\n\t\t\t\t\t\t// TODO translation\n\t\t\t\t\t\tfor (i in data.errors){\n\t\t\t\t\t\t\tvar label = \$('<p/>').addClass('inline-error').html(data.errors[i]);\n\t\t\t\t\t\t\tlabel.insertAfter('[name='+i+']');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmyScrollToError();\n\t\t\t\t\t\treturn;\n  \t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\talertIndiciaError(data);\n        }\n\t},\n    complete: function (){\n  \t\tjQuery('.loading-button').removeClass('loading-button');\n  \t}\n});\nsetAtlasStatus = function() {\n  if (jQuery(\"#occ-territorial:checked\").length == 0) {\n      jQuery(\"select[name=occAttr\\:" . $occurrence_atlas_code_id . "],select[name^=occAttr\\:" . $occurrence_atlas_code_id . "\\:]\").val('');\n  } else {\n      if(jQuery(\"select[name=occAttr\\:" . $occurrence_atlas_code_id . "],select[name^=occAttr\\:" . $occurrence_atlas_code_id . "\\:]\").val() == '') {\n        // Find the BB02 option (depends on the language what val it has)\n        var bb02;\n        jQuery.each(jQuery(\"select[name=occAttr\\:" . $occurrence_atlas_code_id . "],select[name^=occAttr\\:" . $occurrence_atlas_code_id . "\\:]\").find('option'), function(index, option) {\n          if (option.text.substr(0,4)=='BB02') {\n            bb02 = option.value;\n            return; // just from the each loop\n          }\n        });\n        jQuery(\"select[name=occAttr\\:" . $occurrence_atlas_code_id . "],select[name^=occAttr\\:" . $occurrence_atlas_code_id . "\\:]\").val(bb02);\n      }\n  }\n};\njQuery(\"#occ-territorial\").change(setAtlasStatus);\nif(\$.browser.msie) {\n    jQuery(\"#occ-territorial\").click(function() {\n        \$(this).change();\n    });\n}\n\n";
       if ($mode != 3) {
           data_entry_helper::$javascript .= "setAtlasStatus();\n";
       }
       // reset the atlas when not looking at a old occurrence.
       $r .= '</div>';
       // add map panel.
       $options = iform_map_get_map_options($args, $readAuth);
       $olOptions = iform_map_get_ol_options($args);
       // $options['layers'] = array('locationLayer', 'occListLayer');
       $options['searchLayer'] = 'false';
       $options['initialFeatureWkt'] = null;
       $options['proxy'] = '';
       $options['scroll_wheel_zoom'] = false;
       $options['width'] = 'auto';
       // TBD remove from arglist
       $r .= "<div class=\"mnhnl-btw-mappanel\">\n";
       $r .= data_entry_helper::map_panel($options, $olOptions);
       // for timing reasons, all the following has to be done after the map is loaded.
       // 1) feature selector for occurrence list must have the map present to attach the control
       // 2) location placer must have the location layer populated and the map present in
       //    order to zoom the map into the location.
       // 3) occurrence list feature adder must have map present in order to zoom into any
       //    current selection.
       data_entry_helper::$onload_javascript .= "\n\n\nlocationChange = function(obj){\n  locationLayer.destroyFeatures();\n  if(obj.value != ''){\n    jQuery.getJSON(\"" . $svcUrl . "\" + \"/data/location/\"+obj.value +\n      \"?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"] . "\" +\n      \"&callback=?\", function(data) {\n            if (data.length>0) {\n              var parser = new OpenLayers.Format.WKT();\n              for (var i=0;i<data.length;i++)\n        {\n          if(data[i].centroid_geom){\n            " . self::readBoundaryJs('data[i].centroid_geom', $args['map_projection']) . "\n            feature.style = {label: data[i].name,\n\t\t\t\t\t\t     strokeColor: \"Green\",\n                             strokeWidth: 2,\n                             fillOpacity: 0};\n            centre = feature.geometry.getCentroid();\n            centrefeature = new OpenLayers.Feature.Vector(centre, {}, {label: data[i].name});\n            locationLayer.addFeatures([feature, centrefeature]);\n          }\n          if(data[i].boundary_geom){\n            " . self::readBoundaryJs('data[i].boundary_geom', $args['map_projection']) . "\n            feature.style = {strokeColor: \"Blue\", strokeWidth: 2};\n            locationLayer.addFeatures([feature]);\n          }\n          locationLayer.map.zoomToExtent(locationLayer.getDataExtent());\n        }\n      }\n    });\n     jQuery.getJSON(\"" . $svcUrl . "\" + \"/data/location\" +\n      \"?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"] . "&callback=?&parent_id=\"+obj.value, function(data) {\n            if (data.length>0) {\n              var parser = new OpenLayers.Format.WKT();\n              for (var i=0;i<data.length;i++)\n        {\n          if(data[i].centroid_geom){\n            " . self::readBoundaryJs('data[i].centroid_geom', $args['map_projection']) . "\n            locationLayer.addFeatures([feature]);\n          }\n          if(data[i].boundary_geom){\n            " . self::readBoundaryJs('data[i].boundary_geom', $args['map_projection']) . "\n            feature.style = {label: data[i].name,\n              labelAlign: \"cb\",\n              strokeColor: \"Blue\",\n                        strokeWidth: 2};\n            locationLayer.addFeatures([feature]);\n           }\n         }\n      }\n        });\n  }\n};\n// upload location initial value into map.\njQuery('#imp-location').each(function(){\n  locationChange(this);\n});\njQuery('#imp-location').unbind('change');\njQuery('#imp-location').change(function(){\n  locationChange(this);\n});\nvar selected = \$('#controls').tabs('option', 'selected');\n\n// Only leave the click control activated for edit/add occurrence tab.\nif(selected != 1){\n    locationLayer.map.editLayer.clickControl.deactivate();\n}\n\$('#controls').bind('tabsshow', function(event, ui) {\n        if(ui.index == 1)\n        {\n         locationLayer.map.editLayer.clickControl.activate();\n        }\n        else\n        {\n         locationLayer.map.editLayer.clickControl.deactivate();\n        }\n    }\n);\nactivateAddList = 1;\nthisOccID = " . $thisOccID . ";\naddListFeature = function(div, r, record, count) {\n  if(activateAddList == 0)\n    return;\n  if(r == count)\n    activateAddList = 0;\n    var parser = new OpenLayers.Format.WKT();\n    " . self::readBoundaryJs('record.geom', $args['map_projection']) . "\n    if(record.id != thisOccID || 1==" . ($surveyReadOnly ? 1 : 0) . " || 1==" . ($occReadOnly ? 1 : 0) . "){\n      feature.attributes.id = record.id;\n      feature.attributes.taxon = record.taxon;\n      feature.attributes.count = record.count;\n      occListLayer.addFeatures([feature]);\n      if(record.id == " . $thisOccID . "){\n        var bounds=feature.geometry.getBounds();\n        locationLayer.map.setCenter(bounds.getCenterLonLat());\n      }\n    } else {\n      locationLayer.map.editLayer.destroyFeatures();\n      locationLayer.map.editLayer.addFeatures([feature]);\n      var bounds=feature.geometry.getBounds()\n      var centre=bounds.getCenterLonLat();\n      locationLayer.map.setCenter(centre);\n    }\n};\nhighlight = function(id){\n  if(id == " . $thisOccID . "){\n    if(occListLayer.map.editLayer.features.length > 0){\n      var bounds=occListLayer.map.editLayer.features[0].geometry.getBounds()\n      var centre=bounds.getCenterLonLat();\n      occListLayer.map.setCenter(centre);\n      return;\n    }\n  }\n  for(var i = 0; i < occListLayer.features.length; i++){\n    if(occListLayer.features[i].attributes.id == id){\n      control.unselectAll();\n      var bounds=occListLayer.features[i].geometry.getBounds()\n      var centre=bounds.getCenterLonLat();\n      occListLayer.map.setCenter(centre);\n      control.select(occListLayer.features[i]);\n      return;\n    }\n  }\n}\n";
       if ($mode != 1) {
           data_entry_helper::$onload_javascript .= "\n\$('div#occ_grid').indiciaDataGrid('rpt:reports_for_prebuilt_forms/MNHNL/mnhnl_btw_list_occurrences', {\n    indiciaSvc: '" . $svcUrl . "',\n    dataColumns: ['taxon', 'territorial', 'count'],\n    reportColumnTitles: {taxon : '" . lang::get('LANG_Species') . "', territorial : '" . lang::get('LANG_Territorial') . "', count : '" . lang::get('LANG_Count') . "'},\n    actionColumns: {'" . lang::get('LANG_Show') . "' : \"" . url('node/' . $node->nid, array('query' => 'occurrence_id=£id£')) . "\",\n            '" . lang::get('LANG_Highlight') . "' : \"script:highlight(£id£);\"},\n    auth : { nonce : '" . $readAuth['nonce'] . "', auth_token : '" . $readAuth['auth_token'] . "'},\n    parameters : { survey_id : '" . $args['survey_id'] . "',\n            parent_id : '" . $parentSample['sample:id'] . "',\n            territorial_attr_id : '" . $occurrence_territorial_id . "',\n            count_attr_id : '" . $occurrence_count_id . "'},\n    itemsPerPage : 12,\n    callback : addListFeature ,\n    cssOdd : ''\n  });\n\n// activateAddList = 0;\n\n";
       }
       $r .= "</div><div><form><input id=\"return-to-main\" type=\"button\" value=\"" . lang::get('LANG_Return') . "\" onclick=\"window.location.href='" . url('node/' . $node->nid, array('query' => 'Main')) . "'\"></form></div></div>\n";
       if (method_exists(get_called_class(), 'getTrailerHTML')) {
           $r .= call_user_func(array(get_called_class(), 'getTrailerHTML'), $args);
       }
       return $r;
   }
 /**
  * Return the generated form output.
  * @return Form HTML.
  */
 public static function get_form($args, $node, $response = null)
 {
     global $user;
     $logged_in = $user->uid > 0;
     $r = '';
     // Get authorisation tokens to update and read from the Warehouse.
     $writeAuth = data_entry_helper::get_auth($args['website_id'], $args['password']);
     $readAuth = data_entry_helper::get_read_auth($args['website_id'], $args['password']);
     $svcUrl = data_entry_helper::$base_url . '/index.php/services';
     $presetLayers = array();
     // read out the activated preset layers
     if (isset($args['preset_layers'])) {
         foreach ($args['preset_layers'] as $layer => $active) {
             if ($active !== 0) {
                 $presetLayers[] = $layer;
             }
         }
     }
     // When invoked by GET there are the following modes:
     // Not logged in: Display an information message.
     // No additional arguments: display the survey selector.
     // Additional argument - newSample: display the main page, no occurrence or occurrence list tabs. Survey tab active.
     // Additional argument - sample_id=<id>: display the main page, fill in the main sample details, "Add Occurrence" tab present, survey tab active.
     // Additional argument - occurrence_id=<id>: display the main page, fill in the main sample details, "Add Occurrence" tab active.
     $mode = 0;
     // default mode : display survey selector
     // mode 1: display new sample: no occurrence list or add occurrence tabs. Survey tab active
     // mode 2: display existing sample. Survey tab active. No occurence details filled in.
     // mode 3: display existing occurrence. Add Occurrence tab active. Occurence details filled in.
     // mode 4: NO LONGER USED. display Occurrence List. Occurrence List tab active. No occurence details filled in.
     $readOnly = false;
     // On top of this, things can be flagged as readonly. RO mode 2+4 means no Add Occurrence tab.
     if (!$logged_in) {
         return lang::get('LANG_not_logged_in');
     }
     $parentSample = array();
     $parentErrors = null;
     $parentLoadID = null;
     $childSample = array();
     $childErrors = null;
     $childLoadID = null;
     $saveErrors = data_entry_helper::$validation_errors;
     $thisOccID = -1;
     // IDs have to be >0, so this is outside the valid range
     $displayThisOcc = true;
     // when populating from the DB rather than POST we have to be
     // careful with selection object, as geom in wrong format.
     if ($_POST) {
         if (array_key_exists('website_id', $_POST)) {
             // Indicia POST, already handled.
             if (array_key_exists('newSample', $_GET)) {
                 if (!is_null(data_entry_helper::$entity_to_load)) {
                     $mode = 1;
                     // errors with new sample, entity populated with post, so display this data.
                     $parentSample = data_entry_helper::$entity_to_load;
                     $parentErrors = $saveErrors;
                 } else {
                     // else new sample just saved, so reload it ready to add occurrences
                     // OR, child sample/occurrence saved against new parent sample, in which case parent sample is in the post.
                     $mode = 2;
                     $parentLoadID = array_key_exists('sample:parent_id', $_POST) ? $_POST['sample:parent_id'] : $response['outer_id'];
                 }
             } else {
                 // could have saved parent sample or child sample/occurrence pair.
                 if (array_key_exists('sample:parent_id', $_POST)) {
                     // have saved child sample/occurrence pair
                     $parentLoadID = $_POST['sample:parent_id'];
                     // load the parent sample.
                     $mode = 3;
                     if (isset(data_entry_helper::$entity_to_load)) {
                         // errors so display Edit Occurrence page.
                         $childSample = data_entry_helper::$entity_to_load;
                         $childErrors = $saveErrors;
                         $displayThisOcc = false;
                         if ($childSample['occurrence:id']) {
                             $thisOccID = $childSample['occurrence:id'];
                         }
                     }
                 } else {
                     // saved parent record. display updated parent, no child.
                     $mode = 2;
                     // display parent sample details, whether errors or not.
                     if (isset(data_entry_helper::$entity_to_load)) {
                         // errors so use posted data.
                         $parentSample = data_entry_helper::$entity_to_load;
                         $parentErrors = $saveErrors;
                     } else {
                         $parentLoadID = $_POST['sample:id'];
                         // load the parent sample.
                     }
                 }
             }
         } else {
             // non Indicia POST, in this case must be the location allocations. add check to ensure we don't corrept the data by accident
             if (iform_loctools_checkaccess($node, 'admin') && array_key_exists('mnhnlbtw', $_POST)) {
                 iform_loctools_deletelocations($node);
                 foreach ($_POST as $key => $value) {
                     $parts = explode(':', $key);
                     if ($parts[0] == 'location' && $value) {
                         iform_loctools_insertlocation($node, $value, $parts[1]);
                     }
                 }
             }
         }
     } else {
         if (array_key_exists('sample_id', $_GET)) {
             $mode = 2;
             $parentLoadID = $_GET['sample_id'];
         } else {
             if (array_key_exists('occurrence_id', $_GET)) {
                 $mode = 3;
                 $childLoadID = $_GET['occurrence_id'];
                 $thisOccID = $childLoadID;
             } else {
                 if (array_key_exists('newSample', $_GET)) {
                     $mode = 1;
                 }
             }
         }
         // else default to mode 0
     }
     // define layers for all maps.
     // each argument is a comma separated list eg:
     // "Name:Lux Outline,URL:http://localhost/geoserver/wms,LAYERS:indicia:nation2,SRS:EPSG:2169,FORMAT:image/png,minScale:0,maxScale:1000000,units:m";
     $optionArray_1 = array();
     $optionArray_2 = array();
     $options = explode(',', $args['layer1']);
     foreach ($options as $option) {
         $parts = explode(':', $option);
         $optionName = $parts[0];
         unset($parts[0]);
         $optionsArray_1[$optionName] = implode(':', $parts);
     }
     $options = explode(',', $args['layer2']);
     foreach ($options as $option) {
         $parts = explode(':', $option);
         $optionName = $parts[0];
         unset($parts[0]);
         $optionsArray_2[$optionName] = implode(':', $parts);
     }
     data_entry_helper::$javascript .= "\n// Create Layers.\n// Base Layers first.\nvar WMSoptions = {\n          LAYERS: '" . $optionsArray_1['LAYERS'] . "',\n          SERVICE: 'WMS',\n          VERSION: '1.1.0',\n          STYLES: '',\n          SRS: '" . $optionsArray_1['SRS'] . "',\n          FORMAT: '" . $optionsArray_1['FORMAT'] . "'\n    };\nbaseLayer_1 = new OpenLayers.Layer.WMS('" . $optionsArray_1['Name'] . "',\n        '" . iform_proxy_url($optionsArray_1['URL']) . "',\n        WMSoptions, {\n             minScale: " . $optionsArray_1['minScale'] . ",\n            maxScale: " . $optionsArray_1['maxScale'] . ",\n            units: '" . $optionsArray_1['units'] . "',\n            isBaseLayer: true,\n            singleTile: true\n        });\nWMSoptions = {\n          LAYERS: '" . $optionsArray_2['LAYERS'] . "',\n          SERVICE: 'WMS',\n          VERSION: '1.1.0',\n          STYLES: '',\n          SRS: '" . $optionsArray_2['SRS'] . "',\n          FORMAT: '" . $optionsArray_2['FORMAT'] . "'\n    };\nbaseLayer_2 = new OpenLayers.Layer.WMS('" . $optionsArray_2['Name'] . "',\n        '" . iform_proxy_url($optionsArray_2['URL']) . "',\n        WMSoptions, {\n             minScale: " . $optionsArray_2['minScale'] . ",\n            maxScale: " . $optionsArray_2['maxScale'] . ",\n            units: '" . $optionsArray_2['units'] . "',\n            isBaseLayer: true,\n            singleTile: true\n        });\n// Create vector layers: one to display the location onto, and another for the occurrence list\n// the default edit layer is used for the occurrences themselves\nlocStyleMap = new OpenLayers.StyleMap({\n                \"default\": new OpenLayers.Style({\n                    fillColor: \"Green\",\n                    strokeColor: \"Black\",\n                    fillOpacity: 0.2,\n                    strokeWidth: 1\n                  })\n  });\nlocationLayer = new OpenLayers.Layer.Vector(\"" . lang::get("LANG_Location_Layer") . "\",\n                                    {styleMap: locStyleMap});\noccStyleMap = new OpenLayers.StyleMap({\n                \"default\": new OpenLayers.Style({\n                    pointRadius: 3,\n                    fillColor: \"Red\",\n                    fillOpacity: 0.3,\n                    strokeColor: \"Red\",\n                    strokeWidth: 1\n          }) });\noccListLayer = new OpenLayers.Layer.Vector(\"" . lang::get("LANG_Occurrence_List_Layer") . "\",\n                                    {styleMap: occStyleMap});\n";
     // Work out list of locations this user can see.
     $locations = iform_loctools_listlocations($node);
     ///////////////////////////////////////////////////////////////////
     // default mode 0 : display survey selector and locations allocator
     ///////////////////////////////////////////////////////////////////
     if ($mode == 0) {
         // If the user has permissions, add tabs so can choose to see
         // locations allocator
         $tabs = array('#surveyList' => lang::get('LANG_Surveys'));
         if (iform_loctools_checkaccess($node, 'admin')) {
             $tabs['#setLocations'] = lang::get('LANG_Allocate_Locations');
         }
         if (iform_loctools_checkaccess($node, 'superuser')) {
             $tabs['#downloads'] = lang::get('LANG_Download');
         }
         if (count($tabs) > 1) {
             $r .= "<div id=\"controls\">\n";
             $r .= data_entry_helper::enable_tabs(array('divId' => 'controls', 'active' => '#surveyList'));
             $r .= "<div id=\"temp\"></div>";
             $r .= data_entry_helper::tab_header(array('tabs' => $tabs));
         }
         if ($locations == 'all') {
             $useloclist = 'NO';
             $loclist = '-1';
         } else {
             // an empty list will cause an sql error, lids must be > 0, so push a -1 to prevent the error.
             if (empty($locations)) {
                 $locations[] = -1;
             }
             $useloclist = 'YES';
             $loclist = implode(',', $locations);
         }
         // Create the Survey list datagrid for this user.
         drupal_add_js(drupal_get_path('module', 'iform') . '/media/js/hasharray.js', 'module');
         drupal_add_js(drupal_get_path('module', 'iform') . '/media/js/jquery.datagrid.js', 'module');
         drupal_add_js("jQuery(document).ready(function(){\n  \$('div#smp_grid').indiciaDataGrid('rpt:mnhnl_btw_list_samples', {\n    indiciaSvc: '" . $svcUrl . "',\n    dataColumns: ['location_name', 'date', 'num_visit', 'num_occurrences', 'num_taxa'],\n    reportColumnTitles: {location_name : '" . lang::get('LANG_Transect') . "', date : '" . lang::get('LANG_Date') . "', num_visit : '" . lang::get('LANG_Visit_No') . "', num_occurrences : '" . lang::get('LANG_Num_Occurrences') . "', num_taxa : '" . lang::get('LANG_Num_Species') . "'},\n    actionColumns: {" . lang::get('LANG_Show') . " : \"" . url('node/' . $node->nid, array('query' => 'sample_id=£id£')) . "\"},\n    auth : { nonce : '" . $readAuth['nonce'] . "', auth_token : '" . $readAuth['auth_token'] . "'},\n    parameters : { survey_id : '" . $args['survey_id'] . "', visit_attr_id : '" . $args['sample_visit_number_id'] . "', closed_attr_id : '" . $args['sample_closure_id'] . "', use_location_list : '" . $useloclist . "', locations : '" . $loclist . "'},\n    itemsPerPage : 12,\n    condCss : {field : 'closed', value : '0', css: 'mnhnl-btw-highlight'},\n    cssOdd : ''\n  });\n});\n\n", 'inline');
         $r .= '<div id="surveyList" class="mnhnl-btw-datapanel"><div id="smp_grid"></div>';
         $r .= '<form><input type="button" value="' . lang::get('LANG_Add_Survey') . '" onclick="window.location.href=\'' . url('node/' . $node->nid, array('query' => 'newSample')) . '\'"></form></div>';
         // Add the locations allocator if user has admin rights.
         if (iform_loctools_checkaccess($node, 'admin')) {
             $r .= '<div id="setLocations" class="mnhnl-btw-datapanel"><form method="post">';
             $r .= "<input type=\"hidden\" id=\"mnhnlbtw\" name=\"mnhnlbtw\" value=\"mnhnlbtw\" />\n";
             $url = $svcUrl . '/data/location';
             $url .= "?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"] . "&parent_id=NULL&orderby=name";
             $session = curl_init($url);
             curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
             $entities = json_decode(curl_exec($session), true);
             $userlist = iform_loctools_listusers($node);
             if (!empty($entities)) {
                 foreach ($entities as $entity) {
                     if (!$entity["parent_id"]) {
                         // only assign parent locations.
                         $r .= "\n<label for=\"location:" . $entity["id"] . "\">" . $entity["name"] . ":</label><select id=\"location:" . $entity["id"] . "\" name=\"location:" . $entity["id"] . "\">";
                         $r .= "<option value=\"\" >&lt;" . lang::get('LANG_Not_Allocated') . "&gt;</option>";
                         $defaultuserid = iform_loctools_getuser($node, $entity["id"]);
                         foreach ($userlist as $uid => $a_user) {
                             if ($uid == $defaultuserid) {
                                 $selected = 'selected="selected"';
                             } else {
                                 $selected = '';
                             }
                             $r .= "<option value=\"" . $uid . "\" " . $selected . ">" . $a_user->name . "</option>";
                         }
                         $r .= "</select>";
                     }
                 }
             }
             $r .= "<input type=\"submit\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Save_Location_Allocations') . "\" />\n";
             $r .= "</form></div>";
         }
         // Add the downloader if user has manager (superuser) rights.
         if (iform_loctools_checkaccess($node, 'superuser')) {
             $r .= '<div id="downloads" class="mnhnl-btw-datapanel">';
             $r .= "<form method=\"post\" action=\"" . data_entry_helper::$base_url . "/index.php/services/report/requestReport?report=mnhnl_btw_transect_direction_report.xml&reportSource=local&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth['nonce'] . "&mode=csv\">";
             $r .= '<p>' . lang::get('LANG_Direction_Report') . '</p>';
             $r .= "<input type=\"hidden\" id=\"params\" name=\"params\" value='{\"survey_id\":" . $args['survey_id'] . ", \"direction_attr_id\":" . $args['sample_walk_direction_id'] . ", \"closed_attr_id\":" . $args['sample_closure_id'] . "}' />";
             $r .= "<input type=\"submit\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Direction_Report_Button') . "\">";
             $r .= "</form>";
             $r .= "<form method=\"post\" action=\"" . data_entry_helper::$base_url . "/index.php/services/report/requestReport?report=mnhnl_btw_download_report.xml&reportSource=local&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth['nonce'] . "&mode=csv\">";
             $r .= '<p>' . lang::get('LANG_Initial_Download') . '</p>';
             $r .= "<input type=\"hidden\" id=\"params\" name=\"params\" value='{\"survey_id\":" . $args['survey_id'] . ", \"closed_attr_id\":" . $args['sample_closure_id'] . ", \"download\": \"INITIAL\"}' />";
             $r .= "<input type=\"submit\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Initial_Download_Button') . "\">";
             $r .= "</form>";
             $r .= "<form method=\"post\" action=\"" . data_entry_helper::$base_url . "/index.php/services/report/requestReport?report=mnhnl_btw_download_report.xml&reportSource=local&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth['nonce'] . "&mode=csv\">";
             $r .= '<p>' . lang::get('LANG_Confirm_Download') . '</p>';
             $r .= "<input type=\"hidden\" id=\"params\" name=\"params\" value='{\"survey_id\":" . $args['survey_id'] . ", \"closed_attr_id\":" . $args['sample_closure_id'] . ", \"download\": \"CONFIRM\"}' />";
             $r .= "<input type=\"submit\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Confirm_Download_Button') . "\">";
             $r .= "</form>";
             $r .= "<form method=\"post\" action=\"" . data_entry_helper::$base_url . "/index.php/services/report/requestReport?report=mnhnl_btw_download_report.xml&reportSource=local&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth['nonce'] . "&mode=csv\">";
             $r .= '<p>' . lang::get('LANG_Final_Download') . '</p>';
             $r .= "<input type=\"hidden\" id=\"params\" name=\"params\" value='{\"survey_id\":" . $args['survey_id'] . ", \"closed_attr_id\":" . $args['sample_closure_id'] . ", \"download\": \"FINAL\"}' />";
             $r .= "<input type=\"submit\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Final_Download_Button') . "\">";
             $r .= "</form></div>";
         }
         // Create Map
         $r .= "<div class=\"mnhnl-btw-mappanel\">\n";
         $r .= data_entry_helper::map_panel(array('presetLayers' => $presetLayers, 'layers' => array('baseLayer_1', 'baseLayer_2', 'locationLayer'), 'initialFeatureWkt' => null, 'width' => 'auto', 'height' => 490, 'editLayer' => false, 'initial_lat' => $args['map_centroid_lat'], 'initial_long' => $args['map_centroid_long'], 'initial_zoom' => (int) $args['map_zoom'], 'scroll_wheel_zoom' => false), array('projection' => $args['map_projection']));
         // Add locations to the map on the locations layer.
         // Zoom in to area which contains the users locations.
         if ($locations != 'all') {
             data_entry_helper::$javascript .= "locationList = [" . implode(',', $locations) . "];\n";
         }
         data_entry_helper::$javascript .= "\n// upload locations into map.\n// Change the location control requests the location's geometry to place on the map.\n\$.getJSON(\"{$svcUrl}\" + \"/data/location\" +\n          \"?mode=json&view=detail&nonce=" . $readAuth['nonce'] . "&auth_token=" . $readAuth['auth_token'] . "\" +\n          \"&parent_id=NULL&callback=?\", function(data) {\n    // store value in saved field?\n  locationLayer.destroyFeatures();\n    if (data.length>0) {\n      var newFeatures = [];\n      var feature;\n      var parser = new OpenLayers.Format.WKT();\n    for (var i=0;i<data.length;i++)\n    {\n";
         if ($locations != 'all') {
             // include restriction on locations if user does not have full access.
             data_entry_helper::$javascript .= "\n        for(var j=0; j<locationList.length; j++) {\n          if(locationList[j] == data[i].id || locationList[j] == data[i].parent_id) {";
         }
         data_entry_helper::$javascript .= "\n        if(data[i].boundary_geom){\n          " . self::readBoundaryJs('data[i].boundary_geom', $args['map_projection']) . "\n          feature.style = {label: data[i].name,\n                        strokeColor: \"Blue\",\n                      strokeWidth: 2};\n          newFeatures.push(feature);\n        }\n";
         if ($locations != 'all') {
             data_entry_helper::$javascript .= "\n          }\n        }\n";
         }
         data_entry_helper::$javascript .= "\n    }\n    locationLayer.addFeatures(newFeatures);\n    locationLayer.map.zoomToExtent(locationLayer.getDataExtent());\n    }\n});\n\$('#controls').bind('tabsshow', function(event, ui) {\n  var y = \$('.mnhnl-btw-datapanel:visible').outerHeight(true) + \$('.mnhnl-btw-datapanel:visible').position().top;\n  if(y < \$('.mnhnl-btw-mappanel').outerHeight(true)+ \$('.mnhnl-btw-mappanel').position().top){\n    y = \$('.mnhnl-btw-mappanel').outerHeight(true)+ \$('.mnhnl-btw-mappanel').position().top;\n  }\n  \$('#controls').height(y - \$('#controls').position().top);\n});\n";
         $r .= "</div>\n";
         if (count($tabs) > 1) {
             $r .= "</div>";
         }
         return $r;
     }
     ///////////////////////////////////////////////////////////////////
     $occReadOnly = false;
     if ($childLoadID) {
         $url = $svcUrl . '/data/occurrence/' . $childLoadID;
         $url .= "?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"];
         $session = curl_init($url);
         curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
         $entity = json_decode(curl_exec($session), true);
         $childSample = array();
         foreach ($entity[0] as $key => $value) {
             $childSample['occurrence:' . $key] = $value;
         }
         if ($entity[0]['downloaded_flag'] == 'F') {
             // Final download complete, now readonly
             $occReadOnly = true;
         }
         $url = $svcUrl . '/data/sample/' . $childSample['occurrence:sample_id'];
         $url .= "?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"];
         $session = curl_init($url);
         curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
         $entity = json_decode(curl_exec($session), true);
         foreach ($entity[0] as $key => $value) {
             $childSample['sample:' . $key] = $value;
         }
         $childSample['sample:geom'] = '';
         // value received from db is not WKT, which is assumed by all the code.
         $thisOccID = $childLoadID;
         // this will be used to load the occurrence into the editlayer.
         $childSample['taxon'] = $childSample['occurrence:taxon'];
         $parentLoadID = $childSample['sample:parent_id'];
     }
     if ($parentLoadID) {
         $url = $svcUrl . '/data/sample/' . $parentLoadID;
         $url .= "?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"];
         $session = curl_init($url);
         curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
         $entity = json_decode(curl_exec($session), true);
         $parentSample = array();
         foreach ($entity[0] as $key => $value) {
             $parentSample['sample:' . $key] = $value;
         }
         if (is_array($locations) && !in_array($entity[0]["location_id"], $locations)) {
             return '<p>' . lang::get('LANG_No_Access_To_Location') . '</p>';
         }
         if ($entity[0]["parent_id"]) {
             return '<p>' . lang::get('LANG_No_Access_To_Sample') . '</p>';
         }
         $parentSample['sample:date'] = $parentSample['sample:date_start'];
         // bit of a bodge
         // default values for attributes from DB are picked up automatically.
     }
     $childSample['sample:date'] = $parentSample['sample:date'];
     // enforce a match between child and parent sample dates
     data_entry_helper::$entity_to_load = $parentSample;
     data_entry_helper::$validation_errors = $parentErrors;
     $attributes = data_entry_helper::getAttributes(array('id' => data_entry_helper::$entity_to_load['sample:id'], 'valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'fieldprefix' => 'smpAttr', 'extraParams' => $readAuth));
     $closedFieldName = $attributes[$args['sample_closure_id']]['fieldname'];
     $closedFieldValue = data_entry_helper::check_default_value($closedFieldName, array_key_exists('default', $attributes[$args['sample_closure_id']]) ? $attributes[$args['sample_closure_id']]['default'] : '0');
     // default is not closed
     $adminPerm = 'IForm node ' . $node->nid . ' admin';
     if ($closedFieldValue == '1' && !user_access($adminPerm)) {
         // sample has been closed, no admin perms. Everything now set to read only.
         $readOnly = true;
         $disabledText = "disabled=\"disabled\"";
         $defAttrOptions = array('extraParams' => $readAuth, 'disabled' => $disabledText);
     } else {
         // sample open.
         $disabledText = "";
         $defAttrOptions = array('extraParams' => $readAuth);
     }
     data_entry_helper::enable_validation('SurveyForm');
     $r .= "<div id=\"controls\">\n";
     $activeTab = 'survey';
     if ($mode == 3 || $mode == 2) {
         $activeTab = 'occurrence';
     }
     // Set Up form tabs.
     if ($mode == 4) {
         $activeTab = 'occurrenceList';
     }
     $r .= data_entry_helper::enable_tabs(array('divId' => 'controls', 'active' => $activeTab));
     $r .= "<div id=\"temp\"></div>";
     $r .= data_entry_helper::tab_header(array('tabs' => array('#survey' => lang::get('LANG_Survey'), '#occurrence' => lang::get($readOnly || $occReadOnly ? 'LANG_Show_Occurrence' : (isset($childSample['sample:id']) ? 'LANG_Edit_Occurrence' : 'LANG_Add_Occurrence')), '#occurrenceList' => lang::get('LANG_Occurrence_List'))));
     // Set up main Survey Form.
     $r .= "<div id=\"survey\" class=\"mnhnl-btw-datapanel\">\n";
     if ($readOnly) {
         $r .= "<strong>" . lang::get('LANG_Read_Only_Survey') . "</strong>";
     }
     $r .= "<form id=\"SurveyForm\" method=\"post\">\n";
     $r .= $writeAuth;
     $r .= "<input type=\"hidden\" id=\"website_id\" name=\"website_id\" value=\"" . $args['website_id'] . "\" />\n";
     $r .= "<input type=\"hidden\" id=\"sample:survey_id\" name=\"sample:survey_id\" value=\"" . $args['survey_id'] . "\" />\n";
     $r .= iform_user_get_hidden_inputs($args);
     if (array_key_exists('sample:id', data_entry_helper::$entity_to_load)) {
         $r .= "<input type=\"hidden\" id=\"sample:id\" name=\"sample:id\" value=\"" . data_entry_helper::$entity_to_load['sample:id'] . "\" />\n";
     }
     $defAttrOptions['validation'] = array('required');
     $defAttrOptions['suffixTemplate'] = 'requiredsuffix';
     if ($locations == 'all') {
         $locOptions = array_merge(array('label' => lang::get('LANG_Transect')), $defAttrOptions);
         $locOptions['extraParams'] = array_merge(array('parent_id' => 'NULL', 'view' => 'detail', 'orderby' => 'name'), $locOptions['extraParams']);
         $r .= data_entry_helper::location_select($locOptions);
     } else {
         // can't use location select due to location filtering.
         $r .= "<label for=\"imp-location\">" . lang::get('LANG_Transect') . ":</label>\n<select id=\"imp-location\" name=\"sample:location_id\" " . $disabled_text . " class=\" \"  >";
         $url = $svcUrl . '/data/location';
         $url .= "?mode=json&view=detail&parent_id=NULL&orderby=name&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"];
         $session = curl_init($url);
         curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
         $entities = json_decode(curl_exec($session), true);
         if (!empty($entities)) {
             foreach ($entities as $entity) {
                 if (in_array($entity["id"], $locations)) {
                     if ($entity["id"] == data_entry_helper::$entity_to_load['sample:location_id']) {
                         $selected = 'selected="selected"';
                     } else {
                         $selected = '';
                     }
                     $r .= "<option value=\"" . $entity["id"] . "\" " . $selected . ">" . $entity["name"] . "</option>";
                 }
             }
         }
         $r .= "</select><span class=\"deh-required\">*</span><br />";
     }
     $languageFilteredAttrOptions = $defAttrOptions + array('language' => iform_lang_iso_639_2($args['language']));
     $r .= data_entry_helper::outputAttribute($attributes[$args['sample_walk_direction_id']], $languageFilteredAttrOptions);
     $r .= data_entry_helper::outputAttribute($attributes[$args['sample_reliability_id']], $languageFilteredAttrOptions);
     $r .= data_entry_helper::outputAttribute($attributes[$args['sample_visit_number_id']], array_merge($languageFilteredAttrOptions, array('default' => 1, 'noBlankText' => true)));
     if ($readOnly) {
         $r .= data_entry_helper::text_input(array_merge($defAttrOptions, array('label' => lang::get('LANG_Date'), 'fieldname' => 'sample:date', 'disabled' => $disabledText)));
     } else {
         $r .= data_entry_helper::date_picker(array('label' => lang::get('LANG_Date'), 'fieldname' => 'sample:date', 'class' => 'vague-date-picker', 'suffixTemplate' => 'requiredsuffix'));
     }
     $r .= data_entry_helper::outputAttribute($attributes[$args['sample_wind_id']], $languageFilteredAttrOptions);
     $r .= data_entry_helper::outputAttribute($attributes[$args['sample_precipitation_id']], $languageFilteredAttrOptions);
     $r .= data_entry_helper::outputAttribute($attributes[$args['sample_temperature_id']], array_merge($defAttrOptions, array('suffixTemplate' => 'nosuffix')));
     $r .= " degC<span class=\"deh-required\">*</span><br />";
     $r .= data_entry_helper::outputAttribute($attributes[$args['sample_cloud_id']], $defAttrOptions);
     $r .= data_entry_helper::outputAttribute($attributes[$args['sample_start_time_id']], array_merge($defAttrOptions, array('suffixTemplate' => 'nosuffix')));
     $r .= " hh:mm<span class=\"deh-required\">*</span><br />";
     $r .= data_entry_helper::outputAttribute($attributes[$args['sample_end_time_id']], array_merge($defAttrOptions, array('suffixTemplate' => 'nosuffix')));
     $r .= " hh:mm<span class=\"deh-required\">*</span><br />";
     unset($defAttrOptions['suffixTemplate']);
     unset($defAttrOptions['validation']);
     if (user_access($adminPerm)) {
         //  users with admin permissions can override the closing of the
         // sample by unchecking the checkbox.
         // Because this is attached to the sample, we have to include the sample required fields in the
         // the post. This means they can't be disabled, so we enable all fields in this case.
         // Normal users can only set this to closed, and they do this using a button/hidden field.
         $r .= data_entry_helper::outputAttribute($attributes[$args['sample_closure_id']], $defAttrOptions);
     } else {
         // hidden closed
         $r .= "<input type=\"hidden\" id=\"" . $closedFieldName . "\" name=\"" . $closedFieldName . "\" value=\"" . $closedFieldValue . "\" />\n";
     }
     if (!empty(data_entry_helper::$validation_errors)) {
         $r .= data_entry_helper::dump_remaining_errors();
     }
     $escaped_id = str_replace(':', '\\\\:', $closedFieldName);
     if (!$readOnly) {
         $r .= "<input type=button id=\"close1\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Save_Survey_Details') . "\";\n        onclick=\"var result = \$('#SurveyForm input').valid();\n          var result2 = \$('#SurveyForm select').valid();\n          if (!result || !result2) {\n              return;\n            }\n            jQuery('#SurveyForm').submit();\">\n";
         if (!user_access($adminPerm) && $mode != 1) {
             $r .= "<input type=button id=\"close2\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Save_Survey_And_Close') . "\"\n        onclick=\"if(confirm('" . lang::get('LANG_Close_Survey_Confirm') . "')){\n          var result = \$('#SurveyForm input').valid();\n          var result2 = \$('#SurveyForm select').valid();\n          if (!result || !result2) {\n              return;\n            }\n          jQuery('#" . $escaped_id . "').val('1');\n            jQuery('#SurveyForm').submit();\n          };\">\n";
         }
     }
     $r .= "</form>";
     $r .= "</div>\n";
     // Set up Occurrence List tab: don't include when creating a new sample as it will have no occurrences
     // Grid populated at a later point
     $r .= "<div id=\"occurrenceList\" class=\"mnhnl-btw-datapanel\">\n";
     if ($mode != 1) {
         drupal_add_js(drupal_get_path('module', 'iform') . '/media/js/hasharray.js', 'module');
         drupal_add_js(drupal_get_path('module', 'iform') . '/media/js/jquery.datagrid.js', 'module');
         $r .= '<div id="occ_grid"></div>';
         $r .= "<form method=\"post\" action=\"" . data_entry_helper::$base_url . "/index.php/services/report/requestReport?report=mnhnl_btw_occurrences_report.xml&reportSource=local&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth['nonce'] . "&mode=csv\">";
         $r .= "<input type=\"hidden\" id=\"params\" name=\"params\" value='{\"survey_id\":" . $args['survey_id'] . ", \"sample_id\":" . data_entry_helper::$entity_to_load['sample:id'] . "}' />";
         $r .= "<input type=\"submit\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Download_Occurrences') . "\">";
         $r .= "</FORM>";
     } else {
         $r .= '<p>' . lang::get('LANG_Page_Not_Available') . '</p>';
     }
     $r .= '</div>';
     // Set up Occurrence tab: don't allow entry of a new occurrence until after top level sample is saved.
     $r .= "<div id=\"occurrence\" class=\"mnhnl-btw-datapanel\">\n";
     if ($mode != 1 && ($mode != 2 && $mode != 4 || $readOnly == false)) {
         data_entry_helper::$entity_to_load = $childSample;
         data_entry_helper::$validation_errors = $childErrors;
         $attributes = data_entry_helper::getAttributes(array('id' => data_entry_helper::$entity_to_load['occurrence:id'], 'valuetable' => 'occurrence_attribute_value', 'attrtable' => 'occurrence_attribute', 'key' => 'occurrence_id', 'fieldprefix' => 'occAttr', 'extraParams' => $readAuth));
         if ($occReadOnly) {
             $r .= "<strong>" . lang::get('LANG_Read_Only_Occurrence') . "</strong>";
             $disabledText = "disabled=\"disabled\"";
             $defAttrOptions['disabled'] = $disabledText;
         } else {
             if ($readOnly) {
                 $r .= "<strong>" . lang::get('LANG_Read_Only_Survey') . "</strong>";
             }
         }
         $r .= "<form method=\"post\">\n";
         $r .= $writeAuth;
         $r .= "<input type=\"hidden\" id=\"website_id\" name=\"website_id\" value=\"" . $args['website_id'] . "\" />\n";
         $r .= "<input type=\"hidden\" id=\"sample:survey_id\" name=\"sample:survey_id\" value=\"" . $args['survey_id'] . "\" />\n";
         $r .= "<input type=\"hidden\" id=\"sample:parent_id\" name=\"sample:parent_id\" value=\"" . $parentSample['sample:id'] . "\" />\n";
         $r .= "<input type=\"hidden\" id=\"sample:date\" name=\"sample:date\" value=\"" . data_entry_helper::$entity_to_load['sample:date'] . "\" />\n";
         if (array_key_exists('sample:id', data_entry_helper::$entity_to_load)) {
             $r .= "<input type=\"hidden\" id=\"sample:id\" name=\"sample:id\" value=\"" . data_entry_helper::$entity_to_load['sample:id'] . "\" />\n";
         }
         if (array_key_exists('occurrence:id', data_entry_helper::$entity_to_load)) {
             $r .= "<input type=\"hidden\" id=\"occurrence:id\" name=\"occurrence:id\" value=\"" . data_entry_helper::$entity_to_load['occurrence:id'] . "\" />\n";
         }
         $r .= "<input type=\"hidden\" id=\"occurrence:record_status\" name=\"occurrence:record_status\" value=\"C\" />\n";
         $r .= "<input type=\"hidden\" id=\"occurrence:downloaded_flag\" name=\"occurrence:downloaded_flag\" value=\"N\" />\n";
         $extraParams = $readAuth + array('taxon_list_id' => $args['list_id']);
         $species_ctrl_args = array('label' => lang::get('LANG_Species'), 'fieldname' => 'occurrence:taxa_taxon_list_id', 'table' => 'taxa_taxon_list', 'captionField' => 'taxon', 'valueField' => 'id', 'columns' => 2, 'extraParams' => $extraParams, 'suffixTemplate' => 'requiredsuffix', 'disabled' => $disabledText, 'defaultCaption' => data_entry_helper::$entity_to_load['occurrence:taxon']);
         $r .= data_entry_helper::autocomplete($species_ctrl_args);
         $r .= data_entry_helper::outputAttribute($attributes[$args['occurrence_confidence_id']], array_merge($languageFilteredAttrOptions, array('noBlankText' => '')));
         $r .= data_entry_helper::sref_and_system(array('label' => lang::get('LANG_Spatial_ref'), 'systems' => array('2169' => 'Luref (Gauss Luxembourg)'), 'suffixTemplate' => 'requiredsuffix'));
         $r .= "<p>" . lang::get('LANG_Click_on_map') . "</p>";
         $r .= data_entry_helper::outputAttribute($attributes[$args['occurrence_count_id']], array_merge($defAttrOptions, array('default' => 1, 'suffixTemplate' => 'requiredsuffix')));
         $r .= data_entry_helper::outputAttribute($attributes[$args['occurrence_approximation_id']], $defAttrOptions);
         $r .= data_entry_helper::outputAttribute($attributes[$args['occurrence_territorial_id']], array_merge($defAttrOptions, array('default' => 1)));
         $r .= data_entry_helper::outputAttribute($attributes[$args['occurrence_atlas_code_id']], $languageFilteredAttrOptions);
         $r .= data_entry_helper::outputAttribute($attributes[$args['occurrence_overflying_id']], $defAttrOptions);
         $r .= data_entry_helper::textarea(array('label' => lang::get('LANG_Comment'), 'fieldname' => 'occurrence:comment', 'disabled' => $disabledText));
         if (!empty(data_entry_helper::$validation_errors)) {
             $r .= data_entry_helper::dump_remaining_errors();
         }
         if (!$readOnly && !$occReadOnly) {
             $r .= "<input type=\"submit\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Save_Occurrence_Details') . "\" />\n";
         }
         $r .= "</form>\n";
         $escaped_terr_id = str_replace(':', '\\\\:', $attributes[$args['occurrence_territorial_id']]['fieldname']);
         $escaped_atlas_id = str_replace(':', '\\\\:', $attributes[$args['occurrence_atlas_code_id']]['fieldname']);
         data_entry_helper::$javascript .= "\nsetAtlasStatus = function() {\n  if (jQuery(\"input[name='" . $escaped_terr_id . "']:checked\").val() == '0') {\n      jQuery('#" . $escaped_atlas_id . "').val('');\n  } else {\n      if(jQuery('#" . $escaped_atlas_id . "').val() == '') {\n        // Find the BB02 option (depends on the language what val it has)\n        var bb02;\n        jQuery.each(jQuery('#" . $escaped_atlas_id . " option'), function(index, option) {\n          if (option.text.substr(0,4)=='BB02') {\n            bb02 = option.value;\n            return; // just from the each loop\n          }\n        });\n        jQuery('#" . $escaped_atlas_id . "').val(bb02);\n      }\n  }\n};\nsetAtlasStatus();\njQuery(\"input[name='" . $escaped_terr_id . "']\").change(setAtlasStatus);\n";
     } else {
         $r .= '<p>' . lang::get('LANG_Page_Not_Available') . '</p>';
     }
     $r .= '</div>';
     // add map panel.
     $r .= "<div class=\"mnhnl-btw-mappanel\">\n";
     $r .= data_entry_helper::map_panel(array('presetLayers' => $presetLayers, 'layers' => array('baseLayer_1', 'baseLayer_2', 'locationLayer', 'occListLayer'), 'initialFeatureWkt' => null, 'width' => 'auto', 'height' => 490, 'initial_lat' => $args['map_centroid_lat'], 'initial_long' => $args['map_centroid_long'], 'initial_zoom' => (int) $args['map_zoom'], 'scroll_wheel_zoom' => false), array('projection' => $args['map_projection']));
     // for timing reasons, all the following has to be done after the map is loaded.
     // 1) feature selector for occurrence list must have the map present to attach the control
     // 2) location placer must have the location layer populated and the map present in
     //    order to zoom the map into the location.
     // 3) occurrence list feature adder must have map present in order to zoom into any
     //    current selection.
     data_entry_helper::$onload_javascript .= "\nvar control = new OpenLayers.Control.SelectFeature(occListLayer);\noccListLayer.map.addControl(control);\nfunction onPopupClose(evt) {\n    // 'this' is the popup.\n    control.unselect(this.feature);\n}\nfunction onFeatureSelect(evt) {\n    feature = evt.feature;\n    popup = new OpenLayers.Popup.FramedCloud(\"featurePopup\",\n               feature.geometry.getBounds().getCenterLonLat(),\n                             new OpenLayers.Size(100,100),\n                             feature.attributes.taxon + \" (\" + feature.attributes.count + \")\",\n                             null, true, onPopupClose);\n    feature.popup = popup;\n    popup.feature = feature;\n    feature.layer.map.addPopup(popup);\n}\nfunction onFeatureUnselect(evt) {\n    feature = evt.feature;\n    if (feature.popup) {\n        popup.feature = null;\n        feature.layer.map.removePopup(feature.popup);\n        feature.popup.destroy();\n        feature.popup = null;\n    }\n}\n\noccListLayer.events.on({\n    'featureselected': onFeatureSelect,\n    'featureunselected': onFeatureUnselect\n});\n\ncontrol.activate();\n\nlocationChange = function(obj){\n  locationLayer.destroyFeatures();\n  if(obj.value != ''){\n    jQuery.getJSON(\"" . $svcUrl . "\" + \"/data/location/\"+obj.value +\n      \"?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"] . "\" +\n      \"&callback=?\", function(data) {\n            if (data.length>0) {\n              var parser = new OpenLayers.Format.WKT();\n              for (var i=0;i<data.length;i++)\n        {\n          if(data[i].centroid_geom){\n            " . self::readBoundaryJs('data[i].centroid_geom', $args['map_projection']) . "\n            feature.style = {label: data[i].name,\n\t\t\t\t\t\t     strokeColor: \"Green\",\n                             strokeWidth: 2,\n                             fillOpacity: 0};\n            centre = feature.geometry.getCentroid();\n            centrefeature = new OpenLayers.Feature.Vector(centre, {}, {label: data[i].name});\n            locationLayer.addFeatures([feature, centrefeature]);\n          }\n          if(data[i].boundary_geom){\n            " . self::readBoundaryJs('data[i].boundary_geom', $args['map_projection']) . "\n            feature.style = {strokeColor: \"Blue\", strokeWidth: 2};\n            locationLayer.addFeatures([feature]);\n          }\n          locationLayer.map.zoomToExtent(locationLayer.getDataExtent());\n        }\n      }\n    });\n     jQuery.getJSON(\"" . $svcUrl . "\" + \"/data/location\" +\n      \"?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"] . "&callback=?&parent_id=\"+obj.value, function(data) {\n            if (data.length>0) {\n              var parser = new OpenLayers.Format.WKT();\n              for (var i=0;i<data.length;i++)\n        {\n          if(data[i].centroid_geom){\n            " . self::readBoundaryJs('data[i].centroid_geom', $args['map_projection']) . "\n            locationLayer.addFeatures([feature]);\n          }\n          if(data[i].boundary_geom){\n            " . self::readBoundaryJs('data[i].boundary_geom', $args['map_projection']) . "\n            feature.style = {label: data[i].name,\n              labelAlign: \"cb\",\n              strokeColor: \"Blue\",\n                        strokeWidth: 2};\n            locationLayer.addFeatures([feature]);\n           }\n         }\n      }\n        });\n  }\n};\n// upload location initial value into map.\njQuery('#imp-location').each(function(){\n  locationChange(this);\n});\njQuery('#imp-location').unbind('change');\njQuery('#imp-location').change(function(){\n  locationChange(this);\n});\nvar selected = \$('#controls').tabs('option', 'selected');\n\n// Only leave the click control activated for edit/add occurrence tab.\nif(selected != 1){\n    locationLayer.map.editLayer.clickControl.deactivate();\n}\n\$('#controls').bind('tabsshow', function(event, ui) {\n        if(ui.index == 1)\n        {\n         locationLayer.map.editLayer.clickControl.activate();\n        }\n        else\n        {\n         locationLayer.map.editLayer.clickControl.deactivate();\n        }\n    }\n);\n";
     if ($mode != 1) {
         data_entry_helper::$onload_javascript .= "\nactivateAddList = 1;\n\naddListFeature = function(div, r, record, count) {\n  if(activateAddList == 0)\n    return;\n  if(r == count)\n    activateAddList = 0;\n    var parser = new OpenLayers.Format.WKT();\n    " . self::readBoundaryJs('record.geom', $args['map_projection']) . "\n    if(record.id != " . $thisOccID . " || 1==" . ($readOnly ? 1 : 0) . " || 1==" . ($occReadOnly ? 1 : 0) . "){\n      feature.attributes.id = record.id;\n      feature.attributes.taxon = record.taxon;\n      feature.attributes.count = record.count;\n      occListLayer.addFeatures([feature]);\n      if(record.id == " . $thisOccID . "){\n        var bounds=feature.geometry.getBounds();\n        locationLayer.map.setCenter(bounds.getCenterLonLat());\n      }\n    } else {\n      if(" . ($displayThisOcc ? 1 : 0) . "){\n        locationLayer.map.editLayer.destroyFeatures();\n      locationLayer.map.editLayer.addFeatures([feature]);\n      var bounds=feature.geometry.getBounds()\n      var centre=bounds.getCenterLonLat();\n      locationLayer.map.setCenter(centre);\n    }\n    }\n};\nhighlight = function(id){\n  if(id == " . $thisOccID . "){\n    if(occListLayer.map.editLayer.features.length > 0){\n      var bounds=occListLayer.map.editLayer.features[0].geometry.getBounds()\n      var centre=bounds.getCenterLonLat();\n      occListLayer.map.setCenter(centre);\n      return;\n    }\n  }\n  for(var i = 0; i < occListLayer.features.length; i++){\n    if(occListLayer.features[i].attributes.id == id){\n      control.unselectAll();\n      var bounds=occListLayer.features[i].geometry.getBounds()\n      var centre=bounds.getCenterLonLat();\n      occListLayer.map.setCenter(centre);\n      control.select(occListLayer.features[i]);\n      return;\n    }\n  }\n}\n\$('div#occ_grid').indiciaDataGrid('rpt:mnhnl_btw_list_occurrences', {\n    indiciaSvc: '" . $svcUrl . "',\n    dataColumns: ['taxon', 'territorial', 'count'],\n    reportColumnTitles: {taxon : '" . lang::get('LANG_Species') . "', territorial : '" . lang::get('LANG_Territorial') . "', count : '" . lang::get('LANG_Count') . "'},\n    actionColumns: {'" . lang::get('LANG_Show') . "' : \"" . url('node/' . $node->nid, array('query' => 'occurrence_id=£id£')) . "\",\n            '" . lang::get('LANG_Highlight') . "' : \"script:highlight(£id£);\"},\n    auth : { nonce : '" . $readAuth['nonce'] . "', auth_token : '" . $readAuth['auth_token'] . "'},\n    parameters : { survey_id : '" . $args['survey_id'] . "',\n            parent_id : '" . $parentSample['sample:id'] . "',\n            territorial_attr_id : '" . $args['occurrence_territorial_id'] . "',\n            count_attr_id : '" . $args['occurrence_count_id'] . "'},\n    itemsPerPage : 12,\n    callback : addListFeature ,\n    cssOdd : ''\n  });\n\n// activateAddList = 0;\n\n";
     }
     $r .= "</div><div><form><input type=\"button\" value=\"" . lang::get('LANG_Return') . "\" onclick=\"window.location.href='" . url('node/' . $node->nid, array('query' => 'Main')) . "'\"></form></div></div>\n";
     return $r;
 }
   /**
    * Return the generated form output.
    * @return Form HTML.
    */
   public static function get_form($args, $node, $response = null)
   {
       global $user;
       global $custom_terms;
       $logged_in = $user->uid > 0;
       $r = '';
       // Get authorisation tokens to update and read from the Warehouse.
       $writeAuth = data_entry_helper::get_auth($args['website_id'], $args['password']);
       $readAuth = data_entry_helper::get_read_auth($args['website_id'], $args['password']);
       $svcUrl = data_entry_helper::$base_url . '/index.php/services';
       $presetLayers = array();
       // read out the activated preset layers
       if (isset($args['preset_layers'])) {
           foreach ($args['preset_layers'] as $layer => $active) {
               if ($active !== 0) {
                   $presetLayers[] = $layer;
               }
           }
       }
       drupal_add_js(drupal_get_path('module', 'iform') . '/media/js/jquery.form.js', 'module');
       data_entry_helper::link_default_stylesheet();
       data_entry_helper::add_resource('jquery_ui');
       if ($args['language'] != 'en') {
           data_entry_helper::add_resource('jquery_ui_' . $args['language']);
       }
       // If not logged in: Display an information message.
       // This form should only be called in POST mode when setting the location allocation.
       //  All other posting is now done via AJAX.
       // When invoked by GET there are the following modes:
       // No additional arguments: mode 0.
       // Additional argument - newSample: mode 1.
       // Additional argument - sample_id=<id>: mode 2.
       // Additional argument - occurrence_id=<id>: mode 3.
       $mode = 0;
       // default mode : output survey selector
       // mode 1: output the main Data Entry page: occurrence list or add/edit occurrence tabs hidden. "Survey" tab active
       // mode 2: output the main Data Entry page, display existing sample. Active tab determined by iform params. No occurence details filled in.
       // mode 3: output the main Data Entry page, display existing occurrence. "Edit Occurrence" tab active. Occurence details filled in.
       $surveyReadOnly = false;
       // On top of this, things can be flagged as readonly. RO mode 2+4 means no Add Occurrence tab.
       if (!$logged_in) {
           return lang::get('LANG_not_logged_in');
       }
       $parentSample = array();
       $parentLoadID = null;
       $childSample = array();
       $childLoadID = null;
       $thisOccID = -1;
       // IDs have to be >0, so this is outside the valid range
       if ($_POST) {
           if (!array_key_exists('website_id', $_POST)) {
               // non Indicia POST, in this case must be the location allocations. add check to ensure we don't corrept the data by accident
               if (iform_loctools_checkaccess($node, 'admin') && array_key_exists('mnhnlbtw', $_POST)) {
                   iform_loctools_deletelocations($node);
                   foreach ($_POST as $key => $value) {
                       $parts = explode(':', $key);
                       if ($parts[0] == 'location' && $value) {
                           iform_loctools_insertlocation($node, $value, $parts[1]);
                       }
                   }
               }
           }
       } else {
           if (array_key_exists('sample_id', $_GET)) {
               $mode = 2;
               $parentLoadID = $_GET['sample_id'];
           } else {
               if (array_key_exists('occurrence_id', $_GET)) {
                   $mode = 3;
                   $childLoadID = $_GET['occurrence_id'];
                   $thisOccID = $childLoadID;
               } else {
                   if (array_key_exists('newSample', $_GET)) {
                       $mode = 1;
                   }
               }
           }
           // else default to mode 0
       }
       // define language strings so they can be used for validation translation.
       data_entry_helper::$javascript .= "var translations = [\n";
       foreach ($custom_terms as $key => $value) {
           if (substr($key, 0, 4) != "LANG") {
               data_entry_helper::$javascript .= "  {key: \"" . $key . "\", translated: \"" . $value . "\"},\n";
           }
       }
       data_entry_helper::$javascript .= "];\n";
       // define layers for all maps.
       // each argument is a comma separated list eg:
       // "Name:Lux Outline,URL:http://localhost/geoserver/wms,LAYERS:indicia:nation2,SRS:EPSG:2169,FORMAT:image/png,minScale:0,maxScale:1000000,units:m";
       $optionArray_1 = array();
       $optionArray_2 = array();
       $optionArray_Location = array();
       $options = explode(',', $args['layer1']);
       foreach ($options as $option) {
           $parts = explode(':', $option);
           $optionName = $parts[0];
           unset($parts[0]);
           $optionsArray_1[$optionName] = implode(':', $parts);
       }
       $options = explode(',', $args['layer2']);
       foreach ($options as $option) {
           $parts = explode(':', $option);
           $optionName = $parts[0];
           unset($parts[0]);
           $optionsArray_2[$optionName] = implode(':', $parts);
       }
       $options = explode(',', $args['locationLayer']);
       foreach ($options as $option) {
           $parts = explode(':', $option);
           $optionName = $parts[0];
           unset($parts[0]);
           $optionsArray_Location[$optionName] = implode(':', $parts);
       }
       // Work out list of locations this user can see.
       $locations = iform_loctools_listlocations($node);
       if ($locations != 'all') {
           data_entry_helper::$javascript .= "locationList = [" . implode(',', $locations) . "];\n";
       }
       data_entry_helper::$javascript .= "\n// Create Layers.\n// Base Layers first.\nvar WMSoptions = {\n          LAYERS: '" . $optionsArray_1['LAYERS'] . "',\n          SERVICE: 'WMS',\n          VERSION: '1.1.0',\n          STYLES: '',\n          SRS: '" . $optionsArray_1['SRS'] . "',\n          FORMAT: '" . $optionsArray_1['FORMAT'] . "'\n    };\nbaseLayer_1 = new OpenLayers.Layer.WMS('" . $optionsArray_1['Name'] . "',\n        '" . iform_proxy_url($optionsArray_1['URL']) . "',\n        WMSoptions, {\n             minScale: " . $optionsArray_1['minScale'] . ",\n            maxScale: " . $optionsArray_1['maxScale'] . ",\n            units: '" . $optionsArray_1['units'] . "',\n            isBaseLayer: true,\n            singleTile: true\n        });\nWMSoptions = {\n          LAYERS: '" . $optionsArray_2['LAYERS'] . "',\n          SERVICE: 'WMS',\n          VERSION: '1.1.0',\n          STYLES: '',\n          SRS: '" . $optionsArray_2['SRS'] . "',\n          FORMAT: '" . $optionsArray_2['FORMAT'] . "'\n    };\nbaseLayer_2 = new OpenLayers.Layer.WMS('" . $optionsArray_2['Name'] . "',\n        '" . iform_proxy_url($optionsArray_2['URL']) . "',\n        WMSoptions, {\n             minScale: " . $optionsArray_2['minScale'] . ",\n            maxScale: " . $optionsArray_2['maxScale'] . ",\n            units: '" . $optionsArray_2['units'] . "',\n            isBaseLayer: true,\n            singleTile: true\n        });\nWMSoptions = {\n          SERVICE: 'WMS',\n          VERSION: '1.1.0',\n          STYLES: '',\n          SRS: '" . $optionsArray_Location['SRS'] . "',\n          FORMAT: '" . $optionsArray_Location['FORMAT'] . "',\n          TRANSPARENT: 'true', ";
       if ($locations != 'all') {
           // when given a restricted feature list we have to use the feature id to filter in order to not go over 2000 char limit on the URL
           // Can only generate the feature id if we access a table directly, not through a view. Go direct to the locations table.
           // don't need to worry about parent_id in this case as we know exactly which features we want.
           // need to use btw_transects view for unrestricted so we can filter by parent_id.
           $locFeatures = array();
           foreach ($locations as $location) {
               $locFeatures[] = "locations." . $location;
           }
           data_entry_helper::$javascript .= "\n        LAYERS: 'indicia:locations',\n        FEATUREID: '" . implode(',', $locFeatures) . "'";
       } else {
           data_entry_helper::$javascript .= "\n        LAYERS: '" . $optionsArray_Location['LAYERS'] . "'";
       }
       data_entry_helper::$javascript .= "\n    };\nlocationListLayer = new OpenLayers.Layer.WMS('" . $optionArray_Location['Name'] . "',\n        '" . iform_proxy_url($optionsArray_Location['URL']) . "',\n        WMSoptions, {\n             minScale: " . $optionsArray_Location['minScale'] . ",\n            maxScale: " . $optionsArray_Location['maxScale'] . ",\n            units: '" . $optionsArray_Location['units'] . "',\n            isBaseLayer: false,\n            singleTile: true\n        });\n// Create vector layers: one to display the location onto, and another for the occurrence list\n// the default edit layer is used for the occurrences themselves\nlocStyleMap = new OpenLayers.StyleMap({\n                \"default\": new OpenLayers.Style({\n                    fillColor: \"Green\",\n                    strokeColor: \"Black\",\n                    fillOpacity: 0.2,\n                    strokeWidth: 1\n                  })\n  });\nlocationLayer = new OpenLayers.Layer.Vector(\"" . lang::get("LANG_Location_Layer") . "\",\n                                    {styleMap: locStyleMap});\noccStyleMap = new OpenLayers.StyleMap({\n                \"default\": new OpenLayers.Style({\n                    pointRadius: 3,\n                    fillColor: \"Red\",\n                    fillOpacity: 0.3,\n                    strokeColor: \"Red\",\n                    strokeWidth: 1\n          }) });\noccListLayer = new OpenLayers.Layer.Vector(\"" . lang::get("LANG_Occurrence_List_Layer") . "\",\n                                    {styleMap: occStyleMap});\n";
       drupal_add_js(drupal_get_path('module', 'iform') . '/media/js/hasharray.js', 'module');
       drupal_add_js(drupal_get_path('module', 'iform') . '/media/js/jquery.datagrid.js', 'module');
       // Work out list of locations this user can see.
       $locations = iform_loctools_listlocations($node);
       ///////////////////////////////////////////////////////////////////
       // default mode 0 : display a page with tabs for survey selector,
       // locations allocator and reports (last two require permissions)
       ///////////////////////////////////////////////////////////////////
       if ($mode == 0) {
           // If the user has permissions, add tabs so can choose to see
           // locations allocator
           $tabs = array('#surveyList' => lang::get('LANG_Surveys'));
           if (iform_loctools_checkaccess($node, 'admin')) {
               $tabs['#setLocations'] = lang::get('LANG_Allocate_Locations');
           }
           if (iform_loctools_checkaccess($node, 'superuser')) {
               $tabs['#downloads'] = lang::get('LANG_Download');
           }
           if (count($tabs) > 1) {
               $r .= "<div id=\"controls\">" . data_entry_helper::enable_tabs(array('divId' => 'controls', 'active' => '#surveyList')) . "<div id=\"temp\"></div>";
               $r .= data_entry_helper::tab_header(array('tabs' => $tabs));
           }
           if ($locations == 'all') {
               $useloclist = 'NO';
               $loclist = '-1';
           } else {
               // an empty list will cause an sql error, lids must be > 0, so push a -1 to prevent the error.
               if (empty($locations)) {
                   $locations[] = -1;
               }
               $useloclist = 'YES';
               $loclist = implode(',', $locations);
           }
           // Create the Survey list datagrid for this user.
           drupal_add_js("jQuery(document).ready(function(){\n  \$('div#smp_grid').indiciaDataGrid('rpt:mnhnl_btw_list_samples', {\n    indiciaSvc: '" . $svcUrl . "',\n    dataColumns: ['location_name', 'date', 'num_visit', 'num_occurrences', 'num_taxa'],\n    reportColumnTitles: {location_name : '" . lang::get('LANG_Transect') . "', date : '" . lang::get('LANG_Date') . "', num_visit : '" . lang::get('LANG_Visit_No') . "', num_occurrences : '" . lang::get('LANG_Num_Occurrences') . "', num_taxa : '" . lang::get('LANG_Num_Species') . "'},\n    actionColumns: {" . lang::get('LANG_Show') . " : \"" . url('node/' . $node->nid, array('query' => 'sample_id=£id£')) . "\"},\n    auth : { nonce : '" . $readAuth['nonce'] . "', auth_token : '" . $readAuth['auth_token'] . "'},\n    parameters : { survey_id : '" . $args['survey_id'] . "', visit_attr_id : '" . $args['sample_visit_number_id'] . "', closed_attr_id : '" . $args['sample_closure_id'] . "', use_location_list : '" . $useloclist . "', locations : '" . $loclist . "'},\n    itemsPerPage : 12,\n    condCss : {field : 'closed', value : '0', css: 'mnhnl-btw-highlight'},\n    cssOdd : ''\n  });\n});\n      ", 'inline');
           $r .= '
 <div id="surveyList" class="mnhnl-btw-datapanel"><div id="smp_grid"></div>
   <form><input type="button" value="' . lang::get('LANG_Add_Survey') . '" onclick="window.location.href=\'' . url('node/' . $node->nid, array('query' => 'newSample')) . '\'"></form></div>';
           // Add the locations allocator if user has admin rights.
           if (iform_loctools_checkaccess($node, 'admin')) {
               $r .= '
 <div id="setLocations" class="mnhnl-btw-datapanel">
   <form method="post">
     <input type="hidden" id="mnhnlbtw" name="mnhnlbtw" value="mnhnlbtw" />\\n';
               $url = $svcUrl . '/data/location?mode=json&view=detail&auth_token=' . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"] . "&parent_id=NULL&orderby=name";
               $session = curl_init($url);
               curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
               $entities = json_decode(curl_exec($session), true);
               $userlist = iform_loctools_listusers($node);
               if (!empty($entities)) {
                   foreach ($entities as $entity) {
                       if (!$entity["parent_id"]) {
                           // only assign parent locations.
                           $r .= "\n<label for=\"location:" . $entity["id"] . "\">" . $entity["name"] . ":</label><select id=\"location:" . $entity["id"] . "\" name=\"location:" . $entity["id"] . "\"><option value=\"\" >&lt;" . lang::get('LANG_Not_Allocated') . "&gt;</option>";
                           $defaultuserid = iform_loctools_getuser($node, $entity["id"]);
                           foreach ($userlist as $uid => $a_user) {
                               $r .= "<option value=\"" . $uid . "\" " . ($uid == $defaultuserid ? 'selected="selected" ' : '') . ">" . $a_user->name . "</option>";
                           }
                           $r .= "</select>";
                       }
                   }
               }
               $r .= "\n      <input type=\"submit\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Save_Location_Allocations') . "\" />\n    </form>\n  </div>";
           }
           // Add the downloader if user has manager (superuser) rights.
           if (iform_loctools_checkaccess($node, 'superuser')) {
               $r .= '
 <div id="downloads" class="mnhnl-btw-datapanel">
   <form method="post" action="' . data_entry_helper::$base_url . '/index.php/services/report/requestReport?report=mnhnl_btw_transect_direction_report.xml&reportSource=local&auth_token=' . $readAuth['auth_token'] . '&nonce=' . $readAuth['nonce'] . '&mode=csv">
     <p>' . lang::get('LANG_Direction_Report') . '</p>
     <input type="hidden" id="params" name="params" value=\'{"survey_id":' . $args['survey_id'] . ', "direction_attr_id":' . $args['sample_walk_direction_id'] . ', "closed_attr_id":' . $args['sample_closure_id'] . '}\' />
     <input type="submit" class="ui-state-default ui-corner-all" value="' . lang::get('LANG_Direction_Report_Button') . '">
   </form>
   <form method="post" action="' . data_entry_helper::$base_url . '/index.php/services/report/requestReport?report=mnhnl_btw_download_report.xml&reportSource=local&auth_token=' . $readAuth['auth_token'] . '&nonce=' . $readAuth['nonce'] . '&mode=csv\\">
     <p>' . lang::get('LANG_Initial_Download') . '</p>
     <input type="hidden" id="params" name="params" value=\'{"survey_id":' . $args['survey_id'] . ', "closed_attr_id":' . $args['sample_closure_id'] . ', "download": "INITIAL"}\' />
     <input type="submit" class=\\"ui-state-default ui-corner-all" value="' . lang::get('LANG_Initial_Download_Button') . '">
   </form>
   <form method="post" action="' . data_entry_helper::$base_url . '/index.php/services/report/requestReport?report=mnhnl_btw_download_report.xml&reportSource=local&auth_token=' . $readAuth['auth_token'] . '&nonce=' . $readAuth['nonce'] . '&mode=csv\\">
     <p>' . lang::get('LANG_Confirm_Download') . '</p>
     <input type="hidden" id="params" name="params" value=\'{"survey_id":' . $args['survey_id'] . ', "closed_attr_id":' . $args['sample_closure_id'] . ', "download": "CONFIRM"}\' />
     <input type="submit" class="ui-state-default ui-corner-all" value="' . lang::get('LANG_Confirm_Download_Button') . '">
   </form>
   <form method="post" action="' . data_entry_helper::$base_url . '/index.php/services/report/requestReport?report=mnhnl_btw_download_report.xml&reportSource=local&auth_token=' . $readAuth['auth_token'] . '&nonce=' . $readAuth['nonce'] . '&mode=csv\\">
     <p>' . lang::get('LANG_Final_Download') . '</p>
     <input type="hidden" id="params" name="params" value=\'{"survey_id":' . $args['survey_id'] . ', "closed_attr_id":' . $args['sample_closure_id'] . ', "download": "FINAL"}\' />
     <input type="submit" class="ui-state-default ui-corner-all" value="' . lang::get('LANG_Final_Download_Button') . '">
   </form>
 </div>';
           }
           // Create Map
           $r .= "<div class=\"mnhnl-btw-mappanel\">\n" . data_entry_helper::map_panel(array('presetLayers' => $presetLayers, 'layers' => array('baseLayer_1', 'baseLayer_2', 'locationListLayer'), 'initialFeatureWkt' => null, 'width' => 'auto', 'height' => 490, 'editLayer' => false, 'initial_lat' => $args['map_centroid_lat'], 'initial_long' => $args['map_centroid_long'], 'initial_zoom' => (int) $args['map_zoom'], 'scroll_wheel_zoom' => false), array('projection' => $args['map_projection'])) . "</div>\n";
           data_entry_helper::$javascript .= "\n\$('#controls').bind('tabsshow', function(event, ui) {\n  var y = \$('.mnhnl-btw-datapanel:visible').outerHeight(true) + \$('.mnhnl-btw-datapanel:visible').position().top;\n  if(y < \$('.mnhnl-btw-mappanel').outerHeight(true)+ \$('.mnhnl-btw-mappanel').position().top){\n    y = \$('.mnhnl-btw-mappanel').outerHeight(true)+ \$('.mnhnl-btw-mappanel').position().top;\n  }\n  \$('#controls').height(y - \$('#controls').position().top);\n});\n";
           if (count($tabs) > 1) {
               // close tabs div if present
               $r .= "</div>";
           }
           return $r;
       }
       ///////////////////////////////////////////////////////////////////
       $occReadOnly = false;
       if ($childLoadID) {
           // load the occurrence and its associated sample (which holds the position)
           $url = $svcUrl . '/data/occurrence/' . $childLoadID;
           $url .= "?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"];
           $session = curl_init($url);
           curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
           $entity = json_decode(curl_exec($session), true);
           $childSample = array();
           foreach ($entity[0] as $key => $value) {
               $childSample['occurrence:' . $key] = $value;
           }
           if ($entity[0]['downloaded_flag'] == 'F') {
               // Final download complete, now readonly
               $occReadOnly = true;
           }
           $url = $svcUrl . '/data/sample/' . $childSample['occurrence:sample_id'];
           $url .= "?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"];
           $session = curl_init($url);
           curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
           $entity = json_decode(curl_exec($session), true);
           foreach ($entity[0] as $key => $value) {
               $childSample['sample:' . $key] = $value;
           }
           $childSample['sample:geom'] = '';
           // value received from db is not WKT, which is assumed by all the code.
           $thisOccID = $childLoadID;
           // this will be used to load the occurrence into the editlayer.
           $childSample['taxon'] = $childSample['occurrence:taxon'];
           $parentLoadID = $childSample['sample:parent_id'];
       }
       if ($parentLoadID) {
           // load the container master sample
           $url = $svcUrl . '/data/sample/' . $parentLoadID;
           $url .= "?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"];
           $session = curl_init($url);
           curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
           $entity = json_decode(curl_exec($session), true);
           $parentSample = array();
           foreach ($entity[0] as $key => $value) {
               $parentSample['sample:' . $key] = $value;
           }
           if (is_array($locations) && !in_array($entity[0]["location_id"], $locations)) {
               return '<p>' . lang::get('LANG_No_Access_To_Location') . '</p>';
           }
           if ($entity[0]["parent_id"]) {
               return '<p>' . lang::get('LANG_No_Access_To_Sample') . '</p>';
           }
           $parentSample['sample:date'] = $parentSample['sample:date_start'];
           // bit of a bodge
           // default values for attributes from DB are picked up automatically.
       }
       $childSample['sample:date'] = $parentSample['sample:date'];
       // enforce a match between child and parent sample dates
       data_entry_helper::$entity_to_load = $parentSample;
       $attributes = data_entry_helper::getAttributes(array('id' => data_entry_helper::$entity_to_load['sample:id'], 'valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'fieldprefix' => 'smpAttr', 'extraParams' => $readAuth));
       $closedFieldName = $attributes[$args['sample_closure_id']]['fieldname'];
       $closedFieldValue = data_entry_helper::check_default_value($closedFieldName, array_key_exists('default', $attributes[$args['sample_closure_id']]) ? $attributes[$args['sample_closure_id']]['default'] : '0');
       // default is not closed
       $adminPerm = 'IForm node ' . $node->nid . ' admin';
       if ($closedFieldValue == '1' && !user_access($adminPerm)) {
           // sample has been closed, no admin perms. Everything now set to read only.
           $surveyReadOnly = true;
           $disabledText = "disabled=\"disabled\"";
           $defAttrOptions = array('extraParams' => $readAuth, 'disabled' => $disabledText);
       } else {
           // sample open.
           $disabledText = "";
           $defAttrOptions = array('extraParams' => $readAuth);
       }
       // with the AJAX code, we deal with the validation semi manually: Form name is meant be invalid as we only want code included.
       data_entry_helper::enable_validation('DummyForm');
       $r .= "<div id=\"controls\">\n";
       $activeTab = 'survey';
       // mode 1 = new Sample, display sample.
       if ($mode == 2) {
           // have specified a sample ID
           if ($args["on_edit_survey_nav"] == "survey") {
               $activeTab = 'survey';
           } else {
               if ($surveyReadOnly || $args["on_edit_survey_nav"] == "list") {
                   $activeTab = 'occurrenceList';
               } else {
                   $activeTab = 'occurrence';
               }
           }
           if ($surveyReadOnly) {
               data_entry_helper::$javascript .= "jQuery('#occ-form').hide();";
           }
       } else {
           if ($mode == 3) {
               // have specified an occurrence ID
               $activeTab = 'occurrence';
           }
       }
       // Set Up form tabs.
       $r .= data_entry_helper::enable_tabs(array('divId' => 'controls', 'active' => $activeTab));
       $r .= "<div id=\"temp\"></div>";
       $r .= data_entry_helper::tab_header(array('tabs' => array('#survey' => lang::get('LANG_Survey'), '#occurrence' => lang::get($surveyReadOnly || $occReadOnly ? 'LANG_Show_Occurrence' : (isset($childSample['sample:id']) ? 'LANG_Edit_Occurrence' : 'LANG_Add_Occurrence')), '#occurrenceList' => lang::get('LANG_Occurrence_List'))));
       // Set up main Survey Form.
       $r .= "<div id=\"survey\" class=\"mnhnl-btw-datapanel\">\n  <p id=\"read-only-survey\"><strong>" . lang::get('LANG_Read_Only_Survey') . "</strong></p>\n  <form id=\"SurveyForm\" action=\"" . iform_ajaxproxy_url($node, 'sample') . "\" method=\"post\">\n    <input type=\"hidden\" id=\"website_id\" name=\"website_id\" value=\"" . $args['website_id'] . "\" />\n    <input type=\"hidden\" id=\"sample:survey_id\" name=\"sample:survey_id\" value=\"" . $args['survey_id'] . "\" />\n    " . iform_user_get_hidden_inputs($args);
       if (array_key_exists('sample:id', data_entry_helper::$entity_to_load)) {
           $r .= "<input type=\"hidden\" id=\"sample:id\" name=\"sample:id\" value=\"" . data_entry_helper::$entity_to_load['sample:id'] . "\" />\n";
       } else {
           $r .= "<input type=\"hidden\" id=\"sample:id\" name=\"sample:id\" value=\"\" disabled=\"disabled\" />\n";
       }
       $defAttrOptions['validation'] = array('required');
       $defAttrOptions['suffixTemplate'] = 'requiredsuffix';
       if ($locations == 'all') {
           $locOptions = array_merge(array('label' => lang::get('LANG_Transect')), $defAttrOptions);
           $locOptions['extraParams'] = array_merge(array('parent_id' => 'NULL', 'view' => 'detail', 'orderby' => 'name'), $locOptions['extraParams']);
           $r .= data_entry_helper::location_select($locOptions);
       } else {
           // can't use location select due to location filtering.
           $r .= "<label for=\"imp-location\">" . lang::get('LANG_Transect') . ":</label>\n<select id=\"imp-location\" name=\"sample:location_id\" " . $disabled_text . " class=\" \"  >";
           $url = $svcUrl . '/data/location?mode=json&view=detail&parent_id=NULL&orderby=name&auth_token=' . $readAuth['auth_token'] . '&nonce=' . $readAuth["nonce"];
           $session = curl_init($url);
           curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
           $entities = json_decode(curl_exec($session), true);
           if (!empty($entities)) {
               foreach ($entities as $entity) {
                   if (in_array($entity["id"], $locations)) {
                       if ($entity["id"] == data_entry_helper::$entity_to_load['sample:location_id']) {
                           $selected = 'selected="selected"';
                       } else {
                           $selected = '';
                       }
                       $r .= "<option value=\"" . $entity["id"] . "\" " . $selected . ">" . $entity["name"] . "</option>";
                   }
               }
           }
           $r .= "</select><span class=\"deh-required\">*</span><br />";
       }
       $languageFilteredAttrOptions = $defAttrOptions + array('language' => iform_lang_iso_639_2($args['language']));
       $r .= data_entry_helper::outputAttribute($attributes[$args['sample_walk_direction_id']], $languageFilteredAttrOptions) . data_entry_helper::outputAttribute($attributes[$args['sample_reliability_id']], $languageFilteredAttrOptions) . data_entry_helper::outputAttribute($attributes[$args['sample_visit_number_id']], array_merge($languageFilteredAttrOptions, array('default' => 1, 'noBlankText' => true)));
       if ($surveyReadOnly) {
           $r .= data_entry_helper::text_input(array_merge($defAttrOptions, array('label' => lang::get('LANG_Date'), 'fieldname' => 'sample:date', 'disabled' => $disabledText)));
       } else {
           $r .= data_entry_helper::date_picker(array('label' => lang::get('LANG_Date'), 'fieldname' => 'sample:date', 'class' => 'vague-date-picker', 'suffixTemplate' => 'requiredsuffix'));
       }
       $r .= data_entry_helper::outputAttribute($attributes[$args['sample_wind_id']], $languageFilteredAttrOptions) . data_entry_helper::outputAttribute($attributes[$args['sample_precipitation_id']], $languageFilteredAttrOptions) . data_entry_helper::outputAttribute($attributes[$args['sample_temperature_id']], array_merge($defAttrOptions, array('suffixTemplate' => 'nosuffix'))) . " degC<span class=\"deh-required\">*</span><br />" . data_entry_helper::outputAttribute($attributes[$args['sample_cloud_id']], $defAttrOptions) . data_entry_helper::outputAttribute($attributes[$args['sample_start_time_id']], array_merge($defAttrOptions, array('suffixTemplate' => 'nosuffix'))) . " hh:mm<span class=\"deh-required\">*</span><br />" . data_entry_helper::outputAttribute($attributes[$args['sample_end_time_id']], array_merge($defAttrOptions, array('suffixTemplate' => 'nosuffix'))) . " hh:mm<span class=\"deh-required\">*</span><br />";
       unset($defAttrOptions['suffixTemplate']);
       unset($defAttrOptions['validation']);
       if (user_access($adminPerm)) {
           //  users with admin permissions can override the closing of the
           // sample by unchecking the checkbox.
           // Because this is attached to the sample, we have to include the sample required fields in the
           // the post. This means they can't be disabled, so we enable all fields in this case.
           // Normal users can only set this to closed, and they do this using a button/hidden field.
           $r .= data_entry_helper::outputAttribute($attributes[$args['sample_closure_id']], $defAttrOptions);
       } else {
           // hidden closed
           $r .= "<input type=\"hidden\" id=\"" . $closedFieldName . "\" name=\"" . $closedFieldName . "\" value=\"" . $closedFieldValue . "\" />\n";
       }
       $escaped_id = str_replace(':', '\\\\:', $closedFieldName);
       if (!$surveyReadOnly) {
           // NB that we don't even include the buttons when readonly.
           data_entry_helper::$javascript .= "\njQuery('#read-only-survey').hide();\njQuery('#ro-sur-occ-warn').hide();\n";
           $r .= "<input type=button id=\"close1\" class=\"ui-state-default ui-corner-all \" value=\"" . lang::get('LANG_Save_Survey_Details') . "\";\n        onclick=\"var result = \$('#SurveyForm input').valid();\n          var result2 = \$('#SurveyForm select').valid();\n          if (!result || !result2) {\n              return;\n            }\n            jQuery('#close1').addClass('loading-button');\n            jQuery('#SurveyForm').submit();\">\n";
           if (!user_access($adminPerm)) {
               if ($mode != 1) {
                   data_entry_helper::$javascript .= "jQuery('#close2').hide();\n";
               }
               $r .= "<input type=button id=\"close2\" class=\"ui-state-default ui-corner-all \" value=\"" . lang::get('LANG_Save_Survey_And_Close') . "\"\n        onclick=\"if(confirm('" . lang::get('LANG_Close_Survey_Confirm') . "')){\n          var result = \$('#SurveyForm input').valid();\n          var result2 = \$('#SurveyForm select').valid();\n          if (!result || !result2) {\n              return;\n            }\n            jQuery('#" . $escaped_id . "').val('1');\n            jQuery('#close2').addClass('loading-button');\n            jQuery('#SurveyForm').submit();\n          };\">\n";
           }
       }
       $r .= "</form></div>\n";
       data_entry_helper::$javascript .= "\nalertIndiciaError = function(data){\n\tvar errorString = \"" . lang::get('LANG_Indicia_Warehouse_Error') . "\";\n\tif(data.error){\terrorString = errorString + ' : ' + data.error;\t}\n\tif(data.errors){\n\t\tfor (var i in data.errors){\n\t\t\terrorString = errorString + ' : ' + data.errors[i];\n\t\t}\t\t\t\t\n\t}\n\talert(errorString);\n\t// the most likely cause is authentication failure - eg the read authentication has timed out.\n\t// prevent further use of the form:\n\t\$('.loading-panel').remove();\n\t\$('.loading-hide').removeClass('loading-hide');\n};\nerrorPos = null;\nclearErrors = function(formSel) {\n\tjQuery(formSel).find('.inline-error').remove();\n\terrorPos = null;\n};\nmyScrollTo = function(selector){\n\tjQuery(selector).filter(':visible').each(function(){\n\t\tif(errorPos == null || jQuery(this).offset().top < errorPos){\n\t\t\terrorPos = jQuery(this).offset().top;\n\t\t\twindow.scroll(0,errorPos);\n\t\t}\n\t});\n};\nmyScrollToError = function(){\n\tjQuery('.inline-error,.error').filter(':visible').prev().each(function(){\n\t\tif(errorPos == null || jQuery(this).offset().top < errorPos){\n\t\t\terrorPos = jQuery(this).offset().top;\n\t\t\twindow.scroll(0,errorPos);\n\t\t}\n\t});\n};\njQuery('#SurveyForm').ajaxForm({ \n\tasync: false,\n\tdataType:  'json', \n    beforeSubmit:   function(data, obj, options){\n    \tvar valid = true;\n    \tclearErrors('form#SurveyForm');\n    \tif (!jQuery('form#SurveyForm > input').valid()) {\n\t\t\tmyScrollToError();\n  \t\t\tjQuery('.loading-button').removeClass('loading-button');\n\t\t\treturn false;\n  \t\t};\n\t\treturn true;\n\t},\n    success:   function(data){\n       // this will leave all the fields populated.\n       \tif(data.success == 'multiple records' && data.outer_table == 'sample'){\n\t\t\twindow.scroll(0,0);\n            jQuery('#SurveyForm > input[name=sample\\:id]').removeAttr('disabled').val(data.outer_id);\n            jQuery('#occ-form > input[name=sample\\:parent_id]').val(data.outer_id);\n            jQuery('#occ-form > input[name=sample\\:date]').val(jQuery('#SurveyForm > input[name=sample\\:date]').val());\n            jQuery('#occ-form').show();\n            jQuery('#na-occ-warn').hide();";
       if (!user_access($adminPerm)) {
           data_entry_helper::$javascript .= "\n\t\t\tif(jQuery('#" . $escaped_id . "').val() == '1'){\n\t\t\t\tjQuery('#read-only-survey').show();\n\t\t\t\tjQuery('#close1').hide();\n\t\t\t\tjQuery('#close2').hide();\n\t\t\t};\n";
       }
       data_entry_helper::$javascript .= "\n\t\t\tswitch(\"" . $args["on_save_survey_nav"] . "\"){\n\t\t\t\tcase \"list\":\n\t\t\t\t\tvar a = \$('ul.ui-tabs-nav a')[2];\n\t\t\t\t\t\$(a).click();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"survey\":\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tvar a = \$('ul.ui-tabs-nav a')[1];\n\t\t\t\t\t\$(a).click();\n\t\t\t\t\tbreak;\n\t\t\t}\n        } else {\n\t\t\tif(data.error){\n\t\t\t\tvar lastIndex = data.error.lastIndexOf('Validation error'); \n    \t\t\tif (lastIndex != -1 && lastIndex  == (data.error.length - 16)){ \n\t\t\t\t\tif(data.errors){\n\t\t\t\t\t\t// TODO translation\n\t\t\t\t\t\tfor (i in data.errors){\n\t\t\t\t\t\t\tvar label = \$('<p/>')\n\t\t\t\t\t\t\t\t.addClass('inline-error')\n\t\t\t\t\t\t\t\t.html(data.errors[i]);\n\t\t\t\t\t\t\tlabel.insertAfter('[name='+i+']');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmyScrollToError();\n\t\t\t\t\t\treturn;\n  \t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\talertIndiciaError(data);\n        }\n\t},\n    complete: function (){\n  \t\tjQuery('.loading-button').removeClass('loading-button');\n  \t}\n});";
       // Set up Occurrence List tab: don't include when creating a new sample as it will have no occurrences
       // Grid populated at a later point
       $r .= "<div id=\"occurrenceList\" class=\"mnhnl-btw-datapanel\"><div id=\"occ_grid\"></div>\n  <form method=\"post\" action=\"" . data_entry_helper::$base_url . "/index.php/services/report/requestReport?report=mnhnl_btw_occurrences_report.xml&reportSource=local&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth['nonce'] . "&mode=csv\">\n    <input type=\"hidden\" id=\"params\" name=\"params\" value='{\"survey_id\":" . $args['survey_id'] . ", \"sample_id\":" . data_entry_helper::$entity_to_load['sample:id'] . "}' />\n    <input type=\"submit\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Download_Occurrences') . "\">\n  </form></div>";
       if ($occReadOnly) {
           // NB that we don't even include the buttons when readonly.
           data_entry_helper::$javascript .= "\njQuery('#ro-occ-occ-warn').show();\njQuery('#ro-sur-occ-warn').hide();\n";
       } else {
           data_entry_helper::$javascript .= "\njQuery('#ro-occ-occ-warn').hide();\n";
       }
       if ($mode == 1) {
           data_entry_helper::$javascript .= "jQuery('#occ-form').hide();";
       } else {
           data_entry_helper::$javascript .= "jQuery('#na-occ-warn').hide();";
       }
       // Set up Occurrence tab: don't allow entry of a new occurrence until after top level sample is saved.
       data_entry_helper::$entity_to_load = $childSample;
       $attributes = data_entry_helper::getAttributes(array('id' => data_entry_helper::$entity_to_load['occurrence:id'], 'valuetable' => 'occurrence_attribute_value', 'attrtable' => 'occurrence_attribute', 'key' => 'occurrence_id', 'fieldprefix' => 'occAttr', 'extraParams' => $readAuth));
       $extraParams = $readAuth + array('taxon_list_id' => $args['list_id'], 'view' => 'detail', 'query' => urlencode(json_encode(array('in' => array('language_iso', array('lat', iform_lang_iso_639_2($args['language'])))))));
       if ($occReadOnly) {
           // if the occurrence has been downloaded, no one can modify it.
           $disabledText = "disabled=\"disabled\"";
           $defAttrOptions['disabled'] = $disabledText;
       }
       $species_ctrl_args = array('label' => lang::get('LANG_Species'), 'fieldname' => 'occurrence:taxa_taxon_list_id', 'table' => 'taxa_taxon_list', 'captionField' => 'taxon', 'valueField' => 'id', 'columns' => 2, 'extraParams' => $extraParams, 'suffixTemplate' => 'requiredsuffix', 'disabled' => $disabledText, 'defaultCaption' => data_entry_helper::$entity_to_load['occurrence:taxon']);
       $escaped_terr_id = str_replace(':', '\\\\:', $attributes[$args['occurrence_territorial_id']]['fieldname']);
       $r .= "  <div id=\"occurrence\" class=\"mnhnl-btw-datapanel\">\n    <p id=\"ro-occ-occ-warn\"><strong>" . lang::get('LANG_Read_Only_Occurrence') . "</strong></p>\n    <p id=\"ro-sur-occ-warn\"><strong>" . lang::get('LANG_Read_Only_Survey') . "</strong></p>\n    <p id=\"na-occ-warn\"><strong>" . lang::get('LANG_Page_Not_Available') . "</strong></p>\n    <form method=\"post\" id=\"occ-form\" action=\"" . iform_ajaxproxy_url($node, 'smp-occ') . "\" >\n    <input type=\"hidden\" id=\"website_id\" name=\"website_id\" value=\"" . $args['website_id'] . "\" />\n    <input type=\"hidden\" id=\"sample:survey_id\" name=\"sample:survey_id\" value=\"" . $args['survey_id'] . "\" />\n    <input type=\"hidden\" id=\"sample:parent_id\" name=\"sample:parent_id\" value=\"" . $parentSample['sample:id'] . "\" />\n    <input type=\"hidden\" id=\"sample:date\" name=\"sample:date\" value=\"" . data_entry_helper::$entity_to_load['sample:date'] . "\" />\n    <input type=\"hidden\" id=\"sample:id\" name=\"sample:id\" value=\"" . data_entry_helper::$entity_to_load['sample:id'] . "\" />\n    <input type=\"hidden\" id=\"occurrence:id\" name=\"occurrence:id\" value=\"" . data_entry_helper::$entity_to_load['occurrence:id'] . "\" />\n    <input type=\"hidden\" id=\"occurrence:record_status\" name=\"occurrence:record_status\" value=\"C\" />\n    <input type=\"hidden\" id=\"occurrence:downloaded_flag\" name=\"occurrence:downloaded_flag\" value=\"N\" />\n    " . data_entry_helper::autocomplete($species_ctrl_args) . "\n    " . data_entry_helper::outputAttribute($attributes[$args['occurrence_confidence_id']], array_merge($languageFilteredAttrOptions, array('noBlankText' => ''))) . "\n    " . data_entry_helper::sref_and_system(array('label' => lang::get('LANG_Spatial_ref'), 'systems' => array('2169' => 'Luref (Gauss Luxembourg)'), 'suffixTemplate' => 'requiredsuffix')) . "\n    <p>" . lang::get('LANG_Click_on_map') . "</p>\n    " . data_entry_helper::outputAttribute($attributes[$args['occurrence_count_id']], array_merge($defAttrOptions, array('default' => 1, 'suffixTemplate' => 'requiredsuffix'))) . "\n    " . data_entry_helper::outputAttribute($attributes[$args['occurrence_approximation_id']], $defAttrOptions) . "\n    " . data_entry_helper::outputAttribute($attributes[$args['occurrence_territorial_id']], array_merge($defAttrOptions, array('default' => 1))) . "\n    " . data_entry_helper::outputAttribute($attributes[$args['occurrence_atlas_code_id']], $languageFilteredAttrOptions) . "\n    " . data_entry_helper::outputAttribute($attributes[$args['occurrence_overflying_id']], $defAttrOptions) . "\n    " . data_entry_helper::textarea(array('label' => lang::get('LANG_Comment'), 'fieldname' => 'occurrence:comment', 'disabled' => $disabledText));
       if (!$surveyReadOnly && !$occReadOnly) {
           $r .= "<input type=\"submit\" id=\"occ-submit\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Save_Occurrence_Details') . "\" />";
       }
       $r .= "  </form>\n";
       data_entry_helper::$javascript .= "\n// because of ID tracking it is easier to rebuild entire list etc.\nretriggerGrid = function(){\n  \$('div#occ_grid').empty();\n  occListLayer.destroyFeatures();\n  activateAddList = 1;\n  thisOccID = -1;\n  \$('div#occ_grid').indiciaDataGrid('rpt:mnhnl_btw_list_occurrences', {\n    indiciaSvc: '" . $svcUrl . "',\n    dataColumns: ['taxon', 'territorial', 'count'],\n    reportColumnTitles: {taxon : '" . lang::get('LANG_Species') . "', territorial : '" . lang::get('LANG_Territorial') . "', count : '" . lang::get('LANG_Count') . "'},\n    actionColumns: {'" . lang::get('LANG_Show') . "' : \"" . url('node/' . $node->nid, array('query' => 'occurrence_id=£id£')) . "\",\n            '" . lang::get('LANG_Highlight') . "' : \"script:highlight(£id£);\"},\n    auth : { nonce : '" . $readAuth['nonce'] . "', auth_token : '" . $readAuth['auth_token'] . "'},\n    parameters : { survey_id : '" . $args['survey_id'] . "',\n            parent_id : jQuery('#SurveyForm [name=sample\\:id]').val(),\n            territorial_attr_id : '" . $args['occurrence_territorial_id'] . "',\n            count_attr_id : '" . $args['occurrence_count_id'] . "'},\n    itemsPerPage : 12,\n    callback : addListFeature ,\n    cssOdd : ''\n  });\n}\n\njQuery('#occ-form').ajaxForm({ \n\tasync: false,\n\tdataType:  'json', \n    beforeSubmit:   function(data, obj, options){\n    \tvar valid = true;\n    \tclearErrors('form#occ-form');\n    \tif (!jQuery('form#occ-form > input').valid()) { valid = false; }\n    \tif (!jQuery('form#occ-form > select').valid()) { valid = false; }\n    \tif(!valid) {\n\t\t\tmyScrollToError();\n\t\t\treturn false;\n\t\t};\n\t\tjQuery('#occ-submit').addClass('loading-button');\n\t\treturn true;\n\t},\n    success:   function(data){\n       // this will leave all the fields populated.\n       \tif(data.success == 'multiple records' && data.outer_table == 'sample'){\n\t\t\twindow.scroll(0,0);\n\t\t\t// cant use reset form, as returns it to original values: if this was called with occurrence_id =<x> then it would repopulate with original occurrence's values\n\t\t\t// website_id, survey_id, record_status, downloaded_flag, sample:entered_sref_system are constants and are left alone. parent_id, date are only set referring to parent sample.\n\t\t\tjQuery('form#occ-form').find('[name^=occAttr\\:]').each(function(){\n\t\t\t\tvar name = jQuery(this).attr('name').split(':');\n\t\t\t\tjQuery(this).attr('name', name[0]+':'+name[1]);\n\t\t\t});\n\t\t\tjQuery('form#occ-form').find('[name=occurrence\\:id],[name=sample\\:id]').val('').attr('disabled', 'disabled');\n\t\t\tjQuery('form#occ-form').find('[name=occurrence\\:taxa_taxon_list_id],[name=occurrence\\:taxa_taxon_list_id\\:taxon],[name=sample\\:entered_sref],[name=sample\\:geom],[name=occurrence\\:comment]').val('');\n\t\t\tjQuery('form#occ-form').find('[name=occAttr\\:" . $args['occurrence_confidence_id'] . "]').find('option').removeAttr('selected');\n\t\t\tjQuery('form#occ-form').find('[name=occAttr\\:" . $args['occurrence_count_id'] . "]').val('1');\n\t\t\tjQuery('form#occ-form').find('input[name=occAttr\\:" . $args['occurrence_approximation_id'] . "],input[name=occAttr\\:" . $args['occurrence_overflying_id'] . "]').filter('[value=0]').attr('checked','checked');\n\t\t\tjQuery('form#occ-form').find('input[name=occAttr\\:" . $args['occurrence_territorial_id'] . "]').filter('[value=1]').attr('checked','checked');\n\t\t\tjQuery('form#occ-form').find('select[name=occAttr\\:" . $args['occurrence_atlas_code_id'] . "]').val('');\n\t\t\tsetAtlasStatus();\n\t\t\tretriggerGrid();\n\t\t\tlocationLayer.map.editLayer.destroyFeatures();\n\t\t\tvar a = \$('ul.ui-tabs-nav a')[1];\n\t\t\t\$(a).empty().html('<span>" . lang::get('LANG_Add_Occurrence') . "</span>');\n\t\t\tswitch(\"" . $args["on_save_occurrence_nav"] . "\"){\n\t\t\t\tcase \"list\":\n\t\t\t\t\ta = \$('ul.ui-tabs-nav a')[2];\n\t\t\t\t\t\$(a).click();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"survey\":\n\t\t\t\t\ta = \$('ul.ui-tabs-nav a')[0];\n\t\t\t\t\t\$(a).click();\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n        } else {\n\t\t\tif(data.error){\n\t\t\t\tvar lastIndex = data.error.lastIndexOf('Validation error'); \n    \t\t\tif (lastIndex != -1 && lastIndex  == (data.error.length - 16)){ \n\t\t\t\t\tif(data.errors){\n\t\t\t\t\t\t// TODO translation\n\t\t\t\t\t\tfor (i in data.errors){\n\t\t\t\t\t\t\tvar label = \$('<p/>')\n\t\t\t\t\t\t\t\t.addClass('inline-error')\n\t\t\t\t\t\t\t\t.html(data.errors[i]);\n\t\t\t\t\t\t\tlabel.insertAfter('[name='+i+']');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmyScrollToError();\n\t\t\t\t\t\treturn;\n  \t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\talertIndiciaError(data);\n        }\n\t},\n    complete: function (){\n  \t\tjQuery('.loading-button').removeClass('loading-button');\n  \t}\n});\nsetAtlasStatus = function() {\n  if (jQuery(\"input[name=occAttr\\:" . $args['occurrence_territorial_id'] . "]:checked,input[name^=occAttr\\:" . $args['occurrence_territorial_id'] . "\\:]:checked\").val() == '0') {\n      jQuery(\"select[name=occAttr\\:" . $args['occurrence_atlas_code_id'] . "],select[name^=occAttr\\:" . $args['occurrence_atlas_code_id'] . "\\:]\").val('');\n  } else {\n      if(jQuery(\"select[name=occAttr\\:" . $args['occurrence_atlas_code_id'] . "],select[name^=occAttr\\:" . $args['occurrence_atlas_code_id'] . "\\:]\").val() == '') {\n        // Find the BB02 option (depends on the language what val it has)\n        var bb02;\n        jQuery.each(jQuery(\"select[name=occAttr\\:" . $args['occurrence_atlas_code_id'] . "],select[name^=occAttr\\:" . $args['occurrence_atlas_code_id'] . "\\:]\").find('option'), function(index, option) {\n          if (option.text.substr(0,4)=='BB02') {\n            bb02 = option.value;\n            return; // just from the each loop\n          }\n        });\n        jQuery(\"select[name=occAttr\\:" . $args['occurrence_atlas_code_id'] . "],select[name^=occAttr\\:" . $args['occurrence_atlas_code_id'] . "\\:]\").val(bb02);\n      }\n  }\n};\njQuery(\"input[name='" . $escaped_terr_id . "']\").change(setAtlasStatus);\n";
       $r .= '</div>';
       // add map panel.
       $r .= "<div class=\"mnhnl-btw-mappanel\">\n";
       $r .= data_entry_helper::map_panel(array('presetLayers' => $presetLayers, 'layers' => array('baseLayer_1', 'baseLayer_2', 'locationLayer', 'occListLayer'), 'initialFeatureWkt' => null, 'width' => 'auto', 'height' => 490, 'initial_lat' => $args['map_centroid_lat'], 'initial_long' => $args['map_centroid_long'], 'initial_zoom' => (int) $args['map_zoom'], 'scroll_wheel_zoom' => false), array('projection' => $args['map_projection']));
       // for timing reasons, all the following has to be done after the map is loaded.
       // 1) feature selector for occurrence list must have the map present to attach the control
       // 2) location placer must have the location layer populated and the map present in
       //    order to zoom the map into the location.
       // 3) occurrence list feature adder must have map present in order to zoom into any
       //    current selection.
       data_entry_helper::$onload_javascript .= "\nvar control = new OpenLayers.Control.SelectFeature(occListLayer);\noccListLayer.map.addControl(control);\nfunction onPopupClose(evt) {\n    // 'this' is the popup.\n    control.unselect(this.feature);\n}\nfunction onFeatureSelect(evt) {\n    feature = evt.feature;\n    popup = new OpenLayers.Popup.FramedCloud(\"featurePopup\",\n               feature.geometry.getBounds().getCenterLonLat(),\n                             new OpenLayers.Size(100,100),\n                             feature.attributes.taxon + \" (\" + feature.attributes.count + \")\",\n                             null, true, onPopupClose);\n    feature.popup = popup;\n    popup.feature = feature;\n    feature.layer.map.addPopup(popup);\n}\nfunction onFeatureUnselect(evt) {\n    feature = evt.feature;\n    if (feature.popup) {\n        popup.feature = null;\n        feature.layer.map.removePopup(feature.popup);\n        feature.popup.destroy();\n        feature.popup = null;\n    }\n}\n\noccListLayer.events.on({\n    'featureselected': onFeatureSelect,\n    'featureunselected': onFeatureUnselect\n});\n\ncontrol.activate();\n\nlocationChange = function(obj){\n  locationLayer.destroyFeatures();\n  if(obj.value != ''){\n    jQuery.getJSON(\"" . $svcUrl . "\" + \"/data/location/\"+obj.value +\n      \"?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"] . "\" +\n      \"&callback=?\", function(data) {\n            if (data.length>0) {\n              var parser = new OpenLayers.Format.WKT();\n              for (var i=0;i<data.length;i++)\n        {\n          if(data[i].centroid_geom){\n            " . self::readBoundaryJs('data[i].centroid_geom', $args['map_projection']) . "\n            feature.style = {label: data[i].name,\n\t\t\t\t\t\t     strokeColor: \"Green\",\n                             strokeWidth: 2,\n                             fillOpacity: 0};\n            centre = feature.geometry.getCentroid();\n            centrefeature = new OpenLayers.Feature.Vector(centre, {}, {label: data[i].name});\n            locationLayer.addFeatures([feature, centrefeature]);\n          }\n          if(data[i].boundary_geom){\n            " . self::readBoundaryJs('data[i].boundary_geom', $args['map_projection']) . "\n            feature.style = {strokeColor: \"Blue\", strokeWidth: 2};\n            locationLayer.addFeatures([feature]);\n          }\n          locationLayer.map.zoomToExtent(locationLayer.getDataExtent());\n        }\n      }\n    });\n     jQuery.getJSON(\"" . $svcUrl . "\" + \"/data/location\" +\n      \"?mode=json&view=detail&auth_token=" . $readAuth['auth_token'] . "&nonce=" . $readAuth["nonce"] . "&callback=?&parent_id=\"+obj.value, function(data) {\n            if (data.length>0) {\n              var parser = new OpenLayers.Format.WKT();\n              for (var i=0;i<data.length;i++)\n        {\n          if(data[i].centroid_geom){\n            " . self::readBoundaryJs('data[i].centroid_geom', $args['map_projection']) . "\n            locationLayer.addFeatures([feature]);\n          }\n          if(data[i].boundary_geom){\n            " . self::readBoundaryJs('data[i].boundary_geom', $args['map_projection']) . "\n            feature.style = {label: data[i].name,\n              labelAlign: \"cb\",\n              strokeColor: \"Blue\",\n                        strokeWidth: 2};\n            locationLayer.addFeatures([feature]);\n           }\n         }\n      }\n        });\n  }\n};\n// upload location initial value into map.\njQuery('#imp-location').each(function(){\n  locationChange(this);\n});\njQuery('#imp-location').unbind('change');\njQuery('#imp-location').change(function(){\n  locationChange(this);\n});\nvar selected = \$('#controls').tabs('option', 'selected');\n\n// Only leave the click control activated for edit/add occurrence tab.\nif(selected != 1){\n    locationLayer.map.editLayer.clickControl.deactivate();\n}\n\$('#controls').bind('tabsshow', function(event, ui) {\n        if(ui.index == 1)\n        {\n         locationLayer.map.editLayer.clickControl.activate();\n        }\n        else\n        {\n         locationLayer.map.editLayer.clickControl.deactivate();\n        }\n    }\n);\n";
       if ($mode != 1) {
           data_entry_helper::$onload_javascript .= "\nactivateAddList = 1;\nthisOccID = " . $thisOccID . ";\n\naddListFeature = function(div, r, record, count) {\n  if(activateAddList == 0)\n    return;\n  if(r == count)\n    activateAddList = 0;\n    var parser = new OpenLayers.Format.WKT();\n    " . self::readBoundaryJs('record.geom', $args['map_projection']) . "\n    if(record.id != thisOccID || 1==" . ($surveyReadOnly ? 1 : 0) . " || 1==" . ($occReadOnly ? 1 : 0) . "){\n      feature.attributes.id = record.id;\n      feature.attributes.taxon = record.taxon;\n      feature.attributes.count = record.count;\n      occListLayer.addFeatures([feature]);\n      if(record.id == " . $thisOccID . "){\n        var bounds=feature.geometry.getBounds();\n        locationLayer.map.setCenter(bounds.getCenterLonLat());\n      }\n    } else {\n      locationLayer.map.editLayer.destroyFeatures();\n      locationLayer.map.editLayer.addFeatures([feature]);\n      var bounds=feature.geometry.getBounds()\n      var centre=bounds.getCenterLonLat();\n      locationLayer.map.setCenter(centre);\n    }\n};\nhighlight = function(id){\n  if(id == " . $thisOccID . "){\n    if(occListLayer.map.editLayer.features.length > 0){\n      var bounds=occListLayer.map.editLayer.features[0].geometry.getBounds()\n      var centre=bounds.getCenterLonLat();\n      occListLayer.map.setCenter(centre);\n      return;\n    }\n  }\n  for(var i = 0; i < occListLayer.features.length; i++){\n    if(occListLayer.features[i].attributes.id == id){\n      control.unselectAll();\n      var bounds=occListLayer.features[i].geometry.getBounds()\n      var centre=bounds.getCenterLonLat();\n      occListLayer.map.setCenter(centre);\n      control.select(occListLayer.features[i]);\n      return;\n    }\n  }\n}\n\$('div#occ_grid').indiciaDataGrid('rpt:mnhnl_btw_list_occurrences', {\n    indiciaSvc: '" . $svcUrl . "',\n    dataColumns: ['taxon', 'territorial', 'count'],\n    reportColumnTitles: {taxon : '" . lang::get('LANG_Species') . "', territorial : '" . lang::get('LANG_Territorial') . "', count : '" . lang::get('LANG_Count') . "'},\n    actionColumns: {'" . lang::get('LANG_Show') . "' : \"" . url('node/' . $node->nid, array('query' => 'occurrence_id=£id£')) . "\",\n            '" . lang::get('LANG_Highlight') . "' : \"script:highlight(£id£);\"},\n    auth : { nonce : '" . $readAuth['nonce'] . "', auth_token : '" . $readAuth['auth_token'] . "'},\n    parameters : { survey_id : '" . $args['survey_id'] . "',\n            parent_id : '" . $parentSample['sample:id'] . "',\n            territorial_attr_id : '" . $args['occurrence_territorial_id'] . "',\n            count_attr_id : '" . $args['occurrence_count_id'] . "'},\n    itemsPerPage : 12,\n    callback : addListFeature ,\n    cssOdd : ''\n  });\n\n// activateAddList = 0;\n\n";
       }
       $r .= "</div><div><form><input type=\"button\" value=\"" . lang::get('LANG_Return') . "\" onclick=\"window.location.href='" . url('node/' . $node->nid, array('query' => 'Main')) . "'\"></form></div></div>\n";
       return $r;
   }