Strange jQuery XML problem - javascript

I have a list of quotes in an XML document. Each quote is wrapped like this:
<Item>
<Quote>This is a quote!</Quote>
<Source>-- this is the Source of the Quote!</Source>
</Item>
Here's the jQuery:
var html = '';
var tmpl = '<li class=""><p class="quote">__quote</p><p class="source">__source</p></li>';
$(quoteObj).find('Item').each(function(){
$that = $(this);
var _quote = $that.children('Quote').text();
var _source = $that.children('Source').text();
var qhtml = tmpl.replace('__quote', _quote).replace('__source', _source);
html += qhtml;
});
return html;
In the end product, the QUOTES are all there, but the SOURCES aren't. I can't for the life of me figure out why. What's right in front of me that I can't see?
ADDITIONAL INFORMATION TO ANSWER COMMENTS:
The XML is properly formed, and I changed it above.
I added the var tmpl line to show what I'm replacing in the loop. The __quote is being replaced, and the __source is at least being acted upon, since the second <p> is empty, instead of containing a string.
I have checked the actual XML coming back from the AJAX call, and it is all there, as it should be.
It seems to me this is some sort of issue with scoping and this, or with the action of the .children() method, but I still can't find it.
ONE LAST NOTE:
Changed the XML tag case to Initial Caps, which it is in the document in question.

jQuery doesn't parse XML. Passing an XML string to $() simply assigns the string as the innerHTML property of an element, which has variable and unpredictable results. You need to parse the XML yourself, using the browser's built-in XML parser, and then pass the resulting document into jQuery:
var parseXml;
if (window.DOMParser) {
parseXml = function(xmlStr) {
return ( new window.DOMParser() ).parseFromString(xmlStr, "text/xml");
};
} else if (typeof window.ActiveXObject != "undefined" && new window.ActiveXObject("Microsoft.XMLDOM")) {
parseXml = function(xmlStr) {
var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = "false";
xmlDoc.loadXML(xmlStr);
return xmlDoc;
};
} else {
parseXml = function() { return null; }
}
var xmlStr = "<Item><Quote>This is a quote!</Quote><Source>-- this is the Source of the Quote!</Source></Item>";
var xmlDoc = parseXml(xmlStr);
$xml = $(xmlDoc);
$xml.find('Item').each(function() {
// Do stuff with each item here
alert("Item");
});

Just tried this and the only thing I had to change was the find line to match the case of the XML node, eg
$(quoteObj).find('ITEM').each( function() {
I did also change the $that assignment line to include the var keyword, but it was working before I did that
var $that = $(this);

Related

Dynamically creating ODT using WebODF / Javascript

Using javascript, I need to create an .odt file and populate the contents with data in javascript variables. The only thing that I have found that might work is WebODF. An example that seems similar to it is here.
When I am trying to do something similar to PDF with pdfkit (using node) I can do something like this:
PDFDocument = require('pdfkit');
var doc = new PDFDocument();
doc.pipe(fs.createWriteStream(fileName));
doc.text("Fist line");
doc.text("Second line");
Is it possible to do something similar to it using WebODF? I've found ops.OpInsertText, but I'm not sure how I can use it to actually insert text.
Again, ideally the solution is only in javascript.
If I got your question right, you want to create a new file dynamically using data in JavaScript variable.
You ca refer this answer to load a file from javascript variable in form of byte Array.
And this will get you up and running with a odt file ,which you can save to desired location.
function saveByteArrayLocally(error, data) {
var mime = "application/vnd.oasis.opendocument.text";
var blob = new Blob([data.buffer], {type: mime});
var res = $http({
method: 'POST', url: myWebServiceUrl,
headers: {'Content-Type': undefined},
data: blob
});
res.success(function(data, status, headers, config) {
console.log(status);
});
}
NOTE: You can use multer,express.js framework to design services as backend to save files.
This may help you.In this example I am attaching the Value returned from promt to the cursor position inside the webodf. You can similarly insert data to any other elements offest().
pressing crtl+space will show a promt, and whatever we type there is inserted to odf.
function insertBreakAtPoint(e) {
var range;
var textNode;
var offset;
var key = prompt("Enter the JSON Key", "name");
{% raw %}
var key_final = '{{address.'+key+'}}';
{% endraw %}
var caretOverlay=$('.webodf-caretOverlay').offset();
if (document.caretPositionFromPoint) {
range = document.caretPositionFromPoint(
caretOverlay.left, caretOverlay.top
);
textNode = range.offsetNode;
offset = range.offset;
} else if (document.caretRangeFromPoint) {
range = document.caretRangeFromPoint(
caretOverlay.left, caretOverlay.top
);
textNode = range.startContainer;
offset = range.startOffset;
}
#only split TEXT_NODEs
if (textNode.nodeType == 3) {
var replacement = textNode.splitText(offset);
var keynode = document.createTextNode(key_final);
textNode.parentNode.insertBefore(keynode, replacement);
}
}
function KeyPress(e) {
var evtobj = window.event? event : e
if (evtobj.keyCode == 32 && evtobj.ctrlKey)
insertBreakAtPoint();
}
document.onkeydown = KeyPress;

jquery to use .get and retrieve variables from text file

I have a list of names in a text file
example:
user1 = Edwin Test //first line of text file
user2 = Test Edwin //second line of text file
I would like each lines data to be set to a variable:
user1 and user2 //so that after jquery loads I can user $user1 and it will give Edwin Test
Text file will be in the same folder as jquery file.
My code:
$.get('users.txt', function(data) {
alert(data);
var lines = data.split("\n");
$.each(lines, function() {
var line=perLine[i].split(' ');
});
});
When i load the page using mamp locally, I am able to see the contents on the file using the alert but when i type for example (user1) in the console it says that the variable is not set.
Here's what I think you want:
$.get('users.txt', function(data) {
var lines = data.split("\n");
$.each(lines, function(i) {
var line = lines[i].split(' = ');
window[line[0]] = line[1];
});
});
later on...
console.log(user1); // "Edwin Test"
var users = {};
var lines = data.split("\n");
$.each(lines, function (key, value) {
var prep = value.split(" = ");
users[prep[0]] = prep[1];
});
To output user1 You would call users.user1
JSFiddle
The code adds lots of variables to the global namespace. Also, it invites bugs because $.get is asynchronous and so code that depends on the variables existing needs to be called where shown in the comment to be guaranteed to work. This would be considered bad style by many, but here's how to do it:
$.get('users.txt', function(data) {
alert(data);
var lines = data.split("\n");
var i,l=lines.length,parts;
for(i=0;i<l;++i){
parts = lines[i].split('=');
if (parts.length == 2){
try {
// window is the global object. window['x']=y sets x as a global
window['$'+parts[0]] = parts[1]; // call the var $something
} catch(e) {}; // fail silently when parts are malformed
}
// put any code that relies on the variables existing HERE
}
});
Here's what you might do instead:
Put the data in an object. Pass the object to a function showVars(vars) that contains the next step.
$.get('users.txt', function(data) {
alert(data);
var lines = data.split("\n");
var i,l=lines.length,parts, vars = {};
for(i=0;i<l;++i){
parts = lines[i].split('=');
if (parts.length == 2){
try {
vars[parts[0]] = parts[1];
} catch(e) {}; // fail silently when parts are malformed
}
showVars(vars); // put any code that relies on the variables existing HERE
}
});
function showVars(vars){
// put whatever uses/displays the vars here
}
Yet another way to make this easier to change the data format. If you can store the data in this format, called JSON:
['Edwin Test','Test Edwin','Someone Else','Bug Tester']
Then the parser is either a one liner array = JSON.parse(jsonString) or sometimes is done for you by jQuery and put in data. JSON can store all kinds of data, and there is support for it in other languages libraries besides Javascript, such as PHP, python, perl, java, etc.
$.get('users.txt', function(data) {
alert(data);
var lines = data.split("\n");
for(var i = 0 ; i < lines.length; i++){
var line=lines[i].split(' ');
});
});
I think you are missing the i in the loop.
I guess you could also do
$.each(lines, function(i) {
var line=lines[i].split(' ');
});
In any event, I would probably recommend that you do this string splitting on the server instead and deliver it to the client in the correct/ready form.

Need help turning a jQuery object back into a string

(i am new. please bear with me.) I have a jquery object that I need to convert back to html to use. What I am doing is using jQuery's get to get the HTML DOM of a local file. The data returned is then made into an object and I perform some tweaks on it (like changing hrefs etc.)
$.get(imagePath + "bloghome.aspx", function (data) {
var pageHtml = $(data);
pageHtml.find('a').each(function () {
var longHref = $(this).attr('href');
var tmp = longHref.lastIndexOf('ID=');
var id = longHref.substring(tmp + 3) + '.htm';
var newHref = imagePath.concat(id);
$(this).attr('href', newHref);
});
});
the object is created in the second line and then i change the hrefs. What I need now is to turn that object back into a string so that I can write it to a file.
I am using PhoneGap but any help would be appreciated as I am stumped
You can do this way using pageHtml[0].outerHTML:
$.get(imagePath + "bloghome.aspx", function (data) {
var pageHtml = $(data);
pageHtml.find('a').each(function () {
var longHref = $(this).attr('href');
var tmp = longHref.lastIndexOf('ID=');
var id = longHref.substring(tmp + 3) + '.htm';
var newHref = imagePath.concat(id);
$(this).attr('href', newHref);
var htmlString = pageHtml[0].outerHTML; //<-- Here
});
});
from http://api.jquery.com/html/
console.log(pageHtml.html());
Can you just do
pageHtml.html();
?
EDIT: Using this will only give you the contents inside the main wrapping element, if you want the entire thing, you can use:
pageHtml[0].outerHTML;
instead.

Help me properly make an AJAX call

I have a JavaScript function that is being called. I need to have it call a PHP function and return a true/false.
The script with the function is in the file /db/cancel_hike.php
My current JS looks like this:
function uncancelHike( hike_id )
{
//var url = "/db/cancel_hike.php;
var success = null;
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.open("GET", url , true);
request.onreadystatechange = function()
{
if (request.readyState == 4)
{
var xmlDoc = request.responseXML;
// obtain the array of markers and loop through it
markers = xmlDoc.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++)
{
// obtain the attribues of each marker
success = markers[i].getAttribute("success");
if ( success == "true" )
{
document.getElementById("success").style.display = 'block';
document.getElementById("warning").style.display = 'none';
document.getElementById("error").style.display = 'error';
}
if ( success == "false" )
{
document.getElementById("success").style.display = 'none';
document.getElementById("warning").style.display = 'none';
document.getElementById("error").style.display = 'block';
}
}
}
}
request.send(null);
return false;
}
What I am having trouble with is:
How to call an actual function in the PHP script?
Do I absolutely need to have some XML returned? Or is there a way to just get back the returned value?
I am using YUI JS library. Do I need to make some calls to it, or is it not necessary in this case?
How to call an actual function in the PHP script?
You can't. You request URIs.
Write a PHP script that calls the function you want and place it at the URI you call.
(You can use query strings and the like as the input to an if statement that you use to conditionally call different functions)
Do I absolutely need to have some XML returned? Or is there a way to just get back the returned value?
You can return any kind of data you like.
I am using YUI JS library. Do I need to make some calls to it, or is it not necessary in this case?
It's a library. You never need to make calls to it. It often simplifies the code you have to write.
How to call an actual function in the PHP script?
Do I absolutely need to have some XML returned? Or is there a way to just get back the returned value?
Well, you don't call the actual function. What you want to do is pass variables using GET, that is, by appending them to the URL like file_name.php?var1=this&var2=that to pass var1 of "this" and var2 equaling "that." You retrieve them in the PHP file with $_GET['this'] and $_GET['that']. Whatever PHP outputs to the page via echo, print_r, etc. is then sent back in a request object as part of its responseText property.
You just set url in request.open to a URL on your site. For example, in your .js file:
request.open("GET", "answer_me.php?hike_id=" + hike_id, true);
And in your .php file:
<?php
$hike_id = $_GET['hike_id'];
if ($hike_id < 5) {
echo "true"; // echo true would return "1", BTW
} else {
echo "false"; // echo false would return nothing
}
Note that that will just return a string value to request.responseText of false, thus you could do this:
var result = request.responseText;
if (result === "true") {
...
document.getElementById("success").style.display = "block";
...
} else {
...
document.getElementById("success").style.display = "none";
...
}
You do not need it to be XML, especially as it looks like you're not really using the loop (the same three DOM elements are being assigned values each time).
And honestly, for AJAX I'd recommend using a framework like jQuery (or YUI, although I don't find its AJAX stuff as intuitive). Your entire code would look like this:
var $success = $("#success");
var $error = $("#error");
function cancelHikeCallback(data) {
var is_success = (data === "true");
$success.toggle(is_success);
$error.toggle(!is_success);
}
function cancelHike(hikeIdToSend) {
$.get("/db/cancel_hike.php", {hike_id: hikeIdToSend}, cancelHikeCallback);
}
IMO things like jQuery's $.ajax ($.get is a specialized form of $.ajax) make this stuff much easier to read and debug.
jsFiddle Example

jQuery XML: Count number of leaf nodes

How can I count the number of leaf nodes coming off a particular XML node using jQuery?
The XML in question looks similar to this. I want all leaf nodes coming off the <Errors> node.
<Errors>
<ErrorParentCat>
<ErrorTag/>
<ErrorTag2/>
</ErrorParentCat>
</Errors>
In this example I want <ErrorTag/> and <ErrorTag2/> counted only. The result should therefore be 2. Also <ErrorParentCat> is an example tag, there could be many within <Errors> with different names.
Once I have the number I would like a list of these leaf nodes too, if possible.
Assuming you already have an XMLDocument named xml:
var $xml = $(xml),
count = $xml.find('*').filter(function ()
{
return $(this).children().length === 0;
}).length;
console.log(count);
You can also just pass the XML string directly to the jQuery function:
var $xml = $('<Errors><ErrorParentCat><ErrorTag/><ErrorTag2/></ErrorParentCat></Errors>');
// the rest is the same
jsfiddle demo →
Edit you said you wanted a list of those leaf nodes. In the code above, you've already got them:
var $xml = /* whatever */,
$leafNodes = $xml.find('*').filter(function ()
{
return $(this).children().length === 0;
}),
count = $leafNodes.length;
Edit #2 as Tim Down has pointed out (see comments below), you cannot just pass the XML string to $() in IE (!##$ing IE). You should use the jQuery 1.5 function $.parseXML() to parse an arbitrary well-formed XML string into an XMLDocument:
var xmlDoc = $.parseXML('<Errors><ErrorParentCat><ErrorTag/><ErrorTag2/></ErrorParentCat></Errors>'),
$xml = $(xmlDoc);
/* the rest is unchanged */
new jsfiddle demo →
Loads of ways to do this:
var countThem = 0;
jQuery.ajax({
type: "GET",
url: 'blahblah.xml',
dataType: ($.browser.msie) ? "text/xml" : "xml",
success: function(xml) {
var xml2 = load_xml(xml);
$(xml2).find('Errors').each(function(){
$(xml2).find('ErrorParentCat').each(function(){
alert($(this).text()); //alert the contents
countThem++;
});
});
alert(countThem); //alert the total number
}
});
and the XML load function:
function load_xml(msg) {
if ( typeof msg == 'string') {
if (window.DOMParser)//Firefox
{
parser=new DOMParser();
data=parser.parseFromString(text,"text/xml");
}else{ // Internet Explorer
data=new ActiveXObject("Microsoft.XMLDOM");
data.async="false";
data.loadXML(msg);
}
} else {
data = msg;
}
return data;
}

Categories