问题
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.
回答1:
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.
回答2:
Here is a horizontal version of @SoonDead's pure and simple answer with a bottom shelf and a horizontal divider.
The result should look like this:
fiddle here
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("main").style.height = e.pageY + 2 + "px";
document.getElementById("dragbar").style.top = e.pageY + 2 + "px";
document.getElementById("bottomshelf").style.top = e.pageY + 17 + "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);
body, html {
width:100%;
height:100%;
padding:0;
margin:0;
}
#header {
background-color: wheat;
width:100%;
height: 50px;
}
#main {
background-color: BurlyWood;
float: top;
position: absolute;
top:50px;
width:100%;
bottom: 38px;
overflow-y: hidden;
}
#dragbar {
background-color:grey;
width:100%;
float: top;
top:120px;
bottom:0px;
height: 15px;
cursor: row-resize;
position:absolute;
}
#bottomshelf {
background-color: IndianRed;
width:100%;
float: top;
position: absolute;
top:135px;
bottom: 38px;
}
#footer {
background-color: PaleGoldenRod;
width:100%;
height: 38px;
bottom:0;
position:absolute;
}
<div id="header">header <span id="mousestatus"></span>
<span id="clickevent"></span>
</div>
<div id="main">main area:
The bottom shelf will slide over this.
</div>
<div id="dragbar">drag me up or down</div>
<div id="bottomshelf">
<span id="position"></span>
bottom shelf</div>
<div id="footer">footer</div>
回答3:
I don't have enough reputation to add comment to "SoonDead"s solutions, so I have to do this. :-( The solutions are great and worked out for me, except for IE8
1) The line
e.preventDefault();
has two issues for IE8
- the argument "e"vent is not defined.
- preventDefault method is not defined for e
So the above line is replaced with:
e = e || window.event;
e.preventDefault ? e.preventDefault() : e.returnValue=false;
The above stopped the errors (and I stopped here since I don't really care about IE8 but do not want error boxes popping up for the hapless user). So yes, in my app IE8 users cannot resize.
However, I did chase it down a little, and found these issues:
- Code flow did not enter the onmousemove function
- The
e.pageX
will have to be replaced bye.clientX
ore.screenX
(depending on your case) since I could not see pageX as a property in the IE8 debugger.
回答4:
Here are some options discussed on SO.
My personal recommendation would be jQuery Resizable.
As BenjaminGruenbaum said in a comment, jQuery is JavaScript. If you don't want to load the full jQuery library, you'll need to find which parts of the jQuery library you need and pull out the source JavaScript to use. It's certainly doable.
来源:https://stackoverflow.com/questions/16635959/emulate-frameset-separator-behavior