【问题标题】:HTML drag event does not fire in firefoxHTML 拖动事件不会在 firefox 中触发
【发布时间】:2012-12-04 21:56:07
【问题描述】:

我有一个表,我需要在其上实现可拖动的标题列。我使用 Chrome 作为浏览器实现了它,一切正常。当我在 Firefox (17.0.1) 中测试它时,我注意到 drag 事件没有触发。不过,dragstart 确实如此。我在下面的标记中简化了问题。在 Chrome 中加载时,每次拖动时鼠标移动时,顶部标签都会更新。在 Firefox 中,它仍然是 0。

<!DOCTYPE html>
<html>
<head>
<title>TH Drag Test</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<style>
table,td,th {
    border: solid thin black;
}
</style>
<script>
    $(document).ready(function() {
        $("th").bind("drag", function(event) {
            $("#lbl").html(event.originalEvent.offsetX);
        });
    });
</script>
</head>
<body>
    <span id="lbl">0</span>
    <table>
        <thead>
            <tr>
                <th draggable="true">Column A</th>
                <th draggable="true">Column B</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>One</td>
                <td>Two</td>
            </tr>
            <tr>
                <td>Three</td>
                <td>Four</td>
            </tr>
        </tbody>
    </table>
</body>
</html>

【问题讨论】:

  • 我可以使用最新的 Chrome 和 FF 在我的系统上确认此行为。您是否尝试过使用较旧的 FF 版本?最近,根据我的经验,FF 在从一个“主要”版本切换到另一个版本时经常会丢失一些功能。

标签: javascript css html firefox


【解决方案1】:

在为 Firefox 解决这个问题时,我做了噩梦。我需要将 div 拖到日记上并检测放置的坐标,以便知道用户选择了哪个日期和时间。

为了触发拖动事件,我在 dragstart 事件处理程序中添加了以下行:

event.dataTransfer.setData('Text', this.id);

然而,最难解决的是如何在拖动结束时获取 x 和 y 坐标,因为这些不会在 Firefox 的 dragend 事件处理程序中返回。我尝试使用上面提到的鼠标事件,但我发现这些在拖动过程中不起作用,并且仅在调用 dragend 事件处理程序后才被调用。因此,我只使用了 dragend 事件来检测用户何时释放了 div,然后使用下一个鼠标移动事件来获取坐标并执行任何其他需要的工作。我发现这适用于 IE、Firefox 和 Chrome。 这是一个演示的html / javascript:

 <div>
<div id = "todrag" class = "testdiv" draggable="true"><p>Please drag me</p></div>

<div id = "destination" class = "testdiv"><p>To here</p></div>
<p id = "coords"></p>
<p id = "compareords"></p>
</div>

<script>
    var down = true;
    var m_xcoordDrag = 0;
    var m_ycoordDrag = 0;
    var m_xcoordMove = 0;
    var m_ycoordMove = 0;
    var m_dragReleased = false;
    var m_coordselement = document.getElementById("coords");
    var m_compareordselement = document.getElementById("compareords");

    function OnMouseMove(e) {
        m_xcoordMove = e.x;
        m_ycoordMove = e.y;
        m_coordselement.innerHTML = e.x + "," + e.y;

        if (m_dragReleased) {
            m_compareordselement.innerHTML = "X:" + m_xcoordDrag + ", " + m_xcoordMove + " Y:" + m_ycoordDrag + ", " + m_ycoordMove;

            m_dragReleased = false;
        }
    }

    dragstart = function (event) {

        event.dataTransfer.setData('Text', this.id);
        stop = false;
    }

    dragend = function (event) {
        m_dragReleased = true;

        m_xcoordDrag = event.x;
        m_ycoordDrag = event.y;
    }

    document.onmousemove = OnMouseMove;

    var toDrag = document.getElementById("todrag");

    toDrag.addEventListener('dragstart', dragstart);
    toDrag.addEventListener('dragend', dragend);

</script>

我希望这会有所帮助!

【讨论】:

  • 这行得通。副作用是设置文本数据将导致浏览器对放置事件使用默认处理程序。如果目标是触发拖动事件但不使用浏览器默认放置处理程序,请选择Text以外的非标准数据类型@
  • “设置文本数据将导致浏览器使用默认处理程序...到...不使用浏览器默认放置处理程序选择文本以外的非标准数据类型”。我遇到了这个确切的问题。我希望这是一个答案,所以我可以投票。最终使用“weorijwefij”而不是“text”,它现在的工作方式应该是这样。
【解决方案2】:

被切掉的位http://pastebin.com/bD2g3SqL

编辑:

这确实有效,但是我还没有找到访问 offsetX 和 offsetY 属性的方法,由于某种原因,事件的 FF 版本不包含它们。

<!DOCTYPE html>
<html>
<head>
<title>TH Drag Test</title>
<style>
table,td,th {
    border: solid thin black;
}
</style>
<script>
    function Init(){
        var n= document.getElementsByTagName("th");
        var j=0;

        for (var i=0; i<n.length; i++){
            n[i].addEventListener('drag', function (e){
                document.getElementById("lbl").textContent= j++;
            }, false);
        }

        for (var i=0; i<n.length; i++){
            n[i].addEventListener('dragstart', function (e){
                e.dataTransfer.setData('text/plain', 'node');
            }, false);
        }
    }
</script>
</head>
<body onload="Init();">
    <span id="lbl"></span>
    <table>
        <thead>
            <tr>
                <th draggable="true">Column A</th>
                <th draggable="true">Column B</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>One</td>
                <td>Two</td>
            </tr>
            <tr>
                <td>Three</td>
                <td>Four</td>
            </tr>
        </tbody>
    </table>
</body>
</html>

显然,您需要做的是“初始化”拖动 (source.)

EDIT2:

显然,拖动事件(如图)中有一个错误,它不会更新 clientX 和 clientY 属性(source。)它们会在其他一些事件上更新,例如 dragover 事件,但是该事件只会触发当对象被拖动到一个合理的放置目标上时。摆脱这种愚蠢情况的方法就是这样粗暴:

<!DOCTYPE html>
<html>
<head>
<title>TH Drag Test</title>
<style>
table,td,th {
    border: solid thin black;
}
</style>
<script>    
    var down= false;

    document.onmousemove= OnMouseMove;

    function Init(){
        var n= document.getElementsByTagName('th');

        for (var i=0; i<n.length; i++){
            n[i].onmousedown= OnMouseDown;
        }

        document.onmouseup= OnMouseUp;
    }

    function OnMouseDown(e){
        down= true;
    }

    function OnMouseUp(e){
        down= false;
    }

    function OnMouseMove(e){
        if (!down) return;

        document.getElementById('lbl').textContent= e.pageX ? ('x: ' + e.pageX + ' y: ' + e.pageY) : ('x: ' + (e.clientX + document.documentElement.scrollLeft + document.body.scrollLeft) + ' y: ' + (e.clientY + document.documentElement.scrollTop + document.body.scrollTop));
    }

</script>
</head>
<body onload="Init();">
    <span id="lbl"></span>
    <table>
        <thead>
            <tr>
                <th draggable="true">Column A</th>
                <th draggable="true">Column B</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>One</td>
                <td>Two</td>
            </tr>
            <tr>
                <td>Three</td>
                <td>Four</td>
            </tr>
        </tbody>
    </table>
</body>
</html>

【讨论】:

  • 因为你的内联javascript,我杀了两只小猫。
  • 好吧,这里要记住的重要一点是,你是杀死他们的人。另外,this.
  • 我刚刚在 Firefox 便携式 3.6.28 中测试了所有这些,但它们都没有按预期工作。丹麦的某些东西已经腐烂了。
  • 确实如此。您需要调用 dataTransfer.setData 才能触发拖动事件。我没有在任何地方的 FF 文档中注意到这一点
  • count_of_years_and_its_still_as_bad_as_it_used_to_be += 2
【解决方案3】:

Firefox 需要在 dragstart 事件中设置“某事”(我们在这里称为“初始化”)来初始化其余的拖动事件。

这可能是因为所有 DOM 元素在 XUL 中默认都是draggable="true"。 (参考:https://bugzilla.mozilla.org/show_bug.cgi?id=646823#c4

例子:

<div id="something" draggable="true" ondragstart="event.dataTransfer.setData('text/plain', 'node');">Drag me</div>

Chrome 不需要这种“初始化”。

【讨论】:

    猜你喜欢
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    • 2015-12-19
    • 2015-03-16
    • 1970-01-01
    相关资源
    最近更新 更多