2

what is the best way to do following using angular js

when writing text on a contenteditable div need to detect special word like ' {{FULL_NAME}} ' and covert to tag with pre-deifined constant words

example - if some one write

' His name is {{FULL_NAME}} '

should be instantly convert to ' His name is john smith '

DevÁsith
  • 1,072
  • 12
  • 38

2 Answers2

1

Here is a demo plunker: http://plnkr.co/edit/GKYxXiDKv7fBeaE7rrZA?p=preview

Service:

app.factory('interpolator', function(){

  var dict = { .... };

  return function(str){
    return (str || "").replace(/\{\{([^\}]+)\}\}/g, function(all, match){
      return dict[match.trim().toLowerCase()] || all;
    });    
  };
});

Directive:

app.directive('edit',[ 'interpolator', function(interpolator){
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {

      element.on('blur', function(e) {
        scope.$apply(function() {
          var content = interpolator(element.text());
          element.text(content);
          ngModel.$setViewValue(content);
        });
      });

      ngModel.$formatters.push(interpolator);

      ngModel.$render = function() {
        element.text(ngModel.$viewValue);
        ngModel.$setViewValue(ngModel.$viewValue);
      };
    }
  };
}]);
Ilan Frumer
  • 32,059
  • 8
  • 70
  • 84
0

Here's an example using simple DOM methods, based on other answers I've provided on Stack Overflow. It also uses Rangy to save and restore the selection while doing the substitutions so that the caret does not move.

Demo:

http://jsbin.com/zuvevocu/2

Code:

var editorEl = document.getElementById("editor");
var keyTimer = null, keyDelay = 100;

function createKeyword(matchedTextNode) {
    var el = document.createElement("b");
    el.style.backgroundColor = "yellow";
    el.style.padding = "2px";
    el.contentEditable = false;
    var matchedKeyword = matchedTextNode.data.slice(1, -1); // Remove the curly brackets
    matchedTextNode.data = (matchedKeyword.toLowerCase() == "name") ? "John Smith" : "REPLACEMENT FOR " + matchedKeyword;
    el.appendChild(matchedTextNode);
    return el;
}

function surroundInElement(el, regex, surrounderCreateFunc) {
    // script and style elements are left alone
    if (!/^(script|style)$/.test(el.tagName)) {
        var child = el.lastChild;
        while (child) {
            if (child.nodeType == 1) {
                surroundInElement(child, regex, surrounderCreateFunc);
            } else if (child.nodeType == 3) {
                surroundMatchingText(child, regex, surrounderCreateFunc);
            }
            child = child.previousSibling;
        }
    }
}

function surroundMatchingText(textNode, regex, surrounderCreateFunc) {
    var parent = textNode.parentNode;
    var result, surroundingNode, matchedTextNode, matchLength, matchedText;
    while ( textNode && (result = regex.exec(textNode.data)) ) {
        matchedTextNode = textNode.splitText(result.index);
        matchedText = result[0];
        matchLength = matchedText.length;
        textNode = (matchedTextNode.length > matchLength) ?
            matchedTextNode.splitText(matchLength) : null;
        surroundingNode = surrounderCreateFunc(matchedTextNode.cloneNode(true));
        parent.insertBefore(surroundingNode, matchedTextNode);
        parent.removeChild(matchedTextNode);
    }
}

function updateKeywords() {
    var savedSelection = rangy.saveSelection();
    surroundInElement(editorEl, /\{\w+\}/, createKeyword);
    rangy.restoreSelection(savedSelection);
}

function keyUpHandler() {
    if (keyTimer) {
        window.clearTimeout(keyTimer);
    }
    keyTimer = window.setTimeout(function() {
        updateKeywords();
        keyTimer = null;
    }, keyDelay);
}

editorEl.onkeyup = keyUpHandler;

Related:

Community
  • 1
  • 1
Tim Down
  • 318,141
  • 75
  • 454
  • 536