예제 #1
0
 /** 
  * Get the location control as a select dropdown.
  */
 private static function get_control_locationselect($auth, $args, $tabalias, $options)
 {
     self::$want_location_layer = true;
     $location_list_args = array_merge(array('label' => lang::get('LANG_Location_Label'), 'view' => 'detail', 'extraParams' => array_merge(array('orderby' => 'name', 'website_id' => $args['website_id']), $auth['read'])), $options);
     return data_entry_helper::location_select($location_list_args);
 }
 public static function get_sample_form($args, $node, $response)
 {
     global $user;
     if (!module_exists('iform_ajaxproxy')) {
         return 'This form must be used in Drupal with the Indicia AJAX Proxy module enabled.';
     }
     require_once dirname(dirname(__FILE__)) . '/map_helper.php';
     $auth = data_entry_helper::get_read_write_auth($args['website_id'], $args['password']);
     $sampleId = isset($_GET['sample_id']) ? $_GET['sample_id'] : null;
     if ($sampleId) {
         data_entry_helper::load_existing_record($auth['read'], 'sample', $sampleId);
         $locationId = data_entry_helper::$entity_to_load['sample:location_id'];
     } else {
         $locationId = isset($_GET['site']) ? $_GET['site'] : null;
         // location ID also might be in the $_POST data after a validation save of a new record
         if (!$locationId && isset($_POST['sample:location_id'])) {
             $locationId = $_POST['sample:location_id'];
         }
     }
     $r .= '<form method="post" id="sample">';
     $r .= $auth['write'];
     // we pass through the read auth. This makes it possible for the get_submission method to authorise against the warehouse
     // without an additional (expensive) warehouse call, so it can get location details.
     $r .= '<input type="hidden" name="read_nonce" value="' . $auth['read']['nonce'] . '"/>';
     $r .= '<input type="hidden" name="read_auth_token" value="' . $auth['read']['auth_  token'] . '"/>';
     $r .= '<input type="hidden" name="website_id" value="' . $args['website_id'] . '"/>';
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         $r .= '<input type="hidden" name="sample:id" value="' . data_entry_helper::$entity_to_load['sample:id'] . '"/>';
     }
     $r .= '<input type="hidden" name="sample:survey_id" value="' . $args['survey_id'] . '"/>';
     // pass a param that sets the next page to display
     $r .= '<input type="hidden" name="page" value="grid"/>';
     if ($locationId) {
         $site = data_entry_helper::get_population_data(array('table' => 'location', 'extraParams' => $auth['read'] + array('view' => 'detail', 'id' => $locationId, 'deleted' => 'f')));
         $site = $site[0];
         $r .= '<input type="hidden" name="sample:location_id" value="' . $locationId . '"/>';
         $r .= '<input type="hidden" name="sample:entered_sref" value="' . $site['centroid_sref'] . '"/>';
         $r .= '<input type="hidden" name="sample:entered_sref_system" value="' . $site['centroid_sref_system'] . '"/>';
     }
     if ($locationId && isset(data_entry_helper::$entity_to_load['sample:id'])) {
         // for reload of existing, don't let the user switch the transect as that would mess everything up.
         $r .= '<label>' . lang::get('Transect') . ':</label><span>' . $site['name'] . '</span><br/>';
     } else {
         // Output only the locations for this website and transect type. Note we load both transects and sections, just so that
         // we always use the same warehouse call and therefore it uses the cache.
         $locationTypes = helper_base::get_termlist_terms($auth, 'indicia:location_types', array('Transect', 'Transect Section'));
         $availableSites = data_entry_helper::get_population_data(array('report' => 'library/locations/locations_list', 'extraParams' => $auth['read'] + array('website_id' => $args['website_id'], 'location_type_id' => $locationTypes[0]['id'], 'locattrs' => 'CMS User ID', 'attr_location_cms_user_id' => $user->uid), 'nocache' => true));
         // convert the report data to an array for the lookup, plus one to pass to the JS so it can keep the hidden sref fields updated
         $sitesLookup = array();
         $sitesJs = array();
         foreach ($availableSites as $site) {
             $sitesLookup[$site['location_id']] = $site['name'];
             $sitesJs[$site['location_id']] = $site;
         }
         data_entry_helper::$javascript .= "indiciaData.sites = " . json_encode($sitesJs) . ";\n";
         $options = array('label' => lang::get('Select Transect'), 'validation' => array('required'), 'blankText' => lang::get('please select'), 'lookupValues' => $sitesLookup);
         if ($locationId) {
             $options['default'] = $locationId;
         }
         $r .= data_entry_helper::location_select($options);
     }
     if (!$locationId) {
         $r .= '<input type="hidden" name="sample:entered_sref" value="" id="entered_sref"/>';
         $r .= '<input type="hidden" name="sample:entered_sref_system" value="" id="entered_sref_system"/>';
         // sref values for the sample will be populated automatically when the submission is built.
     }
     $r .= data_entry_helper::date_picker(array('label' => lang::get('Date'), 'fieldname' => 'sample:date'));
     $sampleMethods = helper_base::get_termlist_terms($auth, 'indicia:sample_methods', array('Transect'));
     $attributes = data_entry_helper::getAttributes(array('id' => $sampleId, 'valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'fieldprefix' => 'smpAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id'], 'sample_method_id' => $sampleMethods[0]['id']));
     $r .= get_attribute_html($attributes, $args, array('extraParams' => $auth['read']));
     $r .= '<input type="hidden" name="sample:sample_method_id" value="' . $sampleMethods[0]['id'] . '" />';
     $r .= '<input type="submit" value="' . lang::get('Next') . '" class="ui-state-default ui-corner-all" />';
     $r .= '</form>';
     data_entry_helper::enable_validation('sample');
     return $r;
 }
 /**
  * Return the generated form output.
  * @param array $args List of parameter values passed through to the form depending on how the form has been configured.
  * This array always contains a value for language.
  * @param object $node The Drupal node object.
  * @param array $response When this form is reloading after saving a submission, contains the response from the service call.
  * Note this does not apply when redirecting (in this case the details of the saved object are in the $_GET data).
  * @return Form HTML.
  */
 public static function get_form($args, $node, $response = null)
 {
     $form = '<form action="#" method="POST" id="entry_form">';
     if ($_POST) {
         $auth = data_entry_helper::get_read_write_auth($args['website_id'], $args['password']);
         self::subscribe($args, $auth);
     } else {
         // don't bother with write auth for initial form load, as read auth is cached and faster
         $auth = array('read' => data_entry_helper::get_read_auth($args['website_id'], $args['password']));
     }
     if (!empty($_GET['id'])) {
         data_entry_helper::load_existing_record($auth['read'], 'species_alert', $_GET['id']);
         // enforce permissions
         if (data_entry_helper::$entity_to_load['species_alert:user_id'] != hostsite_get_user_field('indicia_user_id')) {
             return lang::get('You cannot modify a species alert subscription created by someone else');
         }
         $form .= data_entry_helper::hidden_text(array('fieldname' => 'species_alert:id', 'default' => $_GET['id']));
     }
     // if not logged in, then ask for details to register against
     global $user;
     if (!hostsite_get_user_field('id') || !isset($user) || empty($user->mail) || !hostsite_get_user_field('last_name')) {
         $form .= "<fieldset><legend>" . lang::get('Your details') . ":</legend>\n";
         $default = empty($_POST['first_name']) ? hostsite_get_user_field('first_name', '') : $_POST['first_name'];
         $form .= data_entry_helper::text_input(array('label' => lang::get('First name'), 'fieldname' => 'first_name', 'validation' => array('required'), 'default' => $default, 'class' => 'control-width-4'));
         $default = empty($_POST['surname']) ? hostsite_get_user_field('last_name', '') : $_POST['surname'];
         $form .= data_entry_helper::text_input(array('label' => lang::get('Last name'), 'fieldname' => 'surname', 'validation' => array('required'), 'default' => $default, 'class' => 'control-width-4'));
         $default = empty($_POST['email']) ? empty($user->mail) ? '' : $user->mail : $_POST['email'];
         $form .= data_entry_helper::text_input(array('label' => lang::get('Email'), 'fieldname' => 'email', 'validation' => array('required', 'email'), 'default' => $default, 'class' => 'control-width-4'));
         $form .= "</fieldset>\n";
     } else {
         $form .= data_entry_helper::hidden_text(array('fieldname' => 'first_name', 'default' => hostsite_get_user_field('first_name')));
         $form .= data_entry_helper::hidden_text(array('fieldname' => 'surname', 'default' => hostsite_get_user_field('last_name')));
         $form .= data_entry_helper::hidden_text(array('fieldname' => 'email', 'default' => $user->mail));
         $form .= data_entry_helper::hidden_text(array('fieldname' => 'user_id', 'default' => hostsite_get_user_field('indicia_user_id')));
     }
     $form .= "<fieldset><legend>" . lang::get('Alert criteria') . ":</legend>\n";
     // Output the species selection control
     // Default after saving with a validation failure can be pulled direct from the post, but
     // when reloading we don't need a default taxa taxon list ID since we already know the meaning
     // ID or external key.
     $default = empty($_POST['taxa_taxon_list_id']) ? '' : $_POST['taxa_taxon_list_id'];
     if (empty($_POST['taxa_taxon_list_id:taxon'])) {
         $defaultCaption = empty(data_entry_helper::$entity_to_load['species_alert:preferred_taxon']) ? '' : data_entry_helper::$entity_to_load['species_alert:preferred_taxon'];
     } else {
         $defaultCaption = $_POST['taxa_taxon_list_id:taxon'];
     }
     $form .= data_entry_helper::species_autocomplete(array('label' => lang::get('Alert species'), 'helpText' => lang::get('Select the species you are interested in receiving alerts in ' . 'relation to if you want to receive alerts on a single species.'), 'fieldname' => 'taxa_taxon_list_id', 'cacheLookup' => true, 'extraParams' => $auth['read'] + array('taxon_list_id' => $args['list_id']), 'class' => 'control-width-4', 'default' => $default, 'defaultCaption' => $defaultCaption));
     if (empty($default)) {
         // Unless we've searched for the species name then posted (and failed), then the
         // default will be empty. We might therefore be reloading existing data which has
         // a meaning ID or external key.
         if (!empty(data_entry_helper::$entity_to_load['species_alert:external_key'])) {
             $form .= data_entry_helper::hidden_text(array('fieldname' => 'species_alert:external_key', 'default' => data_entry_helper::$entity_to_load['species_alert:external_key']));
         } elseif (!empty(data_entry_helper::$entity_to_load['species_alert:taxon_meaning_id'])) {
             $form .= data_entry_helper::hidden_text(array('fieldname' => 'species_alert:taxon_meaning_id', 'default' => data_entry_helper::$entity_to_load['species_alert:taxon_meaning_id']));
         }
     }
     if (!empty($args['full_lists'])) {
         $form .= data_entry_helper::select(array('label' => lang::get('Select full species lists'), 'helpText' => lang::get('If you want to restrict the alerts to records of any ' . 'species within a species list, then select the list here.'), 'fieldname' => 'species_alert:taxon_list_id', 'blankText' => lang::get('<Select a species list>'), 'table' => 'taxon_list', 'valueField' => 'id', 'captionField' => 'title', 'extraParams' => $auth['read'] + array('id' => $args['full_lists'], 'orderby' => 'title'), 'class' => 'control-width-4'));
     }
     $form .= data_entry_helper::location_select(array('label' => lang::get('Select location'), 'helpText' => lang::get('If you want to restrict the alerts to records within a certain boundary, select it here.'), 'fieldname' => 'species_alert:location_id', 'id' => 'imp-location', 'blankText' => lang::get('<Select boundary>'), 'extraParams' => $auth['read'] + array('location_type_id' => $args['location_type_id'], 'orderby' => 'name'), 'class' => 'control-width-4'));
     $form .= data_entry_helper::checkbox(array('label' => lang::get('Alert on initial entry'), 'helpText' => lang::get('Tick this box if you want to receive a notification when the record is first input into the system.'), 'fieldname' => 'species_alert:alert_on_entry'));
     $form .= data_entry_helper::checkbox(array('label' => lang::get('Alert on verification as correct'), 'helpText' => lang::get('Tick this box if you want to receive a notification when the record has been verified as correct.'), 'fieldname' => 'species_alert:alert_on_verify'));
     $form .= "</fieldset>\n";
     $form .= '<input type="Submit" value="Subscribe" />';
     $form .= '</form>';
     data_entry_helper::enable_validation('entry_form');
     iform_load_helpers(array('map_helper'));
     $mapOptions = iform_map_get_map_options($args, $auth['read']);
     $map = map_helper::map_panel($mapOptions);
     global $indicia_templates;
     return str_replace(array('{col-1}', '{col-2}'), array($form, $map), $indicia_templates['two-col-50']);
 }
 public static function get_sample_form($args, $node, $response)
 {
     global $user;
     if (!module_exists('iform_ajaxproxy')) {
         return 'This form must be used in Drupal with the Indicia AJAX Proxy module enabled.';
     }
     iform_load_helpers(array('map_helper'));
     $auth = data_entry_helper::get_read_write_auth($args['website_id'], $args['password']);
     $sampleId = isset($_GET['sample_id']) ? $_GET['sample_id'] : null;
     $locationId = null;
     if ($sampleId) {
         data_entry_helper::load_existing_record($auth['read'], 'sample', $sampleId, 'detail', false, true);
         $locationId = data_entry_helper::$entity_to_load['sample:location_id'];
     } else {
         // location ID also might be in the $_POST data after a validation save of a new record
         if (isset($_POST['sample:location_id'])) {
             $locationId = $_POST['sample:location_id'];
         }
     }
     $url = explode('?', $args['my_obs_page'], 2);
     $params = NULL;
     $fragment = NULL;
     // fragment is always at the end.
     if (count($url) > 1) {
         $params = explode('#', $url[1], 2);
         if (count($params) > 1) {
             $fragment = $params[1];
         }
         $params = $params[0];
     } else {
         $url = explode('#', $url[0], 2);
         if (count($url) > 1) {
             $fragment = $url[1];
         }
     }
     $args['my_obs_page'] = url($url[0], array('query' => $params, 'fragment' => $fragment, 'absolute' => TRUE));
     $r = '<form method="post" id="sample">';
     $r .= $auth['write'];
     $r .= '<input type="hidden" name="page" value="mainSample"/>';
     $r .= '<input type="hidden" name="website_id" value="' . $args['website_id'] . '"/>';
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         $r .= '<input type="hidden" name="sample:id" value="' . data_entry_helper::$entity_to_load['sample:id'] . '"/>';
     }
     $r .= '<input type="hidden" name="sample:survey_id" value="' . $args['survey_id'] . '"/>';
     $r .= '<div id="cols" class="ui-helper-clearfix"><div class="left" style="width: ' . (98 - (isset($args['percent_width']) ? $args['percent_width'] : 50)) . '%">';
     // Output only the locations for this website and location type.
     $availableSites = data_entry_helper::get_population_data(array('report' => 'library/locations/locations_list', 'extraParams' => $auth['read'] + array('website_id' => $args['website_id'], 'location_type_id' => $args['locationType'], 'locattrs' => 'CMS User ID', 'attr_location_cms_user_id' => $user->uid), 'nocache' => true));
     // convert the report data to an array for the lookup, plus one to pass to the JS so it can keep the map updated
     $sitesLookup = array();
     $sitesIds = array();
     $sitesJs = array();
     foreach ($availableSites as $site) {
         $sitesLookup[$site['location_id']] = $site['name'];
         $sitesIds[] = $site['location_id'];
     }
     $sites = data_entry_helper::get_population_data(array('table' => 'location', 'extraParams' => $auth['read'] + array('website_id' => $args['website_id'], 'id' => $sitesIds, 'view' => 'detail')));
     foreach ($sites as $site) {
         $sitesJs[$site['id']] = $site;
     }
     data_entry_helper::$javascript .= "indiciaData.sites = " . json_encode($sitesJs) . ";\n";
     if ($locationId) {
         $r .= '<input type="hidden" name="sample:location_id" id="sample_location_id" value="' . $locationId . '"/>';
         // for reload of existing, don't let the user switch the square as that could mess everything up.
         $r .= '<label>' . lang::get('1km square') . ':</label><span>' . $sitesJs[$locationId]['name'] . '</span><br/>' . lang::get('<p class="ui-state-highlight page-notice ui-corner-all">Please use the map to select a more precise location for your timed observation.</p>');
     } else {
         $options = array('label' => lang::get('Select 1km square'), 'validation' => array('required'), 'blankText' => lang::get('Please select'), 'lookupValues' => $sitesLookup, 'id' => "sample_location_id");
         // if ($locationId) $options['default'] = $locationId;
         $r .= data_entry_helper::location_select($options) . lang::get('<p class="ui-state-highlight page-notice ui-corner-all">After selecting the 1km square, use the map to select a more precise location for your timed observation.</p>');
     }
     // [spatial reference]
     $systems = array();
     foreach (explode(',', str_replace(' ', '', $args['spatial_systems'])) as $system) {
         $systems[$system] = lang::get("sref:{$system}");
     }
     $r .= data_entry_helper::sref_and_system(array('label' => lang::get('Grid Ref'), 'systems' => $systems));
     $r .= data_entry_helper::file_box(array('table' => 'sample_image', 'readAuth' => $auth['read'], 'caption' => lang::get('Upload photo(s) of timed search area')));
     $sampleMethods = helper_base::get_termlist_terms($auth, 'indicia:sample_methods', array('Field Observation'));
     $attributes = data_entry_helper::getAttributes(array('id' => $sampleId, 'valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'fieldprefix' => 'smpAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id'], 'sample_method_id' => $sampleMethods[0]['id']));
     $r .= get_user_profile_hidden_inputs($attributes, $args, '', $auth['read']);
     if (isset($_GET['date'])) {
         $r .= '<input type="hidden" name="sample:date" value="' . $_GET['date'] . '"/>';
         $r .= '<label>' . lang::get('Date') . ':</label> <span class="value-label">' . $_GET['date'] . '</span><br/>';
     } else {
         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
             // @todo The date format should be a global configurable option. It should also be applied to reloading of custom date attributes.
             $d = new DateTime(data_entry_helper::$entity_to_load['sample:date']);
             data_entry_helper::$entity_to_load['sample:date'] = $d->format('d/m/Y');
         }
         $r .= data_entry_helper::date_picker(array('label' => lang::get('Date'), 'fieldname' => 'sample:date'));
     }
     // are there any option overrides for the custom attributes?
     if (isset($args['custom_attribute_options']) && $args['custom_attribute_options']) {
         $blockOptions = get_attr_options_array_with_user_data($args['custom_attribute_options']);
     } else {
         $blockOptions = array();
     }
     $r .= get_attribute_html($attributes, $args, array('extraParams' => $auth['read']), null, $blockOptions);
     $r .= '<input type="hidden" name="sample:sample_method_id" value="' . $sampleMethods[0]['id'] . '" />';
     $r .= '<input type="submit" value="' . lang::get('Next') . '" />';
     $r .= '<a href="' . $args['my_obs_page'] . '" class="button">' . lang::get('Cancel') . '</a>';
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         $r .= '<button id="delete-button" type="button" class="ui-state-default ui-corner-all" />' . lang::get('Delete') . '</button>';
     }
     $r .= "</div>";
     // left
     $r .= '<div class="right" style="width: ' . (isset($args['percent_width']) ? $args['percent_width'] : 50) . '%">';
     // [place search]
     $georefOpts = iform_map_get_georef_options($args, $auth['read']);
     $georefOpts['label'] = lang::get('Search for Place on Map');
     // can't use place search without the driver API key
     if ($georefOpts['driver'] == 'geoplanet' && empty(helper_config::$geoplanet_api_key)) {
         $r .= '<span style="display: none;">The form structure includes a place search but needs a geoplanet api key.</span>';
     } else {
         $r .= data_entry_helper::georeference_lookup($georefOpts);
     }
     // [map]
     $options = iform_map_get_map_options($args, $auth['read']);
     if (!empty(data_entry_helper::$entity_to_load['sample:wkt'])) {
         $options['initialFeatureWkt'] = data_entry_helper::$entity_to_load['sample:wkt'];
     }
     $olOptions = iform_map_get_ol_options($args);
     if (!isset($options['standardControls'])) {
         $options['standardControls'] = array('layerSwitcher', 'panZoomBar');
     }
     $r .= map_helper::map_panel($options, $olOptions);
     data_entry_helper::$javascript .= "\nmapInitialisationHooks.push(function(mapdiv) {\n  var defaultStyle = new OpenLayers.Style({pointRadius: 6,fillOpacity: 0,strokeColor: \"Red\",strokeWidth: 1});\n  var SiteStyleMap = new OpenLayers.StyleMap({\"default\": defaultStyle});\n  indiciaData.SiteLayer = new OpenLayers.Layer.Vector('1km square',{styleMap: SiteStyleMap, displayInLayerSwitcher: true});\n  mapdiv.map.addLayer(indiciaData.SiteLayer);\n  if(jQuery('#sample_location_id').length > 0) {\n    if(jQuery('#sample_location_id').val() != ''){\n      var parser = new OpenLayers.Format.WKT();\n      var feature = parser.read(indiciaData.sites[jQuery('#sample_location_id').val()].geom);\n      indiciaData.SiteLayer.addFeatures([feature]);\n      // for existing data we zoom on the site, not this parent location\n    } \n    jQuery('#sample_location_id').change(function(){\n      indiciaData.SiteLayer.destroyFeatures();\n      if(jQuery('#sample_location_id').val() != ''){\n        var parser = new OpenLayers.Format.WKT();\n        var feature = parser.read(indiciaData.sites[jQuery('#sample_location_id').val()].geom);\n        indiciaData.SiteLayer.addFeatures([feature]);\n        var layerBounds = indiciaData.SiteLayer.getDataExtent().clone(); // use a clone\n        indiciaData.SiteLayer.map.zoomToExtent(layerBounds);\n      }\n    });\n  }\n});\n";
     $r .= "</div>";
     // right
     $r .= '</form>';
     // Recorder Name - assume Easy Login uid
     if (function_exists('module_exists') && module_exists('easy_login')) {
         $userId = hostsite_get_user_field('indicia_user_id');
         // For non easy login test only     $userId = 1;
         foreach ($attributes as $attrID => $attr) {
             if (strcasecmp('Recorder Name', $attr["untranslatedCaption"]) == 0 && !empty($userId)) {
                 // determining which you have used is difficult from a services based autocomplete, esp when the created_by_id is not available on the data.
                 data_entry_helper::add_resource('autocomplete');
                 data_entry_helper::$javascript .= "bindRecorderNameAutocomplete(" . $attrID . ", '" . $userId . "', '" . data_entry_helper::$base_url . "', '" . $args['survey_id'] . "', '" . $auth['read']['auth_token'] . "', '" . $auth['read']['nonce'] . "');\n";
             }
         }
     }
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         // allow deletes if sample id is present.
         data_entry_helper::$javascript .= "jQuery('#delete-button').click(function(){\n  if(confirm(\"" . lang::get('Are you sure you want to delete this walk?') . "\")){\n    jQuery('#delete-form').submit();\n  } // else do nothing.\n});\n";
         // note we only require bare minimum in order to flag a sample as deleted.
         $r .= '<form method="post" id="delete-form" style="display: none;">';
         $r .= $auth['write'];
         $r .= '<input type="hidden" name="page" value="delete"/>';
         $r .= '<input type="hidden" name="website_id" value="' . $args['website_id'] . '"/>';
         $r .= '<input type="hidden" name="sample:id" value="' . data_entry_helper::$entity_to_load['sample:id'] . '"/>';
         $r .= '<input type="hidden" name="sample:deleted" value="t"/>';
         $r .= '</form>';
     }
     data_entry_helper::enable_validation('sample');
     return $r;
 }
 /**
  * Get the location control as a select dropdown.
  * Default control ordering is by name.
  * reportProvidesOrderBy option should be set to true if the control is populated by a report that
  * provides its own Order By statement, if the reportProvidesOrderBy option is not set in this situation, then the report
  * will have two Order By statements and will fail. 
  */
 protected static function get_control_locationselect($auth, $args, $tabAlias, $options)
 {
     if (isset($options['extraParams'])) {
         foreach ($options['extraParams'] as $key => &$value) {
             $value = apply_user_replacements($value);
         }
         $options['extraParams'] = array_merge($auth['read'], $options['extraParams']);
     } else {
         $options['extraParams'] = array_merge($auth['read']);
     }
     if (empty($options['reportProvidesOrderBy']) || $options['reportProvidesOrderBy'] == 0) {
         $options['extraParams']['orderby'] = 'name';
     }
     $location_list_args = array_merge(array('label' => lang::get('LANG_Location_Label'), 'view' => 'detail'), $options);
     return data_entry_helper::location_select($location_list_args);
 }
예제 #6
0
 /**
  * Get the transect control
  */
 protected static function get_control_transect($auth, $args, $tabalias, $options)
 {
     $defAttrOptions = array('extraParams' => $auth['read'], 'validation' => array('required'));
     if (self::$locations == 'all') {
         $locOptions = array_merge(array('label' => lang::get('LANG_Transect'), 'id' => 'sample:location_id'), $defAttrOptions);
         $locOptions['extraParams'] = array_merge(array('parent_id' => 'NULL', 'view' => 'detail', 'orderby' => 'name'), $locOptions['extraParams']);
         $ret = data_entry_helper::location_select($locOptions);
     } else {
         // can't use location select due to location filtering.
         $ret = "<label for=\"sample:location_id\">" . lang::get('LANG_Transect') . ":</label>\n<select id=\"sample:location_id\" name=\"sample:location_id\" " . $disabled_text . " class=\" \"  >";
         $url = self::$svcUrl . '/data/location?mode=json&view=detail&parent_id=NULL&orderby=name&auth_token=' . $auth['read']['auth_token'] . '&nonce=' . $auth['read']["nonce"];
         // could do new multiple fetch query
         $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"], self::$locations)) {
                     if ($entity["id"] == data_entry_helper::$entity_to_load['sample:location_id']) {
                         $selected = 'selected="selected"';
                     } else {
                         $selected = '';
                     }
                     $ret .= "<option value=\"" . $entity["id"] . "\" " . $selected . ">" . $entity["name"] . "&nbsp;</option>";
                 }
             }
         }
         $ret .= "</select>";
     }
     $ret .= "<input type=hidden name=\"sample:location_name\" value=\"\" /><br />";
     data_entry_helper::$javascript .= "\njQuery(\"#sample\\\\:location_id\").change(function(){\n  jQuery('[name=sample\\:location_name]').val(jQuery(this).find(':selected')[0].text);\n  jQuery('.displayTransectDetails').empty().append('<span>'+jQuery('[name=sample\\:location_name]').val()+'</span>');\n});\njQuery(\"#sample\\\\:location_id\").change();\n";
     return $ret;
 }
   /**
    * 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;
   }
예제 #8
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;
}
 public static function get_sample_form($args, $node, $response)
 {
     global $user;
     if (!module_exists('iform_ajaxproxy')) {
         return 'This form must be used in Drupal with the Indicia AJAX Proxy module enabled.';
     }
     iform_load_helpers(array('map_helper'));
     $auth = data_entry_helper::get_read_write_auth($args['website_id'], $args['password']);
     $sampleId = isset($_GET['sample_id']) ? $_GET['sample_id'] : null;
     if ($sampleId) {
         data_entry_helper::load_existing_record($auth['read'], 'sample', $sampleId);
         $locationId = data_entry_helper::$entity_to_load['sample:location_id'];
     } else {
         $locationId = isset($_GET['site']) ? $_GET['site'] : null;
         // location ID also might be in the $_POST data after a validation save of a new record
         if (!$locationId && isset($_POST['sample:location_id'])) {
             $locationId = $_POST['sample:location_id'];
         }
     }
     $url = explode('?', $args['my_walks_page'], 2);
     $params = NULL;
     $fragment = NULL;
     // fragment is always at the end.
     if (count($url) > 1) {
         $params = explode('#', $url[1], 2);
         if (count($params) > 1) {
             $fragment = $params[1];
         }
         $params = $params[0];
     } else {
         $url = explode('#', $url[0], 2);
         if (count($url) > 1) {
             $fragment = $url[1];
         }
     }
     $args['my_walks_page'] = url($url[0], array('query' => $params, 'fragment' => $fragment, 'absolute' => TRUE));
     $r = '<form method="post" id="sample">';
     $r .= $auth['write'];
     // we pass through the read auth. This makes it possible for the get_submission method to authorise against the warehouse
     // without an additional (expensive) warehouse call, so it can get location details.
     $r .= '<input type="hidden" name="page" value="mainSample"/>';
     $r .= '<input type="hidden" name="read_nonce" value="' . $auth['read']['nonce'] . '"/>';
     $r .= '<input type="hidden" name="read_auth_token" value="' . $auth['read']['auth_token'] . '"/>';
     $r .= '<input type="hidden" name="website_id" value="' . $args['website_id'] . '"/>';
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         $r .= '<input type="hidden" name="sample:id" value="' . data_entry_helper::$entity_to_load['sample:id'] . '"/>';
     }
     $r .= '<input type="hidden" name="sample:survey_id" value="' . $args['survey_id'] . '"/>';
     if (isset($args['include_map_samples_form']) && $args['include_map_samples_form']) {
         $r .= '<div id="cols" class="ui-helper-clearfix"><div class="left" style="width: ' . (98 - (isset($args['percent_width']) ? $args['percent_width'] : 50)) . '%">';
     }
     if ($locationId) {
         $site = data_entry_helper::get_population_data(array('table' => 'location', 'extraParams' => $auth['read'] + array('view' => 'detail', 'id' => $locationId, 'deleted' => 'f')));
         $site = $site[0];
         $r .= '<input type="hidden" name="sample:location_id" value="' . $locationId . '"/>';
         $r .= '<input type="hidden" name="sample:entered_sref" value="' . $site['centroid_sref'] . '"/>';
         $r .= '<input type="hidden" name="sample:entered_sref_system" value="' . $site['centroid_sref_system'] . '"/>';
     }
     if ($locationId && (isset(data_entry_helper::$entity_to_load['sample:id']) || isset($_GET['site']))) {
         // for reload of existing or the the site is specified in the URL, don't let the user switch the transect as that would mess everything up.
         $r .= '<label>' . lang::get('Transect') . ':</label> <span class="value-label">' . $site['name'] . '</span><br/>';
     } else {
         // Output only the locations for this website and transect type. Note we load both transects and sections, just so that
         // we always use the same warehouse call and therefore it uses the cache.
         $typeTerms = array(empty($args['transect_type_term']) ? 'Transect' : $args['transect_type_term'], empty($args['section_type_term']) ? 'Section' : $args['section_type_term']);
         $locationTypes = helper_base::get_termlist_terms($auth, 'indicia:location_types', $typeTerms);
         $siteParams = $auth['read'] + array('website_id' => $args['website_id'], 'location_type_id' => $locationTypes[0]['id']);
         if ((!isset($args['user_locations_filter']) || $args['user_locations_filter']) && (!isset($args['managerPermission']) || !user_access($args['managerPermission']))) {
             $siteParams += array('locattrs' => 'CMS User ID', 'attr_location_cms_user_id' => $user->uid);
         } else {
             $siteParams += array('locattrs' => '');
         }
         $availableSites = data_entry_helper::get_population_data(array('report' => 'library/locations/locations_list', 'extraParams' => $siteParams, 'nocache' => true));
         // convert the report data to an array for the lookup, plus one to pass to the JS so it can keep the hidden sref fields updated
         $sitesLookup = array();
         $sitesJs = array();
         foreach ($availableSites as $site) {
             $sitesLookup[$site['location_id']] = $site['name'];
             $sitesJs[$site['location_id']] = $site;
         }
         // bolt in branch locations. Don't assume that branch list is superset of normal sites list.
         // Only need to do if not a manager - they have already fetched the full list anyway.
         if (isset($args['branch_assignment_permission']) && user_access($args['branch_assignment_permission']) && $siteParams['locattrs'] != '') {
             $siteParams['locattrs'] = 'Branch CMS User ID';
             $siteParams['attr_location_branch_cms_user_id'] = $user->uid;
             unset($siteParams['attr_location_cms_user_id']);
             $availableSites = data_entry_helper::get_population_data(array('report' => 'library/locations/locations_list', 'extraParams' => $siteParams, 'nocache' => true));
             foreach ($availableSites as $site) {
                 $sitesLookup[$site['location_id']] = $site['name'];
                 $sitesJs[$site['location_id']] = $site;
             }
             natcasesort($sitesLookup);
             // merge into original list in alphabetic order.
         }
         data_entry_helper::$javascript .= "indiciaData.sites = " . json_encode($sitesJs) . ";\n";
         $options = array('label' => lang::get('Select Transect'), 'validation' => array('required'), 'blankText' => lang::get('please select'), 'lookupValues' => $sitesLookup);
         if ($locationId) {
             $options['default'] = $locationId;
         }
         $r .= data_entry_helper::location_select($options);
     }
     if (!$locationId) {
         $r .= '<input type="hidden" name="sample:entered_sref" value="" id="entered_sref"/>';
         $r .= '<input type="hidden" name="sample:entered_sref_system" value="" id="entered_sref_system"/>';
         // sref values for the sample will be populated automatically when the submission is built.
     }
     $sampleMethods = helper_base::get_termlist_terms($auth, 'indicia:sample_methods', array('Transect'));
     $attributes = data_entry_helper::getAttributes(array('id' => $sampleId, 'valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'fieldprefix' => 'smpAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id'], 'sample_method_id' => $sampleMethods[0]['id']));
     $r .= get_user_profile_hidden_inputs($attributes, $args, '', $auth['read']);
     if (isset($_GET['date'])) {
         $r .= '<input type="hidden" name="sample:date" value="' . $_GET['date'] . '"/>';
         $r .= '<label>' . lang::get('Date') . ':</label> <span class="value-label">' . $_GET['date'] . '</span><br/>';
     } else {
         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
             // @todo The date format should be a global configurable option. It should also be applied to reloading of custom date attributes.
             $d = new DateTime(data_entry_helper::$entity_to_load['sample:date']);
             data_entry_helper::$entity_to_load['sample:date'] = $d->format('d/m/Y');
         }
         $r .= data_entry_helper::date_picker(array('label' => lang::get('Date'), 'fieldname' => 'sample:date'));
     }
     // are there any option overrides for the custom attributes?
     if (isset($args['custom_attribute_options']) && $args['custom_attribute_options']) {
         $blockOptions = get_attr_options_array_with_user_data($args['custom_attribute_options']);
     } else {
         $blockOptions = array();
     }
     $r .= get_attribute_html($attributes, $args, array('extraParams' => $auth['read']), null, $blockOptions);
     $r .= '<input type="hidden" name="sample:sample_method_id" value="' . $sampleMethods[0]['id'] . '" />';
     $r .= '<input type="submit" value="' . lang::get('Next') . '" />';
     $r .= '<a href="' . $args['my_walks_page'] . '" class="button">' . lang::get('Cancel') . '</a>';
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         $r .= '<button id="delete-button" type="button" class="ui-state-default ui-corner-all" />' . lang::get('Delete') . '</button>';
     }
     if (isset($args['include_map_samples_form']) && $args['include_map_samples_form']) {
         $r .= "</div>" . '<div class="right" style="width: ' . (isset($args['percent_width']) ? $args['percent_width'] : 50) . '%">';
         // no place search: [map]
         $options = iform_map_get_map_options($args, $auth['read']);
         if (!empty(data_entry_helper::$entity_to_load['sample:wkt'])) {
             $options['initialFeatureWkt'] = data_entry_helper::$entity_to_load['sample:wkt'];
         }
         $olOptions = iform_map_get_ol_options($args);
         if (!isset($options['standardControls'])) {
             $options['standardControls'] = array('layerSwitcher', 'panZoomBar');
         }
         $r .= map_helper::map_panel($options, $olOptions);
         $r .= "</div>";
         // right
     }
     $r .= '</form>';
     // Recorder Name - assume Easy Login uid
     if (function_exists('module_exists') && module_exists('easy_login')) {
         $userId = hostsite_get_user_field('indicia_user_id');
         // For non easy login test only     $userId = 1;
         foreach ($attributes as $attrID => $attr) {
             if (strcasecmp('Recorder Name', $attr["untranslatedCaption"]) == 0 && !empty($userId)) {
                 // determining which you have used is difficult from a services based autocomplete, esp when the created_by_id is not available on the data.
                 data_entry_helper::add_resource('autocomplete');
                 data_entry_helper::$javascript .= "bindRecorderNameAutocomplete(" . $attrID . ", '" . $userId . "', '" . data_entry_helper::$base_url . "', '" . $args['survey_id'] . "', '" . $auth['read']['auth_token'] . "', '" . $auth['read']['nonce'] . "');\n";
             }
         }
     }
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         // allow deletes if sample id is present.
         data_entry_helper::$javascript .= "jQuery('#delete-button').click(function(){\n  if(confirm(\"" . lang::get('Are you sure you want to delete this walk?') . "\")){\n    jQuery('#delete-form').submit();\n  } // else do nothing.\n});\n";
         // note we only require bare minimum in order to flag a sample as deleted.
         $r .= '<form method="post" id="delete-form" style="display: none;">';
         $r .= $auth['write'];
         $r .= '<input type="hidden" name="page" value="delete"/>';
         $r .= '<input type="hidden" name="website_id" value="' . $args['website_id'] . '"/>';
         $r .= '<input type="hidden" name="sample:id" value="' . data_entry_helper::$entity_to_load['sample:id'] . '"/>';
         $r .= '<input type="hidden" name="sample:deleted" value="t"/>';
         $r .= '</form>';
     }
     data_entry_helper::enable_validation('sample');
     return $r;
 }
예제 #10
0
 public static function add_sites_to_any_user($auth, $args, $tabalias, $options, $path)
 {
     //Need to call this so we can use indiciaData.read
     data_entry_helper::$js_read_tokens = $auth['read'];
     if (!function_exists('iform_ajaxproxy_url')) {
         return 'An AJAX Proxy module must be enabled for user sites administration to work.';
     }
     $r = "<form><fieldset><legend>" . lang::get('Add locations to the sites lists for other users') . "</legend>";
     if (empty($options['locationTypes']) || !preg_match('/^([0-9]+,( )?)*[0-9]+$/', $options['locationTypes'])) {
         return 'The sites form is not correctly configured. Please provide the location type you can add.';
     }
     $locationTypes = explode(',', str_replace(' ', '', $options['locationTypes']));
     if (empty($options['mySitesPsnAttrId']) || !preg_match('/^[0-9]+$/', $options['mySitesPsnAttrId'])) {
         return 'The sites form is not correctly configured. Please provide the person attribute ID used to store My Sites.';
     }
     if (!empty($options['locationParamFromURL']) && !empty($_GET[$options['locationParamFromURL']])) {
         $locationIdFromURL = $_GET[$options['locationParamFromURL']];
     } else {
         $locationIdFromURL = 0;
     }
     //If we don't want to automatically get the location id from the URL, then display a drop-down of locations the user can select from
     if (empty($locationIdFromURL)) {
         $r .= '<label>' . lang::get('Location :') . '</label> ';
         //Get a list of all the locations that match the given location types (in this case my sites are returned first, although this isn't a requirement)
         $r .= data_entry_helper::location_select(array('id' => 'location-select', 'nocache' => true, 'report' => 'reports_for_prebuilt_forms/Shorewatch/locations_with_my_sites_first', 'extraParams' => $auth['read'] + array('location_type_ids' => $options['locationTypes'], 'user_id' => hostsite_get_user_field('indicia_user_id'), 'my_sites_person_attr_id' => $options['mySitesPsnAttrId']), 'blankText' => '<' . lang::get('please select') . '>'));
     }
     //Get the user select control
     $r .= self::user_select_for_add_sites_to_any_user_control($auth['read'], $args);
     $r .= '<input id="add-user-site-button" type="button" value="' . lang::get('Add to this User\'s Sites List') . '"/><br></form><br>';
     $postUrl = iform_ajaxproxy_url(null, 'person_attribute_value');
     //Firstly check both a uer and location have been selected.
     //Then get the current user/sites saved in the database and if the new combination doesn't already exist then call a function to add it.
     data_entry_helper::$javascript .= "\n    function duplicateCheck(locationId, userId) {\n      var userIdToAdd = \$('#user-select').val();\n      var locationIdToAdd = locationId;\n      var sitesReport = indiciaData.read.url +'/index.php/services/report/requestReport?report=library/locations/all_user_sites.xml&mode=json&mode=json&callback=?';\n        \n      var sitesReportParameters = {\n        'person_site_attr_id': '" . $options['mySitesPsnAttrId'] . "',\n        'auth_token': indiciaData.read.auth_token,\n        'nonce': indiciaData.read.nonce,\n        'reportSource':'local'\n      };\n        \n      if (!userIdToAdd||!locationIdToAdd) {\n        alert('Please select both a user and a location to add.');\n      } else {\n        \$.getJSON (\n          sitesReport,\n          sitesReportParameters,\n          function (data) {\n            var duplicateDetected=false;\n            \$.each(data, function(i, dataItem) {\n              if (userIdToAdd==dataItem.pav_user_id&&locationIdToAdd==dataItem.location_id) {\n                  duplicateDetected=true;\n              }\n            });\n            if (duplicateDetected===true) {\n              alert('The site/user combination you are adding already exists in the database.');\n            } else {\n              addUserSiteData(locationId, userIdToAdd);\n            }\n          }\n        );\n      }    \n    }\n    ";
     //After duplicate check is performed, add the user/site combination to the person_attribute_values database table
     data_entry_helper::$javascript .= "\n    function addUserSiteData(locationId, userIdToAdd) {\n      if (!isNaN(locationId) && locationId!=='') {\n        \$.post('{$postUrl}', \n          {\"website_id\":" . $args['website_id'] . ",\"person_attribute_id\":" . $options['mySitesPsnAttrId'] . ",\"user_id\":userIdToAdd,\"int_value\":locationId},\n          function (data) {\n            if (typeof data.error === 'undefined') {\n              alert('User site configuration saved successfully');\n              location.reload();\n            } else {\n              alert(data.error);\n            }              \n          },\n          'json'\n        );\n      }\n    }\n    ";
     //Call duplicate check when administrator elects to save a user/site combination
     data_entry_helper::$javascript .= "\n    \$('#add-user-site-button').click(function() {\n      //We can get the location id from the url or from the locations drop-down depending on the option the administrator has set.\n      var locationId;\n      if (" . $locationIdFromURL . ") {\n        locationId = " . $locationIdFromURL . ";\n      } else {\n        locationId = \$('#location-select').val()       \n      }\n      duplicateCheck(locationId,\$('#dynamic-the_user_id').val());\n    });";
     //Zoom map as user selects locations
     data_entry_helper::$javascript .= "\n    \$('#location-select, #location-search, #locality_id').change(function() {\n      if (typeof indiciaData.mapdiv!=='undefined') {\n        indiciaData.mapdiv.locationSelectedInInput(indiciaData.mapdiv, this.value);\n      }\n    });\n    ";
     //Function for when user elects to remove sites
     data_entry_helper::$javascript .= "\n    user_site_delete = function(pav_id) {\n      var userId=\$('#dynamic-the_user_id').val();\n      \$.post('{$postUrl}', \n        {\"website_id\":" . $args['website_id'] . ",\"id\":pav_id, \"deleted\":\"t\"},\n        function (data) {\n          if (typeof data.error === 'undefined') {\n            location.reload(); \n          } else {\n            alert(data.error);\n          }\n        },\n        'json'\n      );\n    }\n    ";
     return $r;
 }
예제 #11
0
 public static function add_locations_to_user($auth, $args, $tabalias, $options, $path)
 {
     global $user;
     //Need to call this so we can use indiciaData.read
     data_entry_helper::$js_read_tokens = $auth['read'];
     if (!function_exists('iform_ajaxproxy_url')) {
         return 'An AJAX Proxy module must be enabled for user sites administration to work.';
     }
     if (!empty($options['locationDropDownLabel'])) {
         $locationDropDownLabel = $addButtonLabel = $options['locationDropDownLabel'] . ' :';
     } else {
         $locationDropDownLabel = lang::get('Location :');
     }
     if (!empty($options['addButtonLabel'])) {
         $addButtonLabel = $options['addButtonLabel'];
     } else {
         $addButtonLabel = lang::get('Add to this User\'s Sites List');
     }
     if (!empty($options['fieldSetLegend'])) {
         $fieldSetLegendText = $options['fieldSetLegend'];
     } else {
         $fieldSetLegendText = lang::get('Add locations to the sites lists for other users');
     }
     if (!empty($options['rolesExemptFromApproval'])) {
         $RolesExemptFromApproval = explode(',', $options['rolesExemptFromApproval']);
     } else {
         $RolesExemptFromApproval = array();
     }
     $r = "<form><fieldset><legend>" . $fieldSetLegendText . "</legend>";
     if (empty($options['locationTypes']) || !preg_match('/^([0-9]+,( )?)*[0-9]+$/', $options['locationTypes'])) {
         return 'The sites form is not correctly configured. Please provide the location type you can add.';
     }
     $locationTypes = explode(',', str_replace(' ', '', $options['locationTypes']));
     if (empty($options['mySitesPsnAttrId']) || !preg_match('/^[0-9]+$/', $options['mySitesPsnAttrId'])) {
         return 'The sites form is not correctly configured. Please provide the person attribute ID used to store My Sites.';
     }
     if (!empty($options['locationParamFromURL']) && !empty($_GET[$options['locationParamFromURL']])) {
         $locationIdFromURL = $_GET[$options['locationParamFromURL']];
     } else {
         $locationIdFromURL = 0;
     }
     //Get the user_id from the URL if we can, this would hide the user drop-down and make
     //the control applicable to a single user.
     if (!empty($options['userParamFromURL']) && !empty($_GET[$options['userParamFromURL']])) {
         $userIdFromURL = $_GET[$options['userParamFromURL']];
     } elseif (!empty($_GET['dynamic-the_user_id'])) {
         $userIdFromURL = $_GET['dynamic-the_user_id'];
     } else {
         $userIdFromURL = 0;
     }
     $extraParams = array('location_type_ids' => $options['locationTypes'], 'user_id' => hostsite_get_user_field('indicia_user_id'), 'my_sites_person_attr_id' => $options['mySitesPsnAttrId']);
     //Can limit results in location drop-down to certain distance of a post code
     if (!empty($options['postCodeGeomParamName']) && !empty($_GET[$options['postCodeGeomParamName']])) {
         $extraParams['post_code_geom'] = $_GET[$options['postCodeGeomParamName']];
     }
     if (!empty($options['distanceFromPostCodeParamName']) && !empty($_GET[$options['distanceFromPostCodeParamName']])) {
         $extraParams['distance_from_post_code'] = $_GET[$options['distanceFromPostCodeParamName']];
     }
     if (!empty($options['excludedSquareAttrId'])) {
         $extraParams['excluded_square_attr_id'] = $options['excludedSquareAttrId'];
     }
     if (!empty($options['dontReturnAllocatedLocations'])) {
         $extraParams['dont_return_allocated_locations'] = $options['dontReturnAllocatedLocations'];
     }
     if (!empty($options['maxAllocationForLocationAttrId'])) {
         $extraParams['max_allocation_for_location_attr_id'] = $options['maxAllocationForLocationAttrId'];
     }
     //If we don't want to automatically get the location id from the URL, then display a drop-down of locations the user can select from
     if (empty($locationIdFromURL)) {
         $r .= '<label>' . $locationDropDownLabel . '</label> ';
         //Get a list of all the locations that match the given location types (in this case my sites are returned first, although this isn't a requirement)
         $r .= data_entry_helper::location_select(array('id' => 'location-select', 'nocache' => true, 'report' => 'reports_for_prebuilt_forms/Splash/locations_for_add_location_drop_down', 'extraParams' => $auth['read'] + $extraParams, 'blankText' => '<' . lang::get('please select') . '>'));
     }
     //Get the user select control if the user id isn't in the url
     if (empty($userIdFromURL)) {
         $r .= self::user_select_for_add_sites_to_any_user_control($auth['read'], $args);
     }
     $r .= '<input id="add-user-site-button" type="button" value="' . $addButtonLabel . '"/><br></form><br>';
     $postUrl = iform_ajaxproxy_url(null, 'person_attribute_value');
     //Firstly check both a uer and location have been selected.
     //Then get the current user/sites saved in the database and if the new combination doesn't already exist then call a function to add it.
     data_entry_helper::$javascript .= "\n    function duplicateCheck(locationId, userId) {\n      var userIdToAdd = userId;\n      var locationIdToAdd = locationId;\n      var sitesReport = indiciaData.read.url +'/index.php/services/report/requestReport?report=library/locations/all_user_sites.xml&mode=json&mode=json&callback=?';\n        \n      var sitesReportParameters = {\n        'person_site_attr_id': '" . $options['mySitesPsnAttrId'] . "',\n        'auth_token': indiciaData.read.auth_token,\n        'nonce': indiciaData.read.nonce,\n        'reportSource':'local'\n      };\n      \n      if (!userIdToAdd||!locationIdToAdd) {\n        alert('Please select both a user and a location to add.');\n      } else {\n        \$.getJSON (\n          sitesReport,\n          sitesReportParameters,\n          function (data) {\n            var duplicateDetected=false;\n            \$.each(data, function(i, dataItem) {\n              if (userIdToAdd==dataItem.pav_user_id&&locationIdToAdd==dataItem.location_id) {\n                  duplicateDetected=true;\n              }\n            });\n            if (duplicateDetected===true) {\n              alert('The site/user combination you are adding already exists in the database.');\n            } else {\n              addUserSiteData(locationId, userIdToAdd);\n            }\n          }\n        );\n      }    \n    }\n    ";
     //This veriabe holds the updated_by_id=1 if the user is found to be exempt, if they aren't exempt then this is blank so that the
     //updated_by_id is set automatically by the system.
     $updatedBySystem = '';
     //See if any of the user's roles are in the exempt list.
     foreach ($RolesExemptFromApproval as $exemptRole) {
         foreach ($user->roles as $userRole) {
             if ($exemptRole === $userRole) {
                 $updatedBySystem = ',"updated_by_id":1';
             }
         }
     }
     //Add the user/site combination to the person_attribute_values database table.
     //This overrides the function in the my_sites.php file.
     data_entry_helper::$javascript .= "\n    var addUserSiteData = function (locationId, userIdToAdd) {\n      if (!isNaN(locationId) && locationId!=='') {\n        \$.post('{$postUrl}', \n          {\"website_id\":" . $args['website_id'] . ",\"person_attribute_id\":" . $options['mySitesPsnAttrId'] . ",\"user_id\":userIdToAdd,\"int_value\":locationId" . $updatedBySystem . "},\n          function (data) {\n            if (typeof data.error === 'undefined') {\n              alert('User site configuration saved successfully');\n              location.reload();\n            } else {\n              alert(data.error);\n            }              \n          },\n          'json'\n        );\n      }\n    }\n    ";
     //Call duplicate check when administrator elects to save a user/site combination
     data_entry_helper::$javascript .= "\n    \$('#add-user-site-button').click(function() {\n      //We can get the location id from the url or from the locations drop-down depending on the option the administrator has set.\n      var locationId;\n      var userId;\n      if (" . $locationIdFromURL . ") {\n        locationId = " . $locationIdFromURL . ";\n      } else {\n        locationId = \$('#location-select').val();       \n      }\n      if (" . $userIdFromURL . ") {\n        userId = " . $userIdFromURL . ";\n      } else {\n        userId = \$('#user-select').val();     \n      }\n      duplicateCheck(locationId,userId);\n    });";
     //Zoom map as user selects locations
     data_entry_helper::$javascript .= "\n    \$('#location-select, #location-search, #locality_id').change(function() {\n      if (typeof indiciaData.mapdiv!=='undefined') {\n        indiciaData.mapdiv.locationSelectedInInput(indiciaData.mapdiv, this.value);\n      }\n    });\n    ";
     self::user_site_delete($postUrl, $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;
   }
 /**
  * Get the location control as a select dropdown.
  * Default control ordering is by name.
  * reportProvidesOrderBy option should be set to true if the control is populated by a report that
  * provides its own Order By statement, if the reportProvidesOrderBy option is not set in this situation, then the report
  * will have two Order By statements and will fail.
  */
 protected static function get_control_treelocationselect($auth, $args, $tabAlias, $options)
 {
     global $indicia_templates;
     global $user;
     data_entry_helper::$helpTextPos = 'before';
     $indicia_templates['two-col-50'] = '<div class="two_columns"><div id="leftcol" class="column">{col-1}</div><div id="rightcol" class="column">{col-2}</div></div>';
     $r = "";
     if (!array_key_exists('location_type_id', $options)) {
         return "Control [tree location select] must be provided with a location_type_id.<br />";
     }
     if (!array_key_exists('tree_location_type_id', $options)) {
         return "Control [tree location select] must be provided with a tree_location_type_id.<br />";
     }
     $r .= '<span style="display:none;">' . print_r($_SERVER, true) . '</span>';
     if (isset($_SERVER['HTTP_REFERER']) && $_SERVER['HTTP_REFERER'] != '' && ($referer = self::getRefererPath()) !== false) {
         $r .= '<input name="referer" type="hidden" value="' . $referer . '" />';
     }
     $attrArgs = array('valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id'], 'fieldprefix' => 'smpAttr');
     $attrArgs['extraParams'] += array('query' => json_encode(array('in' => array('caption' => array('No Understorey Observed')))));
     $smpAttrs = data_entry_helper::getAttributes($attrArgs, false);
     if (!count($smpAttrs)) {
         throw new exception(lang::get('This form must be used with an "No Understorey Observed" sample attribute.'));
     }
     data_entry_helper::$javascript .= "\n// assume map projection is same as indicia internal\n// Create vector layers: one to display the Parent Site onto, and another for the tree locations list\n// the default edit layer is used for this sample\nvar labelRule = new OpenLayers.Rule({\n        symbolizer: {\n          label : \"\${name}\",\n          fontSize: \"16px\",\n          fontFamily: \"Verdana, Arial, Helvetica,sans-serif\",\n          fontWeight: \"bold\",\n          fontColor: \"#FF0000\",\n          labelAlign: \"cm\",\n          labelYOffset: \"-15\"\n        }\n      });\nvar defaultStyle = new OpenLayers.Style({pointRadius: 6,fillColor: \"Red\",fillOpacity: 0.3,strokeColor: \"Yellow\",strokeWidth: 1});\ndefaultStyle.addRules([labelRule]);\n\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\nTreeStyleMap = new OpenLayers.StyleMap({\"default\": defaultStyle});\nTreeListLayer = new OpenLayers.Layer.Vector('Trees',{styleMap: TreeStyleMap, displayInLayerSwitcher: false});\nvar _zoomToExtent = function(bounds, layer){\n  var dy = Math.max(10, (bounds.top-bounds.bottom) * layer.map.div.settings.maxZoomBuffer);\n  var dx = Math.max(10, (bounds.right-bounds.left) * layer.map.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 (layer.map.getZoomForExtent(bounds) > layer.map.div.settings.maxZoom) {\n    // if showing something small, don't zoom in too far\n    layer.map.setCenter(bounds.getCenterLonLat(), layer.map.div.settings.maxZoom);\n  } else {\n    // Set the default view to show something a bit larger than the size of the grid square\n    layer.map.zoomToExtent(bounds);\n  }\n};\n\$('.scPresence:checkbox').change(function(){\n  var cells = \$(this).closest('tr').find('.scOccAttrCell');\n  if(\$(this).attr('checked')){\n    cells.find('select').addClass('required').removeAttr('disabled');\n    cells.append('<span class=\"deh-required\">*</span>');\n  } else {\n    cells.find('select').removeClass('required').val('').attr('disabled',true);\n    cells.find('.deh-required').remove();\n    cells.find('label.error').remove();\n    cells.find('.error').removeClass('error');\n    cells.find('.inline-error').remove();\n    cells.find('.ui-state-error').removeClass('ui-state-error');\n  }\n});\n\$('.scPresence:checkbox').change();\nindiciaData.searchUpdatesSref=false;\n";
     data_entry_helper::$late_javascript .= "\njQuery('[name=" . str_replace(':', '\\\\:', $smpAttrs[0]['id']) . "],[name^=" . str_replace(':', '\\\\:', $smpAttrs[0]['id']) . "\\\\:]').filter(':checkbox').rules('add', {no_observation: true});\n\$.validator.addMethod('no_observation', function(arg1, arg2){\n  // ignore the hidden zeroing field asscoiated with the boolean\n  if(!\$(arg2).filter(':checkbox').length) return true;\n  var numRows = jQuery('.scPresence').filter(':checkbox').filter('[checked]').length;\n  var isChecked = jQuery(arg2).attr('checked') != false;\n  if(isChecked) return(numRows==0)\n  else if(numRows>0) return true;\n  return false;\n},\n  \"The <strong>" . lang::get('No Understorey Observed') . "</strong> checkbox must be selected if there are no species entered in the Flowering plant phenology grid, otherwise it must be unchecked.\");\n\n";
     self::$treeOccurrenceRecord = false;
     if (self::$loadedSampleId) {
         $location_id = data_entry_helper::$entity_to_load['sample:location_id'];
     } else {
         if (isset($_GET['location_id'])) {
             $location_id = $_GET['location_id'];
         } else {
             $location_id = false;
         }
     }
     $attrArgs = array('valuetable' => 'location_attribute_value', 'attrtable' => 'location_attribute', 'key' => 'location_id', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id'], 'fieldprefix' => 'locAttr', 'location_type_id' => $options['tree_location_type_id']);
     if ($location_id) {
         $attrArgs['id'] = $location_id;
     }
     $attrArgs['extraParams'] += array('query' => json_encode(array('in' => array('caption' => array('Recorder Name')))));
     $locAttrs = data_entry_helper::getAttributes($attrArgs, false);
     $attrArgs = array('valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id'], 'fieldprefix' => 'smpAttr', 'sample_method_id' => $args['sample_method_id']);
     $attrArgs['extraParams'] += array('query' => json_encode(array('in' => array('caption' => array('Recorder Name')))));
     $smpAttrs = data_entry_helper::getAttributes($attrArgs, false);
     if (!count($locAttrs)) {
         throw new exception(lang::get('This form must be used with a "Recorder Name" tree location attribute.'));
     }
     if (!count($smpAttrs)) {
         throw new exception(lang::get('This form must be used with a "Recorder Name" sample attribute.'));
     }
     data_entry_helper::$javascript .= "indiciaData.assignedRecorderAttrID='" . $locAttrs[0]['attributeId'] . "';\n";
     data_entry_helper::$javascript .= "indiciaData.recorderNameID='" . $smpAttrs[0]['id'] . "';\n";
     if ($location_id) {
         $r .= '<div class="page-notice ui-state-highlight ui-corner-all">This visit is registered against the tree highlighted on the map. All fields followed by a red asterisk (<span class="deh-required">*</span>) must be filled in. You can not modify any field that is greyed out.</div>';
         $locationRecord = data_entry_helper::get_population_data(array('table' => 'location', 'extraParams' => $auth['read'] + array('id' => $location_id, "view" => "detail"), 'nocache' => true));
         if (count($locationRecord) != 1) {
             throw new exception(lang::get('Could not identify tree location : ID ') . $location_id);
         }
         if (count($locAttrs) && count($smpAttrs)) {
             data_entry_helper::$entity_to_load[$smpAttrs[0]['fieldname']] = $locAttrs[0]['default'];
         }
         $parentLocationRecord = data_entry_helper::get_population_data(array('table' => 'location', 'extraParams' => $auth['read'] + array('id' => $locationRecord[0]['parent_id'], "view" => "detail"), 'nocache' => true));
         if (count($parentLocationRecord) != 1) {
             throw new exception(lang::get('Could not identify site location : ID ') . $locationRecord[0]['parent_id']);
         }
         // TODO make sure user is allocated this tree, or if sample already exists, that they created this sample, or they are admin
         $registrationSampleRecord = data_entry_helper::get_population_data(array('table' => 'sample', 'extraParams' => $auth['read'] + array('location_id' => $locationRecord[0]['id'], "view" => "detail", "sample_method_id" => $args['reg_sample_method_id']), 'nocache' => true));
         if (count($registrationSampleRecord) != 1) {
             throw new exception(lang::get('Could not identify registration sample for tree location ID ') . $locationRecord[0]['id']);
         }
         $registrationOccurrenceRecord = data_entry_helper::get_population_data(array('table' => 'occurrence', 'extraParams' => $auth['read'] + array('sample_id' => $registrationSampleRecord[0]['id'], "view" => "detail"), 'nocache' => true));
         if (count($registrationOccurrenceRecord) != 1) {
             throw new exception(lang::get('Could not identify registration occurrence for tree location ID ') . $locationRecord[0]['id']);
         }
         if (self::$loadedSampleId) {
             self::$treeOccurrenceRecord = data_entry_helper::get_population_data(array('table' => 'occurrence', 'extraParams' => $auth['read'] + array('sample_id' => self::$loadedSampleId, "view" => "detail", 'taxa_taxon_list_id' => $registrationOccurrenceRecord[0]['taxa_taxon_list_id']), 'nocache' => true));
         } else {
             // need to set sref & system to match tree.
             data_entry_helper::$javascript .= "\n\$('#imp-sref').val('" . $locationRecord[0]['centroid_sref'] . "');\n";
         }
         $r .= data_entry_helper::text_input(array('label' => lang::get('Site'), 'fieldname' => 'dummy:site_name', 'class' => 'control-width-4 tree-details-readonly', 'default' => $parentLocationRecord[0]["name"], 'disabled' => ' readonly="readonly"'));
         // don't need a hidden control.
         $r .= data_entry_helper::text_input(array('label' => lang::get('Tree'), 'fieldname' => 'dummy:tree_name', 'class' => 'control-width-4 tree-details-readonly', 'default' => $locationRecord[0]["name"], 'disabled' => ' readonly="readonly"'));
         $r .= '<input name="sample:location_id" type="hidden" value="' . $location_id . '" />';
         $r .= data_entry_helper::text_input(array('label' => lang::get('Tree Species'), 'fieldname' => 'dummy:tree_species', 'class' => 'control-width-4 tree-details-readonly', 'default' => $registrationOccurrenceRecord[0]["taxon"], 'disabled' => ' readonly="readonly"'));
         if (self::$treeOccurrenceRecord && count(self::$treeOccurrenceRecord)) {
             $r .= '<input name="sc:tree:' . self::$treeOccurrenceRecord[0]['id'] . ':present" type="hidden" value="' . self::$treeOccurrenceRecord[0]['taxa_taxon_list_id'] . '" />';
         } else {
             $r .= '<input name="sc:tree::present" type="hidden" value="' . $registrationOccurrenceRecord[0]['taxa_taxon_list_id'] . '" />';
         }
         if (self::$loadedSampleId) {
             $systems = array(data_entry_helper::$entity_to_load['sample:entered_sref_system'] => data_entry_helper::$entity_to_load['sample:entered_sref_system']);
         } else {
             $systems = array($locationRecord[0]['centroid_sref_system'] => $locationRecord[0]['centroid_sref_system']);
         }
         $r .= data_entry_helper::sref_and_system(array_merge(array('label' => lang::get('Tree Grid Ref'), 'systems' => $systems, 'disabled' => ' readonly="readonly"', 'validation' => '', 'class' => 'control-width-4 tree-details-readonly'), $options));
         data_entry_helper::$javascript .= "\nmapInitialisationHooks.push(function (div) {\n  'use strict';\n  \$.getJSON(ParentLocationLayer.map.div.settings.indiciaSvc + 'index.php/services/data/location/'+" . $locationRecord[0]['parent_id'] . " +\r\n            '?mode=json&view=detail' + ParentLocationLayer.map.div.settings.readAuth + '&callback=?', function(data) {\n    if (typeof data.error!=='undefined') {\n      alert(data.error);\n      return;\n    }\r\n    if (data.length>0) {\r\n      var geomwkt = data[0].boundary_geom || data[0].centroid_geom;\r\n      var parser = new OpenLayers.Format.WKT();\r\n      var feature = parser.read(geomwkt);\r\n      ParentLocationLayer.addFeatures([feature]);\n      // no zoom, but put in other trees at site - will add our name.\n      \$.getJSON(TreeListLayer.map.div.settings.indiciaSvc + 'index.php/services/data/location?parent_id='+data[0].id +\n            '&mode=json&view=detail' + TreeListLayer.map.div.settings.readAuth + '&callback=?', function(tdata) {\n        if (typeof tdata.error!=='undefined') {\n          alert(tdata.error);\n          return;\n        }\n        if (tdata.length>0) {\n          for(var i=0; i<tdata.length; i++){\n            var geomwkt = tdata[i].centroid_geom, feature;\n            var parser = new OpenLayers.Format.WKT();\n            var feature = parser.read(geomwkt);\n            feature.attributes.name = tdata[i].name;\n            TreeListLayer.addFeatures(feature);\n      }}});\r\n  }});\n  if(div.map.editLayer.features.length>0) {\n    var highlighter = new OpenLayers.Control.SelectFeature(div.map.editLayer, {highlightOnly: true});\n    div.map.addControl(highlighter);\n    highlighter.activate();\n    highlighter.highlight(div.map.editLayer.features[0]);\n  }\n});";
         if (self::$loadedSampleId) {
             data_entry_helper::$javascript .= "\n\$('[name=sample\\\\:date]').change(function(){ // sample exists so just check that no sample already taken on that date.\n  \$.getJSON(ParentLocationLayer.map.div.settings.indiciaSvc + 'index.php/services/data/sample?location_id='+" . $locationRecord[0]['id'] . " +\n      '&sample_method_id=" . $args['sample_method_id'] . "&mode=json&view=detail' + ParentLocationLayer.map.div.settings.readAuth + '&callback=?', function(data) {\n    if (typeof data.error!=='undefined') {\n      alert(data.error);\n      return;\n    }\n    var date = \$('[name=sample\\\\:date]').val();\n    date = date.split('/');\n    for(var i = 0; i < data.length; i++){\n      if(data[i][\"id\"] != " . self::$loadedSampleId . " && data[i][\"date_start\"] == date[2]+'-'+date[1]+'-'+date[0]){\n        alert(\"Warning: there is already a visit recorded for this tree on \"+data[i][\"date_start\"]);\n        return;\n    }}\n  });\n});\n";
         } else {
             data_entry_helper::$javascript .= "\n\$('[name=sample\\\\:date]').change(function(){\n  \$.getJSON(ParentLocationLayer.map.div.settings.indiciaSvc + 'index.php/services/data/sample?location_id='+" . $locationRecord[0]['id'] . " +\n  \t\t'&sample_method_id=" . $args['sample_method_id'] . "&mode=json&view=detail&orderby=date_start' + ParentLocationLayer.map.div.settings.readAuth + '&callback=?', function(data) {\n    if (typeof data.error!=='undefined') {\n      alert(data.error);\n      return;\n    }\n    var date = \$('[name=sample\\\\:date]').val();\n    date = date.split('/');\n    for(var i = 0; i < data.length; i++){\n      if(data[i][\"date_start\"] == date[2]+'-'+date[1]+'-'+date[0]) {\n        alert(\"Warning: there is already a visit recorded for this tree on \"+data[i][\"date_start\"]);\n        return;\n      }\n    }\n    for(var i = 0; i < data.length; i++){\n      sdate = data[i][\"date_start\"].split('-');\n      if(sdate[0] > date[2] || (sdate[0] == date[2] && (sdate[1] > date[1] || (sdate[1] == date[1] && sdate[2] >= date[0])))) {\n        alert(\"Warning: there is already a visit recorded for this tree after this date, on \"+data[i][\"date_start\"]);\n        break;\n      }\n    }\n    for(var i = data.length-1; i >=0; i--){\n      sdate = data[i][\"date_start\"].split('-');\n      if(sdate[0] < date[2] || (sdate[0] == date[2] && (sdate[1] < date[1] || (sdate[1] == date[1] && sdate[2] <= date[0])))) {\n        if(confirm(\"There was a previously recorded visit for this tree prior to this date, on \"+data[i][\"date_start\"]+'. Do you wish to use the data from this earlier visit as a starting point? (This will not affect any previously recorded observations - it will just fill in this form with the data from your previous visit, excluding the field diary. You can then update the data with any changes for this visit.)')){\n          // this is an initial save: all attributes have vanilla names.\n          \$('.scPresence').removeAttr('checked');\n          var cells = \$('.scOccAttrCell');\n          \$('#" . data_entry_helper::$validated_form_id . "').find('label.error').remove();\n          \$('#" . data_entry_helper::$validated_form_id . "').find('.error').removeClass('error');\n          \$('#" . data_entry_helper::$validated_form_id . "').find('.inline-error').remove();\n          \$('#" . data_entry_helper::$validated_form_id . "').find('.ui-state-error').removeClass('ui-state-error');\n          cells.find('select').removeClass('required').val('').attr('disabled',true);\n          cells.find('.deh-required').remove();\n          \$('[name^=sc\\\\:tree\\\\:\\\\:occAttr\\\\:]').val('');\n          \$.getJSON(ParentLocationLayer.map.div.settings.indiciaSvc + 'index.php/services/data/occurrence?sample_id='+data[i]['id'] +\n              '&mode=json&view=detail' + ParentLocationLayer.map.div.settings.readAuth + '&callback=?', function(odata) {\n            if (typeof odata.error!=='undefined') {\n              alert(odata.error);\n              return;\n            }\n            var occIDs = [];\n            if(odata.length>0){\n              for(var j = 0; j < odata.length; j++) {\n                occIDs.push(odata[j].id);\n                \$('.scPresence[value='+odata[j].taxa_taxon_list_id+']').each(function(idx, elem){\n                  var cells = \$(elem).attr('checked',true).closest('tr').find('.scOccAttrCell');\n                  cells.find('select').addClass('required').removeAttr('disabled');\n                  cells.append('<span class=\"deh-required\">*</span>');\n                });\n              }\n              \$.getJSON(ParentLocationLayer.map.div.settings.indiciaSvc + 'index.php/services/data/occurrence_attribute_value' +\n                  '?query={\"in\":{\"occurrence_id\":'+JSON.stringify(occIDs) +'}}' +\n                  '&mode=json&view=list' + ParentLocationLayer.map.div.settings.readAuth + '&callback=?', function(adata) {\n                if (typeof adata.error!=='undefined') {\n                  alert(adata.error);\n                  return;\n                }\n                var x = adata;\n                for(var k = 0; k < adata.length; k++){\n                  if(adata[k].id != null){\n                    for(var j = 0; j < odata.length; j++) {\n                      if(odata[j].id == adata[k].occurrence_id){\n                        \$('.scPresence[value='+odata[j].taxa_taxon_list_id+']').closest('tr').find('[name\$=\\\\:occAttr\\\\:'+adata[k]['occurrence_attribute_id']+']').val(adata[k]['raw_value']);\n                        \$('[name=sc\\\\:tree\\\\:\\\\:occAttr\\\\:'+adata[k]['occurrence_attribute_id']+']').val(adata[k]['raw_value']);\n                        break;\n              }}}}});\n          }});\n        }\n        break;\n  }}});\n});\n\n";
         }
         return $r;
     }
     $r .= '<div class="page-notice ui-state-highlight ui-corner-all">All fields followed by a red asterisk (<span class="deh-required">*</span>) must be filled in. You can not modify any field that is greyed out.</div>';
     self::$treeOccurrenceRecord = false;
     if (isset($options['extraParams'])) {
         foreach ($options['extraParams'] as $key => &$value) {
             $value = apply_user_replacements($value);
         }
         $options['extraParams'] = array_merge($auth['read'], $options['extraParams']);
     } else {
         $options['extraParams'] = array_merge($auth['read']);
     }
     if (empty($options['reportProvidesOrderBy']) || $options['reportProvidesOrderBy'] == 0) {
         $options['extraParams']['orderby'] = 'name';
     }
     // Get list of sites alocated to me, using CMS User ID.
     $site_attributes = data_entry_helper::getAttributes(array('valuetable' => 'location_attribute_value', 'attrtable' => 'location_attribute', 'key' => 'location_id', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id'], 'location_type_id' => $options['location_type_id'], 'fieldprefix' => 'locAttr'));
     if (false == ($cmsUserAttr = extract_cms_user_attr($site_attributes))) {
         return 'This form is designed to be used with the "CMS User ID" attribute setup for Site locations in the survey.';
     }
     $response = data_entry_helper::get_population_data(array('table' => 'location_attribute_value', 'extraParams' => $auth['read'] + array('view' => 'list', 'location_attribute_id' => $cmsUserAttr['attributeId'], 'raw_value' => $user->uid), 'nocache' => true));
     if (count($response) == 0) {
         throw new exception(lang::get('You have no sites, so you can not enter any phenology observations. Please create a site and some trees first.'));
     }
     $siteIDs = array();
     foreach ($response as $loc) {
         $siteIDs[] = $loc['location_id'];
     }
     $location_list_args = array_merge(array('label' => lang::get('Site'), 'view' => 'detail', 'fieldname' => 'location:parent_id', 'id' => 'imp-site-location', 'blankText' => lang::get('Please select a site.'), 'validation' => 'required', 'nocache' => true), $options);
     // $options already has the location_type_id set
     $location_list_args['extraParams']['id'] = $siteIDs;
     $r .= data_entry_helper::location_select($location_list_args);
     $location_list_args = array_merge(array('label' => lang::get('Tree'), 'view' => 'detail', 'blankText' => lang::get('Please select a tree.'), 'validation' => 'required', 'nocache' => true), $options);
     $location_list_args['extraParams']['id'] = $siteIDs;
     $location_list_args['location_type_id'] = $options['tree_location_type_id'];
     $r .= data_entry_helper::location_select($location_list_args);
     $r .= data_entry_helper::text_input(array('label' => lang::get('Tree Species'), 'fieldname' => 'dummy:tree_species', 'class' => 'control-width-4 tree-details-readonly', 'disabled' => ' readonly="readonly"', 'validation' => 'required', 'helpText' => lang::get('The following field is filled in automatically when you select a tree.')));
     $r .= '<input name="sc:tree::present" type="hidden" value="" />';
     $systems = array('4326' => lang::get("sref:4326"));
     // this will be overwriten when the tree is loaded.
     $r .= data_entry_helper::sref_and_system(array_merge(array('label' => lang::get('Tree Grid Ref'), 'systems' => $systems, 'disabled' => ' readonly="readonly"', 'validation' => '', 'class' => 'tree-details-readonly', 'helpText' => lang::get('The following field is filled in automatically when you select a tree.')), $options));
     data_entry_helper::$javascript .= "\r\n\$('#imp-site-location').change(function() {\n  \$('#" . data_entry_helper::$validated_form_id . "').find('label.error').remove();\n  \$('#" . data_entry_helper::$validated_form_id . "').find('.error').removeClass('error');\n  \$('#" . data_entry_helper::$validated_form_id . "').find('.inline-error').remove();\n  \$('#" . data_entry_helper::$validated_form_id . "').find('.ui-state-error').removeClass('ui-state-error');\n  ParentLocationLayer.destroyFeatures();\r\n  TreeListLayer.destroyFeatures();\n  var intValue = parseInt(\$(this).val());\r\n  if (!isNaN(intValue)) {\n    \$(this).find('option[value=]').attr('disabled',true);\n    // site list has been populated with correct location_type_ids.\r\n    \$.getJSON(ParentLocationLayer.map.div.settings.indiciaSvc + 'index.php/services/data/location/'+\$(this).val() +\r\n              '?mode=json&view=detail' + ParentLocationLayer.map.div.settings.readAuth + '&callback=?', function(data) {\r\n      if (typeof data.error!=='undefined') {\n        alert(data.error);\n        return;\n      }\n      if (data.length>0) {\r\n        var geomwkt = data[0].boundary_geom || data[0].centroid_geom;\n        // assume single geometry - not a collection, and default style\n        var parser = new OpenLayers.Format.WKT();\n        var feature = parser.read(geomwkt);\n        ParentLocationLayer.addFeatures([feature]);\n        _zoomToExtent(feature.geometry.getBounds(), ParentLocationLayer);\n        \$('#imp-location option[value!=]').not(':selected').remove();\n        \$.getJSON(TreeListLayer.map.div.settings.indiciaSvc + 'index.php/services/data/location?parent_id='+data[0].id +\n              '&mode=json&view=detail' + TreeListLayer.map.div.settings.readAuth + '&callback=?', function(tdata) {\n          if (typeof tdata.error!=='undefined') {\n            alert(tdata.error);\n            return;\n          }\n          if (tdata.length>0) {\n            var features = [], found=false;\n            var bounds = ParentLocationLayer.features[0].geometry.getBounds();\n            for(var i=0; i<tdata.length; i++){\n              var geomwkt = tdata[i].centroid_geom, feature;\n              var parser = new OpenLayers.Format.WKT();\n              var feature = parser.read(geomwkt);\n              feature.attributes.name = tdata[i].name;\n              features.push(feature);\n              bounds.extend(feature.geometry.getBounds());\n              if(\$('#imp-location option[value='+tdata[i].id+']').length == 0)\n                \$('#imp-location').append('<option value=\"'+tdata[i].id+'\">'+tdata[i].name+'</option>');\n              else found=true;\n            }\n            if(!found){ // currently selected tree no longer on this site. Deselect it.\n              \$(this).find('option[value=]').removeAttr('disabled');\n              \$('#imp-location option[value!=]:selected').remove();\n              \$('#imp-location,#imp-sref').val('');\n              TreeListLayer.map.editLayer.destroyFeatures();\n              \$('[name=dummy\\\\:tree_species]').val('');\n            }\n            TreeListLayer.addFeatures(features);\n            _zoomToExtent(bounds, ParentLocationLayer);\n        }});\r\n    }});\n}});\nmapLocationSelectedHooks.push(function(div, data){\n  \$('#" . data_entry_helper::$validated_form_id . "').find('label.error').remove();\n  \$('#" . data_entry_helper::$validated_form_id . "').find('.error').removeClass('error');\n  \$('#" . data_entry_helper::$validated_form_id . "').find('.inline-error').remove();\n  \$('#" . data_entry_helper::$validated_form_id . "').find('.ui-state-error').removeClass('ui-state-error');\n  if(\$('#imp-site-location').val() != data[0].parent_id) {\n    \$('#imp-site-location').val(data[0].parent_id).change();\n    \$('#imp-site-location option[value=]').attr('disabled',true);\n  }\n  if(data[0].parent_id != ''){\n    \$('#imp-location option[value=]').attr('disabled',true);\n  }\n  \$('#'+indiciaData.recorderNameID.replace(/:/g,'\\\\:')).val('');\n  \$.getJSON(ParentLocationLayer.map.div.settings.indiciaSvc + 'index.php/services/data/location_attribute_value?location_id='+data[0]['id'] +\n      '&mode=json&view=list' + ParentLocationLayer.map.div.settings.readAuth + '&callback=?', function(data) {\n    if(data instanceof Array && data.length>0){\n      for (var i=0;i<data.length;i++){\n        if (data[i]['location_attribute_id'] == indiciaData.assignedRecorderAttrID)\n          \$('#'+indiciaData.recorderNameID.replace(/:/g,'\\\\:')).val(data[i].raw_value);\n      }\n  }});\n  // get registration sample and occurrence and fill in species.\n  \$.getJSON(ParentLocationLayer.map.div.settings.indiciaSvc + 'index.php/services/data/sample?location_id='+data[0]['id'] +\n      '&sample_method_id=" . $args['reg_sample_method_id'] . "&mode=json&view=detail' + ParentLocationLayer.map.div.settings.readAuth + '&callback=?', function(data) {\n    if (typeof data.error!=='undefined') {\n      alert(data.error);\n      return;\n    }\n    if(data.length){\n      \$.getJSON(ParentLocationLayer.map.div.settings.indiciaSvc + 'index.php/services/data/occurrence?sample_id='+data[0]['id'] +\n          '&mode=json&view=detail' + ParentLocationLayer.map.div.settings.readAuth + '&callback=?', function(data) {\n        if (typeof data.error!=='undefined') {\n          alert(data.error);\n          return;\n        }\n        if(data.length){\n          \$('[name=dummy\\\\:tree_species]').val(data[0].taxon);\n          \$('[name=sc\\\\:tree\\\\:\\\\:present]').val(data[0].taxa_taxon_list_id);\n      }});\n  }});\n});\n\$('[name=sample\\\\:date]').change(function(){\n  if(\$('#imp-location').val()=='') return;\n  \$.getJSON(ParentLocationLayer.map.div.settings.indiciaSvc + 'index.php/services/data/sample?location_id='+\$('#imp-location').val() +\n  \t\t'&sample_method_id=" . $args['sample_method_id'] . "&mode=json&view=detail&orderby=date_start' + ParentLocationLayer.map.div.settings.readAuth + '&callback=?', function(data) {\n    if (typeof data.error!=='undefined') {\n      alert(data.error);\n      return;\n    }\n    var date = \$('[name=sample\\\\:date]').val();\n    date = date.split('/');\n    for(var i = 0; i < data.length; i++){\n      if(data[i][\"date_start\"] == date[2]+'-'+date[1]+'-'+date[0]) {\n        alert(\"Warning: there is already a visit recorded for this tree on \"+data[i][\"date_start\"]);\n        return;\n      }\n    }\n    for(var i = 0; i < data.length; i++){\n      sdate = data[i][\"date_start\"].split('-');\n      if(sdate[0] > date[2] || (sdate[0] == date[2] && (sdate[1] > date[1] || (sdate[1] == date[1] && sdate[2] >= date[0])))) {\n        alert(\"Warning: there is already a visit recorded for this tree after this date, on \"+data[i][\"date_start\"]);\n        break;\n      }\n    }\n    for(var i = data.length-1; i >=0; i--){\n      sdate = data[i][\"date_start\"].split('-');\n      if(sdate[0] < date[2] || (sdate[0] == date[2] && (sdate[1] < date[1] || (sdate[1] == date[1] && sdate[2] <= date[0])))) {\n        if(confirm(\"There was a previously recorded visit for this tree prior to this date, on \"+data[i][\"date_start\"]+'. Do you wish to use the data from this earlier visit as a starting point? (This will not affect any previously recorded observations - it will just fill in this form with the data from your previous visit, excluding the field diary. You can then update the data with any changes for this visit.)')){\n          // this is an initial save: all attributes have vanilla names.\n          // TODO sample attributes\n          \$('.scPresence').removeAttr('checked');\n          var cells = \$('.scOccAttrCell');\n          cells.find('select').removeClass('required').val('').attr('disabled',true);\n          cells.find('.deh-required').remove();\n          \$('#" . data_entry_helper::$validated_form_id . "').find('label.error').remove();\n          \$('#" . data_entry_helper::$validated_form_id . "').find('.error').removeClass('error');\n          \$('#" . data_entry_helper::$validated_form_id . "').find('.inline-error').remove();\n          \$('#" . data_entry_helper::$validated_form_id . "').find('.ui-state-error').removeClass('ui-state-error');\n          \$('[name^=sc\\\\:tree\\\\:\\\\:occAttr\\\\:]').val('');\n          \$.getJSON(ParentLocationLayer.map.div.settings.indiciaSvc + 'index.php/services/data/occurrence?sample_id='+data[i]['id'] +\n              '&mode=json&view=detail' + ParentLocationLayer.map.div.settings.readAuth + '&callback=?', function(odata) {\n            if (typeof odata.error!=='undefined') {\n              alert(odata.error);\n              return;\n            }\n            var occIDs = [];\n            if(odata.length>0){\n              for(var j = 0; j < odata.length; j++) {\n                occIDs.push(odata[j].id);\n                \$('.scPresence[value='+odata[j].taxa_taxon_list_id+']').each(function(idx, elem){\n                  var cells = \$(elem).attr('checked',true).closest('tr').find('.scOccAttrCell');\n                  cells.find('select').addClass('required').removeAttr('disabled');\n                  cells.append('<span class=\"deh-required\">*</span>');\n                });\n              }\n              \$.getJSON(ParentLocationLayer.map.div.settings.indiciaSvc + 'index.php/services/data/occurrence_attribute_value' +\n                  '?query={\"in\":{\"occurrence_id\":'+JSON.stringify(occIDs) +'}}' +\n                  '&mode=json&view=list' + ParentLocationLayer.map.div.settings.readAuth + '&callback=?', function(adata) {\n                if (typeof adata.error!=='undefined') {\n                  alert(adata.error);\n                  return;\n                }\n                var x = adata;\n                for(var k = 0; k < adata.length; k++){\n                  if(adata[k].id != null){\n                    for(var j = 0; j < odata.length; j++) {\n                      if(odata[j].id == adata[k].occurrence_id){\n                        \$('.scPresence[value='+odata[j].taxa_taxon_list_id+']').closest('tr').find('[name\$=\\\\:occAttr\\\\:'+adata[k]['occurrence_attribute_id']+']').val(adata[k]['raw_value']);\n                        \$('[name=sc\\\\:tree\\\\:\\\\:occAttr\\\\:'+adata[k]['occurrence_attribute_id']+']').val(adata[k]['raw_value']);\n                        break;\n              }}}}});\n          }});\n        }\n        break;\n  }}});\n});\n\n";
     return $r;
 }
예제 #15
0
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<html>
<head>
<title>Map helper test</title>
<link rel="stylesheet" href="demo.css" type="text/css" media="screen">
<link rel="stylesheet" href="../../media/css/default_site.css" type="text/css" media="screen">
</head>
<body>
<div id="wrap">
<h1>Data Entry Helper Map</h1>
<?php 
include '../../client_helpers/data_entry_helper.php';
require 'data_entry_config.php';
$readAuth = data_entry_helper::get_read_auth($config['website_id'], $config['password']);
echo data_entry_helper::sref_and_system(array('label' => 'Spatial Reference'));
echo data_entry_helper::location_select(array('label' => 'Select a known place', 'extraParams' => $readAuth));
echo data_entry_helper::georeference_lookup(array('label' => 'Search for place'));
echo data_entry_helper::postcode_textbox(array('label' => 'Enter postcode', 'hiddenFields' => false, 'fieldname' => 'sample:location_name'));
echo data_entry_helper::map_panel(array('readAuth' => $readAuth));
/*
If you have a GeoServer instance set up and running with your Indicia data as a data source, you can add WMS layers
to the map_panel. In this example the GeoServer instance has a feature type setup to point to the grids_osgb_100k table 
as well as a second one setup to point to the samples table. The namespace the feature types are in is called indicia.
echo data_entry_helper::map_panel(array(
    'readAuth' => $readAuth,
    'indiciaWMSLayers' => array('indicia:grids_osgb_100k', 'indicia:samples')
));
*/
echo data_entry_helper::dump_javascript();
?>
</div>