Demonstrate Javascript Event Propagation.

visualize how event propagate within the dom.

by lid0

HTML

<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<div id="event_status">
    <div class='el inb'></div>
    <div class='status inb'></div>
    <div class='phase inb'></div>
    <div class='console'><pre></pre>

    </div>
</div>
<br>
<div id="main">
    <ul>
        <li class='one'>1</li>
        <li class='two'>2 stopPropogation()</li>
        <li class='three'>3</li>
    </ul>
</div>
<div id="main">
    <ul>
        <li class=''>1</li>
        <li class=''>2</li>
        <li class=''>3 <b>bold</b>

            <ul>
                <li>3.1</li>
                <li>3.2</li>
            </ul>
        </li>
    </ul>
</div>

CSS

#main {
    width:350px;
}
.in_focus {
    border:1px dashed red;
    border-radius:3px;
}
.in_phase {
    border:1px dashed green;
    border-radius:3px;
}
.hl-phase {
    background:#c2c2c2;
}
li {
    background:#cfcfcf;
    border:1px solid darkgray;
}
#event_status {
    position:fixed;
    top:0px;
    right:0px;
    background-color:#F4F4F4;
    padding:5px;
    z-index: 9999;
    min-width:300px;
    min-height:12px;
    opacity:0.8;
}
#event_status .inb {
    display:inline-block;
}
#event_status .el {
    background:#cecece;
    padding:5px;
    position:fixed;
    left:0px;
    display:inline-block;
}

JavaScript

//Dependency Jquery, jQuery UI (effect)

String.prototype.repeat = function (n, s) {
    s = s || "";
    if (n > 0) {
        s += this;
        s = this.repeat(--n, s);
    }
    return s;
};


function set_status(status) {
    if (status == "playing") {
        $("#event_status div.status").html("▶");
    } else {
        $("#event_status div.status").html("∎");
    }

}

var b = 0; //for spacing
var c = 0; //for spacing
var evt_ts = 0; //event timestamp, used as event id.
var animation_step = 0; //track the animation step to crosspond with lines ins "phase" element printed by the print_to_console

var TRACKED_EVENT = "click";
var ANIMATION_DURATION = 500;
var in_animation = false;

//print a message connected with the event phase
var printed_phases = 0;

function print_to_console(msg, handling_element) {

    console.warn(handling_element);


    var sp = $("<span>" + msg + "</span>");
    $("div.console pre").append(sp);
    if (handling_element) {
        var target_el = $(handling_element);
        sp.hover(function () {
            sp.addClass("hl-phase");
            target_el.addClass('in_focus');
        }, function () {
            sp.removeClass("hl-phase");
            target_el.removeClass('in_focus');
        });
    }
    printed_phases += 1;
}


function reset_for_new_event() {
    set_status("end");
    in_animation = false;
    printed_phases = 0;
    c = 0;
    //alert("done");
}

function is_animation_in_progress(evt) {
    //var new_event_ts = evt.timeStamp;
    if (new_event_ts != evt_ts) {

    }

}


$("html")[0].addEventListener(TRACKED_EVENT, function (e) {
    if (in_animation) {
        alert("in progress");
        e.stopPropagation();
        e.stopImmediatePropagation();
        return false;
    } else {
        in_animation = true;
        set_status("playing");
    }
    console.log("BEGIN_ANIMATION");
}, true);


$("*").each(function (i, el) {
    $(el).css('opacity', "0.95"); //not a good idea with heavy dom
    //handle...