JSFiddle - React, Tailwind, and code Playground

by lindenb

HTML

<body>
    <div class="mainpane">
        <div id="t1" class="timeline">
            <div class="event">
                <img src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f1/Hooke_Microscope-03000276-FIG-4.jpg/64px-Hooke_Microscope-03000276-FIG-4.jpg" class="ribbon" />An early <a href="http://en.wikipedia.org/wiki/Microscope">microscope</a> was made in <span class="start">1590</span>

            </div>
            <div class="event">
                <div>
                    <img src="http://upload.wikimedia.org/wikipedia/commons/thumb/9/94/Jan_Verkolje_-_Antonie_van_Leeuwenhoek.jpg/64px-Jan_Verkolje_-_Antonie_van_Leeuwenhoek.jpg" class="ribbon" />(<span class="start">1632</span>-<span class="end">1723</span>) <a href="http://en.wikipedia.org/wiki/Antonie_van_Leeuwenhoek">Antonie van Leeuwenhoek</a> teaches himself to make lenses, constructs simple microscopes and draws protozoa, such as Vorticella from rain water, and bacteria from his own mouth.</div>
            </div>
            <div class="event">
                <img src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/10/13_Portrait_of_Robert_Hooke.JPG/64px-13_Portrait_of_Robert_Hooke.JPG" class="ribbon" /><span class="start">1665</span>: <a href="http://en.wikipedia.org/wiki/Robert_Hooke">Robert Hooke</a> discovers cells in cork, then in living plant tissue using an early compound microscope</div>
            <div class="event">
                <img src="http://upload.wikimedia.org/wikipedia/commons/thumb/9/9c/Rudolf_Virchow_NLM3.jpg/220px-Rudolf_Virchow_NLM3.jpg" class="ribbon" /><span class="start">1855</span>: <a href="http://en.wikipedia.org/wiki/Rudolf_Virchow">Rudolf Virchow</a> states that cells always emerge from cell divisions (omnis cellula ex cellula).</div>
            <div class="event">
                <img src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Louis_Pasteur_by_Pierre_Lamy_Petit.jpg/220px-Louis_Pasteur_by_Pierre_Lamy_Petit.jpg" class="ribbon" />...

CSS

.mainpane {
    position:relative;
     overflow-x: auto;
     overflow-y: auto;
}
.timeline {
    background-color:lightgray;
    border:solid 1px black;
    position:relative;
    

}
.ribbon {
    float: left;
    margin:2px;
    width:64px;
}
.event {
    background-color:white;
    border:solid 1px black;
    position:absolute;
    margin:2px;
    box-shadow: 10px 10px 5px #888888;
}

JavaScript

/** 
test wether two div overlap

from http://stackoverflow.com/questions/5930020 
*/

function testOverlap(a, b) {
    var aPos = a.position();
    var bPos = b.position();

    var aLeft = aPos.left;
    var aRight = aPos.left + a.width();
    var aTop = aPos.top;
    var aBottom = aPos.top + a.height();

    var bLeft = bPos.left;
    var bRight = bPos.left + b.width();
    var bTop = bPos.top;
    var bBottom = bPos.top + b.height();
    return !(bLeft > aRight || bRight < aLeft || bTop > aBottom || bBottom < aTop);
}

/** just parse a year, returns a floating number */
function parseOneDate(t) {
    if (t.lenth == 0) return null;
    var x = parseInt(t) * 1.0;
    return x;
}

/** returns the start/end years of an event */
function parseDates(div) {
    var span = div.find("span[class=start]");
    if (span.length === 0) return null;

    var start = parseOneDate(span.text());
    if (start == null) return null;

    span = div.find("span[class=end]");
    if (span.length == 0) return {
        "start": start * 1.0,
            "end": (start + 1) * 1.0
    };
    var end = parseOneDate(span.text());
    if (end == null || end < start) return null;
    return {
        "start": start * 1.0,
            "end": end * 1.0
    };
}

$(function () {
    var minDate = null,
        maxDate = null,
        i, events = $("#t1").children();
    /** get min/max date, hide div having no date */
    for (i = 0; i < events.length; i++) {
        var evt = events[i];
        var r = parseDates($(evt));
        if (r == null) {
            $(evt).css("display", "none");
            continue;
        }
        if (minDate == null || r.start < minDate) minDate = r.start;
        if (maxDate == null || r.end > maxDate) maxDate = r.end;
    }
    events = $("#t1").children();
    /** sort by date */
    events.sort(function (a, b) {
        var t1 = parseDates($(a));
        var t2 = parseDates($(b));
        if (t1 == null) return (t2 == null ? 0 : -1);
        if (t2 == null)...