Looping through XML and finding the text node - Jquery - javascript

I have got the below XML.
var xml = '<parent1><person><child><name>Name1</name><details><data1>123</data1><data2>34567</data2></details></child></person><person><child><name>Name2</name><details><data1>123</data1><data2>34567</data2></details></child></person></parent1>';
I need to loop through all the children. I only care about the XML tags that has values. Below is the code I am using to loop the same.
addChildren($f);
function addChildren( $parent ) {
$parent.children().each( function( i, child ) {
console.log(child)
if(child.childNodes[i] && child.childNodes[i].nodeType === 3){
//I am not getting all the text nodes here even with nodtype 3 check.
obj.push(
{}
//Push the dynamic key and value)
addChildren( $(child) );
});
Expected output is
{name : Name1, data1 :123, data2:34567}, {name : Name2, data1 :123, data2:34567}.
Could someone please guide me how would I get the key (Tag) and value (text node)

var xml = '<parent1><person><child><name>Name1</name><details><data1>123</data1><data2>34567</data2></details></child></person><person><child><name>Name2</name><details><data1>123</data1><data2>34567</data2></details></child></person></parent1>';
var results = $(xml).find("child").map(function () {
var item = {
name: $(this).children("name").text()
};
$(this).children("details").children().each(function () {
item[this.localName] = $(this).text();
});
return item;
}).toArray();
console.log(results);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Related

How to loop through all the array of objects?

I have an Array of Object to be used to draw a HTML Table:
Array(5)
0: Object
id: 4
name: Sand Jane
address: Green Sand Street
...
...
...
1: Object
2: Object
...
...
...
I am able to do a single name column defined search with
const temp = this.temp.filter(function (d) {
return d.name.toLowerCase().indexOf(val) !== -1 || !val;
});
temp will contain the filtered data of this.temp
Now I just can't figure out how to loop through all object keys (id,name,address...) so that I can do a global column search in the Table.
UPDATE: I have tried this,
const temp = [];
this.temp.forEach(element => {
for (let key in element) {
if (element.hasOwnProperty(key)) {
let v = element[key];
if (v.toString().toLowerCase().indexOf(val) !== -1 || !val) {
temp.push(element);
}
}
}
});
It works but with performance issues.
RESOLVED: Putting a break after temp.push fixed this issue. Thank you all for the guidelines and references.
temp.forEach(item=>{
for(let key in item) {
//item[key] gives you access to each value
}
})
You can iterate through for loops or even you can usefor loop inside a for loop. Either way it's self explanatory.
var dictionary = {
"employee1":[
{"id":"0","name":"Google"},
{"id":"1","name":"eBay"}
],
"employee2": [
{"id":"2","name":"Yahoo"},
{"id":"3","name":"Facebook"}
]
};
var employee1 = dictionary.employee1;
var employee2 = dictionary.employee2;
for ( var i in employee1) {
var id = employee1[i].id;
var name = employee1[i].name;
console.log(id);
console.log(name);
}
for ( var i in employee2) {
var id = employee2[i].id;
var name = employee2[i].name;
console.log(id);
console.log(name);
}

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));
});

FInd object in array by value and update entire object

I have a list of objects and sometimes I receive an update from the API for one of those objects and what I need to do is to find the object with the id of the one to update and update the entire object...
I was trying to avoid a for loop because the list could be very very long.
So what I was trying to use is $.grep but it doesn't seem to work as expected.
Here is what I tried so far:
// item is the response data from the API
var item = res.item;
var index = $.grep(arrayOfItems, function (e, i) {
if (e.id === item.id) {
return i;
}
});
arrayOfItems[index] = item;
the item is not updated unfortunately...
If it's speed you're after, especially with a long list, you may consider indexing your list by id when you first retrieve it, making updates later quicker than having to loop the entire array to find an index.
To demonstrate, assume you have retrieved an array of objects
var data = [
{id:1,data:'hello'},
{id:2,data:'world'},
{id:3,data:'foo'},
{id:4,data:'bar'}];
now create an object which represents your data where the property is the Id (object properties cannot start with a number, so if id is numeric, prefix it) and the value is the index back into the original array. So, the above data would be transformed to
var dataIndex = {
id1:0,
id2:1,
id3:2,
id4:3
};
This can be done trivially with a function
function indexDataById(data)
{
var index = {};
$.each(data, function(e,i){
index['id' + e.id] = i;
});
return index;
}
var dataIndex = indexDataById(data);
Now, when it comes to your update, you can find the index instantly using the id
var updateId = 2;
var elementIdx = dataIndex ['id' + updateId];
data[elementIdx] = myNewData;
The one complication is that you need to go back and update the index if the id of the new data has changed:
var updateId = 2;
var elementIdx = dataIndex [`id` + updateId];
data[elementIdx] = myNewData;
delete dataIndex[elementIdx]
dataIndex['id' + myNewData.id] = elementIdx;
This should be easy enough to handle atomically with your update.
$.map and $.grep return both an array so you will never get the index.
Inside $.map or $.grep function you need to return true or false based
on your filter logic. They re not useful in your case.
if your structure is not ordered you can only loop trough it and stop the loop when you find your element... like that:
var item = res.item;
var index = "";
$.each(arrayOfItems, function(i,v){
if(item.id == v.id){
index = i;
return true;
}
});
arrayOfItems[index] = item;
if you wanna order your structure before loop use this:
arrayOfItems.sort(function(a, b) {
return a.id > b.id;
});
i ve made a fiddle with an example https://jsfiddle.net/L08rk0u3/
try this way using $.grep
var arrList = [
{name :11,id :11},{name :12,id :12},{name :111,id :111},
{name :13,id :13},{name :15,id :15},{name :11,id :11},
{name :41,id :41},{name :31,id :31},{name :81,id :81},
{name :91,id :91},{name :13,id :13},{name :17,id :17},
{name :1111,id :1111}
]
console.log(arrList);
var respItem ={name :1111000,id:1111};
var intSearchedIndex;
$.grep(arrList,function(oneItem,index){
if(respItem.id==oneItem.id){
return intSearchedIndex = index;
}
})
arrList[intSearchedIndex] =respItem;
console.log(intSearchedIndex,arrList);
Try with map method like this.
Code snippets:
// item is the response data from the API
var item = res.item;
var index = $.map(arrayOfItems, function (e, i) {
if (e.id === item.id) {
return i;
}
});
if(index.length)
arrayOfItems[index[0]] = item;
Update:
arrayOfItems[index] = item;
This will work if index array has an single element. See fiddle
But,
arrayOfItems[index[0]] = item;
This is the appropriate way since it is an array.

jQuery get json data, match the ids, then append the custom field value

I am trying to retrieve json data from zendesk, then compare the value of the ids in each ticket that is retrieved from the server with the id inside my table data. If the ids match, then I want to retrieve the custom field value inside the ticket with the matching id, and append it to the table data's that i have named with the product id. The idea is to target each "td/td",and automatically insert the custom field(product id) value when a new "td/td" tag is created. Please help :) The Object 99 at the top is the ticket, the id :175 is the id I am trying to match. the custom_field array[10] value is what I want to append and display. The issue I am having is that the data is not displaying after I append it. I think this has something to do with how I am accessing the data, comparing the ids, then appending the custom field. The array value is returning a -1 instead of comparing the IDs. This is the problem.
//first lets get some json data!
var getjson = $.getJSON("/api/v2/tickets.json)",function (result) {
$.each(result, function(i, field) {
console.log('data',field);
// now lets take the text id for each td and assign it as the id.
$(".sort > tr > td:nth-child(1)").each(function(){
var textid = $(this).text();
$(this).attr('id', textid);
// if the ids match, give me the value of the custom field that is inside the array of the matching id.
var arr = [field];
var arrayvalues = $.inArray('id', arr);
if ($(this).attr('id') == arrayvalues){
/* if the ids match, give me the value of the
custom field that is inside the array of the matching id. */
var returns = $.inArray('value',arr.custom_fields[i]);
// now for each td lets append the value of the custom field.
$(".sort > tr > td:nth-child(7)").each(function () {
$(this).append(returns);
$(this).attr('id','product');
})
}
})
});
See $.inArray usage described at documentation
jQuery.inArray( value, array [, fromIndex ] )
value
Type: Anything The value to search for.
array
Type: Array An array through which to
search. fromIndex Type: Number The index of the array at which to
begin the search. The default is 0, which will search the whole array.
Note, also $.inArray()
Returns: Number
Not certain about return value from $.getJSON ? full json not appear at original post ? , though see
$.getJSON("/api/v2/tickets.json}"
right bracket before closing double-quotation mark at url ?
Try changing js at
var arrayvalues = $.inArray(field).id;
and
var returns = return $.inArray(field).custom_fields('value');
to usage described at documentation, e.g.,
var arr = ["a", "b", "c"];
console.log(
$.inArray("a", arr) // `0`
, $.inArray("b", arr) !== -1 // `true`
, $.inArray("c", arr) === 3 // `false`
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
I figured it out after days of knocking my head against the wall. The following code works perfectly.
var Obj1 = {};
var Obj2 = {};
var Obj3 = {};
var urlstring = "/api/v2/tickets/"+id+".json)";
$.getJSON(urlstring,function (result) {
$.each(result, function(i, value) {
Obj1[result[i].id] = result[i].fields[10].value;
Obj2[result[i].id] = result[i].fields[13].value;
Obj3[result[i].id] = result[i].fields[7].value;
console.log('Obj1', Obj1);
console.log('Obj2', Obj2);
console.log('Obj3', Obj3);
});
$.each(Obj1, function(key, element) {
$(".sort > tr").each(function(){
if($(this).attr('id') == key){
$(this).children('td:nth-child(7)').append(element);
}
});//end tr each
}); //end obj1 each
$.each(Obj2, function(key, element) {
$(".sort > tr").each(function(){
if($(this).attr('id') == key){
$(this).children('td:nth-child(8)').append(element);
}
});//end tr each
}); //end obj2 each
$.each(Obj3, function(key, element) {
$(".sort > tr").each(function(){
if($(this).attr('id') == key){
$(this).children('td:nth-child(6)').append(element);
}
});//end tr each
}); //end obj3 each
});//end json

storing html-nodes as key in array

I want to store elements as the keys in my array and object as values,for example -
var arr = [];
arr[ document.getElementById('something') ] = { data: 'something' , fn : function(){ } };
But the problem is: If I will add another element with the key of : document.getElementById('otherthing').
And later will try to get the value of : arr[ document.getElementById('something') ].data , I will get the value of arr[ document.getElementById('otherthing') ].For Example :
var arr = [];
arr[ document.getElementById('something') ] = { data: 'something' , fn : function(){ } };
arr[ document.getElementById('otherthing') ] = { data: 'otherthing' , fn : function(){ alert('k'); } };
alert( arr[ document.getElementById('otherthing') ].data ); // alerts "otherthing"
alert( arr[ document.getElementById('something') ].data ); // alerts "otherthing" but suppose to alert "something"
How I can fix this problem,I can`t save by id,because I want to support other nodes with no-id
Thanks,Yosy.
EDIT:My answer to this,If you have better answer please write it :) (Inspired by casablanca`s answer)
array for id: key-integer the node id, value the node it self
and the array with data and fn with key of my id,It will look like this :
var idArray = [],nodeArray = [];
idArray[0] = document.getElementById('hello_ducks');
nodeArray[0] = { data: 'hello ducks!!' , fn : function(){ alert('k'); } };
idArray[1] = document.getElementById('hello');
nodeArray[1] = { data: 'hello' , fn : function(){ } };
var testNode = document.getElementById('hello_ducks'), foundId = -1 /*found id*/;
// Do we have testNode in our array?
for(var i = 0 ; i < idArray.length; i++ ){
if( idArray[i] === testNode ){
foundId = i;
}
}
// Do we found our element?
if(foundId >= 0) {
alert( nodeArray[foundId].data ); // "hello ducks!!"
}
I can`t save by id,because I want to support other nodes with no-id
You should keep in mind that in order to get back a node from the array, you have to somehow identify it. If a node doesn't have any such unique identifier, then how do you retrieve it later from the array, or even store it in the first place?
In lower-level languages like C++, every object implicitly has a unique address, but there is no such thing you can use in JavaScript, so you need to manually provide some way of identifying an object, and the DOM ID is the most convenient way of doing this.
If some of your nodes don't initially have an ID, the best way to proceed is to simply assign your own unique ID.
Update: The solution you posted will work, but it's not very efficient because you need to search the entire array every time you need to find a node. Why not simply assign your own ID to those elements which don't have one? For example:
var nextID = 0;
function getID(elem) {
if (elem.hasAttribute('id') == false || elem.id == '')
elem.id = 'dummy-' + (++nodeID);
return elem.id;
}
This way you can always use the ID as a key:
var nodeArray = [];
var e = document.getElementById('hello');
nodeArray[getID(e)] = { ... };
var e = /* element obtained from somewhere, doesn't have an ID */
nodeArray[getID(e)] = { ... }; // still works
I would suggest that instead of using an array for this purpose, you take advantage of the DOM-elements being objects:
document.getElementById('something').info = {data: 'something', fn: function () { } };
but you may end up with some issues with memory leaks in certain older browsers (read: ie6). That is fixed if you use jQuery's data storage instead:
$("#something").data("info", {data: 'something', fn: function () { } });

Categories

Resources