【问题标题】:Drag elements to specific position using jquery or simple js使用 jquery 或简单 js 将元素拖动到特定位置
【发布时间】:2014-11-10 19:19:10
【问题描述】:

首先我很害怕问这个问题,因为你可以评价我不好,但我必须问。 我会自己删除问题,请在 cmets 中告诉我。

当用户将元素向右移动 25px 时,我想将元素移动到特定位置,然后它应该像 new ul 一样自动移动到正确的元素 > li 应该在其第一个 2 级元素中创建,然后如果有人拖动这个元素向右移动了 25px,然后它也应该向右移动,它应该是第 3 级,依此类推。并且也向左侧拖动以恢复到原始位置 当有人将元素向右或向左拖动时,我想制作这样的树结构

[----1--1st level--]
[----2--1st level--]
  [----1--2nd level--]
    [----1--3rd level--]
    [----2--3rd level--]
      [----1--4th level--]
  [----2--2nd level--]
    [----1----]
    [----2----]
    [----3----]

我该怎么做?有没有js库?谢谢

【问题讨论】:

  • 我创建了这个想法here,但它是由 jQuery 创建的。您可以考虑它的代码并使用mootools对其进行模拟,或者如果可能的话将您的js框架更改为jquery......无论如何,如果它对您有用,那么请更改您的问题标题及其标签并在其中包含jQuery然后我写此评论作为并在此处回答。好吗?
  • 我没问题,但我无法将节点拖到此处:fiddle.jshell.net/RAM_Designer/vwnneLfr/4
  • 在此示例中,您可以在单击一个节点后使用键盘的箭头键。这是一种安全的方法。你用方向键测试过吗?
  • 我明白了,但是有什么方法可以用鼠标拖动吗?
  • 当然,我们可以通过 jQuery 来做到这一点,如果你愿意,我可以在这里更改我的代码并创建一个答案,但在这里我不能这样做,因为你的问题标题和它的标签是关于 mootools 的,否则你更改它并在其中包含 jQuery。

标签: javascript jquery html css


【解决方案1】:

我之前在 stackoverflow 上创建并提供了这个想法 here

我知道它可以改进并制作一个更好的版本,但现在你可以使用它并享受它......

它的特点:

»» 支持键盘方向键移动节点(左右)

»» 支持鼠标左右拖动节点

»» 将每个节点的关卡数据保存在DOM中并显示在每个节点上

你可以test it on fiddle


我的代码结果:

JS & jQuery

/*Code by Ram >> https://stackoverflow.com/users/1474613/ram */

(function ($) {
    $.Noder = function (oneOfNodes) {
        this.element = '';
        oneOfNodes=(oneOfNodes instanceof $) ? oneOfNodes : $(oneOfNodes)
        this.baseX=oneOfNodes.position().left;
        this.currentX=0;
    };

    $.Noder.prototype = {
        InitEvents: function () {
            //`this` references the created instance object inside an instace's method,
            //however `this` is set to reference a DOM element inside jQuery event handler functions' scope.
            //So we take advantage of JS's lexical scope and assign the `this` reference to
            //another variable that we can access inside the jQuery handlers
            var that = this;
            //I'm using `document` instead of `this` so it will catch arrow keys
            //on the whole document and not just when the element is focused.
            //Also, Firefox doesn't fire the keypress event for non-printable characters
            //so we use a keydown handler
            $(document).keydown(function (e) {
                var key = e.which;
                if (key == 39) {
                    that.moveRight();
                } else if (key == 37) {
                    that.moveLeft();
                }
            });},
        setElement: function(element){
            this.element = (element instanceof $) ? element : $(element);
            console.log(this.element);
            this.currentX=this.element.position().left;
            console.log('currentX: '+this.currentX);
            this.element.addClass('active');
        },
        moveRight: function () {
            console.log('bseX: '+this.baseX);
            console.log('currentX: '+this.currentX);
            var max=(25*2)+this.baseX;
            console.log('max: '+max);
            if(this.currentX<max)
            {
                this.element.css("left", '+=' + 25);
                this.currentX=this.element.position().left;
                setElementLevel(this.element,this.currentX,this.baseX);
                console.log('currentX: '+this.currentX);
            }
        },
        moveLeft: function () {
            if(this.currentX>this.baseX)
            {
                this.element.css("left", '-=' + 25);
                this.currentX=this.element.position().left;
                setElementLevel(this.element,this.currentX,this.baseX);
                console.log('currentX: '+this.currentX);
            }
        }

    };
    $.Noder.defaultOptions = {
        currentX: 0
    };

}(jQuery));

function setElementLevel(element,currentX,baseX){
    var level=0;
    if (currentX==baseX+25)
        level=1;
    else if(currentX==baseX+25+25)
        level=2;
    element.data('level', level);
    setLevelOnElement(element);
}

function getElementLevel(element){
    console.log(element.data('level'));
    return element.data('level');
}

function setLevelOnElement(element){  
    var level = 0;
    if(typeof getElementLevel(element) !=='undefined')
        level = getElementLevel(element);
    console.log('my level: '+level);
    var $levelElement=element.find( ".node-level" );
    if ($levelElement && $levelElement.length>0)
    {
        $levelElement=$($levelElement[0]); 
        console.log($levelElement);
        $levelElement.html(level);
    }
}

var noder = new $.Noder($("#myTree>.node")[0]);

$("#myTree>.node").on('click',function(){
    $("#myTree>.node").each(function(){
        $(this).removeClass('active')
    });    
    console.log($(this)[0].id +' clicked')

    noder.setElement($(this)[0]);

})
noder.InitEvents();


$(document).ready(function() {
    var $dragging = null;
    var $myTree=$('ul#myTree');
    var $oneOfNodes=null;
    var baseX=0;
    if($myTree.length>0)
    {
        console.log($myTree);
        $oneOfNodes=$($myTree.children()[0]);
        console.log($oneOfNodes);
        baseX=$oneOfNodes.position().left;
        console.log('baseX >> '+baseX);
        console.log($myTree);
        var x=0;
        $('ul#myTree').find('li').each(function(){
            x++;
            console.log(x);
            setLevelOnElement($(this));
        });
    }

    $(document.body).on("mousemove", function(e) {
        if ($dragging) {
            var currentX=$dragging.position().left;
            if(e.pageX>(baseX+25) && e.pageX<(baseX+(2*25)))
            {
                $dragging.offset({left: (baseX+25)});
                setElementLevel($dragging,currentX,baseX);
            }
            else if((e.pageX)>(baseX+(2*25)) )
            {
                $dragging.offset({left: (baseX+(2*25))});
                setElementLevel($dragging,currentX,baseX);
            }
            else if(e.pageX<(baseX+25) )
            {
                $dragging.offset({left: (baseX)});
                setElementLevel($dragging,currentX,baseX);
            }
        }
    });

    $(document.body).on("mousedown",  function (e) {
        var $myTree=$('ul#myTree');
        if($(e.target) && $myTree && $myTree.length>0)
        {
            var $li=$(e.target).parent();
            var $ul=$(e.target).parent().parent();
            if ( $ul.is($myTree) && $(e.target).hasClass("node-level") )
            {
                $ul.find('li').each(function(){
                    $(this).removeClass('active');
                });
                $li.addClass('active');
                $dragging = $($li);
            }
        }
    });

    $(document.body).on("mouseup", function (e) {
        $dragging = null;
    });
});

HTML

<ul id="myTree">
    <li class="node" id="node1">
        <span class="node-level"></span>
        <span class="node-content">Node 1</span>
    </li>
    <li class="node" id="node2">
        <span class="node-level"></span>
        <span class="node-content">Node 2</span>
    </li>
    <li class="node" id="node3">
        <span class="node-level"></span>
        <span class="node-content">Node 3</span>
    </li>
    <li class="node" id="node4">
        <span class="node-level"></span>
        <span class="node-content">Node 4</span>
    </li>
    <li class="node" id="node5">
        <span class="node-level"></span>
        <span class="node-content">Node 5</span>
    </li>
    <li class="node" id="node6">
        <span class="node-level"></span>
        <span class="node-content">Node 6</span>
    </li>
    <li class="node" id="node7">
        <span class="node-level"></span>
        <span class="node-content">Node 7</span>
    </li>
</ul>

CSS

#myTree{
    margin:20px;
    padding:0;
    list-style-type:none;
    font-size:11px;
}
#myTree>li>.node-level{
    padding:6px 10px;
    color:#ddd;
    background:gray;
    position:relative;
    cursor:move;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
#myTree>li>.node-content{
    padding:5px; 15px;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
#myTree>.node:hover {
    background:#acd;
    color:#004;
}
#myTree>.node.active {
    border:1px #a66 solid;
    background:#fd8;
    color:#004;
}
#myTree>li.node {
    width:151px;
    background:#ddd;
    margin-top:2px;
    padding:5px 0px 5px 0;
    color:#555;
    cursor:pointer;
    position:relative;
    border:1px solid #ccc;
}
html, body {
    height:100%;
}
div { width:151px;
    background:#ddd;
    margin-top:2px;
    padding:5px 15px;
    color:#555;
    cursor:pointer;
    position:relative;
    border:1px solid #ccc; }

【讨论】:

  • 作为评论可能比作为答案更好。
  • 这并没有提供问题的答案。要批评或要求作者澄清,请在其帖子下方发表评论。
  • @Dave 问题标题被 Mubasher 更改,他说我的回答对他很有用,所以我再次提供...
  • @emmanuel Mubasher 更改了问题标题,他说我的回答对他很有用,所以我再次提供...
  • 太好了,感谢 Ram,我可以自定义您的代码以使用我的框架
【解决方案2】:

您可以使用html5sortable 库通过connectWith 选项创建一个树形结构的可拖动列表:

$('.sortable').sortable({
  handle: ".handle",
  connectWith: '.connected'
});
* {
  font-family: Ubuntu, Sans-serif;
}
ul li {
  margin: 15px;
}
ul li .handle {
  cursor: pointer;
}
<link href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/html5sortable/0.1.1/html.sortable.min.js"></script>

<ul class="sortable connected">
  <li><i class="fa fa-arrows handle"></i> First Level Foo</li>
  <li><i class="fa fa-arrows handle"></i> First Level Bar</li>
  <li>
    <ul class="sortable connected">
      <li><i class="fa fa-arrows handle"></i> Second Level</li>
    </ul>
  </li>
</ul>

唯一的缺点是它是一个非常干净的库 - 除了拖动之外它并没有做很多事情,所以你需要自己实现其他一切(拖动外部,创建新列表等)(例如,在上面的 sn-p 中,如果您将所有项目拖出内部列表,它就会“消失”并且您无法拖回它)。

不过话虽如此,这应该不会太难,因为html5sortable 有一个简洁的reload 方法,所以你可以在每次向 div 添加新的.sortable 元素时调用它:

$('.sortable').sortable('reload');

不久前我刚刚做了类似的事情(我还使用finderSelect plugin 来创建类似文件管理器的行为,尽管如果你不需要所有这些可能会有点过头了)。

【讨论】:

  • 我不能向右拖动来创建二级和三级节点?
  • @Mubasher 不,正如我所说 - 它不是一个“智能”库,它只是让创建和管理可拖动列表变得更加容易。从那里您可以创建一个经理,在发生这种情况时处理和创建新列表
  • @Mubasher 另外,还有thistutorial
  • 很棒的教程,虽然我会在 ram 给出答案后继续学习。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-12
  • 1970-01-01
  • 1970-01-01
  • 2015-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多