wilzbach/msa

View on GitHub
src/views/Search.js

Summary

Maintainability
A
0 mins
Test Coverage
const boneView = require("backbone-childs");
const k = require('koala-js');
const dom = require('dom-helper');
import {possel} from "../g/selection/Selection";

// this is a very simplistic approach to show search result
// TODO: needs proper styling
const View = boneView.extend({

  initialize: function(data) {
    this.g = data.g;

    this.listenTo(this.g.user, "change:searchText", function(model, prop) {
      this.search(prop);
      return this.render();
    });
    this.sel = [];
    return this.selPos = 0;
  },

  events:
    {"scroll": "_sendScrollEvent"},

  render: function() {
    this.renderSubviews();

    this.el.className = "biojs_msa_searchresult";
    var searchText = this.g.user.get("searchText");
    if ((typeof searchText !== "undefined" && searchText !== null) && searchText.length > 0) {
      if (this.sel.length === 0) {
        this.el.textContent = "no selection found";
      } else {
        this.resultBox = k.mk("div");
        this.resultBox.className = "biojs_msa_searchresult_ovbox";
        this.updateResult();
        this.el.appendChild(this.resultBox);
        this.el.appendChild(this.buildBtns());
      }
    }
    return this;
  },

  updateResult: function() {
      var text = "search pattern: " + this.g.user.get("searchText");
      text += ", selection: " + (this.selPos + 1);
      var seli = this.sel[this.selPos];
      text += " (";
      text += seli.get("xStart") + " - " + seli.get("xEnd");
      text += ", id: " + seli.get("seqId");
      text += ")";
      return this.resultBox.textContent = text;
  },

  buildBtns: function() {
    var prevBtn = k.mk("button");
    prevBtn.textContent = "Prev";
    prevBtn.addEventListener("click", () => {
      return this.moveSel(-1);
    });

    var nextBtn = k.mk("button");
    nextBtn.textContent = "Next";
    nextBtn.addEventListener("click", () => {
      return this.moveSel(1);
    });

    var allBtn = k.mk("button");
    allBtn.textContent = "All";
    allBtn.addEventListener("click", () => {
      return this.g.selcol.reset(this.sel);
    });

    var searchrow = k.mk("div");
    searchrow.appendChild(prevBtn);
    searchrow.appendChild(nextBtn);
    searchrow.appendChild(allBtn);
    searchrow.className = "biojs_msa_searchresult_row";
    return searchrow;
  },

  moveSel: function(relDist) {
    var selNew = this.selPos + relDist;
    if (selNew < 0 || selNew >= this.sel.length) {
      return -1;
    } else {
      this.focus(selNew);
      this.selPos = selNew;
      return this.updateResult();
    }
  },

  focus: function(selPos) {
    var seli = this.sel[selPos];
    var leftIndex = seli.get("xStart");
    this.g.zoomer.setLeftOffset(leftIndex);
    return this.g.selcol.reset([seli]);
  },

  search: function(searchText) {
    // marks all hits
    var origIndex;
    var search = new RegExp(searchText, "gi");
    var newSeli = [];
    var leftestIndex = origIndex = 100042;

    this.model.each(function(seq) {
      var strSeq = seq.get("seq");
      return (() => {
        var match;
        var result = [];
        while (match = search.exec(strSeq)) {
          var index = match.index;
          var args = {xStart: index, xEnd: index + match[0].length - 1, seqId:
            seq.get("id")};
          newSeli.push(new possel(args));
          result.push(leftestIndex = Math.min(index, leftestIndex));
        }
        return result;
      })();
    });

    this.g.selcol.reset(newSeli);

    // safety check + update offset
    if (leftestIndex === origIndex) { leftestIndex = 0; }
    this.g.zoomer.setLeftOffset(leftestIndex);

    return this.sel = newSeli;
  }
});
export default View;