JSFiddle - React, Tailwind, and code Playground

by Kai

HTML

<script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<script src="http://mallea.net/js/sc2progamers.js"></script>
<div class="sometext">
    I like...MC. But Artosis is good, too... even though he got mopped by Sheth. Who else? ummmm... TLO.
</div>

CSS

.player-info-tooltip {
    position: absolute;
    font: Arial 1.1em;
    padding: 5px;
    
    background-color: rgba(205,66,61,0.4);
    width: 150px;
    height: 80px;
    
    border: solid 1px #000;
    border-radius: 5px;
    box-shadow: 1px 1px 2px #444;
}

.player {
    color: #cd423d;
    cursor: pointer;
}

.player:hover {
    color: #42555b;
}

.info {
    background: url('http://mallea.net/img/qmark.png') no-repeat 0 0;
    padding-left: 15px;
}

JavaScript

// Create and hide tooltip for re-usage
var tooltip_format = '\
    <div>\
        <p>$nick</p>\
        <p>$race</p>\
        <p>$team</p>\
        <p>$country</p>\
    </div>',
    tooltip = $(tooltip_format).addClass('player-info-tooltip').appendTo('body').hide();

// Pluck out only names from JSON
var player_names = _.pluck(progamers, 'nick'),
    // Build regular expression from player names
    re = new RegExp('\\b(' + player_names.join('|').replace(/([\-\*\\])/g, '\\$1?') + ')\\b', 'igm');

// Find all text nodes
var textNodes = $('.sometext').contents().filter(function() {
    return this.nodeType == 3;
});


// Examine text nodes and append superscript to player names
$.each(textNodes, function () {
    var $this = $(this);

    $this.parent().html(
        $this.text().replace(re, function (match) {
            
            var playerinfo = _.select(progamers, function (playerobj) {
    return playerobj.nick == match;
})[0];
            // Cache player info in parent elements
            $('body').data(match + '-cache', {
                'name': match,
                'race': playerinfo.race,
                'team': playerinfo.team,
                'country': playerinfo.country
            });
                   
            return '<span class="player">' + match + '<sup class="info">&nbsp;</sup></span>';
        })
    );
});
  
// Update tooltip contents and display on mouseover
$('.player').mousemove(function (ev) {
    var $this = $(this),
        name = $this.text().trim(),
        tip = tooltip_format
            .replace('$nick', name)
            .replace('$race', $('body').data(name + '-cache').race)
            .replace('$team', $('body').data(name + '-cache').team)
            .replace('$country', $('body').data(name + '-cache').country);
    tooltip.html(tip);
    tooltip.css('top', ev.pageY + 15).css('left', ev.pageX + 15);
    tooltip.show();
});

// Hide tooltip on mouseout
$('.player').mouseout(function (ev) {
    tooltip.hide();
});