Reputation: 172
First of all I am afraid for asking this question because you can rate me bad but I have to ask. I will delete the question by myself just let me know in comments.
I want to move the elements to specific position when user move the an element to right 25px then it should automatically move to the right element like new ul > li should be created in its a first 2nd level of element then if someone drag this element which has moved more to the 25px right then it should also move to the right and it should be the 3rd level and so on. and also to the left side drag to revert to the orignal position I want to make a tree structure like this when someone drag the element to the right or left then
[----1--1st level--]
[----2--1st level--]
[----1--2nd level--]
[----1--3rd level--]
[----2--3rd level--]
[----1--4th level--]
[----2--2nd level--]
[----1----]
[----2----]
[----3----]
how can I do that? is there any js library? Thanks
Upvotes: 3
Views: 1103
Reputation: 17415
I created & provided this idea here on stackoverflow before.
I know it can be improved and make a better version of it but now you can use it and enjoy....
you can test it on fiddle
Result of my codes:
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; }
Upvotes: 2
Reputation: 18427
You can use the html5sortable library to create a tree structure draggable list by using the connectWith
option:
$('.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>
The only downside is that it's a pretty clean library - it doesn't do a whole lot besides dragging, so everything else (dragging outside, creating new lists, etc.) you need to implement on your own (for example, in the snippet above if you drag all the items out of the inner list it "disappears" and you can't drag back to it).
But that being said, it shouldn't prove too difficult, as html5sortable
has a neat little reload
method so you can just call it every time you add a new .sortable
element to the div:
$('.sortable').sortable('reload');
I just did something similar not long ago (I also used the finderSelect
plugin with it to create a file-manager like behavior, although that might be overkill if you don't need all that).
Upvotes: 1