Join the Stack Overflow Community
Stack Overflow is a community of 6.7 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I am creating an AngularJS directive that would bind to a property on the controller scope which contains an 'htm'l string. The string is pulled from a database on the backend. I wish to append the html to an element which contains the directive attribute. Afterwards I would like to drill into the newly created element and surround each 'word' with a span. I have achieved the latter using a jQuery extension function similar to the jQuery highlight plugin. In fact my code is a modification of the original code for this plugin:

jQuery.extend({
highlight: function (node, re) {
    if (node.nodeType === 3) {
        var match = node.data.match(re);
        if (match) {
            var highlight = document.createElement('span');               
            highlight.className = 'highlight';
            var wordNode = node.splitText(match.index);
            wordNode.splitText(match[0].length);
            var wordClone = wordNode.cloneNode(true);
            highlight.appendChild(wordClone);             
            wordNode.parentNode.replaceChild(highlight, wordNode);
            return 1; //skip added node in parent
        }
    } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
            !/(script|style)/i.test(node.tagName) && // ignore script and style nodes
            !(node.tagName === 'SPAN' && node.hasAttribute('ng-class'))) { // skip if already highlighted
        for (var i = 0; i < node.childNodes.length; i++) {
            i += jQuery.highlight(node.childNodes[i], re);
        }
    }
    return 0;
}
});

jQuery.fn.highlight = function (times) {
  var pattern = "\\b([^ ]+)\\b";
  var re = new RegExp(pattern);
  return this.each(function () {
    jQuery.highlight(this, re);
 });
};

The code for my directive:

.directive('spanner', function($compile){
var linkFn = function(scope, element)
{
   element.append(scope.spanner);
   element.highlight();
   $compile(element.contents())(scope);
};

return {
    scope: {
        spanner: '='
    },
    restrict: 'A',
    link: linkFn
  };  
});

This works fine but I am using jQuery. I would prefer to extend jQlite which ships with AngularJs (or perhaps do it in a way which requires no extension at all!). I tried to extend jQlite but failed each time. Can someone suggest a way I can do this without relying on jQuery? I think this would substantially improve my understanding of AngularJs. Thanks in advance.

share|improve this question
up vote 1 down vote accepted

Since 90% of the plugin is native script it's a fairly simple port into a directive with no library (jQuery or jQlite) dependencies:

app.directive('highlight', function() {
  /* define highligher variables and function */
  var pattern = "\\b([^ ]+)\\b";
  var re = new RegExp(pattern);

  var highlighter = function(node, re) {
    if (node.nodeType === 3) {
      var match = node.data.match(re);
      if (match) {
        var highlight = document.createElement('span');
        highlight.className = 'highlight';
        var wordNode = node.splitText(match.index);
        wordNode.splitText(match[0].length);
        var wordClone = wordNode.cloneNode(true);
        highlight.appendChild(wordClone);
        wordNode.parentNode.replaceChild(highlight, wordNode);
        return 1; //skip added node in parent
      }
    } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
      !/(script|style)/i.test(node.tagName) && // ignore script and style nodes
      !(node.tagName === 'SPAN' && node.hasAttribute('ng-class'))) { // skip if already highlighted
      for (var i = 0; i < node.childNodes.length; i++) {
        i += highlighter(node.childNodes[i], re);
      }
    }
    return 0;
  }

   /* return directive link function */    
   return function(scope, elem) {
      /* initalize on element */
      highlighter(elem[0], re);
    }    

});

HTML

 <p highlight>Far far away</p>

DEMO

share|improve this answer
    
Thank you! This is amazing! It really validates the Angular way of doing DOM manipulations! I am truly grateful! God bless! – rmg.n3t Jul 17 '14 at 21:19
    
could even put the function into a factoryso it doesn't have to be declared for every element...then just inject that factory – charlietfl Jul 17 '14 at 21:24
    
That is certainly an efficient way to go about it. Thanks again! – rmg.n3t Jul 18 '14 at 1:49

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.