static/js/select.js
/**
 * Build info table based on the dataset and selected contigs.
 * @function buildInfoTable
 * @param {Object} mo - main object
 * @description It re-draws the entire info table to reflect updates in the
 * dataset (e.g., loaded a new dataset; added a new column).
 * 
 * Fields (rows) displayed in the table are determined based on the type and
 * names of data fields.
 * 
 * Each row of the table has five data attributes:
 * - idx: index of data field that is displayed
 * - ref: index of data field that serves as reference
 * - met: how to summarize multiple values; sum or mean
 */
Build info table based on the dataset and selected contigs.
@function buildInfoTable
@param {Object} mo - main object
@description It re-draws the entire info table to reflect updates in the
dataset .

Fields (rows) displayed in the table are determined based on the type and
names of data fields.

Each row of the table has five data attributes:
- idx: index of data field that is displayed
- ref: index of data field that serves as reference
- met: how to summarize multiple values; sum or mean
Build info table based on the dataset and selected contigs . @function buildInfoTable @param { Object } mo - main object @description It re - draws the entire info table to reflect updates in the dataset . Fields ( rows ) displayed in the table are determined based on the type and names of data fields . Each row of the table has five data attributes : - idx : index of data field that is displayed - ref : index of data field that serves as reference - met : how to summarize multiple values ; sum or mean
function buildInfoTable(mo) {
  const table = byId('info-table');
  const div = byId('info-ctrl');
  div.classList.add('hidden');
  const sel = byId('info-ref-sel');
  sel.innerHTML = '';
  sel.add(document.createElement('option'));
  table.innerHTML = '';
  const names = mo.cols.names,
        types = mo.cols.types;
  const splen = mo.cache.splen;
  const n = names.length;
  let name, type, row, metric;
  for (let i = 1; i < n; i++) {
    name = names[i];
    type = types[i];
    if (type.endsWith('wt')) continue;
    if (type === 'num') {
      const opt = document.createElement('option');
      opt.text = name;
      opt.value = i;
      sel.add(opt);
    }
    row = table.insertRow(-1);
    row.setAttribute('data-idx', i);
    const cell = row.insertCell(-1);
    cell.innerHTML = name;
    row.insertCell(-1);
    if (type === 'num') {
      metric = guessColMetric(name);
      if (metric.endsWith('by')) {
        row.setAttribute('data-met', metric.substring(0, metric.length - 2));
        row.setAttribute('data-ref', splen);
      }
      else {
        row.setAttribute('data-met', metric);
        row.setAttribute('data-ref', 0);
      }
    }
    else if (type === 'cat') {
      row.setAttribute('data-ref', splen);
    }
    row.addEventListener('mouseenter', function () {
      if (document.activeElement === sel) return false;
      const mbtn = byId('info-metric-btn'),
            pbtn = byId('info-plot-btn'),
            span = byId('info-ref-span');
      if (mo.cache.npick < 2) {
        for (let dom of [mbtn, pbtn, span]) dom.classList.add('hidden');
      }
      else {
        const type = mo.cols.types[parseInt(this.getAttribute('data-idx'))];
        if (type === 'num') {
          const metric = this.getAttribute('data-met');
          mbtn.title = 'Metric: ' + metric;
          sel.value = this.getAttribute('data-ref');
          mbtn.innerHTML = (metric === 'sum') ? '&Sigma;<i>x</i>' :
            '<span style="text-decoration: overline;"><i>x</i></span>';
          for (let dom of [mbtn, pbtn, span]) dom.classList.remove('hidden');
        }
        else if (type === 'cat') {
          sel.value = this.getAttribute('data-ref');
          span.classList.remove('hidden');
          for (let dom of [mbtn, pbtn]) dom.classList.add('hidden');
        }
        else {
          for (let dom of [mbtn, pbtn, span]) dom.classList.add('hidden');
        }
      }
      div.setAttribute('data-row', this.rowIndex);
      const rect = this.getBoundingClientRect();
      div.style.top = rect.top + 'px';
      div.classList.remove('hidden');
    });
  }
  table.parentElement.addEventListener('mouseleave', InfoTableMouseLeave);
  function InfoTableMouseLeave() {
    if (document.activeElement === sel) return;
    div.classList.add('hidden');
  }
}
function buildInfoTable ( mo ) { const table = byId ( 'info-table' ) ; const div = byId ( 'info-ctrl' ) ; div . classList . add ( 'hidden' ) ; const sel = byId ( 'info-ref-sel' ) ; sel . innerHTML = '' ; sel . add ( document . createElement ( 'option' ) ) ; table . innerHTML = '' ; const names = mo . cols . names , types = mo . cols . types ; const splen = mo . cache . splen ; const n = names . length ; let name , type , row , metric ; for ( let i = 1 ; i < n ; i ++ ) { name = names [ i ] ; type = types [ i ] ; if ( type . endsWith ( 'wt' ) ) continue ; if ( type === 'num' ) { const opt = document . createElement ( 'option' ) ; opt . text = name ; opt . value = i ; sel . add ( opt ) ; } row = table . insertRow ( - 1 ) ; row . setAttribute ( 'data-idx' , i ) ; const cell = row . insertCell ( - 1 ) ; cell . innerHTML = name ; row . insertCell ( - 1 ) ; if ( type === 'num' ) { metric = guessColMetric ( name ) ; if ( metric . endsWith ( 'by' ) ) { row . setAttribute ( 'data-met' , metric . substring ( 0 , metric . length - 2 ) ) ; row . setAttribute ( 'data-ref' , splen ) ; } else { row . setAttribute ( 'data-met' , metric ) ; row . setAttribute ( 'data-ref' , 0 ) ; } } else if ( type === 'cat' ) { row . setAttribute ( 'data-ref' , splen ) ; } row . addEventListener ( 'mouseenter' , function ( ) { if ( document . activeElement === sel ) return false ; const mbtn = byId ( 'info-metric-btn' ) , pbtn = byId ( 'info-plot-btn' ) , span = byId ( 'info-ref-span' ) ; if ( mo . cache . npick < 2 ) { for ( let dom of [ mbtn , pbtn , span ] ) dom . classList . add ( 'hidden' ) ; } else { const type = mo . cols . types [ parseInt ( this . getAttribute ( 'data-idx' ) ) ] ; if ( type === 'num' ) { const metric = this . getAttribute ( 'data-met' ) ; mbtn . title = 'Metric: ' + metric ; sel . value = this . getAttribute ( 'data-ref' ) ; mbtn . innerHTML = ( metric === 'sum' ) ? '&Sigma;<i>x</i>' : '<span style="text-decoration: overline;"><i>x</i></span>' ; for ( let dom of [ mbtn , pbtn , span ] ) dom . classList . remove ( 'hidden' ) ; } else if ( type === 'cat' ) { sel . value = this . getAttribute ( 'data-ref' ) ; span . classList . remove ( 'hidden' ) ; for ( let dom of [ mbtn , pbtn ] ) dom . classList . add ( 'hidden' ) ; } else { for ( let dom of [ mbtn , pbtn , span ] ) dom . classList . add ( 'hidden' ) ; } } div . setAttribute ( 'data-row' , this . rowIndex ) ; const rect = this . getBoundingClientRect ( ) ; div . style . top = rect . top + 'px' ; div . classList . remove ( 'hidden' ) ; } ) ; } table . parentElement . addEventListener ( 'mouseleave' , InfoTableMouseLeave ) ; function InfoTableMouseLeave ( ) { if ( document . activeElement === sel ) return ; div . classList . add ( 'hidden' ) ; } }
Build info table based on the dataset and selected contigs.
Build info table based on the dataset and selected contigs .
// temporarily move control span // reference selection // empty option - clear // clear table // create rows // weights are not displayed // add numeric field to reference selection // create row // 1st cell: field name // 2nd cell: field value // numeric: guess which metric may best describe the field // with reference (default: length) // no reference // categorical: weight by length, metric not relevant // row hover event: append control span // three DOMs: metric (sum or mean), reference selection, plotting // the 4th and permanent button is "hide" // only one contig is selected, then no need for controls // multiple contigs are selected // numeric fields need all controls // categorical fields need only weight // other types don't // append controls to row // hide toolbar