Adding a node just after one node (jstree) - javascript

I'm creating a tree using jstree javascript library https://www.jstree.com/ .I need to create a new node just after current node as a sibling.
Elem 1
Elem 2
Elem 3
My point is when i click on Elem 2 a new node say Elem 2.5 is added in between Elem 2 and Elem 3
so result:--
Elem 1
Elem 2
Elem 2.5
Elem 3
My current code:
$(".appendTree").jstree('create_node', CurrentNode, html, 'last');
by this new ,nodes are always added at the end.is there any api or workaround to handle this??

You will have to figure out the current index for the selected node in the current folder, then pass the index to create_node method instead of your last. See code below. Check demo - Fiddle Demo.
$('.appendTree')
.jstree({
core : {
check_callback : true,
data : coredata
}
})
.on("select_node.jstree", function (e, data) {
var $parent = $('#'+data.node.id).parent();
var index = $parent.children().index( $('#'+data.node.id) ) +1;
if(data.node.parent === '#') {
$parent = '#';
}
$(".appendTree").jstree('create_node', $parent, 'new node', index);
});

Related

Is there any way to cyclically update only a <div> content in pure Javascript?

I'm using a div with a <li> element inside where I add some dynamically created elements (localStorage keys to be more specific). I want to update the div every "x" seconds but only the <div>, not the whole page. I know that it can be done with Ajax and JQuery ($( "#here" ).load(window.location.href + " #here" );).
But is there any way to do this whit pure js?
UPDATE
The specific case is that im picking all the localstorage keys and appending them to a list inside a div. When i use like this (window.onload) it works fine. But I want to update it cyclically. If i use a "setinterval" or a button to call the function the previous keys appends repeatedly. (like: file 1.... then: file 1, file 1 file 2 ... then: file 1 file 1 file 2 file 1 file 1 file 1 file 2 file 3)
window.onload = function cargararchivos() {
localstorage = []
var keys = Object.keys(localStorage);
for (let i = 0; i < keys.length; i++) {
var elemento_lista = document.createElement('li')
elemento_lista.innerHTML = keys[i]
var lista = document.getElementById('lista_archivos')
lista.appendChild(elemento_lista)
localstorage[ keys[i] ] = localStorage.getItem( keys[i] )
elemento_lista.onclick = function()
{alert(JSON.parse(localStorage[keys[i]]))}}
};
This can be done using the setInterval function. It executes a function of your choice after a pre-determined amount of time.
To do this your DIV must have an unique ID, so we can access it using Javascript's getElementById() method.
Here's a simple example, which updates a div with the current time every 1000 milliseconds:
function update() {
document.getElementById("myDiv").innerHTML = new Date();
}
var interval = setInterval(update, 1000);
<div id="myDiv">
</div>
The reason your method works the first time, but doesn't work after that is because the method adds DOM nodes. After the second call, you're seeing DOM nodes from both the first call and second call. After the third call, you'd see nodes from the first, second, and third calls... and so on.
If you want to repeatedly call a method like cargararchivos() that adds DOM nodes, you must first remove any DOM elements that have been previously added. I've updated your code, assuming lista_archivos starts empty (no child elements):
function cargararchivos() {
localstorage = []
var keys = Object.keys(localStorage);
var lista = document.getElementById('lista_archivos')
// Ensure any previously added DOM nodes are removed.
while (lista.firstChild) {
lista.removeChild(lista.firstChild);
}
for (let i = 0; i < keys.length; i++) {
var elemento_lista = document.createElement('li')
elemento_lista.innerHTML = keys[i]
lista.appendChild(elemento_lista)
localstorage[ keys[i] ] = localStorage.getItem( keys[i] )
elemento_lista.onclick = function()
{alert(JSON.parse(localStorage[keys[i]]))}
}
};

Get checked and undetermined nodes

I have been selected a node in jstree. I can get a json value of the selected nodes. But the problem is, I want the parent nodes of the child node , upto root
You can do this with the code as below. Check demo - Fiddle.
function getParentNode(node) {
return $('#tree').jstree().get_parent(node);
}
var nodes = $('#tree').jstree().get_selected('full'), parentNodes = [], parentTexts = [];
nodes.forEach( function(node) {
var parentNode = getParentNode(node);
while (parentNode && parentNode !=='#') {
if (parentNodes.indexOf(parentNode) === -1 ) {
parentNodes.push( parentNode );
parentTexts.push( $('#tree').jstree().get_node(parentNode).text );
}
parentNode = getParentNode(parentNode);
}
})
UPDATE
The code you use could look like:
var checked_ids = [], checked_ids1 = [];
$("#temporary1").find(".jstree-undetermined").each(
function(i, element) {
var nodeId = $(element).closest('.jstree-node').attr("id");
// alert( nodeId );
checked_ids.push( nodeId );
checked_ids1.push( $('#temporary1').jstree().get_node( nodeId ).text );
}
);
Try using jstree's get_path. The way I have it below will return to the console an array of the parents of the selected node.
* get the path to a node, either consisting of node texts, or of node IDs, optionally glued together (otherwise an array)
$('#jstree').jstree().on('changed.jstree', function(e, data) {
console.log(data.instance.get_path(data.node, undefined, true));
});

Highlight phone number and wrap with tag javascript

The following code checks if the selected tag has childnodes. If a child node is present , it loops till a child node is found. When there are no further child nodes found, it loops out i.e it reaches a text node causing the loop to end. The function is made recursive to run until no child node is found. The code runs as per above info, but when I try to match TEXT_NODE (console.log() outputs all text node), replace() is used to identify phone numbers using regex and replaced with hyperlink. The number gets detected and is enclosed with a hyperlink but it gets displayed twice i.e. number enclosed with hyperlink and only the number.Following is the code
function DOMwalker(obj){
var regex = /\+\d{1,4}?[-.\s]?\(?\d{1,3}?\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}/g;
var y = "$&";
if(obj.hasChildNodes()){
var child = obj.firstChild;
while(child){
if(child.nodeType!==3)
{
DOMwalker(child);
}
if (child.nodeType=== 3) {
var text = child.nodeValue;
console.log(typeof text);
var regs = regex.exec(text);
match = text.replace(regex,y);
if(match){
var item = document.createElement('a');
item.setAttribute('href','javascript:void(0);');
var detect = document.createTextNode(match);
var x=item.appendChild(detect);
console.log(x);
child.parentNode.insertBefore(x,child);
}
}
child=child.nextSibling;
}
}
};
$(window).load(function(){
var tag = document.querySelector(".gcdMainDiv div.contentDiv");
DOMwalker(tag);
});
Following are the screenshot of the output:
Here the number gets printed twice instead of one with hyperlink which is been displayed(expected highlighted number with hyperlink) and second widout tags
Following is console.log of x
I have already gone through this.
The solution provided below works well with FF. The problem arises when used in IE11. It throws Unknown runtime error and references the .innerHTML. I used the appenChild(),but the error couldn't be resolved.
You've got a couple of problems with what you posted. First, if a child is not node type 3 and not a SCRIPT node, you re-call recursivetree() but you do not pass the child in. The function will just start over at the first div element and again, infinitely loop.
Second, you're calling replace() on the node itself, and not the node's innerHTML. You're trying to replace a node with a string, which just won't work, and I think you mean to replace any matching numbers within that node, rather than the entire node.
If you have <div>My number is +111-555-9999</div>, you only want to replace the number and not lose everything else.
Try this as a solution:
function recursivetree(obj){
var regex = /\+\d{1,4}?[-.\s]?\(?\d{1,3}?\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}/g;
var y = "$&";
var obj = obj || document.getElementsByTagName('div')[0];
if(obj.hasChildNodes()){
var child = obj.firstChild;
while(child){
if(child.nodeType !== 3 && child.nodeName !== 'SCRIPT'){
//Recall recursivetree with the child
recursivetree(child);
}
//A nodeType of 3, text nodes, sometimes do not have innerHTML to replace
//Check if the child has innerHTML and replace with the regex
if (child.innerHTML !== undefined) {
child.innerHTML = child.innerHTML.replace(regex,y);
}
child=child.nextSibling;
}
}
}
recursivetree();
Fiddle: http://jsfiddle.net/q07n5mz7/
Honestly? If you're trying to loop through the entire page and replace all instances of numbers, just do a replace on the body.
var regex = /\+\d{1,4}?[-.\s]?\(?\d{1,3}?\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}/g;
var y = "$&";
var body = document.body;
body.innerHTML = body.innerHTML.replace(regex, y);
Fiddle: http://jsfiddle.net/hmdv7adu/
Finally, I got the solution of my question. I referred to this answer which helped me to solve my query.
Here goes the code:
function DOMwalker(obj){
if(obj.hasChildNodes()){
var child = obj.firstChild;
var children = obj.childNodes;
var length = children.length;
for(var i = 0;i<length;i++){
var nodes = children[i];
if(nodes.nodeType !==3){
DOMwalker(nodes);
}
if(nodes.nodeType===3){
//Pass the parameters nodes:current node being traversed;obj:selector being passed as parameter for DOMwalker function
highlight(nodes,obj);
}
}
child = child.nextSibling;
}
}
function highlight(node,parent){
var regex =/(\d{1}-\d{1,4}-\d{1,5})|(\+\d{1,4}?[-.\s]?\(?\d{1,3}?\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9})/g;
//Stores the value of current node which is passed through the if loop
var matchs = node.data.match(regex);
if matchs is true,add it to DOM
if(matchs){
var anchor = document.createElement("a");
var y = /[(]\d[)]|[.-\s]/g;//removes spaces periods or dash,also number within brackets
var remove = number.replace(y,'');
//tel uri,if you have an app like skype for click-to dial
anchor.setAttribute("href","tel:"+remove);
//the anchor tag should be inserted before in the current node in the DOM
parent.insertBefore(anchor,node);
//append it toh the DOM to be displaye don the web page
anchor.appendChild(node);
}
else
{
return false;
}
}
I hope this code helps others.

Inserting an HTML element after text selection

I am trying to insert some HTML after the user has selected some text on the page. I have it working but not optimally and there is one problem in particular:
It relies on the element being on the page, but I don't want it to be. I want to do it all in the code, I am sure it's something relatively simple but need some help :)
I also welcome any other tips/suggestions/feedback!
The code canbe seen working here: http://jsfiddle.net/shE58/ (The selectionchange library is to make this work in FF).
document.addEventListener('selectionchange', function (event) {
var sel = this.getSelection();
// If text is being selected by drag, to wait for them to finish selecting.
jQuery("body").mouseup(function() {
// Ensure there is some text selected and that it is more than one character.
if (sel.toString().length > 1) {
// We only want one #element on the page at a time.
$("#element").remove();
// #TODO: Remove dependency on this:
var el = document.getElementById('selection');
el.innerHTML = '<div id="element"></div>';
var frag = document.createDocumentFragment(), node;
frag.appendChild(el.firstChild);
var range = sel.getRangeAt(0)
var startNode = range.startContainer, startOffset = range.startOffset;
var boundaryRange = range.cloneRange();
boundaryRange.collapse(false);
boundaryRange.insertNode(frag);
boundaryRange.setStart(startNode, startOffset);
boundaryRange.collapse(true);
// Clean up
sel = '';
}
});
});
Solution 1
Remove frag variable and directly add value in insertNode function like this :
boundaryRange.insertNode($('<div id="element"></div>')[0]);
http://jsfiddle.net/N6zz8/
Fix issue when to select right to left :
With a condition check if endOffset is smaller than startOffset.
var startNode = range.startContainer, startOffset = range.startOffset;
if (range.endOffset < range.startOffset) {
startNode = range.endContainer;
startOffset = range.endOffset;
}
http://jsfiddle.net/2c4qw/
Solution 2
Remove unnecessary code, remove 'el' variable like this :
// #TODO: Remove dependency on this:
var frag = document.createDocumentFragment(), node;
$(frag).append($('<div id="element"></div>'));
http://jsfiddle.net/zYSH4/
Solution 3
Declare your variable like this var el = $("<div></div>")[0];. To get this :
// #TODO: Remove dependency on this:
var el = $("<div></div>")[0];
el.innerHTML = '<div id="element"></div>';
var frag = document.createDocumentFragment(), node;
frag.appendChild(el.firstChild);
http://jsfiddle.net/7L3Kf/

How to find & retrieve a node position without relying on id, class or content in javascript

Context:
I need to keep the node selection of an user & be able to retrieve it later.
If there is an id on the html node I will use it.
But the problem arrive when there is no ID. I need to be able to mark this node & be able to find it back even after a page refresh.
I tried a couple of things with childnodes but I failed so far.
You can use the nodes position relative to its siblings to locate it within the dom. When dealing with nested elements, you simply prefix the nodes location with its parents location relative to its siblings. So you end up with a node identifier looking something like this: 2/0/4/1 Where each / corresponds to an additional level of depth. Here is a working example:
function getNodePosition(node){
var node = $(node);
var result;
var parent = node.parent();
var siblings = parent.children();
var pos = siblings.index(node);
result = '/' + pos;
if(parent.length && !parent.is('body')){
result = getNodePosition(parent) + result;
}
return result;
}
function getNodeByPosition(position){
var node = $('body');
var layers = position.substring(1).split('/');
$.each(layers, function(index, val){
val = parseInt(++val);
node = node.find(':nth-child(' + val +')')
});
return node[0];
}
Jsfiddle

Categories

Resources