<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>FHIR Terminology exemplars with Ontoserver</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta name="description" content="Sample code for illustrating use of FHIR's /VAlueSet/$expand" />
  <meta name="author" content="CSIRO" />
  <!-- Le styles -->
  <link data-require="bootstrap@*" data-semver="4.1.3" rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" />
  <link href="style.css" rel="stylesheet" />
  <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
  <!--[if lt IE 9]>
      <script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
  <script data-require="jquery" data-semver="3.2.1" src="https://cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js"></script>
  <script data-require="bootstrap" data-semver="4.1.3" src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
  <script src="script.js"></script>
</head>

<body>
  <div class="container-fluid" style="margin-bottom:5rem;">
    <h2>SNOMED ECL-based ValueSets</h2>
    <p>
      This page allows you to explore the use of SNOMED's ECL expressions via the
      <a href="http://hl7.org/fhir/STU3/valueset-operations.html#expand"><tt>/ValueSet/$expand</tt></a> operation
      on SNOMED Implicit ValueSets.
    </p>
    <p>
      To use it, you can either click on a row in the table below to pre-populate the ECL or manually enter/alter the expression.
      Note that the <tt>| display text |</tt>, while valid in ECL, is not strictly permitted in an Implicit ValueSet URI,
      however Ontoserver is forgiving and does allow it.
    </p>
    <p>
      To test the operation, click the <b>Expand</b> button to issue the appropriate <tt>/ValueSet/$expand</tt> call to Ontoserver.
      The actual request URL and the results will be displayed below.
      Note that the <tt>count</tt> parameter is being used to limit the number of concepts returned to 20.
    </p>
    <table class="table table-striped table-sm table-hover">
      <thead class="thead-dark">
        <tr>
          <th>ECL expression examples</th>
        </tr>
      </thead>
      <tbody>
        <tr onclick="preload('MemberOf 32570481000036109')" class="">
          <td><tt>MemberOf 32570481000036109 |Emergency department diagnosis reference set|</tt></td>
        </tr>
        <tr onclick="preload('< 80146002')" class="">
          <td><tt>&lt;&lt; 80146002 |Appendicitis|</tt></td>
        </tr>
        <tr onclick="preload('DescendantOf 80146002')" class="">
          <td><tt>DescendantOf 80146002</tt></td>
        </tr>
        <tr onclick="preload('<< 80146002')" class="">
          <td><tt>&lt;&lt; 80146002 |Appendicitis|</tt></td>
        </tr>
        <tr onclick="preload('DescendantOrSelfOf 80146002')" class="">
          <td><tt>DescendantOrSelfOf 80146002</tt></td>
        </tr>
        <tr onclick="preload('< 19829001 AND < 301867009')" class="">
          <td><tt>&lt; 19829001 |Disorder of lung| AND &lt; 301867009 |Edema of trunk|</tt></td>
        </tr>
        <tr onclick="preload('< 19829001 OR < 301867009')" class="">
          <td><tt>&lt; 19829001 |Disorder of lung| OR &lt; 301867009 |Edema of trunk|</tt></td>
        </tr>
        <tr onclick="preload('< 19829001 MINUS < 301867009')" class="">
          <td><tt>&lt; 19829001 |Disorder of lung| MINUS &lt; 301867009 |Edema of trunk|</tt></td>
        </tr>
        <tr onclick="preload('<<404684003 : <<47429007 = <<267038008')" class="">
          <td><tt>&lt;&lt; 404684003 |Clinical finding| :<br>
            &nbsp;&nbsp;&nbsp;&nbsp;&lt;&lt; 47429007 |Associated with| = &lt;&lt; 267038008 |Edema|</tt></td>
        </tr>
      </tbody>
    </table>
    <form class="clearfix">
      <div class="form-group row">
        <div class="col-sm-12">
          <tt>
            <textarea class="form-control" id="ecl" placeholder="Enter ECL expression or select one from above"></textarea>
          </tt>
        </div>
      </div>
      <button type="button" class="btn btn-primary float-right" onclick="expand()">Expand</button>
    </form>

    <a class="clear-both" id="requestLink" target="_blank" href=""><pre class="mt-3" id="requestUrl"></pre></a>
    <table class="table table-sm mt-3" id="resultTable">
    </table>
    <pre class="mt-3 bg-light" id="resultJson"></pre>

  </div>
  <!-- /container -->
  <nav class="navbar fixed-bottom navbar-light bg-light">
    <div class="small">
      <a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons Licence" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a>
      <br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">This exemplar</span> by <span xmlns:cc="http://creativecommons.org/ns#" property="cc:attributionName">CSIRO</span> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.
    </div>
  </nav>
</body>

</html>
var base = "https://tx.ontoserver.csiro.au/fhir";
// base = "http://tx.fhir.org/r3";
// base = "http://its.patientsfirst.org.nz/RestService.svc/Terminz";
// base = 'http://fhirtest.uhn.ca/baseDstu3';

function preload(ecl) {
  document.getElementById("ecl").value = ecl || '';
}

function expand() {
  var ecl = document.getElementById("ecl").value;

  // console.log(system, code, display);

  function reqListener() {
    var resultJson = document.getElementById("resultJson");
    resultJson.textContent = this.responseText;

    var table = document.getElementById("resultTable");
    while (table.firstChild) {
      table.removeChild(table.firstChild);
    }

    var json;
    try {
      json = JSON.parse(this.responseText);
    } catch (err) {
      console.log('response', this.response);
      throw err;
    }

    if ('ValueSet' === json.resourceType) {
      
      function append(row, elt, text) {
        var item = document.createElement(elt);
        item.textContent = text;
        row.append(item);
        return row;
      }
      
      var hrow1 = document.createElement('tr');
      var header = document.createElement('th');
      header.setAttribute('colspan', 3);
      header.textContent = "Total matches: " + json.expansion.total;
      hrow1.append(header);
      table.append(hrow1);
      
      var hrow2 = document.createElement('tr');
      append(hrow2, 'th', 'System');
      append(hrow2, 'th', 'Code');
      append(hrow2, 'th', 'Display');
      table.append(hrow2);
      
      json.expansion.contains.forEach(function(c) {
        var row = document.createElement('tr');
        var system = document.createElement('td');
        system.innerHTML = "<tt>"+c.system+"</tt>";
        var code = document.createElement('td');
        code.innerHTML = "<tt class=\"font-weight-bold\">"+c.code+"</tt>";
        var display = document.createElement('td');
        display.textContent = c.display;

        row.appendChild(system);
        row.appendChild(code);
        row.appendChild(display);
        table.appendChild(row);
      });
      
      if (json.expansion.total > json.expansion.contains.length) {
        var frow = document.createElement('tr');
        var footer = document.createElement('th');
        footer.setAttribute('colspan', 3);
        footer.textContent = "remainder of results omitted...";
        frow.append(footer);
        table.append(frow);
      }
      
    } else if ('OperationOutcome' === json.resourceType) {
      // [{"severity":"error","code":"invalid","diagnostics":"[a95793f4-31bd-4f7f-8a92-947444f23bfb]: ValueSet url cannot be empty."}]
      json.issue.forEach(function (i) {
        var row = document.createElement('tr');
        if ('error' === i.severity) {
          row.classList.add('table-danger');
          row.classList.remove('table-warning');
          row.classList.remove('table-info');
        } else if ('warning' === i.severity) {
          row.classList.add('table-warning');
          row.classList.remove('table-danger');
          row.classList.remove('table-info');
        } else {
          row.classList.add('table-info');
          row.classList.remove('table-danger');
          row.classList.remove('table-warning');
        }
        var code = document.createElement('td');
        code.textContent = i.code;
        var diagnostic = document.createElement('td');
        diagnostic.textContent = i.diagnostics;

        row.appendChild(code);
        row.appendChild(diagnostic);
        table.appendChild(row);
      });
    }

    resultJson.textContent = JSON.stringify(json, null, 2);
  }

  var request = "/ValueSet/$expand?url=" + encodeURIComponent("http://snomed.info/sct?fhir_vs=ecl/" + ecl) + "&count=20";

  document.getElementById("requestLink").href = base + request;
  document.getElementById("requestUrl").textContent = "[base]" + request;

  var oReq = new XMLHttpRequest();
  oReq.addEventListener("load", reqListener);
  oReq.open("GET", base + request + "&_format=json");
  oReq.send();

}
/* Put your css in here */
pre {
 white-space: pre-wrap;       /* css-3 */
 white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
 white-space: -pre-wrap;      /* Opera 4-6 */
 white-space: -o-pre-wrap;    /* Opera 7 */
 word-wrap: break-word;       /* Internet Explorer 5.5+ */
}