Copy node from TreePanel to TreePanel keeping the structure - javascript

I have problem with script that will allow me to copy nodes from one Tree to another keeping the structure of folders.
Here's the script written in extjs 6.0
https://fiddle.sencha.com/#fiddle/1dr0
I am able to reconstruct structure from the source tree but unfortunately the copied element is duplicated and I don't know how to handle this. I am not sure if the way how I am doing this is correct so any tips will be helpfull.
The main logic is here:
beforedrop: function (node, data, overModel, dropPosition, dropFunction, eOpts) {
eOpts.trackedParentsNodeList = [];
createParentList(data.records[0], eOpts.trackedParentsNodeList);
var currentNode = node;
for (var i = eOpts.trackedParentsNodeList.length - 1; i >= 0; i--) {
var newNode = createCloneNode(eOpts.trackedParentsNodeList[i]);
currentNode.appendChild(newNode);
currentNode = currentNode.lastChild;
}
}
and here
createParentList = function(data, result){
result.push(data);
if(data.parentNode && data.parentNode.id !== "root")
createParentList(data.parentNode, result);
else return false;
}
createCloneNode = function(node){
return {
"text": node.data.text,
"leaf": node.isLeaf(),
"expanded": node.isExpanded()
};
}
ok, so I was managed to solve this problem and here's solution https://fiddle.sencha.com/#fiddle/1dr0.
Not sure if that's best way to do this, but it works.

Related

jsTree - Closing nodes on a specific level

I have a jstree with 5 levels of nodes. I want to iterate through all nodes to close those nodes for which the level is 4 so that one doesn't see level 5 unless 4 is clicked to expand. If there is a better approach than iterating, I'm all ears!
$("#mytree").bind('ready.jstree', function(event, data) {
var $tree = $(this);
$($tree.jstree().get_json($tree, {
flat: true
}))
.each(function(index, value) {
var node = $("#mytree").jstree().get_node(this.id);
var lvl = node.parents.length;
if (lvl = 4) {
node.close_node(this, true);
}
});
});
I found an answer, in case anyone else is looking to do the same.
Instead of opening all and then closing some, I started with all closed and opened the ones I wanted:
$("#mytree").bind('ready.jstree', function(event, data) {
var $tree = $(this);
$($tree.jstree().get_json($tree, {
flat: true
}))
.each(function(index, value) {
var node = $("#mytree").jstree().get_node(this.id);
var lvl = node.parents.length;
if (lvl <= 3) {
$('#mytree').jstree().open_node({"id":node.id});
}
});
});
If you want to open the nodes of first level, you may try this.
$('#myTree li').each( function() {
var node=$("#myTree").jstree().get_node(this.id);
var level = node.parents.length;
if(level<=1){
$('#myTree').jstree().open_node({"id":node.id});
}
});
It works for me, when I want to display the folders of an azure container. In my case, container is the root node.

Kinvey attribute updates

Looking for a better approach to updating the children's of an object using another object which contain the updated values / new entries.
Here param "pObj" is an object which already some children's, just want to update the pObj with the latest values which available in param "data".
Below code, I was using the Kinvey serverless cloud platform. "Object.children" which is not supported by Kinvey - not clear about the reason.
Below code is working fine for me, but it looks little ugly also fixed depth too.
function mergeObjects(pObj, data) {
var tempObj = {};
if (pObj) {
tempObj = pObj;
}
if (typeof(data) == "object") {
for (var j in data) {
if (!tempObj[j]) {
tempObj[j] = {};
}
if (typeof(data[j]) == "object") {
for (var k in data[j]) {
if (!tempObj[j][k]) {
tempObj[j][k] = {};
}
if (typeof(data[j][k]) == "object") {
for (var l in data[j][k]) {
if (!tempObj[j][k][l]) {
tempObj[j][k][l] = {};
}
tempObj[j][k][l] = data[j][k][l];
}
} else {
tempObj[j][k] = data[j][k];
}
}
} else {
tempObj[j] = data[j];
}
}
}
return tempObj;
}
Kinvey legacy BL uses node 0.10, might this be the reason you cannot use Object.children?
It does support lodash, however, so maybe there's Object manipulation options in the lodash module that you can use instead.
As an alternative, you can check out the new Flex Services, a microservices layer that uses node6. It allows you to inline any npm module you want and deploy a whole node.js runtime into our FSR runtime.

How do I use data out of chrome.storage.get function?

I'm trying to grab data from chrome extension storage, but I can use them only in this function.
var help = new Array();
chrome.storage.local.get(null, function(storage){
//get data from extension storage
help = storage;
console.log(storage);
});
console.log(help); // empty
Result in console:
content.js:1 content script running
content.js:11 []
content.js:8 {/in/%E5%BF%97%E9%B9%8F-%E6%99%8F-013799151/: "link", /in/adam-
isaacs-690506ab/: "link", /in/alex-campbell-brown-832a09a0/: "link",
/in/alex-davies-41513a90/: "link", /in/alex-dunne-688a71a8/: "link", …}
Async function has won. I wrote my code again and now function is called hundreds time, i can not do this in dirrefent way
code:
console.log("content script running");
var cards = document.getElementsByClassName("org-alumni-profile-card");
var searchText = "Connect";
function check(exi, cards) {
chrome.storage.local.get(null, function(storage) {
for (var key in storage) {
if (storage[key] == "link" && key == exi) {
cards.style.opacity = "0.3";
}
}
});
}
for (var i = 0; i < cards.length; i++) {
var ctd = cards[i].getElementsByClassName(
"org-alumni-profile-card__link-text"
);
var msg = cards[i].getElementsByClassName(
"org-alumni-profile-card__messaging-button-shrunk"
);
if (ctd.length < 1 || msg.length > 0) {
cards[i].style.display = "none";
} else {
var exi = cards[i]
.getElementsByClassName("org-alumni-profile-card__full-name-link")[0]
.getAttribute("href");
check(exi, cards[i]);
}
}
SOLUTION of my problem
I wanted to delete this topic, but I can not, so instead of doing that, I'll put here what I've done finally.
The code above is wrong becouse, it was taking a list of links from website and for each from them script was grabbing a data from a storage... Which was stupid of course. I didn't see a solution which was so easy:
Put all your file's code in this function - it grabs data from storage just once.
I'm so sorry for messing up this wonderfull forum with topic like this.
Hope u'll forgive.
help will return undefined because it is referencing a asynchronous function and not the return value of that function. The content from storage looks to be printed on content.js:8, i.e. line 8.

How do I remove all the extra fields that DOJO datastore adds to my fetched items?

When fetching an item from a DOJO datastore, DOJO adds a great deal of extra fields to it. It also changes the way the data is structure.
I know I could manually rebuild ever item to its initial form (this would require me to make updates to both JS code everytime i change my REST object), but there certainly has to be a better way.
Perhaps a store.detach( item ) or something of the sort?
The dojo.data API is being phased out, partly because of the extra fields. You could consider using the new dojo.store API. The store api does not add the extra fields.
I have written a function that does what you are looking to do. It follows. One thing to note, my function converts child objects to the { _reference: 'id' } notation. You may want different behavior.
Util._detachItem = function(item) {
var fnIncludeProperty = function(key) {
return key !== '_0'
&& key !== '_RI'
&& key !== '_RRM'
&& key !== '_S'
&& key !== '__type'
};
var store = item._S;
var fnCreateItemReference = function(itm) {
if (store.isItem(itm)) {
return { _reference: itm.id[0] };
}
return itm;
};
var fnProcessItem = function(itm) {
var newItm = {};
for(var k in itm) {
if(fnIncludeProperty(k)) {
if (dojo.isArray(itm[k])) {
// TODO this could be a problem with arrays with a single item
if (itm[k].length == 1) {
newItm[k] = fnCreateItemReference(itm[k][0]);
} else {
var valArr = [];
dojo.forEach(itm[k], function(arrItm) {
valArr.push(fnCreateItemReference(arrItm));
});
newItm[k] = valArr;
}
} else {
newItm[k] = fnCreateItemReference(itm[k]);
}
}
}
return newItm;
};
return fnProcessItem(item);
};
NOTE: this function is modified from what I originally wrote and I did not test the above code.

Telerik RadTreeView And Client-Side Expand/Collapse

I'm following this approach to expanding and collapsing all nodes in client JavaScript: http://www.telerik.com/help/aspnet/treeview/tree_expand_client_side.html
However, it's taking a REALLY long time to process this, and after expanding then collapsing, I get the "script unresponsive" error, so I was wondering if there was a way to speed this up for a rather large tree? Is there a better way to parse it? Currently, the tree is 4 levels deep.
Thanks.
I got around the "script unresponsive" errors by expanding and collapsing the tree asynchronously. In addition, I expand from the bottom (so you can see the nodes expand) and collapse from the top, but only when it gets to the last node in each branch, so visually it's far more interesting to the user. They can actually see it happen, and if it's not fast (IE7 and before is particularly slow), it's at least entertaining while they wait.
var treeView, nodes;
function expandAllNodesAsynchronously() {
if (<%= expandedLoaded.ToString().ToLower() %>) {
treeView = $find("<%= tv.ClientID %>");
nodes = treeView.get_allNodes();
if (nodes.length > 1) {
doTheWork(expandOneNode, nodes.length);
}
return false;
} else
return true;
}
function expandOneNode(whichNode) {
var actualNode = nodes.length - whichNode;
if (nodes[actualNode].get_nextNode() == null) {
nodes[actualNode].get_parent().expand();
}
}
function collapseAllNodesAsynchronously() {
treeView = $find("<%= tv.ClientID %>");
nodes = treeView.get_allNodes();
if (nodes.length > 1) {
doTheWork(collapseOneNode, nodes.length);
}
}
function collapseOneNode(whichNode) {
if (nodes[whichNode].get_nextNode() == null && nodes[whichNode].get_parent() != nodes[0]) {
nodes[whichNode].get_parent().collapse();
}
}
function doTheWork(operation, cycles) { //, callback
var self = this, // in case you need it
cyclesComplete = 1,
batchSize = 10; // Larger batch sizes will be slightly quicker, but visually choppier
var doOneBatch = function() {
var c = 0;
while(cyclesComplete < cycles) {
operation(cyclesComplete);
c++;
if(c >= batchSize) {
// may need to store interim results here
break;
}
cyclesComplete++;
}
if (cyclesComplete < cycles) {
setTimeout(doOneBatch, 1); // "1" is the length of the delay in milliseconds
}
else {
// Not necessary to do anything when done
//callback(); // maybe pass results here
}
};
// kickoff
doOneBatch();
return null;
};
Start off getting your nodes with yourtreeViewInstance.get_nodes(), and then the child nodes as eachChildNode.get_nodes() and so on down the hierarchy.
Then you can expand each item by calling .set_expanded(true); on each node you want to expand.

Categories

Resources