protected static function get_control_species($auth, $args, $tabAlias, $options)
 {
     data_entry_helper::$onload_javascript .= "indiciaFns.bindTabsActivate(\$(\$('#{$tabAlias}').parent()), function(event, ui) {\r\n      panel = typeof ui.newPanel==='undefined' ? ui.panel : ui.newPanel[0];\r\n      if (panel.id==='{$tabAlias}') { setSectionDropDown(); }\r\n    });\n";
     // we need a place to store the subsites, to save loading from the db on submission
     $r = '<input type="hidden" name="subsites" id="subsites" value="" />';
     // plus hiddens to store the main sample's sref info
     $r .= data_entry_helper::hidden_text(array('fieldname' => 'sample:entered_sref', 'id' => 'imp-sref'));
     $r .= data_entry_helper::hidden_text(array('fieldname' => 'sample:entered_sref_system', 'id' => 'imp-sref-system'));
     $r .= data_entry_helper::hidden_text(array('fieldname' => 'sample:geom', 'id' => 'imp-geom'));
     // plus the sample method ids
     $sampleMethods = helper_base::get_termlist_terms($auth, 'indicia:sample_methods', array('Transect', 'Transect Section'));
     $r .= '<input type="hidden" name="sample:sample_method_id" value="' . $sampleMethods[0]['id'] . '" />';
     $r .= '<input type="hidden" name="subsample:sample_method_id" value="' . $sampleMethods[1]['id'] . '" />';
     // This option forces the grid to load all child sample occurrences, though we will ignore the hidden SampleIDX column and instead
     // use the section column to bind to samples
     $options['speciesControlToUseSubSamples'] = true;
     $r .= parent::get_control_species($auth, $args, $tabAlias, $options);
     // build an array of existing sub sample IDs, keyed by subsite location Id.
     $subSampleIds = array();
     if (isset(data_entry_helper::$entity_to_load)) {
         foreach (data_entry_helper::$entity_to_load as $key => $value) {
             if (preg_match('/^sc:(\\d+):(\\d+):sample:id$/', $key, $matches)) {
                 $subSampleIds[data_entry_helper::$entity_to_load["sc:{$matches['1']}:{$matches['2']}:sample:location_id"]] = $value;
             }
         }
     }
     $r .= '<input type="hidden" name="subSampleIds" value="' . htmlspecialchars(json_encode($subSampleIds)) . '" />';
     return $r;
 }
 protected static function getGrid($args, $node, $auth)
 {
     $r = call_user_func(array(self::$called_class, 'getHeaderHTML'), $args);
     $r .= parent::getGrid($args, $node, $auth);
     $r .= call_user_func(array(self::$called_class, 'getTrailerHTML'), $args);
     return $r;
 }
 /**
  * Get the list of parameters for this form.
  * @return array List of parameters that this form requires.
  */
 public static function get_parameters()
 {
     $r = array_merge(parent::get_parameters(), array(array('fieldname' => 'season_start', 'label' => 'Season Start', 'helpText' => 'Date which always falls in the first week of the recording season, in ddmm format.', 'type' => 'text_input', 'default' => '2803', 'group' => 'Weekly Counts'), array('fieldname' => 'weekday', 'label' => 'Start week on ', 'helpText' => 'Day of week that the recording week starts on.', 'type' => 'select', 'default' => 'Monday', 'options' => array('Sunday' => lang::get('Sunday'), 'Monday' => lang::get('Monday'), 'Tuesday' => lang::get('Tuesday'), 'Wednesday' => lang::get('Wednesday'), 'Thursday' => lang::get('Thursday'), 'Friday' => lang::get('Friday'), 'Saturday' => lang::get('Saturday')), 'group' => 'Weekly Counts'), array('fieldname' => 'weeks', 'label' => 'Weeks', 'helpText' => 'Number of weeks in the recording season.', 'type' => 'text_input', 'default' => '26', 'group' => 'Weekly Counts'), array('fieldname' => 'headings', 'label' => 'Grid heading row formats', 'helpText' => 'Formats for each grid heading row. Specify a comma separated list of format specifiers, one per heading row required. ' . 'A format specifier can contain "week" to output the week number, "start" followed by a PHP date format character to output the date or part of the ' . 'date at the start of the week, or "end" followed by a date format character to output the date or part of the date at the end of the week. Values are ' . 'automatically only output when there is a change from the previous column.', 'type' => 'text_input', 'default' => 'week,startY,startM,startd-endd', 'group' => 'Weekly Counts')));
     foreach ($r as $idx => $param) {
         if ($param['fieldname'] === 'extra_list_id') {
             unset($r[$idx]);
         }
     }
     return $r;
 }
 /**
  * Get the list of parameters for this form.
  * @return array List of parameters that this form requires.
  */
 public static function get_parameters()
 {
     $parentVal = parent::get_parameters();
     $retVal = array();
     foreach ($parentVal as $param) {
         if ($param['name'] == 'structure') {
             $param['default'] = "=About the visit=\r\n" . "?Before inputting your data, please tell us who you are, confirm the date of the visit and which farm you visited.?\r\n" . "[recorder names]\r\n" . "@validation=required\r\n" . "[date]\r\n" . "@default=09/06/2013\r\n" . "@helpText=Click in this box to select the date if it was not Open Farm Sunday.\r\n" . "[place search]\r\n" . "@fieldname=sample:location_name\r\n" . "@validation=required\r\n" . "@helpText=Type in the farm name or grid reference to search for\r\n" . "[farm]\r\n" . "[spatial reference]\r\n" . "@helpText=If you know the exact grid reference then please type it in here, or you can click on the map where you did the survey to set your exact location.\r\n" . "[map]\r\n" . "[*]\r\n" . "=Crop Habitat=\r\n" . "[*]\r\n" . "=Tallies=\r\n" . "[species]\r\n" . "[species attributes]\r\n" . "[sample comment]\r\n" . "[*]\r\n" . "=*=\r\n";
         }
         if ($param['name'] != 'remembered' && $param['name'] != 'extra_list_id') {
             $retVal[] = $param;
         }
     }
     return $retVal;
 }
 /**
  * Returns the species checklist input control.
  * @param array $auth Read authorisation tokens
  * @param array $args Form configuration
  * @param array $options additional options for the control, e.g. those configured in the form structure.
  * @return HTML for the species_checklist control.
  */
 protected static function get_control_species($auth, $args, $tabAlias, $options)
 {
     $options['subSamplePerRow'] = true;
     $options['speciesControlToUseSubSamples'] = true;
     $r = parent::get_control_species($auth, $args, $tabAlias, $options);
     return $r;
 }
 protected static function get_form_html($args, $auth, $attributes)
 {
     // @todo Process the available data to load subsamples (habitats) and associated records correctly.
     // toggle the checkboxes to after the label to match the form.
     global $indicia_templates;
     drupal_add_library('system', 'ui.tooltip', true);
     $indicia_templates['check_or_radio_group_item'] = '<li><label for="{itemId}">{caption}</label><input type="{type}" name="{fieldname}" id="{itemId}" value="{value}"{class}{checked}{title} {disabled}/></li>';
     // Create an array of custom attributes keyed by caption for easy lookup later
     foreach ($attributes as $attr) {
         self::$attrsByCaption[strtolower($attr['caption'])] = $attr;
     }
     // Build a list of the habitat-level attributes as well.
     $attributeOpts = array('valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'fieldprefix' => 'smpAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id'], 'sample_method_id' => $args['habitat_sample_method_id']);
     $habitatAttributes = data_entry_helper::getAttributes($attributeOpts, false);
     foreach ($habitatAttributes as $attr) {
         self::$habitatAttrsByCaption[strtolower($attr['caption'])] = $attr;
     }
     // load the habitat attribute values, if we have an existing sample
     if (!empty(self::$loadedSampleId)) {
         self::load_existing(self::$loadedSampleId, $auth);
     } else {
         data_entry_helper::$javascript .= "indiciaData.existingSubsampleData=[];\n";
     }
     // output some attribute info we can use for validation & business logic
     data_entry_helper::$javascript .= "indiciaData.depthMinLimitAttrNames = " . json_encode(array(self::$attrsByCaption['depth shallow bsl']['fieldname'], self::$attrsByCaption['depth shallow bcd']['fieldname'])) . ";\n";
     data_entry_helper::$javascript .= "indiciaData.depthMaxLimitAttrNames = " . json_encode(array(self::$attrsByCaption['depth deepest bsl']['fieldname'], self::$attrsByCaption['depth deepest bcd']['fieldname'])) . ";\n";
     data_entry_helper::$javascript .= "indiciaData.driftAttrId = " . self::$attrsByCaption['drift dive?']['attributeId'] . ";\n";
     data_entry_helper::$javascript .= "indiciaData.depthCDAttrName = '" . self::$attrsByCaption['tidal correction to chart datum']['fieldname'] . "';\n";
     data_entry_helper::$javascript .= "indiciaData.habitatMinDepthSLAttrId = " . self::$habitatAttrsByCaption['upper depth from sea level']['attributeId'] . ";\n";
     data_entry_helper::$javascript .= "indiciaData.habitatMaxDepthSLAttrId = " . self::$habitatAttrsByCaption['lower depth from sea level']['attributeId'] . ";\n";
     data_entry_helper::$javascript .= "indiciaData.habitatMinDepthCDAttrId = " . self::$habitatAttrsByCaption['upper depth from chart datum']['attributeId'] . ";\n";
     data_entry_helper::$javascript .= "indiciaData.habitatMaxDepthCDAttrId = " . self::$habitatAttrsByCaption['lower depth from chart datum']['attributeId'] . ";\n";
     return parent::get_form_html($args, $auth, $attributes);
 }
 /**
  * Load the list of occurrence attributes into a static variable. 
  *
  * By maintaining a single list of attributes we can track which have already been output.
  * @param array $readAuth Read authorisation tokens.
  * @param integer $surveyId ID of the survey to load occurrence attributes for.
  */
 protected static function load_custom_occattrs($readAuth, $surveyId)
 {
     if (!isset(self::$occAttrs)) {
         // Add any dynamically generated controls
         $attrArgs = array('valuetable' => 'occurrence_attribute_value', 'attrtable' => 'occurrence_attribute', 'key' => 'occurrence_id', 'fieldprefix' => 'occAttr', 'extraParams' => $readAuth, 'survey_id' => $surveyId);
         if (count(self::$occurrenceIds) == 1) {
             // if we have a single occurrence Id to load, use it to get attribute values
             $attrArgs['id'] = self::$occurrenceIds[0];
         }
         self::$occAttrs = data_entry_helper::getAttributes($attrArgs, false);
     }
 }
 protected static function get_control_map($auth, $args, $tabAlias, $options)
 {
     $file = data_entry_helper::$js_path . strtolower("drivers/sref/4326.js");
     // dynamically build a resource to link us to the handler js file.
     data_entry_helper::$required_resources[] = 'sref_handlers_4326';
     data_entry_helper::$resource_list['sref_handlers_4326'] = array('javascript' => array($file));
     $options['gridRefHint'] = true;
     $options['clickForSpatialRef'] = false;
     return parent::get_control_map($auth, $args, $tabAlias, $options);
 }
 public static function get_form($args, $node)
 {
     //Don't use a submit button, as we are saving after each stage of the wizard, so just save on every Next button click. Use additional wizard page at the end as a
     //finish confirmation page, this doesn't need submitting.
     data_entry_helper::$javascript .= "\$('#tab-submit').hide();\n";
     data_entry_helper::$javascript .= 'indiciaData.nid = "' . $node->nid . "\";\n";
     //Use ajax saving so that we can save without full page reload on a lot of pages.
     data_entry_helper::$javascript .= 'indiciaData.ajaxUrl="' . url('iform/ajax/dynamic_progressive_seasearch_survey') . "\";\n";
     $paramsSeparator = variable_get('clean_url', 0) ? '?' : '&';
     data_entry_helper::$javascript .= "indiciaData.paramsSeparator='" . $paramsSeparator . "';\n";
     if (empty($args['in_progress_sample_attr_id'])) {
         drupal_set_message('Please fill in the edit tab option for the In-Progress Sample attribute id');
         return false;
     }
     if (empty($args['gpx_data_attr_id'])) {
         drupal_set_message('Please fill in the edit tab option for the GPX Data attribute id');
         return false;
     }
     if (empty($args['habitat_smpAttr_cluster_ids'])) {
         drupal_set_message('Please fill in the option for the Habitat Sample Attribute Cluster');
         return false;
     }
     if (empty($args['dive_duration_attr_id'])) {
         drupal_set_message('Please fill in the option for the Dive Duration attribute id');
         return false;
     }
     if (empty($args['dive_start_time_attr_id'])) {
         drupal_set_message('Please fill in the option for the Dive Start Time attribute id');
         return false;
     }
     if (empty($args['exif_date_time_attr_id'])) {
         drupal_set_message('Please fill in the option for the Exif Date Times attribute id');
         return false;
     }
     //Hidden and displayed using jQuery
     $r = '<div id="loading">
 <br>
 <br>
 <br>
 <h3>Preparing page...</h3>
 <br>
 <br>
 <br>
 </div>';
     //Hide the attribute that holds whether a sample is in progress or not
     //Also need to hide the label associated with the attribute.
     data_entry_helper::$javascript .= "\n    \$('#smpAttr\\\\:" . $args['in_progress_sample_attr_id'] . "').hide();\n\n    \$('[for=smpAttr\\\\:" . $args['in_progress_sample_attr_id'] . "]').hide();";
     //Same with attribute that holds GPX data
     data_entry_helper::$javascript .= "\n    \$('#smpAttr\\\\:" . $args['gpx_data_attr_id'] . "').hide();\n\n    \$('[for=smpAttr\\\\:" . $args['gpx_data_attr_id'] . "]').hide();";
     //etc
     data_entry_helper::$javascript .= "\n    \$('#smpAttr\\\\:" . $args['exif_date_time_attr_id'] . "').hide();\n\n    \$('[for=smpAttr\\\\:" . $args['exif_date_time_attr_id'] . "]').hide();";
     //Clean up the occurrences tab, remove unused images column on the bottom grid
     //Also remove the name of the Add photos column on main grid as the column is empty is edit mode, and obvious what it is in add mode.
     data_entry_helper::$javascript .= "\n    \$('#first-level-smp-occ-grid-images-0').remove();\n\n    \$('#third-level-smp-occ-grid-images-0').text('');";
     // A jquery selector for the element which must be at the top of the page when moving to the next page. Could be the progress bar or the
     // tabbed div itself.
     if (isset($options['progressBar']) && $options['progressBar'] == true) {
         data_entry_helper::$javascript .= "indiciaData.topSelector=" . "'.wiz-prog'" . ";";
     } else {
         data_entry_helper::$javascript .= "indiciaData.topSelector=" . "'#controls'" . ";";
     }
     $options['progressBar'] = true;
     //Safer to still initialise $getSampleId if there is no sample_id in the $_GET, avoid an error
     if (!empty($_GET['sample_id'])) {
         $getSampleId = $_GET['sample_id'];
     } else {
         $getSampleId = '';
     }
     //When reloading a tab, then we need to move to the next tab
     if (!empty($_GET['load_tab'])) {
         data_entry_helper::$javascript .= "indiciaData.tabToReloadTo=" . $_GET['load_tab'] . ";";
     } else {
         data_entry_helper::$javascript .= "indiciaData.tabToReloadTo=0;";
     }
     //Need a jquery selector when referencing the in-progress sample attribute.
     data_entry_helper::$javascript .= "indiciaData.inProgressAttrSelector='#smpAttr\\\\:" . $args['in_progress_sample_attr_id'] . "';";
     //Need the number of the occurrences tab, so we can hide the Add Photos button in the species grid.
     data_entry_helper::$javascript .= "\n    indiciaData.reloadtabs=[0,4,5,6];\n    indiciaData.occTabIdx=6;\n";
     if (!empty($args['gps_sync_warning'])) {
         data_entry_helper::$javascript .= "indiciaData.gpsSyncWarning=\"" . $args['gps_sync_warning'] . "\";";
     }
     //If option is supplied, warn the user that the GPS device and camera need to be synchronised before they upload GPX file.
     //Also when the screen loads, if there is a "In Progress" attribute (which there should be) and it is not set explicitely as not
     //In Progress, then it must be in progress, so set the attribute to 1.
     data_entry_helper::$javascript .= "\n    \$(window).load(function () {\n      if (indiciaData.gpsSyncWarning) {\n        \$('#file_upload').click(function() {\n            var r = confirm(indiciaData.gpsSyncWarning);\n            if (r != true) {\n              return false;\n            }\n        });\n      }\n      if (\$(indiciaData.inProgressAttrSelector).length && \$(indiciaData.inProgressAttrSelector).val()!=='0') {\n        \$(indiciaData.inProgressAttrSelector).val(1);\n      }\n      indiciaData.getSampleId = '{$getSampleId}';";
     if (!empty($args['no_photos_with_date_warning'])) {
         self::no_photos_with_date_warning($args);
     }
     if (!empty($args['dive_start_outside_one_hour_warning'])) {
         self::dive_start_outside_one_hour_warning($args);
     }
     data_entry_helper::$javascript .= "    \n    });";
     drupal_add_js(drupal_get_path('module', 'iform') . '/media/js/jquery.form.js', 'module');
     data_entry_helper::add_resource('jquery_form');
     return $r . parent::get_form($args, $node);
 }
 /**
  * Override function to add hidden attribute to store linked sample id
  * When adding a survey 1 record this is given the value 0
  * When adding a survey 2 record this is given the sample_id of the corresponding survey 1 record.
  * @param type $args
  * @param type $auth
  * @param type $attributes
  * @return string The hidden inputs that are added to the start of the form
  */
 protected static function getFirstTabAdditionalContent($args, $auth, &$attributes)
 {
     $r = parent::getFirstTabAdditionalContent($args, $auth, $attributes);
     $linkAttr = 'smpAttr:' . $args['survey_1_attr'];
     if (array_key_exists('new', $_GET)) {
         if (array_key_exists('sample_id', $_GET)) {
             // Adding a survey 2 record
             $r .= '<input id="' . $linkAttr . '" type="hidden" name="' . $linkAttr . '" value="' . $_GET['sample_id'] . '"/>' . PHP_EOL;
         } else {
             // Adding a survey 1 record
             $r .= '<input id="' . $linkAttr . '" type="hidden" name="' . $linkAttr . '" value="0"/>' . PHP_EOL;
         }
     }
     return $r;
 }
 public static function get_form($args, $node, $response = null)
 {
     if (is_array($response)) {
         // we have got here via a post that has not been redirected.
         data_entry_helper::$javascript .= "\njQuery('div.field-name-body').remove();\n";
         return '<p>' . lang::get('Your phenology observation has been saved.') . '<p>' . '<p>' . lang::get('The creation of this observation was instigated after adding or modifying a tree, which was done in another tab or window - you may now close this browser tab, should you wish.') . '</p>' . '<a href="JavaScript:window.close()"><input type="button" class="indicia-button" name="close" value="' . lang::get('Close Tab') . '" /></a>';
     }
     return parent::get_form($args, $node, $response);
 }
 /**
  * Returns the species checklist input control setup so that there is one subsample for each tree on the grid.
  * @param array $auth Read authorisation tokens
  * @param array $args Form configuration
  * @param array $options additional options for the control, e.g. those configured in the form structure.
  * @return HTML for the species_checklist control.
  */
 protected static function get_control_species($auth, $args, $tabAlias, $options)
 {
     $options['subSamplePerRow'] = true;
     $options['speciesControlToUseSubSamples'] = true;
     //When the user enters trees onto the species, then we automatically plot them onto the map.
     //The is done on load (in edit mode) and onChange
     data_entry_helper::$javascript .= "\n    mapInitialisationHooks.push(function (div) {\n      var i, featureToRemove;\n      var defaultStyle = new OpenLayers.Style({\n        'pointRadius': 30,\n        'graphicWidth': 16,\n        'graphicHeight': 16,\n        'graphicOpacity': 0.8,\n        'fillOpacity': 0,\n        'strokeColor': 'green',\n        'strokeOpacity': 1,\n        'strokeWidth': 2,\n      });\n      var s = new OpenLayers.StyleMap({\n        'default': defaultStyle, \n      });\n      //Array to store tree feature id associated with each tree grid ref cell, if this cell changes then we\n      //can change the feature as required\n      var treeFeaturesStore=[];\n      indiciaData.mapdiv = div;\n      treeLayer = new OpenLayers.Layer.Vector('Tree Layer', {styleMap: s});\n      indiciaData.mapdiv.map.addLayer(treeLayer); \n      //Load tree features in edit mode\n      \$(document).ready(function () {\n        \$('[class^=\"scGridRef\"]').each(function () {\n          if (\$(this).val()) {\n            draw_tree_to_map(\$(this).val(), \$(this).attr('id'), treeFeaturesStore);\n          }\n        });\n      });\n      \n      \$('[class^=\"scGridRef\"]').live('change',function () {\n        //Remove old tree when change is made.\n        //Cycle through the array of existing plotted trees, remove it if we find a match (match using id of the onscreen spatial referene text field)\n        for (i=0; i<treeFeaturesStore.length; i++) {\n          if (treeFeaturesStore[i][0]==\$(this).attr('id')) {\n            featureToRemove = treeLayer.getFeatureById(treeFeaturesStore[i][1]);\n            treeLayer.removeFeatures(featureToRemove);\n          }\n        }\n        if (\$(this).val()) {\n          draw_tree_to_map(\$(this).val(), \$(this).attr('id'), treeFeaturesStore);\n        }\n      });\n    });";
     //bng = British Nation Grid - Trees only support this spatial reference system
     data_entry_helper::$javascript .= "\n    function draw_tree_to_map(bng_ref, fieldId, treeFeaturesStore) {\n      var refString = \"'\" + bng_ref + \"'\";\n      \$.getJSON(\"" . data_entry_helper::$base_url . "/index.php/services/spatial/sref_to_wkt\"+\n        \"?sref=\" + bng_ref +\n        \"&system=\" + \"OSGB\" +\n        \"&callback=?\", \n        function(data) {\n          //Ignore errors as our regex spatial reference checker already handles this and we don't want to warn user twice\n          if(typeof data.error == 'undefined') {\n            var attributes = {name: 'tree_map'};\n            var polygon=OpenLayers.Geometry.fromWKT(data.wkt);\n            if (indiciaData.mapdiv.map.projection.getCode() != indiciaData.mapdiv.indiciaProjection.getCode()) {\n              polygon.transform(indiciaData.mapdiv.indiciaProjection, indiciaData.mapdiv.map.projection);\n            }\n            var feature = new OpenLayers.Feature.Vector(polygon, attributes);\n            treeLayer.addFeatures([feature]);\n            //Store the feature against the tree field id, so we can remove it when the value is changed\n            treeFeaturesStore.push([fieldId, feature.id]);\n          }\n        }\n      );\n    }";
     $r = parent::get_control_species($auth, $args, $tabAlias, $options);
     return $r;
 }