To begin, let's try to figure out how to find such a sequence number. Simplify the task and assume that there are no nested blocks. Then you can find all occurrences of the selected text as long as its position is less than or equal to the left border of the selection. The search function may be:
function findAndCount(text, search, limit) { var count = 0; var fromIndex = 0; var pos = text.indexOf(search, fromIndex); while (pos >= 0 && pos <= limit) { ++count; fromIndex = pos + search.length; pos = text.indexOf(search, fromIndex); }; return count; }
The next task is to come up with a way to find the left selection boundary for a document with nested blocks. Range has the property startContainer - the element with which the range starts. Elements seem to have no position property in the text, but you can try to replace the element with a unique sequence of characters, and find the position of this sequence in the text of the parent.
Unique text can be generated like this:
function generateBoundary(text, tryLimit) { var boundary; var pos = 0; do { --tryLimit; boundary = Math.random().toString(36).substring(2, 15); // лаконичное решение из интернета pos = text.indexOf(boundary); } while (pos >= 0 && tryLimit > 0); return boundary; }
The position of the element is as follows (I use jQuery):
function findElTextPosition($el, $parent) { var boundary = generateBoundary($parent.text(), 5); $el.replaceWith(boundary); var pos = $parent.text().indexOf(boundary); return pos; }
Test:
$(function() { var $mainEl = $('#text'); $(document).on('mouseup', '#text', function(e) { var selection = document.getSelection().getRangeAt(0); var text = $mainEl.text(); var selectedText = selection.toString(); var offset = selection.startOffset; var childOffset = 0; if (selection.startContainer !== $mainEl[0]) { // если выделение во вложенном элементе childOffset = findElTextPosition($(selection.startContainer), $mainEl); } console.log(selectedText, findAndCount(text, selectedText, offset + childOffset)); }); });
The method is of course so-so, and if you do not clone the #text element, then it works only once. But you can finish it if you want.
PS Probably there is no reason to use this approach, unless you are writing something very special.