So I do have a loop of droppable areas where user is able to drop items. Size of the loop can be different. It depends on user's input. You can check fiddle here
Here is my droppable area:
$(".projLeader ol").droppable({
tolerance: 'pointer',
hoverClass: 'highlight',
drop: function(ev, ui)
{
var zz = ui.draggable.text()
var xyz = itm.includes(zz);
if (xyz === false)
{
var item = ui.draggable;
if (!ui.draggable.closest('.placeholder').length) item = item.clone().draggable();// if item was dragged from the source list - clone it
//this.innerHTML = ''; // clean the placeholder
item.addClass('dropClass').appendTo(this);
// append item to placeholder
//add to array
itm.push(zz);
var n = $(this).closest("div.proc").find(".dropClass").length;
$(this).closest("div.proc").find("h6").text("Items Dropped: " + n + ".");
}
else
{
alert('Name is Already Exist');
}
}
});
The problem is I got warning message for each field. For example if I drop item in box1 and then want to drop same item in box2 I got warning message. How can I fix it? Thanks for any help
I spent some time understanding your code and here's the solution. I added some code to detect if an existing box already exists.Hope it helps :)!
var itm = [];
$( "#savebutton" ).click(function() { LISTOBJ.saveList(); });
$("#myAccordion").accordion({heightStyle:"content", active: false, collapsible:true});
$("#myAccordion li").draggable({
appendTo: "body",
helper: "clone",
start: function(ev, ui){ ui.helper.width($(this).width()); }
});
$(".projLeader ol").droppable({
tolerance: 'pointer',
hoverClass: 'highlight',
drop: function(ev, ui)
{
var zz = ui.draggable.text()
var xyz = itm.includes(zz);
if (xyz === false)
{
var item = ui.draggable;
var map = {}, i , size;
var flag = false;
if (!ui.draggable.closest('.placeholder').length){
item = item.clone().draggable();// if item was dragged from the source list - clone it
//this.innerHTML = ''; // clean the placeholder
item.addClass('dropClass').appendTo(this);
// append item to placeholder
//add to array
var n = $(this).closest("div.proc").find(".dropClass").length;
$(this).closest("div.proc").find("h6").text("Items Dropped: " + n + ".");
var listOfElements = $(this).closest("div.proc").find("li").text();
var newarr = listOfElements.split('x');
newarr.shift();
var actualArrayLength = newarr.length;
for (i = 0, size = newarr.length; i < size; i++){
if (map[newarr[i]]){
xyz = true;
alert("Name is Already Exist");
$(this).closest("div.proc").find("h6").text("Items Dropped: " + (n - 1) + ".");
$(this).closest("div.proc").find("li:last-child").remove();
return false;
}
else{
map[newarr[i]] = true;
newarr[newarr.length - 1];
}
}
}
}
}
});
$(".projLeader").on('click', '.closer', function(){
var item = $(this).closest('.item');
itm.splice(item);
item.fadeTo(200, 0, function(){ item.remove(); })
});
var LISTOBJ = {
saveList: function() {
var listCSV = "";
$( ".projLeader li" ).each(function() {
if (listCSV === "") {
listCSV = $(this).text();
} else {
listCSV += ", " + $(this).text();
}
$("#output").text(listCSV);
$(".hiddenListInput").val(listCSV);
});
}
}
body {
font-family: verdana;
font-size: 12px;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
margin-bottom: 10px;
}
ol{list-style-type: none;}
.item { height:20px; width: 180px; margin:5px; padding:5px; border:1px solid gray; background-color: #cd8; position: relative; }
.item .closer { position: absolute; right: 5px; top: 2px; font: bold 14px arial; color: #666; padding: 1px 3px; line-height: 1; cursor: pointer; display: none;}
.item .closer:hover { color: #000; }
.placeholder { height: 30px; width: 195px; margin: 5px; background: #eee; border: 1px dashed #999; }
.placeholder .item { margin: 0; }
ol .item .closer { display: block; }
.highlight { border: 1px solid red; background: #fff; }
.highlight .item { opacity: 0.3; }
.ui-draggable-dragging { z-index: 99; opacity: 1 !important; }
.dropClass {
background-color: lightblue;
padding-left: 10px;
width: 180px;
border: 1px solid black;
border-radius: 8px;
margin-bottom: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<h1 class="ui-widget-header">Products</h1>
<div id="myAccordion">
<h3>T-Shirts</h3>
<div>
<ul>
<li class="item"><span class="closer">x</span>Lolcat Shirt</li>
<li class="item"><span class="closer">x</span>Cheezeburger Shirt</li>
<li class="item"><span class="closer">x</span>Buckit Shirt</li>
</ul>
</div>
<h3>Bags</h3>
<div>
<ul>
<li class="item"><span class="closer">x</span>Zebra Striped</li>
<li class="item"><span class="closer">x</span>Black Leather</li>
<li class="item"><span class="closer">x</span>Alligator Leather</li>
</ul>
</div>
<h3>Gadgets</h3>
<div>
<ul>
<li class="item"><span class="closer">x</span>iPhone</li>
<li class="item"><span class="closer">x</span>iPod</li>
<li class="item"><span class="closer">x</span>iPad</li>
</ul>
</div>
</div>
<div class='proc'><pre>
<h6> </h6><br /></pre>
<div class="projLeader">
<label>Box1:</label>
<div class="ui-widget-content">
<ol id = "ID1">
<li class="placeholder" name="projLeader"></li>
<input type="hidden" name="projLeader" class="hiddenListInput1" />
</ol>
</div>
</div>
</div>
<div class='proc'><pre>
<h6> </h6><br /></pre>
<div class="projLeader">
<label>Box2:</label>
<div class="ui-widget-content">
<ol id = "ID2" >
<li class="placeholder" name="projLeader"></li>
<input type="hidden" name="projLeader" class="hiddenListInput2" />
</ol>
</div>
</div>
</div>
<br/>
<input type="submit" id="savebutton" class="button" value="Save" onclick="userSubmitted = true;" />
<div id="output"></div>
Related
I have divs that automatically cycle to the next div and show its contents after every few seconds. The functionality works fine however, there seems to be a gap when the last div hides and the first div is meant to show as the underline in the corresponding link for the div has a slight delay- it should change immediately. I can't figure out why this is happening. Also, I am trying execute the function 5 seconds after the page has loaded .delay(5000) does not seem to work. Below is the code:
var homeLinks = ['i-t', 'o-c', 'c-f', 'i-c', 'c-u'];
var currentLink = 0;
var hovered = false;
$(".home-link").hover(function() {
hovered = true;
$('.home-' + homeLinks[currentLink]).hide();
$('[data-hover=' + homeLinks[currentLink] + ']').toggleClass('default-underline');
currentLink = homeLinks.indexOf($(this).attr('data-hover'));
$('[data-hover=' + homeLinks[currentLink] + ']').toggleClass('default-underline');
$('.home-' + homeLinks[currentLink]).show();
}, function() {
hovered = false;
});
var autoNavInterval = setInterval(autoNav, 3000);
function autoNav() {
if (hovered === false) {
$('.home-' + homeLinks[currentLink]).hide();
$('[data-hover=' + homeLinks[currentLink] + ']').toggleClass('default-underline');
currentLink++;
if (currentLink >= homeLinks.length) {
currentLink = 0;
}
$('[data-hover=' + homeLinks[currentLink] + ']').toggleClass('default-underline');
$('.home-' + homeLinks[currentLink]).show();
}
}
.left-fill {
background: #0000006b;
height: 100vh;
}
.right-fill {
background: pink;
height: 100vh;
}
.vc_col-sm-6 {
width: 50%;
float: left;
}
.pivot-nav {
list-style: none;
font-family: 'Montserrat';
text-align: left;
}
.pivot-nav li a {
font-size: 1.6rem;
font-weight: 700;
text-transform: uppercase;
display: inline-block;
position: relative;
color: #fff;
text-decoration: none;
line-height: 40px;
}
.pivot-nav li a.default-underline::after,
.pivot-nav li a:hover::after {
width: 100%;
}
.pivot-nav:hover a.default-underline:not(:hover)::after {
width: 0;
}
.pivot-nav li a::after {
bottom: 0;
content: "";
display: block;
height: 4px;
position: absolute;
background: #fff;
transition: width 0.3s ease 0s;
width: 0;
}
.home-o-c,
.home-c-f,
.home-i-c,
.home-c-u {
display: none;
}
.our-company {
clear: both;
display: block;
height: 50vh;
}
.cf2 {
clear: both;
display: block;
height: 50vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="left-fill text-left wpb_column vc_column_container vc_col-sm-6">
<div class="wpb_wrapper">
<p class="home-i-t">TEXT One</p>
<p class="home-o-c">TEXT One</p>
<p class="home-c-f">TExt for C f.</p>
<p class="home-i-c">Some more text fo i c.</p>
<p class="home-c-u">Get in touch </p>
</div>
</div>
<div class="home-fill right-fill text-right wpb_column vc_column_container vc_col-sm-6">
<div class="wpb_wrapper">
<ul class="pivot-nav">
<li class="pivot-nav-item"><a data-hover="o-c" class="home-link" href="#" data-toggle="my-scrollspy-2">O C</a></li>
<li class="pivot-nav-item"><a data-hover="c-f" class="home-link" href="#" data-toggle="my-scrollspy-2">C F</a></li>
<li class="pivot-nav-item"><a data-hover="i-c" class="home-link" href="#" data-toggle="my-scrollspy-2">I C</a></li>
<li class="pivot-nav-item" data-toggle="my-scrollspy-2"><a data-hover="c-u" class="home-link" href="#">C U</a></li>
</ul>
</div>
</div>
To start function 5 secounds after the page was loaded first you need to be sure that your script starts working after the document is ready. Use the basic jQuery function $(function () { /* code executed after the document loaded */ } );.
Than use simple javaScript function setTimeout.
The underline switched between C U and O C longer because you set the currentLink value to 0 after you iterate through every element in the array homeLinks and the 0 element would be an a with data-hover="i-t" which doesn't exist. You can remove the first string from the array or create an element in the list or set the currentLink value to 1 after you reach the homeLinks value with currentLink.
I fixed your script code to do exactly what you described with as few changes as possible:
$(function () {
var homeLinks = ['i-t', 'o-c', 'c-f', 'i-c', 'c-u'];
var currentLink = 0;
var hovered = false;
$(".home-link").hover(function () {
hovered = true;
$('.home-' + homeLinks[currentLink]).hide();
$('[data-hover=' + homeLinks[currentLink] + ']').toggleClass('default-underline');
currentLink = homeLinks.indexOf($(this).attr('data-hover'));
$('[data-hover=' + homeLinks[currentLink] + ']').toggleClass('default-underline');
$('.home-' + homeLinks[currentLink]).show();
}, function (event) {
hovered = false;
currentLink = 0;
$('.wpb_wrapper p').hide();
$(event.target).toggleClass('default-underline');
});
setTimeout(() => {
var autoNavInterval = setInterval(autoNav, 1000);
}, 1000);
function autoNav() {
if (hovered === false) {
$('.home-' + homeLinks[currentLink]).hide();
$('[data-hover=' + homeLinks[currentLink] + ']').toggleClass('default-underline');
currentLink++;
if (currentLink >= homeLinks.length) {
currentLink = 1;
}
$('[data-hover=' + homeLinks[currentLink] + ']').toggleClass('default-underline');
$('.home-' + homeLinks[currentLink]).show();
}
else {
}
}
});
I have a drag and drop list of parent and child categories. I want to set the data attributes to the numerical order when I hit the test button. The parent data attribute currently works. But I'm having trouble getting the child data attribute to work correctly.
So for each parent, the child category should be number 1,2,3... and then the count should reset for the next parent. Right now the child doesn't reset for the new parent. How can I get the child to reference its parent so I can get the counter to reset?
Not sure if this is the best way to accomplish this. The end goal is to grab those data attributes and use that number to update the orderId in the database.
$(".categories").sortable({
connectWith: ".categories",
placeholder: "placeholder",
start: function(event, ui) {
if (ui.helper.hasClass('child-category')) {
ui.placeholder.removeClass('placeholder');
ui.placeholder.addClass('placeholder-sub');
} else {
ui.placeholder.removeClass('placeholder-sub');
ui.placeholder.addClass('placeholder');
}
},
sort: function(event, ui) {
var pos;
if (ui.helper.hasClass('child-category')) {
pos = ui.position.left + 20;
$('#cursor').text(ui.position.left + 20);
} else if (ui.helper.hasClass('parent-category')) {
pos = ui.position.left;
$('#cursor').text(ui.position.left);
}
if (pos >= 32 && !ui.helper.hasClass('child-category')) {
ui.placeholder.removeClass('placeholder');
ui.placeholder.addClass('placeholder-sub');
ui.helper.addClass('child-category');
ui.helper.removeClass('parent-category');
} else if (pos < 25 && ui.helper.hasClass('child-category')) {
ui.placeholder.removeClass('placeholder-sub');
ui.placeholder.addClass('placeholder');
ui.helper.removeClass('child-category');
ui.helper.addClass('parent-category');
}
}
});
$(".category").attr("data-order-parent", "");
$(".category").attr("data-order-child", "");
var i = 1;
$(".parent-category").each(function() {
$(this).attr("data-order-parent", i);
var j = 1;
$(".child-category").each(function() {
$(this).attr("data-order-child", j);
j++;
});
i++;
});
.categories {
list-style: none outside none;
}
.category {
background: #fff;
border: 1px solid #ddd;
cursor: move;
height: 50px;
line-height: 50px;
padding: 0 10px;
width: 480px;
}
.category:hover {
background-color: #F5F5F5;
}
.child-category {
margin-left: 40px;
width: 440px;
}
.placeholder {
background: #fff;
border: 1px dashed #ccc;
height: 50px;
width: 480px;
}
.placeholder-sub {
background: #fff;
border: 1px dashed #ccc;
height: 50px;
width: 440px;
margin-left: 40px;
}
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<button id="TEST" type="button">TEST</button>
<ul class='categories'>
<li class="category parent-category" data-order-parent="" data-order-child="">
categoryName-1
</li>
<li class="category parent-category" data-order-parent="" data-order-child="">
categoryName-2
</li>
<li class="category parent-category" data-order-parent="" data-order-child="">
categoryName-3
</li>
<li class="category parent-category" data-order-parent="" data-order-child="">
categoryName-4
</li>
</ul>
You should just iterate over your categories only once: children always follow after the last parent, so it is not so difficult to keep track.
Add this to the sortable object argument:
stop: function(event, ui) {
$(".category").attr("data-order-parent", "");
$(".category").attr("data-order-child", "");
var i = 1, j = 1;
$(".category").each(function() { // Iterate all categories (not only parents)
if ($(this).is(".parent-category")) { // Is it parent or child?
$(this).attr("data-order-parent", i++);
j = 1; // Reset child counter
} else {
$(this).attr("data-order-child", j++);
}
});
}
i have this piece of code and i would like to look for duplicates
and if found i want to get alert that it already exists so users cant insert that word/tag. can some one please help
<div id="tags">
<span>a</span> <span>b</span>
<input type="text" value="" class="paste" id="search" placeholder="Add a tag" />
</div>
<script>
$("#tags input").on({
focusout : function() {
var txt= this.value.replace(/[^a-z0-9\+\-\.\#]/ig,''); // allowed characters
if(txt) $("<span/>",{text:txt.toLowerCase(), insertBefore:this});
this.value="";
if (($('#tags span').length) >4) {
$('#tags input').prop('disabled', true);
}
},
keyup : function(ev) {
// if: comma|enter|space (delimit more keyCodes with | pipe)
if(/(188|13|32)/.test(ev.which)) $(this).focusout();
}
});
$('#tags').on('click', 'span', function() {
if(confirm("Remove "+ $(this).text() +"?")) $(this).remove();
$('#tags input').prop('disabled', false);
});
});
</script>
DEMO
You can have a map of added tags, and before adding the tag, check if it exists:
$(function() { // DOM ready
// ::: TAGS BOX
// added tags (mark 'a' and 'b' as already added)
let tags = {
'a': true,
'b': true
};
$("#tags input").on({
focusout: function() {
var txt = this.value.replace(/[^a-z0-9\+\-\.\#]/ig, ''); // allowed characters
if (txt) {
if (tags[txt]) { // if the tag already exists show an error
console.log(txt + ' already exists');
} else {
$("<span/>", {
text: txt.toLowerCase(),
insertBefore: this
});
tags[txt] = true; // add the tag
}
}
this.value = "";
if (($('#tags span').length) > 4) {
$('#tags input').prop('disabled', true);
}
},
keyup: function(ev) {
// if: comma|enter|space (delimit more keyCodes with | pipe)
if (/(188|13|32)/.test(ev.which)) $(this).focusout();
}
});
$('#tags').on('click', 'span', function() {
if (confirm("Remove " + $(this).text() + "?")) {
$(this).remove();
var text = $(this).text();
tags[text] = false; // remove the tag
}
$('#tags input').prop('disabled', false);
});
});
#tags {
float: left;
border: 1px solid #ccc;
padding: 5px;
font-family: Arial;
}
#tags>span {
cursor: pointer;
display: block;
float: left;
color: #fff;
background: #789;
padding: 5px;
padding-right: 25px;
margin: 4px;
}
#tags>span:hover {
opacity: 0.7;
}
#tags>span:after {
position: absolute;
content: "×";
border: 1px solid;
padding: 2px 5px;
margin-left: 3px;
font-size: 11px;
}
#tags>input {
background: #eee;
border: 0;
margin: 4px;
padding: 7px;
width: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="search-container">
<div id="tags">
<span>a</span> <span>b</span>
<input type="text" value="" class="paste" id="search" placeholder="Add a tag" />
</div>
</div>
I have a jqtree and I should send which nodes were changed using AJAX, to do such a thing, I've used a recursive function to read the whole JSON, the problem is, I just want to send which node was affected. the user can only change one item at a time since the tree is drag-and-drop.
Clarifying:
The page is loaded, and the structure is as well (check on firebug):
then, the user selects and drags child1 into node2:
by doing that the new JSON is generated, then, it's separated and classified into vpais (parents) and vfilhos (children)
However, as you can see, it's not necessary to send all parents and children because only one node will be changed (and it will always be, simply because only one item can be dragged at a time). Is there a way to know which node was dragged and its new parent?
Thanks for making so far :)
My code:
$(document).ready(function() {
var data = [{
label: 'node1',
id: 1,
children: [{
label: 'child1',
id: 2
}, {
label: 'child3',
id: 3
}, {
label: 'child2',
id: 4
}, {
label: 'child2',
id: 5
}]
}, {
label: 'node2',
id: 6,
children: [{
label: 'child3',
id: 7
}]
}];
$('#tree1').tree({
data: data,
autoOpen: false,
dragAndDrop: true
});
console.log("Original Structure" + $('#tree1').tree('toJson'));
$('#tree1').bind(
'tree.move',
function(event) {
data = $(this).tree('toJson');
event.preventDefault();
event.move_info.do_move();
console.log("New Structure" + $(this).tree('toJson'));
data = $(this).tree('toJson');
var dadSon = [];
var dad = [],
son = [];
var group = "";
var randomic = "";
(function printDadSon(data, parent) {
if (!data) return;
for (var i = 0; i < (data.length); i++) {
if (parent && parent != 'undefined') {
dadSon[i] = ('vpai= ' + parent + "&" + 'vfilho= ' + data[i].id + "&");
group += dadSon[i];
}
printDadSon(data[i].children, data[i].id);
}
})(JSON.parse(data));
var temp = group.length;
group = group.substring(0, temp - 1);
console.log(dadSon);
$.ajax({
type: 'POST',
url: 'sistema.agrosys.com.br',
dataType: 'json',
data: group
});
console.log("Done");
}
);
});
#navdata {
width: auto;
height: auto;
flex: 1;
padding-bottom: 1px;
}
#navgrid {
width: 50%;
height: 200px;
overflow-x: visible;
overflow-y: scroll;
border: solid 1px #79B7E7;
background-color: white;
}
#header {
background-color: #79B7E7;
width: 99.6%;
text-align: center;
border: 1px solid white;
margin: 1px;
}
.jqtree-element {
background-color: white;
border: 1px solid white;
height: 23px;
color: red;
}
.jqtree-tree .jqtree-title {
color: black;
}
ul.jqtree-tree {
margin-top: 0px;
margin-left: 1px;
}
ul.jqtree-tree,
ul.jqtree-tree ul.jqtree_common {
list-style: none outside;
margin-bottom: 0;
padding: 0;
}
ul.jqtree-tree ul.jqtree_common {
display: block;
text-align: left;
padding-left: 0px;
margin-left: 20px;
margin-right: 0;
}
ul.jqtree-tree li.jqtree-closed > ul.jqtree_common {
display: none;
}
ul.jqtree-tree li.jqtree_common {
clear: both;
list-style-type: none;
}
ul.jqtree-tree .jqtree-toggler {
color: #325D8A;
}
ul.jqtree-tree .jqtree-toggler:hover {
color: #3966df;
text-decoration: none;
}
.jqtree-tree .jqtree-title.jqtree-title-folder {
margin-left: 0;
}
span.jqtree-dragging {
color: #fff;
background: #79B7E7;
opacity: 0.8;
cursor: pointer;
padding: 2px 8px;
}
ul.jqtree-tree li.jqtree-selected > .jqtree-element,
ul.jqtree-tree li.jqtree-selected > .jqtree-element:hover {
background: -webkit-gradient(linear, left top, left bottom, from(#BEE0F5), to(#79B7E7));
}
<!DOCTYPE html>
<!-- Programa: JqTree | Envia nova estrutura JSON como v pai e vfilho -->
<!-- Autor: Calne Ricardo de Souza -->
<!-- Data: 06/07/2015 -->
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://sistema.agrosys.com.br/sistema/labs/tree.jquery.js"></script>
<link rel="stylesheet" href="http://sistema.agrosys.com.br/sistema/labs/jqtree.css">
<script src="http://sistema.agrosys.com.br/sistema/labs/jquery-cookie/src/jquery.cookie.js"></script>
</head>
<body>
<div id="navgrid">
<div id="header">Header</div>
<div id="tree1">
<ul class="jqtree_common jqtree-tree">
<li class="jqtree_common jqtree-folder">
<div class="jqtree-element jqtree_common">
<a class="jqtree_common jqtree-toggler">â–¼</a>
<span class="jqtree_common jqtree-title jqtree-title-folder">node1</span>
</div>
<ul class="jqtree_common ">
<li class="jqtree_common">
<div class="jqtree-element jqtree_common">
<span class="jqtree-title jqtree_common">child2</span>
</div>
</li>
<li class="jqtree_common">
<div class="jqtree-element jqtree_common">
<span class="jqtree-title jqtree_common">child1</span>
</div>
</li>
</ul>
</li>
<li class="jqtree_common jqtree-folder">
<div class="jqtree-element jqtree_common">
<a class="jqtree_common jqtree-toggler">â–¼</a>
<span class="jqtree_common jqtree-title jqtree-title-folder">node2</span>
</div>
<ul class="jqtree_common ">
<li class="jqtree_common">
<div class="jqtree-element jqtree_common">
<span class="jqtree-title jqtree_common">child3</span>
</div>
</li>
</ul>
</li>
</ul>
</div>
</div>
</body>
</html>
I think mutation observers work very well here.
if (typeof(MutationObserver) != "undefined")
{
//this is new functionality
//observer is present in firefox/chrome and IE11+
// select the target node
// create an observer instance
observer = new MutationObserver(observeJSONTree);
// configuration of the observer:
var config = { attributes: false, childList: true, characterData: false, subtree: true };
// pass in the target node, as well as the observer options
observer.observe([tree container], config);
}
function observerJSONTree(e)
{
for (eventObject in e)
{
switch(e[eventObject].type)
{
case 'characterData' :
//when text is changed
//for now do nothing
break;
case 'childList' :
//childs added or removed
if (e[eventObject].addedNodes.length > 0)
{
//childs added
//do something
}
if (e[eventObject].removedNodes.length > 0)
{
//childs removed
}
break;
}
}
}
The config object determines which events should be listened to. In this case we listen to changes to childs in the container of the tree.
When a change is detected it will fire the mutation observer call to the function specified. In the event data is stored about the edit made. For a child drag/drop these are two events. Child removal and child appending.
Really hard to explain, but I'll do my best. So I've got a JSON data used on a JqTree and I'm trying to get which are the parents and the children and put them in little blocks.
My Tree:
and its data AKA structure:
var data = [
{"name":"node1","id":1,"is_open":true,"children":[
{"name":"child2","id":2},
{"name":"child2","id":3},
{"name":"child1","id":4}
]},
{"name":"node1","id":5,"is_open":true,"children":[
{"name":"child2","id":6}
]}
];
What I want to do is to put them into variables, like these:
variables dad and son and their ids
dad = 1 son = 2
dad = 2 son = 3 and so on.
Notice that dad = 2 is also the son = 2
Thus, my tree would be:
dad = 1 son = 2
dad = 1 son = 3
dad = 1 son = 4
dad = 5 son = 6
I need it this way because I'll send it using AJAX like this:
data:dad+"&"+son, and if you check my code you will notice that this will be sent when the user changes the structure with the cursor, so it will be always one dad and one son, thus, no array needed.
Why:
I need to send it that way because I'm using a shitty and limited language on the server side (it's not mine)
My Tree explained:
The original data will in the future be sent by this shitty server like this dad = 1 & son = 2, then I will do "simply" the reverse.
My server compares the original data with the new one and gives me the difference that I should transform into that way again and send it using ajax.
Right now, as you can see, I'm sending only the "difference" POSITIONS.
$('#tree1').bind(
'tree.move',
function(event) {
data = $(this).tree('toJson');
event.preventDefault();
// do the move first, and _then_ POST back.
event.move_info.do_move();
console.log("New Structure" + $(this).tree('toJson'));
POSITIONS = $(this).tree('toJson');
POSITIONS = getDiff(data, POSITIONS);
alert("Difference\n\n" + POSITIONS);
$.post('http://localhost:8080/JqTree/Hello', {
tree: POSITIONS
});
alert("done");
}
);
Thank you so much for reading this far.
This is my code:
$(document).ready(function() {
var POSITIONS;
//Mandar o response aqui no data
var data = [{
label: 'node1',
id: 1,
children: [{
label: 'child1',
id: 2
}, {
label: 'child2',
id: 3
}, {
label: 'child2',
id: 6
}]
}, {
label: 'node2',
id: 4,
children: [{
label: 'child3',
id: 5
}]
}];
$('#tree1').tree({
data: data,
autoOpen: false,
dragAndDrop: true
});
function getDiff(a, b) {
var diff = (isArray(a) ? [] : {});
recursiveDiff(a, b, diff);
return diff;
}
function recursiveDiff(a, b, node) {
var checked = [];
for (var prop in a) {
if (typeof b[prop] == 'undefined') {
addNode(prop, '[[removed]]', node);
} else if (JSON.stringify(a[prop]) != JSON.stringify(b[prop])) {
// if value
if (typeof b[prop] != 'object' || b[prop] == null) {
addNode(prop, b[prop], node);
} else {
// if array
if (isArray(b[prop])) {
addNode(prop, [], node);
recursiveDiff(a[prop], b[prop], node[prop]);
}
// if object
else {
addNode(prop, {}, node);
recursiveDiff(a[prop], b[prop], node[prop]);
}
}
}
}
}
function addNode(prop, value, parent) {
parent[prop] = value;
}
function isArray(obj) {
return (Object.prototype.toString.call(obj) === '[object Array]');
}
console.log("Original Structure" + $('#tree1').tree('toJson'));
$('#tree1').bind(
'tree.move',
function(event) {
data = $(this).tree('toJson');
event.preventDefault();
// do the move first, and _then_ POST back.
event.move_info.do_move();
console.log("New Structure" + $(this).tree('toJson'));
POSITIONS = $(this).tree('toJson');
POSITIONS = getDiff(data, POSITIONS);
alert("Difference\n\n" + POSITIONS);
$.post('http://localhost:8080/JqTree/Hello', {
tree: POSITIONS
});
alert("done");
}
);
});
#navdata {
width: auto;
height: auto;
flex: 1;
padding-bottom: 1px;
}
#navgrid {
width: 50%;
height: 200px;
overflow-x: visible;
overflow-y: scroll;
border: solid 1px #79B7E7;
background-color: white;
}
#header {
background-color: #79B7E7;
width: 99.6%;
text-align: center;
border: 1px solid white;
margin: 1px;
}
.jqtree-element {
background-color: white
/*#DDEBF7*/
;
border: 1px solid white;
height: 23px;
color: red;
}
.jqtree-tree .jqtree-title {
color: black;
}
ul.jqtree-tree {
margin-top: 0px;
margin-left: 1px;
}
ul.jqtree-tree,
ul.jqtree-tree ul.jqtree_common {
list-style: none outside;
margin-bottom: 0;
padding: 0;
}
ul.jqtree-tree ul.jqtree_common {
display: block;
text-align: left;
padding-left: 0px;
margin-left: 20px;
margin-right: 0;
/*border-left:20px solid #DDEBF7;*/
}
ul.jqtree-tree li.jqtree-closed > ul.jqtree_common {
display: none;
}
ul.jqtree-tree li.jqtree_common {
clear: both;
list-style-type: none;
}
ul.jqtree-tree .jqtree-toggler {
color: #325D8A;
}
ul.jqtree-tree .jqtree-toggler:hover {
color: #3966df;
text-decoration: none;
}
.jqtree-tree .jqtree-title.jqtree-title-folder {
margin-left: 0;
}
span.jqtree-dragging {
color: #fff;
background: #79B7E7;
opacity: 0.8;
cursor: pointer;
padding: 2px 8px;
}
ul.jqtree-tree li.jqtree-selected > .jqtree-element,
ul.jqtree-tree li.jqtree-selected > .jqtree-element:hover {
background: -webkit-gradient(linear, left top, left bottom, from(#BEE0F5), to(#79B7E7));
}
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://sistema.agrosys.com.br/sistema/labs/tree.jquery.js"></script>
<link rel="stylesheet" href="http://sistema.agrosys.com.br/sistema/labs/jqtree.css">
<script src="http://sistema.agrosys.com.br/sistema/labs/jquery-cookie/src/jquery.cookie.js"></script>
</head>
<body>
<div id="navgrid">
<div id="header">Header</div>
<div id="tree1">
<ul class="jqtree_common jqtree-tree">
<li class="jqtree_common jqtree-folder">
<div class="jqtree-element jqtree_common">
<a class="jqtree_common jqtree-toggler">â–¼</a>
<span class="jqtree_common jqtree-title jqtree-title-folder">node1</span>
</div>
<ul class="jqtree_common ">
<li class="jqtree_common">
<div class="jqtree-element jqtree_common">
<span class="jqtree-title jqtree_common">child2</span>
</div>
</li>
<li class="jqtree_common">
<div class="jqtree-element jqtree_common">
<span class="jqtree-title jqtree_common">child1</span>
</div>
</li>
</ul>
</li>
<li class="jqtree_common jqtree-folder">
<div class="jqtree-element jqtree_common">
<a class="jqtree_common jqtree-toggler">â–¼</a>
<span class="jqtree_common jqtree-title jqtree-title-folder">node2</span>
</div>
<ul class="jqtree_common ">
<li class="jqtree_common">
<div class="jqtree-element jqtree_common">
<span class="jqtree-title jqtree_common">child3</span>
</div>
</li>
</ul>
</li>
</ul>
</div>
</div>
</body>
</html>