parse output and style xml data - javascript

I have xml located on a remote server with the following format:
<query_results>
<row id="1">
<distance>...</distance>
<post_title>...</post_title>
<post_excerpt>...</post_excerpt>
<ID>...</ID>
</row
<row id="2">
.........................etc
</query_results>
I need my javascript to go through each of these rows in a way so that I can append each to a div on my html document with a class for styling without the script caring too much what the individual names are for each element in each row. I have used Jquery's parse XML function, however i am lost after that. Anybody got a good idea how to do this? Any help is appreciated a lot.

I made a JSFiddle with a possible solution to your problem. It loads your sample XML from this Gist.
In the HTML there is a placeholder:
<div id="query_results"/>
You can load the file using JQuery ajax:
$.ajax({
type: "GET",
url: "/url/to/your/file.xml",
dataType: "xml",
success: parser
});
In the parser function you can use .find() and .children() to navigate the XML:
function parser(xml) {
$(xml).find('query_results').children().each(function() {
var row = $(this);
var id = row.attr("id");
var rowContents = "";
row.children().each(function() {
var tag = $(this);
var tagName = tag[0].tagName;
rowContents += "<div class='"+tagName+"'>"+tag.text()+"</div>";
});
var newRow = "<div id='row"+id+"'>"+rowContents+"</div>";
$("#query_results").append(newRow);
});
}
I used the row IDs and names to create and ID for each row DIV, for example:
<div id="row1"> ... </div>
And then used the tag names inside each row as classes:
<div class="distance"> ... </div>
<div class="post_title"> ... </div>
The parser() function above builds the divs and adds them to the placeholder div. The final result will be:
<div id="query_results">
<div id="row1">
<div class="distance">...</div>
<div class="post_title">...</div>
<div class="post_excerpt">...</div>
<div class="ID">...</div>
</div>
<div id="row2">...</div>
</div>
Then you can style the result in CSS using selectors such as:
#query_results div { ... }
#query_results div div { ... }
#row1 .distance { ... }
#row2 .ID { ... }

Related

How to receive AJAX (json) response in a divs with same class name individually?

I've been getting crazier day after day with this, I can't find an answer, I've spent like 100h+ with this... I hope someone could help me out!
UPDATE:
So to make myself more clear on this issue and be able to get help from others, I basically have 3 containers named "main-container" they all have 3 containers as childs all with the same class name, and when I submit the button, I trigger an ajax function to load the JSON strings comming from php into the child divs, the problem is that I get the 3 "main_containers" to load the ajax at the same time, I only want to load the ajax if I press the button of each "main_container" individually.
I've been using jquery and vanilla JS as well but seems I just can't get it done!
This is how I currently trigger the button with jquery:
$('.trigger_button_inside_divs').click(my_ajax_function);
And this is how my ajax looks like:
function my_ajax_function(){
$.ajax({
dataType: "JSON",
type: 'POST',
url: test.php,
success: function(data) {
$('.div_to_render_JSON_1').html(data.PHP_JSON_1_RECEIVED);
$('.div_to_render_JSON_2').html(data.PHP_JSON_2_RECEIVED);
$('.div_to_render_JSON_3').html(data.PHP_JSON_3_RECEIVED);
}
});
}
HTML looks like this:
<div class="main_container">
<div class="my_div">
//div_to_render_JSON_1
</div>
<div class="my_div">
//div_to_render_JSON_2
</div>
<div class="my_div">
//div_to_render_JSON_3
</div>
<button class="trigger_ajax_function_btn">Click to load ajax</button> //this btn loads ajax into the div class "my_div"
</div>
<div class="main_container">
<div class="my_div">
//div_to_render_JSON_1
</div>
<div class="my_div">
//div_to_render_JSON_2
</div>
<div class="my_div">
//div_to_render_JSON_3
</div>
<button class="trigger_ajax_function_btn">Click to load ajax</button> //this btn loads ajax into the div class "my_div"
</div>
<div class="main_container">
<div class="my_div">
//div_to_render_JSON_1
</div>
<div class="my_div">
//div_to_render_JSON_2
</div>
<div class="my_div">
//div_to_render_JSON_3
</div>
<button class="trigger_ajax_function_btn">Click to load ajax</button> //this btn loads ajax into the div class "my_div"
</div>
So in conclusion, each of those 6 "divs" has a button that triggers an function containing my ajax to render inside that particular div. But what I get is that every time I click that triggering button, I get the ajax to render in all of the 6 divs, instead of render on each particular div only when I click its particular button.
Thanks a lot people, I really hope to get this done!
Cheers.
PD:
This is something a programmer did to achieve what I'm trying to achieve but I just can't figure out what in this code is that is making possible clicking 1 button and affect THAT html element , even though they all have the same class.
(function(){
$("form input[type=submit]").click(function() {
$("input[type=submit]", $(this).parents("form")).removeAttr("clicked");
$(this).attr("clicked", "true");
});
var xhr = new XMLHttpRequest();
var el;
function SetDataInTheForm()
{
var resp = JSON.parse(xhr.response)
var pt=0
var ct=0
var gt=0
Array.prototype.forEach.call(el.querySelectorAll(".test"),function(e,i){
e.innerHTML=resp[i].name
})
Array.prototype.forEach.call(el.querySelectorAll(".p"),function(e,i){
e.innerHTML=parseFloat(resp[i].p).toFixed(0)
pt+=parseFloat(resp[i].p)
})
Array.prototype.forEach.call(el.querySelectorAll(".c"),function(e,i){
e.innerHTML=parseFloat(resp[i].c).toFixed(0)
ct+=parseFloat(resp[i].c)
})
Array.prototype.forEach.call(el.querySelectorAll(".g"),function(e,i){
e.innerHTML=parseFloat(resp[i].g).toFixed(0)
gt+=parseFloat(resp[i].g)
})
el.querySelector(".wtp").innerHTML=parseFloat(resp[0].total).toFixed(0)+" "+resp[0].unit
el.querySelector(".wtc").innerHTML=parseFloat(resp[1].total).toFixed(0)+" "+resp[1].unit
el.querySelector(".wtg").innerHTML=parseFloat(resp[2].total).toFixed(0)+" "+resp[2].unit
el.querySelector(".pt").innerHTML=pt.toFixed(0)
el.querySelector(".ct").innerHTML=ct.toFixed(0)
el.querySelector(".gt").innerHTML=gt.toFixed(0)
}
function HandleSubmit(e)
{
el=e.currentTarget
e.preventDefault();
xhr.open("POST","/url_here.php",true)
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded")
xhr.onload=SetDataInTheForm
var button=e.currentTarget.querySelector("input[type=submit][clicked=true]")
button.removeAttribute("clicked")
xhr.send($("#"+e.currentTarget.id).serialize()+"&"+button.getAttribute("name")+"=on")
}
[].forEach.call(document.querySelectorAll("._form_"),function(form){
form.addEventListener("submit",HandleSubmit,false);
})
})()
Remember that $('.div_container_to_render_JSON') is a new selector that selects all elements with a class div_container_to_render_JSON. What you want to happen is figuring out where that click came from, and find the corresponding div_container_to_render_JSON.
Luckily for you, a jQuery click handler sets the this keyword to the HTMLElement where the click was captured. You can use this to get the parent element.
$('.your-button').on('click', function () {
const myButton = $(this);
$.ajax({
// ...
success (data) {
myButton.parent().html(data.PHP_JSON_RECEIVED);
// or if you need to find a parent further up in the chain
// myButton.parents('.div_container_to_render_JSON').html(data.PHP_JSON_RECEIVED);
}
});
});
The problem is that your class selector is indeed selecting all your divs at the same time.
Solution, set identifiers for your divs as such:
<div class="my_div" id="my_div_1">
and then you can use those id's to fill in the data:
$('#my_div_1').html(data.PHP_JSON_1_RECEIVED);
and repeat for your 6 divs (notice the change from class selector '.' to identifier selector '#')
Thanks for the replies people. I finally figured it out after days of hard work, it was something really simple.. here's the answer:
$('.trigger_button_inside_divs').click(my_ajax_function);
var thisButton = $(this);
var thisDiv = thisButton.closest(".main_container");
function my_ajax_function(){
$.ajax({
dataType: "JSON",
type: 'POST',
url: test.php,
success: function(data) {
thisDiv.find('.div_to_render_JSON_1').html(data.PHP_JSON_1_RECEIVED);
thisDiv.find('.div_to_render_JSON_2').html(data.PHP_JSON_2_RECEIVED);
thisDiv.find('.div_to_render_JSON_3').html(data.PHP_JSON_3_RECEIVED);
}
});
}

How to get attribute text using ajax?

I'm trying to get attribute text using ajax but not working. For example
get.php
<div id="get" title="New Text"></div>
html
<div id="title"></div>
javascript
$.ajax({
url: 'index.php?route=get.php',
dataType: 'html',
success: function(html) {
var title = $(html).find('#get').attr('title').text();
console.log(title);
$('#title').text(title);
}
});
Assuming data returned by $.ajax() is <div id="get" title="New Text"></div> the method find() will not work as it looks into descendant. You can directly get its attribute as
var title = $(html).attr('title');
OR, Create a DOM element with returned data as HTML then use find()
var title = $('<div />').html(html).find('#get').attr('title');
var html = '<div id="get" title="New Text">12345</div>'
var title = $(html).attr('title');
$('#title').text(title);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="title"></div>
If you want to get value of attribute, you should use $.attr('attr') instead of $.attr('attr').text()

Jquery AJAX id selector and post with change class

I have one question. I am trying to make a ajax post with id and also trying to change the class which data-id selected.
I have created this DEMO from codepen.io
In this demo you can see there is a two container div and the container divs inside some different color div.
So what i am trying to do. When i click .change_pri then that clicked (.style, style1, style2) will automatically change .type style like:
<div class="test" id="1">
<div class="type style">selected color</div> <-- class is style
<div class="select_types">
<div class="type_s"><div class="change_pri style" data-id="0">0</div></div>
<div class="type_s"><div class="change_pri style1" data-id="1">1</div></div>
<div class="type_s"><div class="change_pri style2" data-id="2">2</div></div>
</div>
</div>
after clicking change_pri style2 then it need to looks like this:
<div class="test" id="1">
<div class="type style2">selected color</div> <-- after clicking class is style2
<div class="select_types">
<div class="type_s"><div class="change_pri style" data-id="0">0</div></div>
<div class="type_s"><div class="change_pri style1" data-id="1">1</div></div>
<div class="type_s"><div class="change_pri style2" data-id="2">2</div></div>
</div>
</div>
and post the data-id with ajax.
I do not know how the rest of that section, but I was able to do so. Anyone can help me in this regard ?
$(function() {
var i;
i = $(this).attr('id');
});
$('.change_pri').on('click', function(e) {
e.preventDefault();
$.ajax({
type: "POST",
url: "chage_number.php",
data: {
id: i,
},
});
});
The Javascript with the AJAX request should probably look something like this:
$('.change_pri').click(function(){
var dataid = $(this).attr('data-id');
var id = $(this).closest('.test').attr('id');
$.ajax({
type: "POST",
url: "chage_number.php",
data: { dataid : dataid, id: id }
}).success(function(result){
alert(result);
});
});
And then depending on what you want to do back-end, you can access that variable in chage_number.php via $_POST['id'].
So a simple example would be
chage_number.php
echo $_POST['id'] . ", ". $_POST['dataid'];
This should alert() both ids.
you can try this..
$('.change_pri').on('click', function(e) {
var styletype = $(this).attr('class').split(' ')[1];
var ctoremove = $('.type').attr('class').split(' ')[1];
$('.type').removeClass(ctoremove).addClass(styletype);
$.ajax({
type: "POST",
url: "chage_number.php",
data: { id: i }
}).success(function(result){
alert(result);
});
});
and here is the FIDDLE
I take it as the second container should be an example of what happens clicking the div's of the first one.
See this working example, it should do what you asked for: http://codepen.io/anon/pen/qdxVzW
This is where you get an alert telling you which data-id you clicked and then it changes the class of the .type element
alert($(this).attr('data-id')); //this can be removed, it's just a test
$('#test-1 > .type') //remove styleN and add the needed one
.removeClass('style0')
.removeClass('style1')
.removeClass('style2')
.addClass('style'+$(this).attr('data-id'))
The part about the ajax call remains almost the same, with a little modification when it comes to setting the id to be sent:
$('.change_pri').on('click', function(e) {
//As suggested by #Mackan, a little modification: store data-id
var dataId = $(this).attr('data-id');
$.ajax({
type: "POST",
url: "chage_number.php",
data: {
id: dataId //send the correct id
}
});
});
The function at the beginning of the script can be safely removed, it doesn't affect the rest of the code :)
I was almost forgetting: add a 0 to the style which doesn't have a number, like:
<div class="change_pri style0" data-id="0">0</div></div>
Otherwise when it come's to data-id=0 the script doesn't know what to do. Of course, same thing should be done into css code:
.style0{
background-color:red;
color:#ffffff;
margin:5px;
}

too much HTML in an ajax script?

I read from this page that appending a lot of elements is bad practice and I should build up a string during each iteration of the loop and then set the HTML of the DOM element to that string. Does the same go for using too much HTML in the loop?
I have an AJAX script that parses JSON data. It requires adding data to different existing elements, like this:
$.ajax({
url: "url",
success: function (data) {
$(data.query.results.json.json).each(function (index, item) {
var title = item.title, // A,B,C or D
age = item.age,
background = item.background,
ingredient = item.Ingredient;
$('.'+ title+'_ingredient').html(''+ingredient+'')
$('.'+ title+'_age').html(''+age+'')
$('.'+ title+'_background').html(''+background+'')
});
},
error: function () {}
});
HTML:
<div class="A_ingredient"></div>
<div class="B_ingredient"></div>
<div class="C_ingredient"></div>
<div class="D_ingredient"></div>
<div class="A_age"></div>
<div class="B_age"></div>
<div class="C_age"></div>
<div class="D_age"></div>
<div class="A_background"></div>
<div class="B_background"></div>
<div class="C_background"></div>
<div class="D_background"></div>
Is it necessary to build up a string first? If so, can you show me how to do that?
It is purely about the time it takes to process calls to html() so they simply recommend you reduce the number of calls. In this case you could build them once in a loop then sets the div html once for each.
Update:
Based on your update, aside from all the extra trailing quotes you don't need to add (a string is a string is a string), your code is fine as is. You only hit each item once.
e.g.
$.ajax({
url: "url",
success: function (data) {
$(data.query.results.json.json).each(function (index, item) {
var title = item.title, // A,B,C or D
age = item.age,
background = item.background,
ingredient = item.Ingredient;
$('.'+ title+'_ingredient').html(ingredient);
$('.'+ title+'_age').html(age);
$('.'+ title+'_background').html(background);
});
},
error: function () {}
});
Note: If your item properties (Age, Background, Ingredient) are simple values (not objects or arrays), yo do not need the leading ''+s either.
Previous
Assuming you actually want to concatenate the results (you are only keeping the last ingredient at the moment), you could do something like this:
e.g.
$.ajax({
url: "url",
success: function (data) {
var ingredients = '';
$(data.query.results.json.json).each(function (index, item) {
var title = item.title;
var ingredient = item.Ingredient;
ingredients += ingredient;
});
$('.aclass').html(ingredients);
$('.bclass').html(ingredients);
$('.cclass').html(ingredients);
$('.dclass').html(ingredients);
},
error: function () {}
});
Which can be reduced to:
$('.aclass,.bclass,.cclass,.dclass').html(ingredients);
The contents of each div are identical in your example, so you only need a single string.
In this instance you would probably need some form of delimiter between ingredients, but your example is too vague.
e.g.
ingredients += ingredient + '<br/>';
In your example, you're setting the HTML on many different document elements.
If they're grouped in some way, for example all in a Div with ID #Container, you could build a string of the HTML and set the content of the whole Div at the end of it, something like this:
$.ajax({
url: "url",
success: function (data) {
var sHTML="";
$(data.query.results.json.json).each(function (index, item) {
var title = item.title,
background = item.background,
ingredient = item.Ingredient;
// not sure what your actual HTML is (div/span/td etc) but somethign like this?
sHTML+="<div>"; // an opening container for this item
sHTML+='<div class="'+title+'_ingredient">'+ingredient+'</div>')
sHTML+='<div class="'+title+'_age">'+title+'</div>')
sHTML+='<div class="'+title+'_background">'+background+'</div>')
sHTML+="</div>";
});
$("#Container").html(sHTML);
},
error: function () {}
});
Note I haven't tested this code, but you see the principal hopefully.
That is, build a string of the HTML then set one element at the end with the content.
I have done this a lot in a recent project and haven't seen any speed issues (maybe 50 'items' to set in my case).
HTML will initially look like this :
<div id="container">
</div>
Then end up like this (2 x items in this example) :
<div id="container">
<div>
<div class="<sometitle1>_ingredient">ingredient 1</div>
<div class="<sometitle1>_age">age 1</div>
<div class="<sometitle1>_background">background 1</div>
</div>
<div>
<div class="<sometitle2>_ingredient">ingredient 2</div>
<div class="<sometitle2>_age">age 2</div>
<div class="<sometitle2>_background">background 2</div>
</div>
</div>
subsequent calls will replace the element's content with new values, replacing the old items.
Building a string is, I would imagine, less processor-heavy than setting the html() on lots of elements individually. Each time you use html() I'm guessing that the browser has to go some way towards working out any knock-on effects like expanding the width of an element to accomodate it or whether events will still work as they did, etc - even if actual rendering is only run at the end of the process. This way you use html() once, although what you're setting is more complex.
Hope this helps.

How to detect the div in which a link to a javascript function has been clicked

I have the following html code:
<div id="result1" class="result">
... some html ...
... link
... some html ...
</div>
<div id="result2" class="result">
... some html ...
... link
... some html ...
</div>
<div id="result3" class="result">
</div>
<div id="result4" class="result">
</div>
The goal is to update the content of the next div when I click on the link. So for instance, when I click on a link in #result2, the content of #result3 will be updated.
Here is the javascript function:
<script>
function updateNext(elem, uri) {
$.ajax({
url: uri,
success: function(data) {
elem.closest('.result').nextAll().html('');
elem.closest('.result').next().html(data);
}
});
}
</script>
However, when I use the link, elem is set as the window, not the link itself.
The content of the div is generated by a server which should not know the position of the div in which the code he is generating will be.
I also tried with a
<a href="javascript:" onclick="updateNext(...
with no other result...
any idea ? :-)
Thanks,
Arnaud.
this returns the window when used in href, but here it returns the actual link:
... link
Don't forget to use the jQuery $ in:
$(elem).closest('.result').nextAll().html('');
$(elem).closest('.result').next().html(data);
Why do you use inline scripts when you alrady are using jQuery?
I've setup a Fiddle for you which does what you want: http://jsfiddle.net/eLA3P/1/
The example code:
$('div.result a').click(function() {
$(this).closest('div.result').next().html('test');
return false;
});
First, you must remove those href="javascript:..." attributes. Please never use them again, they are evil.
Then, bind a click handler via jQuery, which you are alredy using:
// since you dynamically self-update the a elements, use "live()":
$("div.result a").live("click", function () {
var $myDiv = $(this).closest("div.result");
$.ajax({
url: "/build/some/url/with/" + $myDiv.attr("id"),
success: function(data) {
$myDiv.next("div.result").html(data);
}
});
return false;
});
Done.
Try to use jQuery to bind the event instead putting a javascript link in the href.
<div id="result1" class="result">
link
</div>
$('.resultLink').click(function(){
var elem = $(this);
$.ajax({
url: uri,
success: function(data) {
elem.closest('.result').nextAll().html('');
elem.closest('.result').next().html(data);
}
});
});
You should do it like this:
http://jsfiddle.net/hJhC7/
The inline JavaScript is gone, and the href is being used to store the "uri", whatever that might be. I'm assuming it's different for each link.
The //remove this lines are just to make $.ajax work with jsFiddle.
$('.update').click(function(e) {
e.preventDefault();
var elem = $(this);
$.ajax({
type: 'post', //remove this
data: {html: Math.random() }, //remove this
url: $(this).attr('href'),
success: function(data) {
//not sure why you're doing this
//elem.closest('.result').nextAll().html('');
elem.closest('.result').next().html(data);
}
});
});
with this HTML:
<div id="result1" class="result">
link
</div>
<div id="result2" class="result">
link
</div>
<div id="result3" class="result">
link
</div>

Categories