public static function mnhnl_reptiles_species_checklist()
 {
     global $indicia_templates;
     $options = data_entry_helper::check_arguments(func_get_args(), array('listId', 'occAttrs', 'readAuth', 'extraParams', 'lookupListId'));
     $options = data_entry_helper::get_species_checklist_options($options);
     data_entry_helper::add_resource('json');
     data_entry_helper::add_resource('autocomplete');
     $occAttrControls = array();
     $occAttrs = array();
     // Load any existing sample's occurrence data into $entity_to_load
     $subSamples = array();
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         data_entry_helper::preload_species_checklist_occurrences(data_entry_helper::$entity_to_load['sample:id'], $options['readAuth'], false, array(), $subSamples, false);
     }
     // load the full list of species for the grid, including the main checklist plus any additional species in the reloaded occurrences.
     $options['extraParams']['view'] = 'detail';
     $occList = self::get_species_checklist_occ_list($options);
     // If we managed to read the species list data we can proceed
     if (!array_key_exists('error', $occList)) {
         $attributes = data_entry_helper::getAttributes(array('id' => null, 'valuetable' => 'occurrence_attribute_value', 'attrtable' => 'occurrence_attribute', 'key' => 'occurrence_id', 'fieldprefix' => "{fieldname}", 'extraParams' => $options['readAuth'], 'survey_id' => array_key_exists('survey_id', $options) ? $options['survey_id'] : null));
         // Get the attribute and control information required to build the custom occurrence attribute columns
         data_entry_helper::species_checklist_prepare_attributes($options, $attributes, $occAttrControls, $occAttrs);
         $grid = "<p>" . lang::get('LANG_SpeciesInstructions') . "</p>\n";
         if (isset($options['lookupListId'])) {
             $grid .= self::get_species_checklist_clonable_row($options, $occAttrControls, $attributes);
         }
         $grid .= '<table class="ui-widget ui-widget-content mnhnl-species-grid ' . $options['class'] . '" id="' . $options['id'] . '">';
         $grid .= self::get_species_checklist_header($options, $occAttrs);
         $rows = array();
         $rowIdx = 0;
         foreach ($occList as $occ) {
             $ttlid = $occ['taxon']['id'];
             $firstCell = data_entry_helper::mergeParamsIntoTemplate($occ['taxon'], 'taxon_label', false, true);
             if ($options['PHPtaxonLabel']) {
                 $firstCell = eval($firstCell);
             }
             $colspan = ' colspan="' . count($attributes) . '"';
             // assume always removeable and presence is hidden.
             $firstrow = '<td class="ui-state-default remove-row" style="width: 1%" rowspan="' . ($options['occurrenceComment'] ? "3" : "2") . '" >X</td>';
             $firstrow .= str_replace('{content}', $firstCell, str_replace('{colspan}', $colspan, $indicia_templates['taxon_label_cell']));
             $existing_record_id = $occ['id'];
             $hidden = $options['rowInclusionCheck'] == 'checkbox' ? '' : ' style="display:none"';
             if ($options['rowInclusionCheck'] == 'alwaysFixed' || $options['rowInclusionCheck'] == 'alwaysRemovable' || data_entry_helper::$entity_to_load != null && array_key_exists("sc:{$ttlid}:{$existing_record_id}:present", data_entry_helper::$entity_to_load)) {
                 $checked = ' checked="checked"';
             } else {
                 $checked = '';
             }
             $secondrow = "<td class=\"scPresenceCell\"{$hidden}>" . ($options['rowInclusionCheck'] != 'hasData' ? "<input type=\"hidden\" class=\"scPresence\" name=\"sc:{$ttlid}:{$existing_record_id}:present\" value=\"0\"/><input type=\"checkbox\" class=\"scPresence\" name=\"sc:{$ttlid}:{$existing_record_id}:present\" {$checked} />" : '') . "</td>";
             foreach ($occAttrControls as $attrId => $control) {
                 if ($existing_record_id) {
                     $search = preg_grep("/^sc:" . $ttlid . "[_[0-9]*]?:{$existing_record_id}:occAttr:{$attrId}" . '[:[0-9]*]?$/', array_keys(data_entry_helper::$entity_to_load));
                     $ctrlId = count($search) === 1 ? implode('', $search) : "sc:{$ttlid}:{$existing_record_id}:occAttr:{$attrId}";
                 } else {
                     $ctrlId = "sc:{$ttlid}:x{$rowIdx}:occAttr:{$attrId}";
                 }
                 if (isset(data_entry_helper::$entity_to_load[$ctrlId])) {
                     $existing_value = data_entry_helper::$entity_to_load[$ctrlId];
                 } elseif (array_key_exists('default', $attributes[$attrId])) {
                     $existing_value = $attributes[$attrId]['default'];
                 } else {
                     $existing_value = '';
                 }
                 $oc = str_replace('{fieldname}', $ctrlId, $control);
                 if (!empty($existing_value)) {
                     // For select controls, specify which option is selected from the existing value
                     if (substr($oc, 0, 7) == '<select') {
                         $oc = str_replace('value="' . $existing_value . '"', 'value="' . $existing_value . '" selected="selected"', $oc);
                     } else {
                         if (strpos($oc, 'checkbox') !== false) {
                             if ($existing_value == "1") {
                                 $oc = str_replace('type="checkbox"', 'type="checkbox" checked="checked"', $oc);
                             }
                         } else {
                             $oc = str_replace('value=""', 'value="' . $existing_value . '"', $oc);
                         }
                     }
                     // assume all error handling/validation done client side
                 }
                 $secondrow .= str_replace(array('{label}', '{content}'), array(lang::get($attributes[$attrId]['caption']), $oc), $indicia_templates[$options['attrCellTemplate']]);
             }
             $thirdrow = "";
             if ($options['occurrenceComment']) {
                 $thirdrow .= "\n<td class=\"ui-widget-content scCommentCell\" {$colspan}><label for=\"sc:{$ttlid}:{$existing_record_id}:occurrence:comment\" class=\"auto-width\" >" . lang::get("Comment") . " : </label><input class=\"scComment\" type=\"text\" name=\"sc:{$ttlid}:{$existing_record_id}:occurrence:comment\" " . "id=\"sc:{$ttlid}:{$existing_record_id}:occurrence:comment\" value=\"" . htmlspecialchars(data_entry_helper::$entity_to_load["sc:{$ttlid}:{$existing_record_id}:occurrence:comment"]) . "\" /></td>";
             }
             $rows[] = '<tr>' . $firstrow . '</tr>';
             $rows[] = '<tr class="scMeaning-' . $occ['taxon']['taxon_meaning_id'] . ' scDataRow">' . $secondrow . '</tr>';
             // no images.
             if ($thirdrow != "") {
                 $rows[] = '<tr class="scMeaning-' . $occ['taxon']['taxon_meaning_id'] . ' scDataRow">' . $thirdrow . '</tr>';
             }
             // no images.
             $rowIdx++;
         }
         $grid .= "\n<tbody>\n";
         if (count($rows) > 0) {
             $grid .= implode("\n", $rows) . "\n";
         } else {
             $grid .= "<tr style=\"display: none\"><td></td></tr>\n";
         }
         $grid .= "</tbody>\n</table>\n";
         if ($options['rowInclusionCheck'] == 'hasData') {
             $grid .= '<input name="rowInclusionCheck" value="hasData" type="hidden" />';
         }
         // If the lookupListId parameter is specified then the user is able to add extra rows to the grid,
         // selecting the species from this list. Add the required controls for this.
         if (isset($options['lookupListId'])) {
             $grid .= "<label for=\"taxonLookupControl\" class=\"auto-width\">" . lang::get('Add species to list') . " : </label> <input id=\"taxonLookupControl\" name=\"taxonLookupControl\" >";
             // Javascript to add further rows to the grid
             data_entry_helper::$javascript .= "var formatter = function(rowData,taxonCell) {\r\n  taxonCell.html(\"" . lang::get('loading') . "\");\r\n  jQuery.getJSON('" . data_entry_helper::$base_url . "/index.php/services/data/taxa_taxon_list/' + rowData.id +\r\n            '?mode=json&view=detail&auth_token=" . $options['readAuth']['auth_token'] . "&nonce=" . $options['readAuth']["nonce"] . "&callback=?', function(mdata) {\r\n    if(mdata instanceof Array && mdata.length>0){\r\n      jQuery.getJSON('" . data_entry_helper::$base_url . "/index.php/services/data/taxa_taxon_list' +\r\n            '?mode=json&view=detail&auth_token=" . $options['readAuth']['auth_token'] . "&nonce=" . $options['readAuth']["nonce"] . "&taxon_meaning_id='+mdata[0].taxon_meaning_id+'&taxon_list_id=" . $options["extra_list_id"] . "&callback=?', function(data) {\r\n        var taxaList = '';\r\n         if(data instanceof Array && data.length>0){\r\n          for (var i=0;i<data.length;i++){\r\n            if(data[i].preferred == 'f')\r\n              taxaList += (taxaList == '' ? '' : ', ')+data[i].taxon;\r\n            else\r\n              taxaList = '<em>'+data[i].taxon+'</em>'+(taxaList == '' ? '' : ', '+taxaList);\r\n            }\r\n          }\r\n          taxonCell.html(taxaList).removeClass('extraCommonNames');\r\n        });\r\n    }})\r\n}  \r\nbindSpeciesAutocomplete(\"taxonLookupControl\",\"" . data_entry_helper::$base_url . "index.php/services/data\", \"" . $options['id'] . "\", \"" . $options['lookupListId'] . "\", {\"auth_token\" : \"" . $options['readAuth']['auth_token'] . "\", \"nonce\" : \"" . $options['readAuth']['nonce'] . "\"}, formatter);\r\n";
         }
         // No help text
         return $grid;
     } else {
         return $taxalist['error'];
     }
 }
 /**
  * Helper function to generate a species checklist from a given taxon list.
  *
  * Please not that although this is based on the data_entry_helper function, it has only been tested with the following
  * options for seasearch - @id,@useThirdLevelSamples,@lookupListId,@gridIdAttributeId,@speciesControlToUseSubSamples,@subSamplePerRow,@resizeWidth,@resizeHeight
  * If you intend to use any other options, they will require further testing or development.
  *
  */
 private static function species_checklist($options)
 {
     global $indicia_templates;
     data_entry_helper::add_resource('addrowtogrid');
     $options = data_entry_helper::get_species_checklist_options($options);
     $classlist = array('ui-widget', 'ui-widget-content', 'species-grid');
     if (!empty($options['class'])) {
         $classlist[] = $options['class'];
     }
     if ($options['subSamplePerRow']) {
         // we'll track 1 sample per grid row.
         $smpIdx = 0;
     }
     if ($options['columns'] > 1 && count($options['mediaTypes']) > 1) {
         throw new Exception('The species_checklist control does not support having more than one occurrence per row (columns option > 0) ' . 'at the same time has having the mediaTypes option in use.');
     }
     data_entry_helper::add_resource('json');
     data_entry_helper::add_resource('autocomplete');
     $filterArray = data_entry_helper::get_species_names_filter($options);
     $filterNameTypes = array('all', 'currentLanguage', 'preferred', 'excludeSynonyms');
     //make a copy of the options so that we can maipulate it
     $overrideOptions = $options;
     //We are going to cycle through each of the name filter types
     //and save the parameters required for each type in an array so
     //that the Javascript can quickly access the required parameters
     foreach ($filterNameTypes as $filterType) {
         $overrideOptions['speciesNameFilterMode'] = $filterType;
         $nameFilter[$filterType] = data_entry_helper::get_species_names_filter($overrideOptions);
         $nameFilter[$filterType] = json_encode($nameFilter[$filterType]);
     }
     if (count($filterArray)) {
         $filterParam = json_encode($filterArray);
         data_entry_helper::$javascript .= "indiciaData['taxonExtraParams-" . $options['id'] . "'] = {$filterParam};\n";
         // Apply a filter to extraParams that can be used when loading the initial species list, to get just the correct names.
         if (isset($options['speciesNameFilterMode']) && !empty($options['listId'])) {
             $filterFields = array();
             $filterWheres = array();
             self::parse_species_name_filter_mode($options, $filterFields, $filterWheres);
             if (count($filterWheres)) {
                 $options['extraParams'] += array('query' => json_encode(array('where' => $filterWheres)));
             }
             $options['extraParams'] += $filterFields;
         }
     }
     data_entry_helper::$js_read_tokens = $options['readAuth'];
     data_entry_helper::$javascript .= "indiciaData['rowInclusionCheck-" . $options['id'] . "'] = '" . $options['rowInclusionCheck'] . "';\n";
     data_entry_helper::$javascript .= "indiciaData['copyDataFromPreviousRow-" . $options['id'] . "'] = '" . $options['copyDataFromPreviousRow'] . "';\n";
     data_entry_helper::$javascript .= "indiciaData['includeSpeciesGridLinkPage-" . $options['id'] . "'] = '" . $options['includeSpeciesGridLinkPage'] . "';\n";
     data_entry_helper::$javascript .= "indiciaData.speciesGridPageLinkUrl = '" . $options['speciesGridPageLinkUrl'] . "';\n";
     data_entry_helper::$javascript .= "indiciaData.speciesGridPageLinkParameter = '" . $options['speciesGridPageLinkParameter'] . "';\n";
     data_entry_helper::$javascript .= "indiciaData.speciesGridPageLinkTooltip = '" . $options['speciesGridPageLinkTooltip'] . "';\n";
     data_entry_helper::$javascript .= "indiciaData['editTaxaNames-" . $options['id'] . "'] = '" . $options['editTaxaNames'] . "';\n";
     data_entry_helper::$javascript .= "indiciaData['subSpeciesColumn-" . $options['id'] . "'] = '" . $options['subSpeciesColumn'] . "';\n";
     data_entry_helper::$javascript .= "indiciaData['subSamplePerRow-" . $options['id'] . "'] = " . ($options['subSamplePerRow'] ? 'true' : 'false') . ";\n";
     if ($options['copyDataFromPreviousRow']) {
         data_entry_helper::$javascript .= "indiciaData['previousRowColumnsToInclude-" . $options['id'] . "'] = '" . $options['previousRowColumnsToInclude'] . "';\n";
         data_entry_helper::$javascript .= "indiciaData.langAddAnother='" . lang::get('Add another') . "';\n";
     }
     if (count($options['mediaTypes'])) {
         data_entry_helper::add_resource('plupload');
         // store some globals that we need later when creating uploaders
         $relpath = data_entry_helper::getRootFolder() . data_entry_helper::client_helper_path();
         $interim_image_folder = isset(parent::$interim_image_folder) ? parent::$interim_image_folder : 'upload/';
         data_entry_helper::$javascript .= "indiciaData.uploadSettings = {\n";
         data_entry_helper::$javascript .= "  uploadScript: '" . $relpath . "upload.php',\n";
         data_entry_helper::$javascript .= "  destinationFolder: '" . $relpath . $interim_image_folder . "',\n";
         data_entry_helper::$javascript .= "  jsPath: '" . data_entry_helper::$js_path . "'";
         if (isset($options['resizeWidth'])) {
             data_entry_helper::$javascript .= ",\n  resizeWidth: " . $options['resizeWidth'];
         }
         if (isset($options['resizeHeight'])) {
             data_entry_helper::$javascript .= ",\n  resizeHeight: " . $options['resizeHeight'];
         }
         if (isset($options['resizeQuality'])) {
             data_entry_helper::$javascript .= ",\n  resizeQuality: " . $options['resizeQuality'];
         }
         data_entry_helper::$javascript .= "\n}\n";
         if ($indicia_templates['file_box'] != '') {
             data_entry_helper::$javascript .= "file_boxTemplate = '" . str_replace('"', '\\"', $indicia_templates['file_box']) . "';\n";
         }
         if ($indicia_templates['file_box_initial_file_info'] != '') {
             data_entry_helper::$javascript .= "file_box_initial_file_infoTemplate = '" . str_replace('"', '\\"', $indicia_templates['file_box_initial_file_info']) . "';\n";
         }
         if ($indicia_templates['file_box_uploaded_image'] != '') {
             data_entry_helper::$javascript .= "file_box_uploaded_imageTemplate = '" . str_replace('"', '\\"', $indicia_templates['file_box_uploaded_image']) . "';\n";
         }
     }
     $occAttrControls = array();
     $occAttrs = array();
     $occAttrControlsExisting = array();
     $taxonRows = array();
     $subSampleRows = array();
     if (!empty($options['useThirdLevelSamples']) && $options['useThirdLevelSamples'] == true) {
         $useThirdLevelSamples = true;
     } else {
         $useThirdLevelSamples = false;
     }
     // Load any existing sample's occurrence data into $entity_to_load
     if (isset(data_entry_helper::$entity_to_load['sample:id']) && $options['useLoadedExistingRecords'] === false) {
         self::preload_species_checklist_occurrences(data_entry_helper::$entity_to_load['sample:id'], $options['readAuth'], $options['mediaTypes'], $options['reloadExtraParams'], $subSampleRows, $options['speciesControlToUseSubSamples'], isset($options['subSampleSampleMethodID']) ? $options['subSampleSampleMethodID'] : '', $options['id'], $useThirdLevelSamples);
     }
     // load the full list of species for the grid, including the main checklist plus any additional species in the reloaded occurrences.
     $taxalist = data_entry_helper::get_species_checklist_taxa_list($options, $taxonRows);
     // If we managed to read the species list data we can proceed
     if (!array_key_exists('error', $taxalist)) {
         $attrOptions = array('id' => null, 'valuetable' => 'occurrence_attribute_value', 'attrtable' => 'occurrence_attribute', 'key' => 'occurrence_id', 'fieldprefix' => "sc:-idx-::occAttr", 'extraParams' => $options['readAuth'], 'survey_id' => array_key_exists('survey_id', $options) ? $options['survey_id'] : null);
         if (isset($options['attributeIds'])) {
             // make sure we load the grid ID attribute
             if (!empty($options['gridIdAttributeId']) && !in_array($options['gridIdAttributeId'], $options['attributeIds'])) {
                 $options['attributeIds'][] = $options['gridIdAttributeId'];
             }
             $attrOptions['extraParams'] += array('query' => json_encode(array('in' => array('id' => $options['attributeIds']))));
         }
         $attributes = data_entry_helper::getAttributes($attrOptions);
         // Merge in the attribute options passed into the control which can override the warehouse config
         if (isset($options['occAttrOptions'])) {
             foreach ($options['occAttrOptions'] as $attrId => $attr) {
                 if (isset($attributes[$attrId])) {
                     $attributes[$attrId] = array_merge($attributes[$attrId], $attr);
                 }
             }
         }
         // Get the attribute and control information required to build the custom occurrence attribute columns
         data_entry_helper::species_checklist_prepare_attributes($options, $attributes, $occAttrControls, $occAttrControlsExisting, $occAttrs);
         $beforegrid = '<span style="display: none;">Step 1</span>' . "\n";
         if (isset($options['lookupListId'])) {
             $subSampleImagesToLoad = array();
             //Cycle through sub-samples of the main parent sample
             foreach ($subSampleRows as $subSampleIdx => $subSampleRow) {
                 foreach (data_entry_helper::$entity_to_load as $key => $value) {
                     $keyParts = explode(':', $key);
                     //Get an array of sample media to load onto the grid
                     if (strpos($key, 'third-level-smp-occ-grid') !== false && strpos($key, ':sample_medium:id') !== false) {
                         if (!in_array($keyParts[3], $subSampleImagesToLoad)) {
                             $subSampleImagesToLoad[] = $keyParts[3];
                         }
                     }
                 }
             }
             //For each sub-sample, add a row to the occurrences grid with the image loaded, this is then ready for the user.
             //To create occurrences with
             if (isset($subSampleImagesToLoad)) {
                 $mediaIdArray = array();
                 foreach ($subSampleImagesToLoad as $subSampleImageIdx => $subSampleImageToLoad) {
                     $mediaIdArray[] = $subSampleImageToLoad;
                     $beforegrid .= self::get_species_checklist_empty_row_with_image($options, $occAttrControls, $attributes, $subSampleImageIdx, $subSampleImageToLoad);
                 }
                 $encodedMediaArray = json_encode($mediaIdArray);
                 data_entry_helper::$javascript .= "indiciaData.encodedMediaArray=" . json_encode($encodedMediaArray) . ";\n";
             }
             $beforegrid .= self::get_species_checklist_clonable_row($options, $occAttrControls, $attributes);
         }
         $onlyImages = true;
         if ($options['mediaTypes']) {
             foreach ($options['mediaTypes'] as $mediaType) {
                 if (substr($mediaType, 0, 6) !== 'Image:') {
                     $onlyImages = false;
                 }
             }
         }
         $grid = data_entry_helper::get_species_checklist_header($options, $occAttrs, $onlyImages);
         $rows = array();
         $imageRowIdxs = array();
         $taxonCounter = array();
         $rowIdx = 0;
         // tell the addTowToGrid javascript how many rows are already used, so it has a unique index for new rows
         data_entry_helper::$javascript .= "indiciaData['gridCounter-" . $options['id'] . "'] = " . count($taxonRows) . ";\n";
         data_entry_helper::$javascript .= "indiciaData['gridSampleCounter-" . $options['id'] . "'] = " . count($subSampleRows) . ";\n";
         // Loop through all the rows needed in the grid
         // Get the checkboxes (hidden or otherwise) that indicate a species is present
         if (is_array(data_entry_helper::$entity_to_load)) {
             $presenceValues = preg_grep("/^sc:[0-9]*:[0-9]*:present\$/", array_keys(data_entry_helper::$entity_to_load));
         }
         // if subspecies are stored, then need to load up the parent species info into the $taxonRows data
         if ($options['subSpeciesColumn']) {
             self::load_parent_species($taxalist, $options);
             if ($options['subSpeciesRemoveSspRank']) {
                 // remove subspecific rank information from the displayed subspecies names by passing a regex
                 data_entry_helper::$javascript .= "indiciaData.subspeciesRanksToStrip='" . lang::get('(form[a\\.]?|var\\.?|ssp\\.)') . "';\n";
             }
         }
         // track if there is a row we are editing in this grid
         $hasEditedRecord = false;
         if ($options['mediaTypes']) {
             $mediaBtnLabel = lang::get($onlyImages ? 'Add images' : 'Add media');
             $mediaBtnClass = 'sc' . $onlyImages ? 'Image' : 'Media' . 'Link';
         }
         foreach ($taxonRows as $txIdx => $rowIds) {
             $ttlId = $rowIds['ttlId'];
             $loadedTxIdx = isset($rowIds['loadedTxIdx']) ? $rowIds['loadedTxIdx'] : -1;
             $existing_record_id = isset($rowIds['occId']) ? $rowIds['occId'] : false;
             // Multi-column input does not work when image upload allowed
             $colIdx = count($options['mediaTypes']) ? 0 : (int) floor($rowIdx / (count($taxonRows) / $options['columns']));
             // Find the taxon in our preloaded list data that we want to output for this row
             $taxonIdx = 0;
             while ($taxonIdx < count($taxalist) && $taxalist[$taxonIdx]['id'] != $ttlId) {
                 $taxonIdx += 1;
             }
             if ($taxonIdx >= count($taxalist)) {
                 continue;
             }
             // next taxon, as this one was not found in the list
             $taxon = $taxalist[$taxonIdx];
             // If we are using the sub-species column then when the taxon has a parent (=species) this goes in the
             // first column and we put the subsp in the second column in a moment.
             if (isset($options['subSpeciesColumn']) && $options['subSpeciesColumn'] && !empty($taxon['parent'])) {
                 $firstColumnTaxon = $taxon['parent'];
             } else {
                 $firstColumnTaxon = $taxon;
             }
             // map field names if using a cached lookup
             if ($options['cacheLookup']) {
                 $firstColumnTaxon = $firstColumnTaxon + array('preferred_name' => $firstColumnTaxon['preferred_taxon'], 'common' => $firstColumnTaxon['default_common_name']);
             }
             // Get the cell content from the taxon_label template
             $firstCell = helper_base::mergeParamsIntoTemplate($firstColumnTaxon, 'taxon_label');
             // If the taxon label template is PHP, evaluate it.
             if ($options['PHPtaxonLabel']) {
                 $firstCell = eval($firstCell);
             }
             // Now create the table cell to contain this.
             $colspan = isset($options['lookupListId']) && $options['rowInclusionCheck'] != 'alwaysRemovable' ? ' colspan="2"' : '';
             $row = '';
             // Add a delete button if the user can remove rows, add an edit button if the user has the edit option set, add a page link if user has that option set.
             if ($options['rowInclusionCheck'] == 'alwaysRemovable') {
                 $imgPath = empty(helper_base::$images_path) ? helper_base::relative_client_helper_path() . "../media/images/" : helper_base::$images_path;
                 $speciesGridLinkPageIconSource = $imgPath . "nuvola/find-22px.png";
                 if ($options['editTaxaNames']) {
                     $row .= '<td class="row-buttons">
                  <img class="action-button remove-row" src=' . $imgPath . 'nuvola/cancel-16px.png>
                  <img class="action-button edit-taxon-name" src=' . $imgPath . 'nuvola/package_editors-16px.png>';
                     if ($options['includeSpeciesGridLinkPage']) {
                         $row .= '<img class="species-grid-link-page-icon" title="' . $options['speciesGridPageLinkTooltip'] . '" alt="Notes icon" src=' . $speciesGridLinkPageIconSource . '>';
                     }
                     $row .= '</td>';
                 } else {
                     $row .= '<td class="row-buttons"><img class="action-button remove-row" src=' . $imgPath . 'nuvola/cancel-16px.png>';
                     if ($options['includeSpeciesGridLinkPage']) {
                         $row .= '<img class="species-grid-link-page-icon" title="' . $options['speciesGridPageLinkTooltip'] . '" alt="Notes icon" src=' . $speciesGridLinkPageIconSource . '>';
                     }
                     $row .= '</td>';
                 }
             }
             // if editing a specific occurrence, mark it up
             $editedRecord = isset($_GET['occurrence_id']) && $_GET['occurrence_id'] == $existing_record_id;
             $editClass = $editedRecord ? ' edited-record ui-state-highlight' : '';
             $hasEditedRecord = $hasEditedRecord || $editedRecord;
             // Verified records can be flagged with an icon
             //Do an isset check as the npms_paths form for example uses the species checklist, but doesn't use an entity_to_load
             if (isset(data_entry_helper::$entity_to_load["sc:{$loadedTxIdx}:{$existing_record_id}:record_status"])) {
                 $status = data_entry_helper::$entity_to_load["sc:{$loadedTxIdx}:{$existing_record_id}:record_status"];
                 if (preg_match('/[VDR]/', $status)) {
                     $img = false;
                     switch ($status) {
                         case 'V':
                             $img = 'ok';
                             $statusLabel = 'verified';
                             break;
                         case 'D':
                             $img = 'dubious';
                             $statusLabel = 'queried';
                             break;
                         case 'R':
                             $img = 'cancel';
                             $statusLabel = 'rejected';
                             break;
                     }
                     if ($img) {
                         $label = lang::get($statusLabel);
                         $title = lang::get('This record has been {1}. Changing it will mean that it will need to be rechecked by an expert.', $label);
                         $firstCell .= "<img alt=\"{$label}\" title=\"{$title}\" src=\"{$imgPath}nuvola/{$img}-16px.png\">";
                     }
                 }
             }
             $row .= str_replace(array('{content}', '{colspan}', '{editClass}', '{tableId}', '{idx}'), array($firstCell, $colspan, $editClass, $options['id'], $colIdx), $indicia_templates['taxon_label_cell']);
             $hidden = $options['rowInclusionCheck'] == 'checkbox' ? '' : ' style="display:none"';
             // AlwaysFixed mode means all rows in the default checklist are included as occurrences. Same for
             // AlwayeRemovable except that the rows can be removed.
             // If we are reloading a record there will be an entity_to_load which will indicate whether present should be checked.
             // This has to be evaluated true or false if reloading a submission with errors.
             if ($options['rowInclusionCheck'] == 'alwaysFixed' || $options['rowInclusionCheck'] == 'alwaysRemovable' || data_entry_helper::$entity_to_load != null && array_key_exists("sc:{$loadedTxIdx}:{$existing_record_id}:present", data_entry_helper::$entity_to_load) && data_entry_helper::$entity_to_load["sc:{$loadedTxIdx}:{$existing_record_id}:present"] == true) {
                 $checked = ' checked="checked"';
             } else {
                 $checked = '';
             }
             $row .= "\n<td class=\"scPresenceCell\" headers=\"{$options['id']}-present-{$colIdx}\"{$hidden}>";
             $fieldname = "sc:{$options['id']}-{$txIdx}:{$existing_record_id}:present";
             if ($options['rowInclusionCheck'] === 'hasData') {
                 $row .= "<input type=\"hidden\" name=\"{$fieldname}\" id=\"{$fieldname}\" value=\"{$taxon['id']}\"/>";
             } else {
                 // this includes a control to force out a 0 value when the checkbox is unchecked.
                 $row .= "<input type=\"hidden\" class=\"scPresence\" name=\"{$fieldname}\" value=\"0\"/>" . "<input type=\"checkbox\" class=\"scPresence\" name=\"{$fieldname}\" id=\"{$fieldname}\" value=\"{$taxon['id']}\" {$checked} />";
             }
             // If we have a grid ID attribute, output a hidden
             if (!empty($options['gridIdAttributeId'])) {
                 $gridAttributeId = $options['gridIdAttributeId'];
                 if (empty($existing_record_id)) {
                     //If in add mode we don't need to include the occurrence attribute id
                     $fieldname = "sc:{$options['id']}-{$txIdx}::occAttr:{$gridAttributeId}";
                     $row .= "<input type=\"hidden\" name=\"{$fieldname}\" id=\"{$fieldname}\" value=\"{$options['id']}\"/>";
                 } else {
                     $search = preg_grep("/^sc:[0-9]*:{$existing_record_id}:occAttr:{$gridAttributeId}:" . '[0-9]*$/', array_keys(data_entry_helper::$entity_to_load));
                     if (!empty($search)) {
                         $match = array_pop($search);
                         $parts = explode(':', $match);
                         //The id of the existing occurrence attribute value is at the end of the data
                         $idxOfOccValId = count($parts) - 1;
                         //$txIdx is row number in the grid. We cannot simply take the data from entity_to_load as it doesn't contain the row number.
                         $fieldname = "sc:{$options['id']}-{$txIdx}:{$existing_record_id}:occAttr:{$gridAttributeId}:{$parts[$idxOfOccValId]}";
                         $row .= "<input type=\"hidden\" name=\"{$fieldname}\" id=\"{$fieldname}\" value=\"{$options['id']}\"/>";
                     }
                 }
             }
             $row .= "</td>";
             if ($options['speciesControlToUseSubSamples']) {
                 $row .= "\n<td class=\"scSampleCell\" style=\"display:none\">";
                 $fieldname = "sc:{$options['id']}-{$txIdx}:{$existing_record_id}:occurrence:sampleIDX";
                 $value = $options['subSamplePerRow'] ? $smpIdx : $rowIds['smpIdx'];
                 $row .= "<input type=\"hidden\" class=\"scSample\" name=\"{$fieldname}\" id=\"{$fieldname}\" value=\"{$value}\" />";
                 $row .= "</td>";
                 // always increment the sample index if 1 per row.
                 if ($options['subSamplePerRow']) {
                     $smpIdx++;
                 }
             }
             $idx = 0;
             if ($options['mediaTypes']) {
                 $existingImages = is_array(data_entry_helper::$entity_to_load) ? preg_grep("/^sc:{$loadedTxIdx}:{$existing_record_id}:occurrence_medium:id:[a-z0-9]*\$/", array_keys(data_entry_helper::$entity_to_load)) : array();
                 $row .= "\n<td class=\"ui-widget-content scAddMediaCell\">";
                 $style = count($existingImages) > 0 ? ' style="display: none"' : '';
                 $fieldname = "add-media:{$options['id']}-{$txIdx}:{$existing_record_id}";
                 $row .= "<a href=\"\"{$style} class=\"add-media-link button {$mediaBtnClass}\" id=\"{$fieldname}\">" . "{$mediaBtnLabel}</a>";
                 $row .= "</td>";
             }
             // Are we in the first column of a multicolumn grid, or doing single column grid? If so start new row.
             if ($colIdx === 0) {
                 $rows[$rowIdx] = $row;
             } else {
                 $rows[$rowIdx % ceil(count($taxonRows) / $options['columns'])] .= $row;
             }
             $rowIdx++;
             if ($options['mediaTypes'] && count($existingImages) > 0) {
                 $totalCols = ($options['lookupListId'] ? 2 : 1) + 1 + count($occAttrControls) + ($options['occurrenceComment'] ? 1 : 0) + ($options['occurrenceSensitivity'] ? 1 : 0) + (count($options['mediaTypes']) ? 1 : 0);
                 $rows[$rowIdx] = '<td colspan="' . $totalCols . '">' . data_entry_helper::file_box(array('table' => "sc:{$options['id']}-{$txIdx}:{$existing_record_id}:occurrence_medium", 'loadExistingRecordKey' => "sc:{$loadedTxIdx}:{$existing_record_id}:occurrence_medium", 'mediaTypes' => $options['mediaTypes'], 'readAuth' => $options['readAuth'])) . '</td>';
                 $imageRowIdxs[] = $rowIdx;
                 $rowIdx++;
             }
         }
         $grid .= "\n<tbody>\n";
         if (count($rows) > 0) {
             $grid .= data_entry_helper::species_checklist_implode_rows($rows, $imageRowIdxs);
         }
         $grid .= "</tbody>\n";
         $grid = str_replace(array('{class}', '{id}', '{content}'), array(' class="' . implode(' ', $classlist) . '"', " id=\"{$options['id']}\"", $grid), $indicia_templates['data-input-table']);
         // in hasData mode, the wrap_species_checklist method must be notified of the different default
         // way of checking if a row is to be made into an occurrence. This may differ between grids when
         // there are multiple grids on a page.
         if ($options['rowInclusionCheck'] == 'hasData') {
             $grid .= '<input name="rowInclusionCheck-' . $options['id'] . '" value="hasData" type="hidden" />';
             if (!empty($options['hasDataIgnoreAttrs'])) {
                 $grid .= '<input name="hasDataIgnoreAttrs-' . $options['id'] . '" value="' . implode(',', $options['hasDataIgnoreAttrs']) . '" type="hidden" />';
             }
         }
         // If the lookupListId parameter is specified then the user is able to add extra rows to the grid,
         // selecting the species from this list. Add the required controls for this.
         if (isset($options['lookupListId'])) {
             // Javascript to add further rows to the grid
             if (isset($indicia_templates['format_species_autocomplete_fn'])) {
                 data_entry_helper::$javascript .= 'formatter = ' . $indicia_templates['format_species_autocomplete_fn'];
             } else {
                 data_entry_helper::$javascript .= "formatter = '" . $indicia_templates['taxon_label'] . "';\n";
             }
             if (!empty(parent::$warehouse_proxy)) {
                 $url = parent::$warehouse_proxy . "index.php/services/data";
             } else {
                 $url = helper_base::$base_url . "index.php/services/data";
             }
             data_entry_helper::$javascript .= "if (typeof indiciaData.speciesGrid==='undefined') {indiciaData.speciesGrid={};}\n";
             data_entry_helper::$javascript .= "indiciaData.speciesGrid['{$options['id']}']={};\n";
             data_entry_helper::$javascript .= "indiciaData.speciesGrid['{$options['id']}'].cacheLookup=" . ($options['cacheLookup'] ? 'true' : 'false') . ";\n";
             data_entry_helper::$javascript .= "indiciaData.speciesGrid['{$options['id']}'].numValues=" . (!empty($options['numValues']) ? $options['numValues'] : 20) . ";\n";
             data_entry_helper::$javascript .= "indiciaData.speciesGrid['{$options['id']}'].selectMode=" . (!empty($options['selectMode']) && $options['selectMode'] ? 'true' : 'false') . ";\n";
             //encoded media array is just and array of media items that has been json_encoded.
             //Add a row to the occurrence grid for each media item.
             data_entry_helper::$javascript .= "\n        if (indiciaData.encodedMediaArray) {\n          var encodedMediaArray = eval(indiciaData.encodedMediaArray);\n          for (var i=0; i<encodedMediaArray.length; i++) {\n            makeImageRowOrSpareRow('" . $options['id'] . "', {'auth_token' : '" . $options['readAuth']['auth_token'] . "', 'nonce' : '" . $options['readAuth']['nonce'] . "'},'" . $options['lookupListId'] . "','{$url}', null, false, null, null, encodedMediaArray[i]);\n          }\n        }\n        \r\n";
             data_entry_helper::$javascript .= "makeImageRowOrSpareRow('" . $options['id'] . "', {'auth_token' : '" . $options['readAuth']['auth_token'] . "', 'nonce' : '" . $options['readAuth']['nonce'] . "'},'" . $options['lookupListId'] . "','{$url}', null, false, null, null);\r\n";
         }
         // If options contain a help text, output it at the end if that is the preferred position
         $options['helpTextClass'] = isset($options['helpTextClass']) ? $options['helpTextClass'] : 'helpTextLeft';
         $r = $beforegrid . $grid;
         data_entry_helper::$javascript .= "\$('#" . $options['id'] . "').find('input,select').keydown(keyHandler);\n";
         //nameFilter is an array containing all the parameters required to return data for each of the
         //"Choose species names available for selection" filter types
         data_entry_helper::species_checklist_filter_popup($options, $nameFilter);
         if ($options['subSamplePerRow']) {
             // output a hidden block to contain sub-sample hidden input values.
             $r .= '<div id="' . $options['id'] . '-blocks">' . data_entry_helper::get_subsample_per_row_hidden_inputs() . '</div>';
         }
         if ($hasEditedRecord) {
             data_entry_helper::$javascript .= "\$('#{$options['id']} tbody tr').hide();\n";
             data_entry_helper::$javascript .= "\$('#{$options['id']} tbody tr td.edited-record').parent().show();\n";
             data_entry_helper::$javascript .= "\$('#{$options['id']} tbody tr td.edited-record').parent().next('tr.supplementary-row').show();\n";
             $r .= '<p>' . lang::get('You are editing a single record that is part of a larger sample, so any changes to the sample\'s information such as edits to the date or map reference ' . 'will affect the whole sample.') . " <a id=\"species-grid-view-all-{$options['id']}\">" . lang::get('View all the records in this sample or add more records.') . '</a></p>';
             data_entry_helper::$javascript .= "\$('#species-grid-view-all-{$options['id']}').click(function(e) {\n  \$('#{$options['id']} tbody tr').show();\n  \$(e.currentTarget).hide();\n});\n";
             self::$onload_javascript .= "\nif (\$('#{$options['id']}').parents('.ui-tabs-panel').length) {\n  indiciaFns.activeTab(\$('#controls'), \$('#{$options['id']}').parents('.ui-tabs-panel')[0].id);\n}\n";
         }
         return $r;
     } else {
         return $taxalist['error'];
     }
 }
Beispiel #3
0
 public static function mnhnl_bats2_species_checklist($args, $options)
 {
     global $indicia_templates;
     //    $options = data_entry_helper::check_arguments($options, array('listId', 'occAttrs', 'readAuth', 'extraParams', 'lookupListId'));
     $options = data_entry_helper::get_species_checklist_options($options);
     data_entry_helper::add_resource('json');
     data_entry_helper::add_resource('autocomplete');
     $occAttrControls = array();
     $occAttrs = array();
     $retVal = '';
     // Load any existing sample's occurrence data into $entity_to_load: first have to load the survey method subsamples.
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         $subSamplesAttrs = array();
         $smpOptions = array('table' => 'sample', 'nocache' => true, 'extraParams' => $options['readAuth'] + array('view' => 'detail', 'parent_id' => data_entry_helper::$entity_to_load['sample:id']));
         $subSamples = data_entry_helper::get_population_data($smpOptions);
         foreach ($subSamples as $sample) {
             $subSamplesAttrs[$sample['id']] = data_entry_helper::getAttributes(array('attrtable' => 'sample_attribute', 'valuetable' => 'sample_attribute_value', 'id' => $sample['id'], 'key' => 'sample_id', 'fieldprefix' => '{MyPrefix}:smpAttr', 'extraParams' => $options['readAuth'], 'survey_id' => $args['survey_id']), true);
             $subSamplesAttrs[$sample['id']][$visitAttr]['validation_rules'] = 'required';
         }
         foreach ($options['surveyMethods'] as $i => $method) {
             $smpID = false;
             foreach ($subSamples as $subSample) {
                 foreach ($subSamplesAttrs[$subSample['id']] as $attr) {
                     if ($attr['attributeId'] == $options['surveyMethodAttrId'] && $attr['default'] == $method['meaning_id']) {
                         $smpID = $subSample['id'];
                         $options['surveyMethods'][$i]['smpID'] = $smpID;
                     }
                 }
             }
             if ($smpID) {
                 self::preload_species_checklist_occurrences($smpID, $method['meaning_id'], $options['readAuth']);
             }
         }
     }
     // load the full list of species for the grid, including the main checklist plus any additional species in the reloaded occurrences.
     $options['extraParams']['view'] = 'detail';
     $occList = self::get_species_checklist_occ_list($options);
     // If we managed to read the species list data we can proceed
     if (!array_key_exists('error', $occList)) {
         $attributes = data_entry_helper::getAttributes(array('id' => null, 'valuetable' => 'occurrence_attribute_value', 'attrtable' => 'occurrence_attribute', 'key' => 'occurrence_id', 'fieldprefix' => "{fieldname}", 'extraParams' => $options['readAuth'], 'survey_id' => array_key_exists('survey_id', $options) ? $options['survey_id'] : null));
         foreach ($attributes as $idx => $attr) {
             $attributes[$idx]['class'] = "scCheckTaxon";
         }
         // this allows extra validation
         // Get the attribute and control information required to build the custom occurrence attribute columns
         self::species_checklist_prepare_attributes($options, $attributes, $occAttrControls, $occAttrs);
         $retVal = "<p>" . lang::get('LANG_SpeciesInstructions') . "</p>\n";
         if (isset($options['lookupListId'])) {
             self::$cloneableTable = self::get_species_checklist_clonable_row($options, $occAttrControls, $attributes);
         }
         $retVal .= '<table class="ui-widget ui-widget-content mnhnl-species-grid ' . $options['class'] . '" id="' . $options['id'] . '">';
         $retVal .= self::get_species_checklist_header($options, $attributes) . '<tbody>';
         $attrsPerRow = array();
         foreach ($attributes as $attrId => $attr) {
             $row = substr($attr['inner_structure_block'], 3);
             if (!isset($attrsPerRow[$row])) {
                 $attrsPerRow[$row] = array();
             }
             $attrsPerRow[$row][] = $attr["attributeId"];
         }
         $rows = array();
         $rowIdx = 0;
         // each row grouping is driven by the ttlid, not the occurrence, as there is a different occurrence for each survey method.
         // that said we want it to be in general occurrence order so it matches the order in which the occurrences are created
         // i.e. in order of first occurrence in ttl group
         $ttlidList = array();
         $ttlList = array();
         foreach ($occList as $occ) {
             $ttlid = $occ['taxon']['id'];
             if (!in_array($ttlid, $ttlidList)) {
                 $ttlidList[] = $ttlid;
                 $ttlList[$ttlid] = $occ['taxon'];
             }
         }
         foreach ($ttlidList as $ttlid) {
             $id = 1;
             foreach ($options['surveyMethods'] as $method) {
                 $existing_record_id = '';
                 foreach ($occList as $occIt) {
                     // get the occurrence for this method/ttl combination
                     if ($occIt['taxon']['id'] == $ttlid && $occIt['method'] == $method['meaning_id']) {
                         $occ = $occIt;
                         $existing_record_id = $occ['id'];
                     }
                 }
                 $retVal .= '<tr class="scMeaning-' . $ttlList[$ttlid]['taxon_meaning_id'] . ' scDataRow sg-tr-' . $method['meaning_id'] . ' ' . ($id == '1' ? 'scFirstRow' : '') . '">';
                 if ($id == '1') {
                     $firstCell = data_entry_helper::mergeParamsIntoTemplate($ttlList[$ttlid], 'taxon_label', false, true);
                     if ($options['PHPtaxonLabel']) {
                         $firstCell = eval($firstCell);
                     }
                     // assume always removeable and scPresence is hidden.
                     $retVal .= '<td class="ui-state-default remove-row" style="width: 1%" rowspan="' . count($attrsPerRow) . '">X</td>';
                     $retVal .= str_replace('{content}', $firstCell, str_replace('{colspan}', 'rowspan="' . count($attrsPerRow) . '"', $indicia_templates['taxon_label_cell']));
                 }
                 $ctrlId = "sc:" . $method['meaning_id'] . ":{$ttlid}:" . ($existing_record_id ? $existing_record_id : "x" . $rowIdx) . ":present";
                 $retVal .= '<td>' . $method['term'] . ':</td><td class="scPresenceCell" style="display:none"><input type="hidden" class="scPresence" name="' . $ctrlId . '" value="1" /></td><td><span>';
                 foreach ($attrsPerRow[$id] as $attrId) {
                     // no complex values in checkboxes as the controls are vanilla
                     if ($existing_record_id) {
                         $search = preg_grep("/^sc:" . $method['meaning_id'] . ":{$ttlid}:{$existing_record_id}:occAttr:{$attrId}" . '[:[0-9]*]?$/', array_keys(data_entry_helper::$entity_to_load));
                         $ctrlId = count($search) === 1 ? implode('', $search) : "sc:" . $method['meaning_id'] . ":{$ttlid}:{$existing_record_id}:occAttr:{$attrId}";
                     } else {
                         $ctrlId = "sc:" . $method['meaning_id'] . ":{$ttlid}:x{$rowIdx}:occAttr:{$attrId}";
                     }
                     if (isset(data_entry_helper::$entity_to_load[$ctrlId])) {
                         $existing_value = data_entry_helper::$entity_to_load[$ctrlId];
                     } elseif (array_key_exists('default', $attributes[$attrId])) {
                         $existing_value = $attributes[$attrId]['default'];
                     } else {
                         $existing_value = '';
                     }
                     $control = $occAttrControls[$attrId];
                     $oc = str_replace('{fieldname}', $ctrlId, $control);
                     if (!empty($existing_value)) {
                         // TBD selects
                         if (strpos($oc, 'checkbox') !== false) {
                             if ($existing_value == "1") {
                                 $oc = str_replace('type="checkbox"', 'type="checkbox" checked="checked"', $oc);
                             }
                         } else {
                             $oc = str_replace('value=""', 'value="' . $existing_value . '"', $oc);
                         }
                         // assume all error handling/validation done client side
                     }
                     $retVal .= '<span class="scKeepTogether">' . $oc . '</span> ';
                 }
                 $retVal .= '</span></td></tr>';
                 $id++;
                 $rowIdx++;
             }
         }
         if ($rowIdx == 0) {
             $retVal .= "<tr style=\"display: none\"><td></td></tr>\n";
         }
         $retVal .= "</tbody></table>\n";
         data_entry_helper::$javascript .= "\njQuery('#species,.scClonableRow').find(':checkbox').addClass('sgCheckbox');\n";
         if ($options['rowInclusionCheck'] == 'hasData') {
             $r .= '<input name="rowInclusionCheck" value="hasData" type="hidden" />';
         }
         // If the lookupListId parameter is specified then the user is able to add extra rows to the grid,
         // selecting the species from this list. Add the required controls for this.
         if (isset($options['lookupListId'])) {
             $retVal .= "<label for=\"taxonLookupControl\" class=\"auto-width\">" . lang::get('Add species to list') . " : </label><input id=\"taxonLookupControl\" name=\"taxonLookupControl\" >";
             // Javascript to add further rows to the grid
             data_entry_helper::$javascript .= "var formatter = function(rowData,taxonCell) {\n  taxonCell.html(\"" . lang::get('loading') . "\");\n  jQuery.getJSON('" . data_entry_helper::$base_url . "/index.php/services/data/taxa_taxon_list/' + rowData.id +\n            '?mode=json&view=detail&auth_token=" . $options['readAuth']['auth_token'] . "&nonce=" . $options['readAuth']["nonce"] . "&callback=?', function(mdata) {\n    if(mdata instanceof Array && mdata.length>0){\n      jQuery.getJSON('" . data_entry_helper::$base_url . "/index.php/services/data/taxa_taxon_list' +\n            '?mode=json&view=detail&auth_token=" . $options['readAuth']['auth_token'] . "&nonce=" . $options['readAuth']["nonce"] . "&taxon_meaning_id='+mdata[0].taxon_meaning_id+'&taxon_list_id=" . $options["extra_list_id"] . "&callback=?', function(data) {\n        var taxaList = '';\n         if(data instanceof Array && data.length>0){\n          for (var i=0;i<data.length;i++){\n            if(data[i].preferred == 'f')\n              taxaList += (taxaList == '' ? '' : '<br/>')+data[i].taxon;\n            else\n              taxaList = '<em>'+data[i].taxon+'</em>'+(taxaList == '' ? '' : '<br/>'+taxaList);\n            }\n          }\n          taxonCell.html(taxaList).removeClass('extraCommonNames');\n        });\n    }})\n}  \nbindSpeciesAutocomplete(\"taxonLookupControl\",\"" . data_entry_helper::$base_url . "index.php/services/data\", \"" . $options['id'] . "\", \"" . $options['lookupListId'] . "\", {\"auth_token\" : \"" . $options['readAuth']['auth_token'] . "\", \"nonce\" : \"" . $options['readAuth']['nonce'] . "\"}, formatter, \"" . lang::get('LANG_Duplicate_Taxon') . "\", " . $options['max_species_ids'] . ");\n";
         }
         // No help text
         return $retVal;
     } else {
         return $occList['error'];
     }
 }
 public static function my_species_checklist($options)
 {
     global $indicia_templates;
     $base = base_path();
     if (substr($base, -1) != '/') {
         $base .= '/';
     }
     $indicia_templates['taxon_label'] = '{taxon}<br/><img src="' . $base . drupal_get_path('module', 'iform') . '/client_helpers/prebuilt_forms/images/ofs_pollinator/{taxonComp}.png" alt="[{taxon} Image]">';
     // load taxon list
     // load attributes.
     $options = data_entry_helper::get_species_checklist_options($options);
     //make a copy of the options so that we can maipulate it
     $overrideOptions = $options;
     $occAttrControls = array();
     $occAttrs = array();
     $taxonRows = array();
     // at this stage no preloading: no editing of existing data.
     // load the full list of species for the grid, including the main checklist plus any additional species in the reloaded occurrences.
     $taxalist = self::get_species_checklist_taxa_list($options, $taxonRows);
     // If we managed to read the species list data we can proceed
     if (!array_key_exists('error', $taxalist)) {
         $attrOptions = array('id' => null, 'valuetable' => 'occurrence_attribute_value', 'attrtable' => 'occurrence_attribute', 'key' => 'occurrence_id', 'fieldprefix' => "sc:-idx-::occAttr", 'extraParams' => $options['readAuth'], 'survey_id' => array_key_exists('survey_id', $options) ? $options['survey_id'] : null);
         $attributes = data_entry_helper::getAttributes($attrOptions);
         // Get the attribute and control information required to build the custom occurrence attribute columns
         data_entry_helper::species_checklist_prepare_attributes($options, $attributes, $occAttrControls, $occAttrs);
         $grid = "\n";
         // No look up list -> no cloneable row
         $grid .= '<table class="ui-widget ui-widget-content species-grid ' . $options['class'] . '" id="' . $options['id'] . '">';
         $visibleColIdx = 0;
         $grid .= "<thead class=\"ui-widget-header\"><tr><th>Wings</th><th>Other Features</th>";
         for ($i = 0; $i < $options['columns']; $i++) {
             $grid .= self::get_species_checklist_col_header($options['id'] . "-species-{$i}", lang::get('species_checklist.species'), $visibleColIdx, $options['colWidths'], '', '');
             $grid .= self::get_species_checklist_col_header($options['id'] . "-present-{$i}", lang::get('species_checklist.present'), $visibleColIdx, $options['colWidths'], 'display:none', '');
             foreach ($occAttrs as $idx => $a) {
                 $filename = preg_replace('/\\s+/', '-', strtolower($a));
                 $grid .= self::get_species_checklist_col_header($options['id'] . "-attr{$idx}-{$i}", lang::get($a), $visibleColIdx, $options['colWidths'], '', $base . drupal_get_path('module', 'iform') . '/client_helpers/prebuilt_forms/images/ofs_pollinator/' . $filename . '.png');
             }
         }
         $grid .= '</tr></thead>';
         $rows = array();
         $taxonCounter = array();
         $rowIdx = 0;
         $grid .= "\n<tbody>\n";
         if (count($taxonRows)) {
             $grid .= '<tr class="top"><td rowspan="2" class="dot-right"><b>No obvious wings</b></td><td>Antennae short</td>' . self::dump_one_row(0, $taxonRows[0], $taxalist, $taxonRows, $occAttrControls, $attributes, $options) . '</tr>';
         }
         if (count($taxonRows) > 1) {
             $grid .= '<tr class="dot-top"><td>Antennae varying lengths</td>' . self::dump_one_row(1, $taxonRows[1], $taxalist, $taxonRows, $occAttrControls, $attributes, $options) . '</tr>';
         }
         if (count($taxonRows) > 2) {
             $grid .= '<tr class="top"><td rowspan="2" class="dot-right"><b>One pair of wings</b><br/>One pair of wings, usually clear<br />Wings, held out from or held along the body</td><td rowspan="2" class="scOtherFeaturesCell" >Antennae usually short<br/><img src="' . $base . drupal_get_path('module', 'iform') . '/client_helpers/prebuilt_forms/images/ofs_pollinator/short-antennae.png" alt=""></td>' . self::dump_one_row(2, $taxonRows[2], $taxalist, $taxonRows, $occAttrControls, $attributes, $options) . '</tr>';
         }
         if (count($taxonRows) > 3) {
             $grid .= '<tr class="dot-top">' . self::dump_one_row(3, $taxonRows[3], $taxalist, $taxonRows, $occAttrControls, $attributes, $options) . '</tr>';
         }
         if (count($taxonRows) > 4) {
             $grid .= '<tr class="top"><td class="dot-right"><b>Two pairs of wings</b><br/>Two pairs of wings, coloured</td><td>Antennae usually long</td>' . self::dump_one_row(4, $taxonRows[4], $taxalist, $taxonRows, $occAttrControls, $attributes, $options) . '</tr>';
         }
         if (count($taxonRows) > 5) {
             $grid .= '<tr class="dot-top"><td rowspan="2" class="dot-right">Two pairs of wings, usually clear<br/>Wings held out from or held along body</td><td rowspan="2" class="scOtherFeaturesCell" >Antennae usually long<br/><img src="' . $base . drupal_get_path('module', 'iform') . '/client_helpers/prebuilt_forms/images/ofs_pollinator/long-antennae.png" alt=""></td>' . self::dump_one_row(5, $taxonRows[5], $taxalist, $taxonRows, $occAttrControls, $attributes, $options) . '</tr>';
         }
         if (count($taxonRows) > 6) {
             $grid .= '<tr class="dot-top">' . self::dump_one_row(6, $taxonRows[6], $taxalist, $taxonRows, $occAttrControls, $attributes, $options) . '</tr>';
         }
         $txnID = 7;
         if (count($taxonRows) > $txnID) {
             $grid .= '<tr class="top"><td class="dot-right"><b>?</b></td><td></td>' . '<td class="scTaxonCell">Unknown Other?</td>' . '<td style="display:none" class="scPresenceCell"><input type="hidden" value="' . $taxonRows[$txnID]["ttlId"] . '" id="sc:' . $options['id'] . '-' . $txnID . '::present" name="sc:' . $options['id'] . '-' . $txnID . '::present"></td>' . '<td class="scOccAttrCell ui-widget-content scComment" colspan="' . count($attributes) . '"><input type="text" value="" name="sc:' . $options['id'] . '-' . $txnID . '::comment" id="sc:' . $options['id'] . '-' . $txnID . '::comment"></td></tr>';
         }
         $grid .= "</tbody>\n</table>\n";
         $grid .= '<input name="rowInclusionCheck" value="hasData" type="hidden" />';
         $r .= $grid;
         return $r;
     } else {
         return $taxalist['error'];
     }
 }