How to get text based column number

I split the content of the Html (which belongs to the eBook) into several columns using the following steps .

1) I added HTML inside the content inside the container.

<body>
<div id="container">
    <div id="content">

        BOOK HTML CONTENT

        <span id="endMarker"></span>
    </div>
</div>
</body>

2) Then I added the CSS style of the content and the container as shown below:

#container {
    width: 240px;
    overflow: hidden;
    background-color: yellow;
}
#content {
     position: relative;
     height: 30em;

    -moz-column-width: 240px;
    -webkit-column-width: 240px;
    column-width: 240px;

    -moz-column-gap: 10px;
    -webkit-column-gap: 10px;
    column-gap: 10px;
}

Now, I want to find the column number of text (or row) using javascript?

There are more questions about SO that show how to get the column number based on the identifier. In my case there are no identifiers. The only thing that is available is the text (or string), and I need to get the column number by looking at the contents of the Html.

I currently have two “solutions” to get the column number, but they are incomplete.

1) , , window.find(text), , .

2) - <span> . ( ).

columnCount = Math.floor($('#marker').position().left/(columnWidth + columnGap));

, .

, . , . .

+4
2

, . jsfiddle

OP jQuery, jQuery , . ( )

:

  • , (css: ).
  • / .
  • "", .
  • (), .
  • .

DOM , DOM .

2017/6/1 : .

  $('#find').click( () => {
    var text = $('#findtext').val();
    var columns = [];

    var doms = [];
    while (window.find(text, false)) {
      var sel = window.getSelection();
      if (sel) {
        var range = sel.getRangeAt(0);

        var el = document.createElement("span");
        var frag = document.createDocumentFragment();
        frag.appendChild(el);
        range.insertNode(frag);

        columns.push(Math.floor(el.offsetLeft/(_columnWidth + _columnGap)));
        doms.push(el);
      }
    }

    /// distinct
    columns = columns.filter( (value, index, self) => self.indexOf(value) === index );

    /// show result    
    $("#foundlist").empty();
    for (var i=0; i<columns.length; i++)
      $("#foundlist").append(`<li><a href="#" onclick="setColumn(${columns[i]})">Found in Column ${columns[i]+1}</a></li>`);

    /// remove dom. keep dom tree clean
    while (doms.length > 0) {
      var dom = doms.pop();
      dom.parentNode.removeChild(dom);
    }
  });
+3

<span> , , , .

, . TreeWalker, node DOM.

node .

, jQuery . DOM .

var columnWidth = 240,
    columnGap   = 10;

function getColumn(text) {
  // the subtree to search in
  var root = document.getElementById('content');
  // define an iterator that only searches in text nodes
  var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
    // filter the text nodes to those containing the search text
    acceptNode: function(node) {
      if ( node.data.includes(text) ) {
        return NodeFilter.FILTER_ACCEPT;
      }
    }
  });

  // look if there is a result
  if (treeWalker.nextNode()) {
    var node = treeWalker.currentNode;

    // get start index of found text
    var index = node.data.indexOf(text);
    // and split into two nodes, referencing the second part
    var foundTextNode = node.splitText(index);

    // define an empty inline element
    var span = document.createElement('span');
    // insert it between the two text nodes
    var elem = node.parentElement;
    elem.insertBefore(span, foundTextNode);

    // compute the column from the position of the element
    // you might have to account for margins here
    var x = span.getBoundingClientRect().left - root.getBoundingClientRect().left;
    var column = Math.floor(x / (columnWidth + columnGap));

    // restore previous state
    elem.removeChild(span);
    elem.normalize();

    return column;
  } else {
    // no result
    return false;
  }
}

, , . ,

<p>The quick brown fox <em>jumps</em> over the lazy dog.</p>

"fox jumps over" .

0

Source: https://habr.com/ru/post/1677750/


All Articles