Search code examples
javascripthtmlframeset

Emulate Frameset Separator Behavior


The HTML5 current specification removed the <frameset> tag.

There is a nice feature of <frameset> which is not easy to reproduce without it:

In a frameset, you can change the position of the line separating the frames with the mouse.

How would I provide the same functionality with with using DIVs in JavaScript?

I've come across the following which demonstrates the behavior I'm looking for. However I would like to avoid using JQuery, even though using jQuery should be the preferred way.


Solution

  • After looking at your example fiddle, I can say that this is actually quite easy without jQuery.

    All the functions there are just simple innerHTML and style manipulation, and event subscription.

    A direct rewrite of that code without jQuery would be:

    var i = 0;
    
    document.getElementById("dragbar").onmousedown = function (e) {
    
        e.preventDefault();
        document.getElementById("mousestatus").innerHTML = "mousedown" + i++;
        window.onmousemove = function (e) {
            document.getElementById("position").innerHTML = e.pageX + ', ' + e.pageY;
            document.getElementById("sidebar").style.width = e.pageX + 2 + "px";
            document.getElementById("main").style.left = e.pageX + 2 + "px";
        };
    
        console.log("leaving mouseDown");
    };
    
    window.onmouseup = function (e) {
        document.getElementById("clickevent").innerHTML = 'in another mouseUp event' + i++;
        window.onmousemove = null;
    };
    

    So here is the same fiddle with pure JS.


    EDIT: As @BenjaminGruenbaum pointed out, overriding the on* properties on a DOM element is not the same as specifying a new event handler.

    Overriding properties like onmouseup, onload, onclick on DOM elements is the "old" way, and therefore it was supported in even the stone age of JS. My code above was written like that.

    Nowadays the standard way of adding and removing event handlers are addEventListener and removeEventListener. They are not supported in old IE (but this can be worked around).

    It let's you attach unlimited number of listeners to the same event and they will not interfere with each other.

    So the same functionality can be achieved by:

    var i = 0;
    
    function dragBarMouseDown(e) {
        e.preventDefault();
        document.getElementById("mousestatus").innerHTML = "mousedown" + i++;
        window.addEventListener("mousemove", windowMouseMove, false);
        console.log("leaving mouseDown");
    }
    
    function windowMouseMove(e) {
        document.getElementById("position").innerHTML = e.pageX + ', ' + e.pageY;
        document.getElementById("sidebar").style.width = e.pageX + 2 + "px";
        document.getElementById("main").style.left = e.pageX + 2 + "px";
    }
    
    function windowMouseUp(e) {
        document.getElementById("clickevent").innerHTML = 'in another mouseUp event' + i++;
        window.removeEventListener("mousemove", windowMouseMove, false);
    }
    
    document.getElementById("dragbar").addEventListener("mousedown", dragBarMouseDown, false);
    
    window.addEventListener("mouseup", windowMouseUp, false);
    

    Fiddle.

    Note that in this case my functions are not anonymous, so a self executing function for scoping would make sense here, if you are not already in function scope.