From 81135ba11c2e53081ccdd3a7d6a766051f666f4e Mon Sep 17 00:00:00 2001 From: dc Date: Wed, 25 Aug 2021 18:37:05 -0400 Subject: [PATCH 1/4] adds hook to em for interactive dropdowns after pubmed search --- PubmedSearchExternalModule.php | 269 +++++++++++++++++++++++++++------ README.md | 39 +++++ ajax.php | 18 +++ config.json | 65 +++++++- css/lookup-assistant.css | 6 + css/select2-bootstrap.min.css | 8 + css/select2.min.css | 1 + emLoggerTrait.php | 118 +++++++++++++++ js/lookupAssistant.js | 195 ++++++++++++++++++++++++ js/select2.full.min.js | 2 + test.php | 6 - test3.php | 6 - 12 files changed, 669 insertions(+), 64 deletions(-) create mode 100644 ajax.php create mode 100644 css/lookup-assistant.css create mode 100644 css/select2-bootstrap.min.css create mode 100644 css/select2.min.css create mode 100644 emLoggerTrait.php create mode 100644 js/lookupAssistant.js create mode 100644 js/select2.full.min.js delete mode 100644 test.php delete mode 100644 test3.php diff --git a/PubmedSearchExternalModule.php b/PubmedSearchExternalModule.php index 06b4ec6..a3d6f88 100644 --- a/PubmedSearchExternalModule.php +++ b/PubmedSearchExternalModule.php @@ -4,27 +4,34 @@ use ExternalModules\AbstractExternalModule; use ExternalModules\ExternalModules; +use \REDCap as REDCap; +require_once("emLoggerTrait.php"); + define('SLEEP_TIME', 1); define('MAX_RETRIES', 5); class PubmedSearchExternalModule extends AbstractExternalModule { public function getPids() { - $sql="SELECT DISTINCT(s.project_id) AS project_id FROM redcap_external_modules m, redcap_external_module_settings s INNER JOIN redcap_projects AS p ON p.project_id = s.project_id WHERE p.date_deleted IS NULL AND m.external_module_id = s.external_module_id AND s.value = 'true' AND m.directory_prefix = 'pubmedSearch' AND s.`key` = 'enabled'"; - $q = db_query($sql); - - if ($error = db_error()) { - error_log("PubmedSearchExternalModule ERROR: $error"); - } - - $pids = array(); - while ($row = db_fetch_assoc($q)) { - $pids[] = $row['project_id']; - } - return $pids; + $sql="SELECT DISTINCT(s.project_id) AS project_id FROM redcap_external_modules m, redcap_external_module_settings s INNER JOIN redcap_projects AS p ON p.project_id = s.project_id WHERE p.date_deleted IS NULL AND m.external_module_id = s.external_module_id AND s.value = 'true' AND m.directory_prefix = 'pubmed_search' AND s.`key` = 'enabled'"; + $q = db_query($sql); + + if ($error = db_error()) { + error_log("PubmedSearchExternalModule ERROR: $error"); + } + + $pids = array(); + while ($row = db_fetch_assoc($q)) { + $pids[] = $row['project_id']; + } + return $pids; } public function pubmed() { + // check if cron is enabled in settings + if( ! $this->settings['enable-cron']){ + return; + } $pids = $this->getPids(); error_log("PubmedSearchExternalModule::pubmed with ".json_encode($pids)); foreach ($pids as $pid) { @@ -32,7 +39,7 @@ public function pubmed() { } } - public function pubmedRun($pid) { + public function pubmedRun($pid, $specific_record=null) { error_log("PubmedSearchExternalModule::pubmedRun with $pid"); # field names $firstName = $this->getProjectSetting("first_name", $pid); @@ -56,8 +63,11 @@ public function pubmedRun($pid) { array_push($fields, $institutionField); } } - - $json = \REDCap::getData($pid, "json", NULL, $fields); + if (is_null($specific_record)){ + $json = \REDCap::getData($pid, "json", NULL, $fields); + }else{ + $json = \REDCap::getData($pid, "json", [$specific_record['record_id']], $fields); + } $data = json_decode($json, true); # organize the data @@ -102,31 +112,69 @@ public function pubmedRun($pid) { # process the data $upload = array(); foreach ($names as $values) { - $row = self::getPubMed( $values[$firstName], - $values[$lastName], - $institutions[$values[$recordId]], - json_decode($values[$helper]), - $values[$citations], - $citations, - $helper); - - if ($row && $row[$helper] && $row[$citations]) { - array_push($upload, array( $recordId => $values[$recordId], - $helper => $row[$helper], - $citations => $row[$citations], - $citationsCount => count(explode("\n", $row[$citations])), - )); + if (is_null($specific_record)){ + $row = self::getPubMed( $values[$firstName], + $values[$lastName], + $institutions[$values[$recordId]], + json_decode($values[$helper]), + $values[$citations], + $citations, + $helper); + }else{ + $inst = $institutions[$values[$recordId]]; + if (! in_array($specific_record['institution'], $inst)){ + $inst[] = $specific_record['institution']; + } + $row = self::getPubMed( + $specific_record['first'], + $specific_record['last'], + $inst, + json_decode($values[$helper]), + $values[$citations], + $citations, + $helper, true); + } + + if ($row && $row[$helper] && $row[$citations]) { + array_push($upload, array( $recordId => $values[$recordId], + $helper => $row[$helper], + $citations => $row[$citations], + $citationsCount => count(explode("\n", $row[$citations])), + )); } } error_log("PubmedSearchExternalModule upload: ".count($upload)." rows"); + // if it's a brand new redcap record, recordid will be null, so will $names + if(!is_null($specific_record) && is_null($specific_record['record_id'])){ + $row = self::getPubMed( + $specific_record['first'], + $specific_record['last'], + $specific_record['institution'], + "", + "", + $citations, + $helper, + true); + if ($row && $row[$helper] && $row[$citations]) { + array_push($upload, array( $recordId => $values[$recordId], + $helper => $row[$helper], + $citations => $row[$citations], + $citationsCount => count(explode("\n", $row[$citations])), + )); + } + } + if (!empty($upload)) { - $feedback = \REDCap::saveData($pid, "json", json_encode($upload)); - error_log("PubmedSearchExternalModule upload: ".json_encode($feedback)); + if (is_null($specific_record) && $this->settings['enable-cron']){ + $feedback = \REDCap::saveData($pid, "json", json_encode($upload)); + error_log("PubmedSearchExternalModule upload: ".json_encode($feedback)); + } } + return json_encode($upload); } - public static function getPubMed($firstName, $lastName, $institutions, $prevCitations, $citationsStr, $citationField, $citationIdField) { + public static function getPubMed($firstName, $lastName, $institutions, $prevCitations, $citationsStr, $citationField, $citationIdField, $deltas=false) { $cs = explode("\n", $citationsStr); $citations = array(); foreach ($cs as $c) { @@ -134,7 +182,7 @@ public static function getPubMed($firstName, $lastName, $institutions, $prevCita array_push($citations, $c); } } - + $upload = array(); $total = 0; $totalNew = 0; @@ -181,15 +229,15 @@ public static function getPubMed($firstName, $lastName, $institutions, $prevCita $output = curl_exec($ch); curl_close($ch); sleep(SLEEP_TIME); - + $pmData = json_decode($output, true); if ($pmData['esearchresult'] && $pmData['esearchresult']['idlist']) { # if the errorlist is not blank, it might search for simplified # it might search for simplified names and produce bad results if (!isset($pmData['esearchresult']['errorlist']) - || !$pmData['esearchresult']['errorlist'] - || !$pmData['esearchresult']['errorlist']['phrasesnotfound'] - || empty($pmData['esearchresult']['errorlist']['phrasesnotfound'])) { + || !$pmData['esearchresult']['errorlist'] + || !$pmData['esearchresult']['errorlist']['phrasesnotfound'] + || empty($pmData['esearchresult']['errorlist']['phrasesnotfound'])) { foreach ($pmData['esearchresult']['idlist'] as $pmid) { if (!in_array($pmid, $pmids)) { $pmids[] = $pmid; @@ -210,7 +258,7 @@ public static function getPubMed($firstName, $lastName, $institutions, $prevCita } $total += count($pmids); $totalNew += count($pmidsUnique); - + $citations = array(); if (!empty($pmidsUnique)) { $pullSize = 10; @@ -234,7 +282,7 @@ public static function getPubMed($firstName, $lastName, $institutions, $prevCita curl_close($ch); sleep(SLEEP_TIME); $data = json_decode($output, true); - + # indexed by PMID $pmcids = array(); foreach ($data['records'] as $record) { @@ -242,7 +290,7 @@ public static function getPubMed($firstName, $lastName, $institutions, $prevCita $pmcids[$record['pmid']] = $record['pmcid']; } } - + $retry = 0; do { $url = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&retmode=xml&id=".implode(",", $pmidsUniqueForPull); @@ -301,11 +349,19 @@ public static function getPubMed($firstName, $lastName, $institutions, $prevCita } } } - $newCitationIds = array_merge($prevCitations, $pmidsUnique); - $uploadRow = array( - $citationIdField => self::json_encode_with_spaces($newCitationIds), - $citationField => implode("\n", $citations), - ); + // + if (! $deltas){ + $newCitationIds = array_merge($prevCitations, $pmidsUnique); + $uploadRow = array( + $citationIdField => self::json_encode_with_spaces($newCitationIds), + $citationField => implode("\n", $citations), + ); + }else{ + $uploadRow = array( + $citationIdField => json_encode($pmidsUnique), + $citationField => json_encode($citations), + ); + } return $uploadRow; } @@ -314,4 +370,127 @@ private static function json_encode_with_spaces($data) { $str = preg_replace("/,/", ", ", $str); return $str; } + + // THESE FUNCTIONS BORROWED FROM LOOKUP ASSISTANT + public $errors = array(); + public $settings = array(); + + private function validateJson($contents) { + // // Verify file exists + // if (file_exists($path)) { + // $contents = file_get_contents($path); + + // Verify contents are json + $obj = json_decode($contents); + + if (json_last_error() == JSON_ERROR_NONE) { + // All good + return $contents; + } else { + $this->emError("Error decoding JSON", json_last_error_msg()); + return false; + // $this->errors[] = "Error decoding path $path: " . json_last_error_msg(); + } + + // } else { + // $this->errors[] = "Unable to locate file $path"; + // } + // return false; + } + + + // Take the project settings and convert them into a more friendly settings object to pass to javascript + public function loadSettings($instrument) { + $set = $this->getProjectSettings(); + $set['module-path'] = $this->getPostURL(); + $set['test-path'] = $this->getTestURL(); + $set['record_id'] = $this->getRecordId(); + $this->settings[] = $set; + } + + function injectLookup($instrument) + { + $this->loadSettings($instrument); + if (!empty($this->errors)) { + $this->emDebug($this->errors); + return false; + } + + // Skip out if there is nothing to do + if (empty($this->settings)) return false; + + // DUMP CONTENTS TO JAVASCRIPT + // Append the select2 controls + $this->insertSelect2(); + + echo ""; + + // // Insert our custom JS + echo ""; + + // Insert our custom JS + echo ""; + echo ""; + ?> + + settings['enable-cron']){ + $this->injectLookup($instrument); + } + } + + + function redcap_survey_page_top($project_id, $record, $instrument, $event_id, $group_id) + { + if( ! $this->settings['enable-cron']){ + $this->injectLookup($instrument); + } + } + + + public function insertSelect2() + { + ?> + + + + getModulePath() . $name; + if (file_exists($file)) { + $contents = file_get_contents($file); + return $contents; + } else { + $this->emError("Unable to find $file"); + } + } + + public function getPostURL(){ + return $this->getUrl("ajax.php", false, false); + // return $this->getUrl("PubmedSearchExternalModule.php", false, false); + // return $this->getModulePath(); + } + public function getTestURL(){ + return $this->getUrl("test.xml", false, false); + // return $this->getUrl("PubmedSearchExternalModule.php", false, false); + // return $this->getModulePath(); + } } diff --git a/README.md b/README.md index 7247867..b307c8e 100644 --- a/README.md +++ b/README.md @@ -20,3 +20,42 @@ A field of type 'notes box' needs to be created for the citations to be placed i Also, a field of type 'text box' needs to be created to store the number of citations that are downloaded. Finally, a field of type 'text box' needs to be created to store a record of which PubMed IDs have been downloaded so that duplicates aren't downloaded. (It is recommended that this final box use the field annotation of '@HIDDEN' so that it is hidden to users. It should not be manually modified; the script will do it all for you!) + +# Lookup Assistant + +This external module provides an easy way to find values from a large list +and add them to a REDCap input field. + +It supports a single group of choices or a nested hierarchy, such as the: +Year, Make, Model or see the example with Country, State, City. + +The 'hierarchy' file must be in JSON format and looks something like: +```json +{ + "United States": { + "Minnesota": { + "Minneapolis": "Minneapolis", + "St. Paul": "St. Paul", + }, + "California": { + "Fresno": "Fresno" + } + } +} +``` +Note that the last level should just have a value that matches the key. + +Only the last level is stored in the input field so it doesn't work backwards and you should probably design your +hierarchy so that it supports unique names for the last level. + +It might be useful to use this if you have a very large list of values to choose from. + + +## Options +When you skip a level in the hierarchy, there are two options. You can either not permit selection of a 'state' until +a 'country' is selected. Or, you can have all states merged into a single field when no country is selected. This +second option can cause delays if the hierarchy is large as the processing is done on the client. + +You can choose whether the final text entry field is editable or not. If it is editable, one can choose a value +that is not part of the lookup. So, you can try and reduce duplicate entries but still permit the entry of a value +not in your hierarchy. diff --git a/ajax.php b/ajax.php new file mode 100644 index 0000000..0a5d2e8 --- /dev/null +++ b/ajax.php @@ -0,0 +1,18 @@ +framework->getProjectId(); +$json_pubmeds = $module->pubmedRun($pid, $post_data); + +// echo json_encode($json_pubmeds); +print_r($json_pubmeds); +?> diff --git a/config.json b/config.json index 6d4923b..6bcc106 100755 --- a/config.json +++ b/config.json @@ -10,23 +10,51 @@ "name": "Scott J. Pearson", "email": "datacore@vumc.org", "institution": "Vanderbilt University Medical Center" + }, + { + "name": "Andy Martin", + "email": "andy123@stanford.edu", + "institution": "Stanford University" + }, + { + "name": "Jae Lee", + "email": "jael@stanford.edu", + "institution": "Stanford University" + }, + { + "name": "Devin Cowan", + "email": "devin.r.cowan@dartmouth.edu", + "institution": "Dartmouth College" } ], + "framework-version": 5, - "permissions": [ + "redcap_data_entry_form_top", + "hook_survey_page_top" ], + "no-auth-pages":["ajax"], + "links": { "project": [ - { - "name": "Test", + { + "name": "Test Pubmedsearch", "icon": "report", - "url": "test3.php" - } - ] + "url": "ajax.php" + } + ] }, + "system-settings": [ + { + "key": "enable-system-debug-logging", + "name": "Enable Debug Logging (system-wide)(optional) Requires installation and configuration of emLogger", + "required": false, + "type": "checkbox" + } + ], + "project-settings": [ { "key": "record_id", @@ -76,9 +104,32 @@ "required": true, "repeatable": true, "type": "field-list" + }, + { + "key": "edit-citations", + "name": "Make citations fields editable
By default, the fields marked as read-only to reduce confusion", + "required": false, + "type": "checkbox" + }, + { + "key": "enable-cron", + "name": "Enable CRON
By default, cron jobs are not enabled. If you enable, pubmed citations will be fetched on the backend at a regular interval and users will not be able to modify them.", + "required": false, + "type": "checkbox" + }, + { + "key": "enable-project-debug-logging", + "name": "Enable Debug Logging
(optional) Requires installation and configuration of emLogger", + "required": false, + "type": "checkbox" + }, + { + "key": "enable-js-debug", + "name": "Enable javascript debugging", + "required": false, + "type": "checkbox" } ], - "crons": [ { "cron_name": "pubmed_cron", diff --git a/css/lookup-assistant.css b/css/lookup-assistant.css new file mode 100644 index 0000000..ed7b9d0 --- /dev/null +++ b/css/lookup-assistant.css @@ -0,0 +1,6 @@ +input[disabled] { + color: #c0c0c0; + padding: 2px; + margin: 0 0 0 0; + background-image: none; +} diff --git a/css/select2-bootstrap.min.css b/css/select2-bootstrap.min.css new file mode 100644 index 0000000..f2f1198 --- /dev/null +++ b/css/select2-bootstrap.min.css @@ -0,0 +1,8 @@ +/*! + * Select2 Bootstrap Theme v0.1.0-beta.10 (https://select2.github.io/select2-bootstrap-theme) + * Copyright 2015-2017 Florian Kissling and contributors (https://github.com/select2/select2-bootstrap-theme/graphs/contributors) + * Licensed under MIT (https://github.com/select2/select2-bootstrap-theme/blob/master/LICENSE) + */ + +.select2-container--bootstrap{display:block}.select2-container--bootstrap .select2-selection{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);background-color:#fff;border:1px solid #ccc;border-radius:4px;color:#555;font-size:14px;outline:0}.select2-container--bootstrap .select2-selection.form-control{border-radius:4px}.select2-container--bootstrap .select2-search--dropdown .select2-search__field{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);background-color:#fff;border:1px solid #ccc;border-radius:4px;color:#555;font-size:14px}.select2-container--bootstrap .select2-search__field{outline:0}.select2-container--bootstrap .select2-search__field::-webkit-input-placeholder{color:#999}.select2-container--bootstrap .select2-search__field:-moz-placeholder{color:#999}.select2-container--bootstrap .select2-search__field::-moz-placeholder{color:#999;opacity:1}.select2-container--bootstrap .select2-search__field:-ms-input-placeholder{color:#999}.select2-container--bootstrap .select2-results__option{padding:6px 12px}.select2-container--bootstrap .select2-results__option[role=group]{padding:0}.select2-container--bootstrap .select2-results__option[aria-disabled=true]{color:#777;cursor:not-allowed}.select2-container--bootstrap .select2-results__option[aria-selected=true]{background-color:#f5f5f5;color:#262626}.select2-container--bootstrap .select2-results__option--highlighted[aria-selected]{background-color:#337ab7;color:#fff}.select2-container--bootstrap .select2-results__option .select2-results__option{padding:6px 12px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option{margin-left:-12px;padding-left:24px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-24px;padding-left:36px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-36px;padding-left:48px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-48px;padding-left:60px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-60px;padding-left:72px}.select2-container--bootstrap .select2-results__group{color:#777;display:block;padding:6px 12px;font-size:12px;line-height:1.42857143;white-space:nowrap}.select2-container--bootstrap.select2-container--focus .select2-selection,.select2-container--bootstrap.select2-container--open .select2-selection{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;border-color:#66afe9}.select2-container--bootstrap.select2-container--open .select2-selection .select2-selection__arrow b{border-color:transparent transparent #999;border-width:0 4px 4px}.select2-container--bootstrap.select2-container--open.select2-container--below .select2-selection{border-bottom-right-radius:0;border-bottom-left-radius:0;border-bottom-color:transparent}.select2-container--bootstrap.select2-container--open.select2-container--above .select2-selection{border-top-right-radius:0;border-top-left-radius:0;border-top-color:transparent}.select2-container--bootstrap .select2-selection__clear{color:#999;cursor:pointer;float:right;font-weight:700;margin-right:10px}.select2-container--bootstrap .select2-selection__clear:hover{color:#333}.select2-container--bootstrap.select2-container--disabled .select2-selection{border-color:#ccc;-webkit-box-shadow:none;box-shadow:none}.select2-container--bootstrap.select2-container--disabled .select2-search__field,.select2-container--bootstrap.select2-container--disabled .select2-selection{cursor:not-allowed}.select2-container--bootstrap.select2-container--disabled .select2-selection,.select2-container--bootstrap.select2-container--disabled .select2-selection--multiple .select2-selection__choice{background-color:#eee}.select2-container--bootstrap.select2-container--disabled .select2-selection--multiple .select2-selection__choice__remove,.select2-container--bootstrap.select2-container--disabled .select2-selection__clear{display:none}.select2-container--bootstrap .select2-dropdown{-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);border-color:#66afe9;overflow-x:hidden;margin-top:-1px}.select2-container--bootstrap .select2-dropdown--above{-webkit-box-shadow:0 -6px 12px rgba(0,0,0,.175);box-shadow:0 -6px 12px rgba(0,0,0,.175);margin-top:1px}.select2-container--bootstrap .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--bootstrap .select2-selection--single{height:34px;line-height:1.42857143;padding:6px 24px 6px 12px}.select2-container--bootstrap .select2-selection--single .select2-selection__arrow{position:absolute;bottom:0;right:12px;top:0;width:4px}.select2-container--bootstrap .select2-selection--single .select2-selection__arrow b{border-color:#999 transparent transparent;border-style:solid;border-width:4px 4px 0;height:0;left:0;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--bootstrap .select2-selection--single .select2-selection__rendered{color:#555;padding:0}.select2-container--bootstrap .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--bootstrap .select2-selection--multiple{min-height:34px;padding:0;height:auto}.select2-container--bootstrap .select2-selection--multiple .select2-selection__rendered{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;line-height:1.42857143;list-style:none;margin:0;overflow:hidden;padding:0;width:100%;text-overflow:ellipsis;white-space:nowrap}.select2-container--bootstrap .select2-selection--multiple .select2-selection__placeholder{color:#999;float:left;margin-top:5px}.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice{color:#555;background:#fff;border:1px solid #ccc;border-radius:4px;cursor:default;float:left;margin:5px 0 0 6px;padding:0 6px}.select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field{background:0 0;padding:0 12px;height:32px;line-height:1.42857143;margin-top:0;min-width:5em}.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:700;margin-right:3px}.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--bootstrap .select2-selection--multiple .select2-selection__clear{margin-top:6px}.form-group-sm .select2-container--bootstrap .select2-selection--single,.input-group-sm .select2-container--bootstrap .select2-selection--single,.select2-container--bootstrap .select2-selection--single.input-sm{border-radius:3px;font-size:12px;height:30px;line-height:1.5;padding:5px 22px 5px 10px}.form-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b,.input-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b,.select2-container--bootstrap .select2-selection--single.input-sm .select2-selection__arrow b{margin-left:-5px}.form-group-sm .select2-container--bootstrap .select2-selection--multiple,.input-group-sm .select2-container--bootstrap .select2-selection--multiple,.select2-container--bootstrap .select2-selection--multiple.input-sm{min-height:30px;border-radius:3px}.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice,.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice,.select2-container--bootstrap .select2-selection--multiple.input-sm .select2-selection__choice{font-size:12px;line-height:1.5;margin:4px 0 0 5px;padding:0 5px}.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field,.select2-container--bootstrap .select2-selection--multiple.input-sm .select2-search--inline .select2-search__field{padding:0 10px;font-size:12px;height:28px;line-height:1.5}.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear,.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear,.select2-container--bootstrap .select2-selection--multiple.input-sm .select2-selection__clear{margin-top:5px}.form-group-lg .select2-container--bootstrap .select2-selection--single,.input-group-lg .select2-container--bootstrap .select2-selection--single,.select2-container--bootstrap .select2-selection--single.input-lg{border-radius:6px;font-size:18px;height:46px;line-height:1.3333333;padding:10px 31px 10px 16px}.form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow,.input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow,.select2-container--bootstrap .select2-selection--single.input-lg .select2-selection__arrow{width:5px}.form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b,.input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b,.select2-container--bootstrap .select2-selection--single.input-lg .select2-selection__arrow b{border-width:5px 5px 0;margin-left:-10px;margin-top:-2.5px}.form-group-lg .select2-container--bootstrap .select2-selection--multiple,.input-group-lg .select2-container--bootstrap .select2-selection--multiple,.select2-container--bootstrap .select2-selection--multiple.input-lg{min-height:46px;border-radius:6px}.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice,.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice,.select2-container--bootstrap .select2-selection--multiple.input-lg .select2-selection__choice{font-size:18px;line-height:1.3333333;border-radius:4px;margin:9px 0 0 8px;padding:0 10px}.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field,.select2-container--bootstrap .select2-selection--multiple.input-lg .select2-search--inline .select2-search__field{padding:0 16px;font-size:18px;height:44px;line-height:1.3333333}.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear,.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear,.select2-container--bootstrap .select2-selection--multiple.input-lg .select2-selection__clear{margin-top:10px}.input-group-lg .select2-container--bootstrap .select2-selection.select2-container--open .select2-selection--single .select2-selection__arrow b,.select2-container--bootstrap .select2-selection.input-lg.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #999;border-width:0 5px 5px}.select2-container--bootstrap[dir=rtl] .select2-selection--single{padding-left:24px;padding-right:12px}.select2-container--bootstrap[dir=rtl] .select2-selection--single .select2-selection__rendered{padding-right:0;padding-left:0;text-align:right}.select2-container--bootstrap[dir=rtl] .select2-selection--single .select2-selection__clear{float:left}.select2-container--bootstrap[dir=rtl] .select2-selection--single .select2-selection__arrow{left:12px;right:auto}.select2-container--bootstrap[dir=rtl] .select2-selection--single .select2-selection__arrow b{margin-left:0}.select2-container--bootstrap[dir=rtl] .select2-selection--multiple .select2-search--inline,.select2-container--bootstrap[dir=rtl] .select2-selection--multiple .select2-selection__choice,.select2-container--bootstrap[dir=rtl] .select2-selection--multiple .select2-selection__placeholder{float:right}.select2-container--bootstrap[dir=rtl] .select2-selection--multiple .select2-selection__choice{margin-left:0;margin-right:6px}.select2-container--bootstrap[dir=rtl] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.has-warning .select2-dropdown,.has-warning .select2-selection{border-color:#8a6d3b}.has-warning .select2-container--focus .select2-selection,.has-warning .select2-container--open .select2-selection{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;border-color:#66512c}.has-warning.select2-drop-active{border-color:#66512c}.has-warning.select2-drop-active.select2-drop.select2-drop-above{border-top-color:#66512c}.has-error .select2-dropdown,.has-error .select2-selection{border-color:#a94442}.has-error .select2-container--focus .select2-selection,.has-error .select2-container--open .select2-selection{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;border-color:#843534}.has-error.select2-drop-active{border-color:#843534}.has-error.select2-drop-active.select2-drop.select2-drop-above{border-top-color:#843534}.has-success .select2-dropdown,.has-success .select2-selection{border-color:#3c763d}.has-success .select2-container--focus .select2-selection,.has-success .select2-container--open .select2-selection{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;border-color:#2b542c}.has-success.select2-drop-active{border-color:#2b542c}.has-success.select2-drop-active.select2-drop.select2-drop-above{border-top-color:#2b542c}.input-group>.select2-hidden-accessible:first-child+.select2-container--bootstrap>.selection>.select2-selection,.input-group>.select2-hidden-accessible:first-child+.select2-container--bootstrap>.selection>.select2-selection.form-control{border-bottom-right-radius:0;border-top-right-radius:0}.input-group>.select2-hidden-accessible:not(:first-child)+.select2-container--bootstrap:not(:last-child)>.selection>.select2-selection,.input-group>.select2-hidden-accessible:not(:first-child)+.select2-container--bootstrap:not(:last-child)>.selection>.select2-selection.form-control{border-radius:0}.input-group>.select2-hidden-accessible:not(:first-child):not(:last-child)+.select2-container--bootstrap:last-child>.selection>.select2-selection,.input-group>.select2-hidden-accessible:not(:first-child):not(:last-child)+.select2-container--bootstrap:last-child>.selection>.select2-selection.form-control{border-bottom-left-radius:0;border-top-left-radius:0}.input-group>.select2-container--bootstrap{display:table;table-layout:fixed;position:relative;z-index:2;width:100%;margin-bottom:0}.input-group>.select2-container--bootstrap>.selection>.select2-selection.form-control{float:none}.input-group>.select2-container--bootstrap.select2-container--focus,.input-group>.select2-container--bootstrap.select2-container--open{z-index:3}.input-group>.select2-container--bootstrap,.input-group>.select2-container--bootstrap .input-group-btn,.input-group>.select2-container--bootstrap .input-group-btn .btn{vertical-align:top}.form-control.select2-hidden-accessible{position:absolute!important;width:1px!important}@media (min-width:768px){.form-inline .select2-container--bootstrap{display:inline-block}} + diff --git a/css/select2.min.css b/css/select2.min.css new file mode 100644 index 0000000..7c18ad5 --- /dev/null +++ b/css/select2.min.css @@ -0,0 +1 @@ +.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px;padding:1px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right;margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb} diff --git a/emLoggerTrait.php b/emLoggerTrait.php new file mode 100644 index 0000000..586f54a --- /dev/null +++ b/emLoggerTrait.php @@ -0,0 +1,118 @@ +Enable Debug Logging (system-wide)(optional) Requires installation and configuration of emLogger", +"required": false, +"type": "checkbox" +}, + +], + +"project-settings": [ + +{ +"key": "enable-project-debug-logging", +"name": "Enable Debug Logging
(optional) Requires installation and configuration of emLogger", +"required": false, +"type": "checkbox" +}, + +], + + */ + +trait emLoggerTrait +{ + private $emLoggerEnabled = null; // Cache logger enabled + private $emLoggerDebug = null; // Cache debug mode + + + /** + * Obtain an instance of emLogger or false if not installed / active + * @return bool|mixed + */ + function emLoggerInstance() { + + // This is the first time used, see if it is enabled on server + if (is_null($this->emLoggerEnabled)) { + $versions = \ExternalModules\ExternalModules::getEnabledModules(); + $this->emLoggerEnabled = isset($versions['em_logger']); + } + + // Return instance if enabled + if ($this->emLoggerEnabled) { + // Try to return the instance of emLogger (which is cached by the EM framework) + try { + return \ExternalModules\ExternalModules::getModuleInstance('em_logger'); + } catch (\Exception $e) { + // Unable to initialize em_logger + error_log("Exception caught - unable to initialize emLogger in " . __NAMESPACE__ . "/" . __FILE__ . "!"); + $this->emLoggerEnabled = false; + } + } + return false; + } + + + /** + * Determine if we are in debug mode either on system or project level and cache + * @return bool + */ + function emLoggerDebugMode() { + // Set if debug mode once on the first log call + if (is_null($this->emLoggerDebug)) { + $systemDebug = $this->getSystemSetting('enable-system-debug-logging'); + $projectDebug = !empty($_GET['pid']) && $this->getProjectSetting('enable-project-debug-logging'); + $this->emLoggerDebug = $systemDebug || $projectDebug; + } + return $this->emLoggerDebug; + } + + + /** + * Do the logging + * The reason we broke it into three functions was to reduce complexity with backtrace and the calling function + */ + function emLog() { + if ($emLogger = $this->emLoggerInstance()) $emLogger->emLog($this->PREFIX, func_get_args(), "INFO"); + } + + + /** + * Wrapper for logging an error + */ + function emError() { + if ($emLogger = $this->emLoggerInstance()) $emLogger->emLog($this->PREFIX, func_get_args(), "ERROR"); + } + + + /** + * Wrapper for logging debug statements + */ + function emDebug() { + if (($emLogger = $this->emLoggerInstance())) { + $emLogger->emLog($this->PREFIX, func_get_args(), "DEBUG"); + } + } + +} diff --git a/js/lookupAssistant.js b/js/lookupAssistant.js new file mode 100644 index 0000000..687af48 --- /dev/null +++ b/js/lookupAssistant.js @@ -0,0 +1,195 @@ +var lookupAssistant = lookupAssistant || {}; +var langMsg68 = ''; + + +lookupAssistant.init = function() { + + setting = lookupAssistant.settings[0]; + + lookupAssistant.log("Setting up field: " + setting.citations); + + // Make a pointer for each of the input fields + $.each(lookupAssistant.settings[0], function(k, v){ + lookupAssistant[k] = $('[name="' + v + '"]'); + lookupAssistant[k].addClass('pubmed_search_field'); + }); + + var r= $('