XML to HTML function for Refreshing Information - javascript

I am making a real time train board that pulls XML data from a website, populates it and animates it in. I have laid it out and got the animation set, but now I need help getting the XML data in the right spots.
Codepen of the animation: http://codepen.io/Spiderian/pen/FBjhk
The XML I'm trying to populate and recheck it every so often.
<trains>
<line><name>2</name><status>GOOD</status><text/><Date/><Time/></line>
<line><name>3</name><status>DELAYS</status><text/><Date/><Time/></line>
<line><name>4</name><status>WORK</status><text/><Date/><Time/></line>
<line><name>5</name><status>GOOD</status><text/><Date/><Time/></line>
</trains>
Will I have to use something different for the .append function to get it to work with the XML?

jQuery will work fine with XML, too. I will focus on the parsing of it in this answer, since I assume you're already familiar with fetching the XML from whatever web service you use with AJAX.
Create a new jQuery object with the XML, and then use the typical selectors to parse it. For example, to get the service on the first line, you can use the following:
var stats = xml.find('line:first status').text();
Here's how you can create a new jQuery object from XML:
var xml = $('<trains>\
<line><name>2</name><status>GOOD</status><text/><Date/><Time/></line>\
<line><name>3</name><status>DELAYS</status><text/><Date/><Time/></line>\
<line><name>4</name><status>WORK</status><text/><Date/><Time/></line>\
<line><name>5</name><status>GOOD</status><text/><Date/><Time/></line>\
</trains>');
Once you have the value from the XML, you can use either text() or html() to add it to your existing markup.
jsFiddle Demo

Related

How to get element from HTML stored in variable

I am running an API to retrieve email from external system. I managed to get HTML code from the returned JSON and store it in a variable. Now, I would like to run some further operations on this HTML - for example get all elements with
[data-type="whatever"].
It would be easy in html document:
var x = document.querySelectorAll('[data-type="whatever"]');
However the HTML document I want to work with is stored in the variable so the code I write in API does not recognise it as a document. How can I do it? Any suggestions with vanilla JS?
You can try something like this.
let rawDoc = '<html><head><title>Working with elements</title></head><body><div id="div1">The text above has been created dynamically.</div></body></html>'
let doc = document.createElement('html');
doc.innerHTML = rawDoc;
let div1 = doc.querySelector('#div1');
console.log(div1)
What if you use innerHTML? or maybe I don't fully understand the question.
Since you are working without a document you have 2 options.
1. Use regex to get what you need (something like /<.+>.+ data-type="whatever".+<\/.+>/gi) should do (but for an exact match you may need to make something better).
2. Insert the html in a hidden part of the dom and select what you need from it (like in Zohir answer - he provided a good example).
I used following code with angular to store whole html content in a variable and pass it as argument to call API.
var htmlBody = $('<div/>').append($('#htmlBody').clone()).html();
This might work for you as i was working on sending email to pass invoice template so try this.

Use dynamic element ID in #{rich:clientId()} function

We can get element by static ID using rich:clientId() function as follows
document.getElementById('#{rich:clientId(JSF_ID)}').click();
However, I need to use a dynamic ID which takes the form of var + "_ID" where var can be employee, student, etc and thus resulting in employee_ID, student_ID as actual ID.
I tried as follows:
dynamicID = var + '_ID';
document.getElementById('#{rich:clientId(dynamicID)}').click();
However, it didn't work. How can I achieve this?
It looks like you are setting dynamicID via JavaScript, am I right?
If yes, the EL-expression #{rich:clientId(dynamicID)} cannot be evaluated as EL on the server during the rendering of the page since the dynamicID is only available on the client (=browser) when the page has already been built up on the server and sent to the browser.
Where does var come from? How is it applied to the component with the dynamicID? Can't you use the same approach for the getElementById?
For concatenating a variable with a constant in JSF on server-side, see the following already answered post Concatenate strings in JSF/JSP EL and Javascript. Basically it gives you a how-to in creation of an own concatenation function for jsp/jsf. Works pretty need.
As a hint: you can use #{rich:element(JSF_ID)} instead of document.getElementById('#{rich:clientId(JSF_ID)}') to keep the source readeable - it will render identical results.
Good luck...

Converting JSON to have a new top-level wrapper

I suspect I am using the wrong terminology, so please bear with me.
I have been using mustache.js very effectively to work with the JSON output of an API. I am working with a sibling API that has outlook that looks mostly similar, excepting that there is no top-level name. I am trying to figure out how to adjust the new JSON output into the other format, such that I can continue using my mustache.js approach (this seems like the easier of the options, the other being using something other than mustache.js, which I am seeking to avoid).
I can use mustache.js to iterate very easily over the following JSON body using the top-level name 'records':
{"records":
[{"dt_created":"08/23/2013 04:49:13 PM","created_by":"x, x","dt_updated":"08/23/2013 04:49:13 PM","updated_by":"x, x","field_60374": ["Project 67"],"field_60331":["Ability to adjust the number of lines dynamically based on the mood of the person 3 rows down, 4th cube, 11th building. A breakthrough in mind-control data processing."],"field_60333": [{"id":"x","first":"x","last":"x"}],"field_60394": [{"id":"x","first":"x","last":"x"}],"field_60414":["11"],"field_60375": ["22"],"field_60395":["A"],"record_id":"1920704","form_id":"10898"},
{"dt_created":"08/23/2013 04:47:45 PM","created_by":"x, x","dt_updated":"08/23/2013 04:47:45 PM","updated_by":"x, x","field_60374":["Project 2"],"field_60331":["Very cool project to allow more than a single invoice to be in an ERP at any one time. Quite a big leap forward."],"field_60333": [{"id":"x","first":"x","last":"x"}],"field_60394": [{"id":"x","first":"x","last":"x"}],"field_60414":["x, x"],"field_60375":["60"],"field_60395": ["A"],"record_id":"1920703","form_id":"10898"}],
"meta":{"total":2,"count":2}
}
The format that I can't iterate through, since it is missing a top-level name, is:
[{"id":"x","user": {"id":"x","first_name":"x","last_name":"x"},"title":"Test Post 3","text":"This is an equally cool and enthralling post.","created_at":"2013-08-29T17:46:04.801Z","updated_at":"2013-08-29T17:46:04.804Z","num_comments":0,"num_likes":0},
{"id":"y","user": {"id":"212342277","first_name":"x","last_name":"x"},"title":"Test Post 1","text":"Super cool content you want to read!","created_at":"2013-08- 29T17:44:58.188Z","updated_at":"2013-08-29T17:44:58.190Z","num_comments":0,"num_likes":0}]
I tried the following to massage the second JSON example into the format of the first:
$.ajax({
[…….],
success: function(json_data){
alert("success");
var template=$('#listPosts').html();
var stuff = {"records":json_data}; //here
var stuff = JSON.stringify(stuff); //here
alert(stuff);
//var html = Mustache.to_html(template, json_data);
var html = Mustache.to_html(template, stuff);
//$('.content-pane').empty();
$('#listOfPostsContainer').html(html);
}
}
I have an alert that pops up with what is in var 'stuff', and it seems to be formatted like the first JSON example, but mustache.js doesn't parse it (I have verified mustache.js executes). Before trying to address any other issues, I wanted to understand if how I am adding a top-level name to the JSON array in the above AJAX call success attribute is correct, or if I have to do it differently.
If I am missing something to help explain this, let me know, so I can add it.

Replace content of a web page with stuff from AJAX response

The idea is to replace the contents of a web page with the same page requested through an ajax call, but only the HTML elements that are different.
Current I have this in my $.ajax success callback:
var replace = function(first, second){
$(first.html() !== second.html())
first.replaceWith(second);
};
replace($('#container'), response.find('#container'));
Which works, but because the content gets always replaced I get to see a "clipping" effect. The ajax request runs multiple times, almost every second, until a certain class is added to the container tag from the ajax response, so the clipping is very annoying.
Basically I want to only replace the elements that have different html, but somehow start from the last level, to prevent replacing of elements that have the same html code.
I made a fiddle example here: http://jsfiddle.net/2u4eB/
So in that markup only the contents of the <b> tag should be replaced, and not the entire div like it is now, because only <b> is different.
Does anyone have any pointers on how could I achieve this?
If you can make some assumptions, then it's not so hard:
Assumption 1: The markup is exactly the same every time
Assumption 2: The only thing which changes is the TEXT inside of certain html tags
You must then know the HTML tags. If you are a consistent person, all of your dynamic data should be wrapped in a similar tag - in your question you mentioned a <b> tag, so lets make a third assumption:
Assumption 3: All dynamic data is wrapped with a <b> tag
Then all you have to do is this:
var replace = function(first, second) {
var oldValues = first.find('b'),
newValues = second.find('b');
oldValues.each(function(i) {
if(oldValues[i].textContent != newValues[i].textContent) {
oldValues[i].textContent = newValues[i].textContent;
}
});
};
replace($('#container'), response.find('#container'));
NOTE: this works because jQuery's find() returns a list of nodes in document order - so Assumption #1 is very important.
I highly recommend using a framework that supports client side binding. (Examples include but are not limited to Knockout, Handlebars, Angular, Underscore) This will give you better results faster than writing low level DOM Manipulation.
Knockout.js and Underscore.js are my favorites, but there are many great options.

Parsing HTML from a JSON String with jQuery

I have no idea what im doing wrong, but I have a JSON string with this:
jsonp443489({"content":"<!DOCTYPE html><html><head><title>Title</title></head><body><p>Hello World</p></body></html>"});
I need to parse this to be able to modify the content. Like, for example, id want to grab the <p>'s content.
Now, in jQuery if i do:
console.log($(json.content).html());
It returns Title.
If i do:
console.log($('p',json.content));
It returns [], or, an empty array.
Finally, if I do just:
console.log($(json.content));
It returns [<title>​Title​</title>​,<p>​Hello World​</p>​]
Which is fine, but then I cant do .find() or anything. Since I wont know what the HTML will be, i cant use $(json.content)[1].
Any ideas?
==UPDATE==
After hacking at this for a couple hours i decided to try XML. My example XML was:
<?xml version=\"1.0\" encoding=\"UTF-8\"?><doc><item>One</item><item>Two</item></doc>
It was giving me the same grief, then it hit me, its a JS object, not a string and jQuery is expecting a string. I went and did
$(JSON.stringify(json.content)).find('item')
And voila! I got an array of two items. I was pretty excited but then when I went and tried it with HTML again (using the JSONP return HTML snippet above):
console.log($(JSON.stringify(json.content)).find('p'));
I still get an empty array. It's driving me mad... Any more ideas?
There might be a better way, but this works (retrieves the p elements):
$('<div />', {html: json.content}).find('p');
What is jsonp443489 here? Why not just do $.parseJSON ?
Once you have done that you should be able to access content inside it and then create a jquery object from that content and search in it.
var json = $.parseJSON(jsoncontent);
$(json.content).find('');// or you can add it to dom and search using $('#id')

Categories

Resources