Link to home
Start Free TrialLog in
Avatar of brianmfalls
brianmfallsFlag for United States of America

asked on

jQuery.highlight.js - Getting the contents of the H(1-6) tag preceding the search string.

The code below highlights user entered search strings from a body of text as the end user types into an input field (keyup function).  In addition to highlighting the matching strings within the body of text, I also need to get the string inside of the preceding header [H(1-6)] tag of any of the aforementioned matching strings.  How can I get the contents (jQuery.html()) of the preceding header tag, or tags (where multiple instances of the search string are present), and return said header contents in an array to onkeyup function?

Example (search string would be "lorem" & "Lorem Header A" and  "Lorem Header B" would be added to array.):
<h3>Lorem Header A</h3>
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ac felis molestie, malesuada urna ac, rhoncus sapien. Nulla eget eros vel turpis imperdiet hendrerit eu non velit. Suspendisse luctus diam nec risus eleifend, ac tempor est lobortis. Nullam hendrerit vulputate orci a efficitur. Donec felis lectus, pulvinar id neque non, varius efficitur arcu. Aenean interdum consequat consectetur. Integer ut lacus diam. Aenean vitae ipsum vel ipsum viverra malesuada. Curabitur pharetra quam vel ex scelerisque, at congue diam feugiat. Vivamus efficitur nulla sem, sit amet ultrices ex scelerisque a. </div>
<h3>Lorem Header B</h3>
<div>Ut ultricies non elit consectetur fermentum. Sed sed pellentesque nunc, ac viverra purus. Sed auctor, quam in sollicitudin tincidunt, ligula risus ultricies purus, id viverra neque libero vitae velit. Aliquam sit amet nunc nec orci sodales gravida at ut enim. Vivamus sit amet quam hendrerit, convallis enim at, dignissim turpis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque at nisl urna. Nullam rhoncus, dui a aliquam lobortis, turpis magna scelerisque tortor, sit amet fermentum ligula tortor a velit. Fusce non aliquet lorem. Aliquam erat volutpat. Morbi ultricies maximus aliquam. Suspendisse iaculis porta condimentum. </div>
<h3>Lorem Header C</h3>
<div>Nullam nec lectus sed urna aliquet varius. Curabitur sed purus tempus, accumsan dui sed, malesuada dui. Nulla elementum vel erat vitae dignissim. Integer enim ligula, porttitor eu ultrices vitae, placerat et felis. Donec velit nisl, sodales in rhoncus eu, volutpat at ante. Sed mollis diam eu posuere condimentum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec sagittis lectus et fermentum porttitor. Duis ornare, metus nec pulvinar porttitor, turpis nulla varius lectus, et fermentum sem justo dictum tellus. Phasellus auctor ornare nibh, sed commodo mauris convallis eu. Curabitur orci elit, semper et libero ut, feugiat eleifend ante. Aenean in purus enim. Nunc rutrum, magna vitae euismod vulputate, est nunc porttitor turpis, et pellentesque leo nulla ut justo.</div>

keyUp function that calls jQuery.highlight function:
function init() {
    $('#bodyFilter').on('keyup', function(){
        console.log($(this).val());
        $('.chaptertext').unhighlight();
        $('.chaptertext').highlight($(this).val());
        try {
            var aTag = $('a[name="anchorTag"]');
            $('.viewport').stop().animate({scrollTop: aTag.offset().top},'slow');
        } catch(err) {
            // no matching strings to scroll to, therefore there is nothing to do...
        }
        return false;
    });
};

Open in new window


jQuery.highlight.js (modified):
jQuery.extend({
    highlight: function (node, re, nodeName, className, nameValue) {
        if (node.nodeType === 3) {
            var match = node.data.match(re);
            if (match) {
                var highlight = document.createElement(nodeName || 'a');
                highlight.className = className || 'highlight';
                highlight.name = nameValue || 'anchorTag';
                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 === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
            for (var i = 0; i < node.childNodes.length; i++) {
                i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
            }
        }
        return 0;
    }
});

jQuery.fn.unhighlight = function (options) {
    var settings = { className: 'highlight', element: 'a' };
    jQuery.extend(settings, options);

    return this.find(settings.element + "." + settings.className).each(function () {
        var parent = this.parentNode;
        parent.replaceChild(this.firstChild, this);
        parent.normalize();
    }).end();
};

jQuery.fn.highlight = function (words, options) {
    var settings = { className: 'highlight', nameValue: 'anchorTag', element: 'a', caseSensitive: false, wordsOnly: false };
    jQuery.extend(settings, options);
    
    if (words.constructor === String) {
        words = [words];
    }
    words = jQuery.grep(words, function(word, i){
      return word != '';
    });
    words = jQuery.map(words, function(word, i) {
      return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
    });
    if (words.length == 0) { return this; };

    var flag = settings.caseSensitive ? "" : "i";
    var pattern = "(" + words.join("|") + ")";
    if (settings.wordsOnly) {
        pattern = "\\b" + pattern + "\\b";
    }
    var re = new RegExp(pattern, flag);
    
    return this.each(function () {
        jQuery.highlight(this, re, settings.element, settings.className, settings.nameValue);
    });
};

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Alexandre Simões
Alexandre Simões
Flag of Switzerland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial