Fun with highlighting- plus occurrence count

https://groups.google.com/d/topic/knockoutjs/iO_rMnwES8Y/discussion http://www.knockmeout.net/2011/06/fun-with-highlighting-in-knockoutjs.html?showComment=1307370451742#c3222361922660848046

HTML

<script src="http://rniemeyer.github.com/KnockMeOut/Scripts/jquery.tmpl.js"></script>
<script src="http://rniemeyer.github.com/KnockMeOut/Scripts/knockout-latest.debug.js"></script>
Highlight: <input data-bind="value: match, valueUpdate: 'afterkeydown'" /> <select data-bind="options: styleChoices, value: style"></select>

<p>Enter a new search term or try selecting text below with your mouse</p>
<hr />
<p data-bind="text:'Found '+counter()">3</p>
<div data-bind="highlightedText: { text: text, highlight: match, css: style, count:counter}, selectedText: match"></div>

CSS

.yellow { background-color: yellow; }
.red { background-color: red; color: #ccc; }
.black { background-color: #000; color: #fff; }
.big { font-size: 1.5em; font-weight: bold; }
input { margin: 5px; width: 150px; }
p { color: #666; }

JavaScript

ko.bindingHandlers.highlightedText = {
    update: function(element, valueAccessor) {
        var options = valueAccessor();
        
    var value = ko.utils.unwrapObservable(options.text);
        var search = ko.utils.unwrapObservable(options.highlight);
        var css = ko.utils.unwrapObservable(options.css); //could be an observable
        if (options.sanitize) {
            value = $('<div/>').text(value).html(); //could do this or something similar to escape HTML before replacement, if there is a risk of HTML injection in this value
        }
        
        if (!search || search.length < 3) {
        element.innerHTML = value
        	return;
        }
        
        const matches = value.match(new RegExp(search, "gi"));

          let temp = value;
          if (matches != null) {
            const myarray = matches.reduce((prev, curr) => {
            	console.log(prev, curr);
              if (prev.length === 0 || prev.every(p => p !== curr)) {
              	
                prev.push(curr);
              }
              return prev;
            }, []);

						console.log(myarray);


            myarray.forEach(m => {
              const replacement = "<span class=" + css + ">" + m + "</span>";
              temp = temp.replace(new RegExp(m, "g"), replacement);
              });
            }
          element.innerHTML = temp;
    }
};

//set a value based on the text that a user selects
ko.bindingHandlers.selectedText = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        var value = valueAccessor();
        ko.utils.registerEventHandler(element, 'mouseup', function() {
            var modelValue = valueAccessor();
            //get the selected text
            var selectedText = '';
            if (window.getSelection) {
                selectedText = window.getSelection();
            } else if (document.getSelection) {
                selectedText = document.getSelection();
            } else if (document.selection)...