I think you can try MutationObserver, and in IE11-, you can use setInterval() for fallback.
UPDATE
Bellow is my answer.
var TextObserver = function () {
};
TextObserver.prototype.observe = function (target, callback) {
    var self = this;
    self.target = target;
    if (window.MutationObserver) {
        self.observer = new MutationObserver(function (mutations) {
            if (mutations.length) {
                var m = mutations[0];
                callback && callback(self.target.textContent, m.oldValue);
            }
        });
        self.observer.observe(self.target, {
            subtree: true,
            characterData: true,
            characterDataOldValue: true
        });
    } else { //for IE11-
        self._oldText = self.target.innerText;
        self.observer = setInterval(function () {
            var newText = self.target.innerText;
            if (self._oldText !== newText) { //changed
                callback && callback(newText, self._oldText);
                self._oldText = newText; //replace the old text;
            }
        }, 300);
    }
    return self;
};
new TextObserver().observe(document.getElementById('test'), function (newValue, oldValue) {
    alert('New value:' + newValue + '; oldValue: ' + oldValue);
});
You can view the whole demo on the jsfiddle.