【问题标题】:Emulate Frameset Separator Behavior模拟框架集分隔符行为
【发布时间】:2013-05-19 14:51:03
【问题描述】:

HTML5 当前规范删除了<frameset> 标签。

<frameset> 有一个不错的功能,没有它就不容易重现:

在框架集中,您可以使用鼠标更改分隔框架的线的位置。

如何在 JavaScript 中使用 DIV 来提供相同的功能?

我遇到了the following,它展示了我正在寻找的行为。但是我想避免使用 JQuery,即使使用 jQuery 应该是首选方式。

【问题讨论】:

  • 这里删除了 cmets。当某人已经声明他们不打算使用某个特定库时,试图说服他们使用它并不是真正的主题,通常也没有帮助 - 特别是当可以创建相同的东西而没有太多大惊小怪时。

标签: javascript html frameset


【解决方案1】:

看了你的示例小提琴后,我可以说没有 jQuery 这实际上很容易。

那里的所有功能都只是简单的innerHTMLstyle操作,以及事件订阅。

不使用 jQuery 直接重写该代码是:

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;
};

所以这里和pure JS 是一样的。


编辑:正如@BenjaminGruenbaum 指出的那样,覆盖DOM 元素上的on* 属性与指定新的事件处理程序不同。

在 DOM 元素上覆盖 onmouseuponloadonclick 等属性是“旧”方式,因此即使在 JS 的石器时代也支持它。我上面的代码就是这样写的。

现在添加和删除事件处理程序的标准方法是addEventListenerremoveEventListener。旧 IE 不支持它们(但可以是 worked around)。

它让您可以将无限数量的侦听器附加到同一个事件,并且它们不会相互干扰。

因此可以通过以下方式实现相同的功能:

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.

请注意,在这种情况下,我的函数不是匿名的,因此如果您尚未在函数范围内,则使用 self executing function 进行范围界定在这里是有意义的。

【讨论】:

  • 谢谢,我知道有一个 15 行的答案。而且它可以从 JQuery 翻译,只是我不知道是谁做的。
  • 这是一个很好的答案,但它并不完全相同,请注意,当您通过将处理程序分配给 on 类型的函数(如 window.onmouseup)来附加事件时,您正在附加一个 只有 事件,如果你添加另一个 window.onmouseup 你会覆盖旧的,这与 jQuery 的 .mouseup 不同,你可能想要查看 addEventListener 是否完全相同。
  • 谢谢。换句话说,在 Vanilla-JS 中你覆盖了监听器,而在 jQuery 中你添加了监听器。很高兴知道。
  • @BenjaminGruenbaum 是的,这是真的,为window.onmouseup 赋值不是订阅事件,而是覆盖已订阅事件的函数。根据onmouseup,它可能会干扰其他脚本。我懒得指出来,但现在我必须将它纳入我的答案中。
  • 你不必感到羞耻。很长时间以来,我一直在寻找像您的“考虑接受我的答案”这样的链接。你的答案很完美。
【解决方案2】:

这是@SoonDead 的纯粹而简单的答案的水平版本,带有底部架子和水平分隔线。

结果应该是这样的:

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】:

    我没有足够的声誉来为“SoonDead”的解决方案添加评论,所以我必须这样做。 :-( 除了 IE8 之外,这些解决方案都很棒并且对我来说很有效

    1) 线 e.preventDefault(); IE8 有两个问题

    • 参数“e”vent 未定义。
    • 没有为 e 定义preventDefault 方法

    所以上面的行被替换为: e = e || window.event; e.preventDefault ? e.preventDefault() : e.returnValue=false;

    以上停止了错误(我在这里停止,因为我并不真正关心 IE8,但不希望为不幸的用户弹出错误框)。所以是的,在我的应用中,IE8 用户无法调整大小。

    但是,我确实追了一点,发现了这些问题:

    1. 代码流没有进入onmousemove函数
    2. e.pageX 必须替换为 e.clientXe.screenX(取决于您的情况),因为我无法将 pageX 视为 IE8 调试器中的属性。

    【讨论】:

    • 因为我已经很接近了,所以我可以使用 IE8。不得不进行以下更改: 1. 将要调用的函数从 onmousedown(在分隔符上)、onmousemove(在主体上)、onmouseup(在主体上)进行更改
    • 因为我已经很接近了,所以我可以使用 IE8。不得不进行以下更改: 1. 将要调用的函数从 onmousedown(在分隔符上)、onmousemove(在主体上)、onmouseup(在主体上)更改为 2. 添加一个全局变量移动,并将其设置为 true在 onmousedown 3. 将 onmousemove 中的所有代码放在 if (moving) 中 4. 在 onmousemove 中添加 var pageX = e.pageX || e.clientX; 5. 在 onmousemove 中将所有 e.pageX 更改为 pageX 6. 在 onmouseup 中 moving = false;
    • &lt;body onMouseMove='f_mouseMove(event)' onMouseUp='f_mouseUp()'&gt; &lt;div id="separator" onmousedown="f_mouseDown(event)"&gt;&lt;/div&gt;
    • var moving = false;
    • function f_mouseDown(e) { e = e || window.event; e.preventDefault ? e.preventDefault() : e.returnValue = false; moving = true; }
    【解决方案4】:

    Here are some options discussed on SO.

    我的个人推荐是jQuery Resizable

    正如 BenjaminGruenbaum 在评论中所说,jQuery JavaScript。如果您不想加载完整的 jQuery 库,则需要找到您需要的 jQuery 库的哪些部分,然后提取要使用的源 JavaScript。这当然是可行的。

    【讨论】:

    • 请参阅我对@BenjaminGruenbaum 的评论。你是对的:jQuery 解决方案可能是最好的解决方案。除非它不可行,因为我根本不知道 jQuery。请不要对我说 jQuery 是每个人的必备品。在这一点上你可能也是对的,但这是我学会忍受的缺陷。我什至用匿名用户名发布了我的问题,以保持不被识别。
    • 我只会在你没有尝试学习它的情况下激怒你。当您可以学习提高时,不要学习缺乏知识! /endFlame
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-20
    相关资源
    最近更新 更多