Getting an uncaught Reference error from callback with Wikipedia API? - javascript

So when I run my set of code independant of the Chrome extension frame work aka in a dummy html file it works fine but when I try to do it out of the chrome extension wikipedia gives me this weird callback function tacked onto my API url.
http://en.wikipedia.org/w/api.php?action=query&titles=Girdling&format=json&prop=extracts&exintro=0&redirects&callback=jQuery1111023737464868463576_1402806465025
What I am actually running in my AJAX call.
var wikiUrl = "http://en.wikipedia.org/w/api.php?action=query&titles=Girdling&format=json&prop=extracts&exintro=0&redirects&callback=?"
$.ajax(wikiUrl,{
dataType: 'jsonp',
cache: true,
success: function(data){
//do things with the response data
}
I get this Error in the console:
Uncaught ReferenceError: jQuery1111023737464868463576_1402806465025 is not defined
As you might suspect the JSON data is wrapped in this function:
jQuery1111023737464868463576_1402806465025({"query":{"pages":{"1822951":{"pageid":1822951,"ns":0,"title":"Girdling","extract":"<p><b>Girdling</b>, also called <b>ring barking</b> or <b>ring-barking</b>, is the complete removal of a strip of bark (consisting of cork cambium, phloem, cambium and sometimes going into the xylem) from around the entire circumference of either a branch or trunk of a woody plant. Girdling results in the death of the entire tree over time. A branch completely girdled will fail and when the main trunk of a tree is girdled, the entire tree will die, if it cannot regrow from above to bridge the wound.</p>\n<p>Among the causes of girdling are human practices, including forestry, horticulture, and vandalism. Foresters use the practice of girdling to thin forests and orchardists use it as a cultural technique to yield larger fruit. Girdling can also be caused by herbivorous mammals feeding on plant bark and by birds and insects, both of which can effectively girdle a tree by boring rows of adjacent holes.</p>\n<p></p>"}}}})
So how do I tell Wikipedia API that I want it to run the success function when it works not that other function? I already tried setting callback=success in my url.

Fixed it somehow? I think some protocol included in most modern sites, but not in my dummy.html site, is that you have to include the type of request it is? (even though it should default to GET?)
AJAX:
var wikiUrl = "http://en.wikipedia.org/w/api.php?action=query&titles="+wikiTitle+"&format=json&prop=extracts&exintro=0&redirects"
$.ajax(wikiUrl,{
type:"GET",
cache: true,
success: function(data){
//do stuff
I also removed the callback=? from the end of my URL. That might have the combination of those two did it for me.

Related

How to display a newly randomly generated quote from a specific API when clicking a button?

Problem- I have an API that displays a random quote once the page loads. My button(div) called "newQuote" doesn't generate a new quote, instead, it displays the exact same quote, making my button useless.
My code can be found on GitHub here
SO-
I have a javascript function, called getNewQuote() that runs when my page loads. This function grabs a quote and author from an API (https://quotesondesign.com/wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1), and appends it to my div with the class quoteTitle and quoteDisplay.
function getNewQuote() {
$.ajax({
url: 'https://quotesondesign.com/wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1',
jsonp: 'jsonp',
cache: 'false',
success: function(data) {
var post = data.shift();
$("#quoteTitle").empty();
$("#quoteDisplay").empty();
$("#quoteTitle").append(post.title);
$("#quoteDisplay").append(post.content);
}
});
}
getNewQuote();
Then, I set another div called newQuote which, when clicked, would display a new quote.
$('#newQuote').on('click', function(e) {
e.preventDefault();
getNewQuote();
Now, to me, it seems that the problem is caching. The reason that I think it is a cache problem is because if I go to the site on my phone using the app Firefox Focus, which (pretty sure) doesn't store any cache, the site will run as wanted, and will change my quote whenever I click on my #newQuote. You can try it for yourself at 'rqg.ronlaniado.me', where it is hosted.
Since my problem is cache, I did use some methods and plans to avoid this.
cache: 'false',
I set cache-ing to false in my .ajax request.
<script src="qg_js.js?v=42"></script>
I put "?v-42 which, according to Google, shouldn't keep cache stored.
If anyone can look through my code and assist me in solving my issue, that'd be great. Also, this is my first time posting here, so sorry if I am a bit messy with everything.
The error was here:
cache: 'false';
The correct usage is:
cache: false;
These quotes caused cache to be kept, meaning that the quotes didn't change.

AJAX modifying the DOM & calling a function

I am on Linux -both browser side & server side- with a recent Firefox 38 or 42 if that matters; this question gives more context, and the github GPLv3 project containing my code. It is not a usual Web application (it would have usually one, and perhaps a dozen, of simultaneous Web users). I am writing or generating both server & browser side code
Let's suppose I have some HTML5 code like
<div id="mydyndiv_id"></div>
I am making an AJAX request with JQuery. On success it should insert some (AJAX generated) HTML element, e.g. <b>bold</b> (in reality it is a much bigger HTML fragment with nested <span>-s whose content is dynamically generated from the POST argument of the AJAX request), into that div and call some other Javascript function doit, e.g. doit(42) only once just after the AJAX request (e.g. that function would clear some other <textarea> in my page, and the 42 argument is provided by the AJAX response). I can change code both on server side (e.g. alter the AJAX processing) and on browser side.
What is the most idiomatic way to achieve that?
making a JSON AJAX which contains both the inserted HTML & the function argument, so the AJAX response could be {"text":"<b>bold</b>", "data": 42}" of Content-type: "application/json" and the Javascript code would be
$.ajax
({url: "/someajax",
method: "POST",
data: {"somearg": "foo"},
datatype: "json",
success: function(jsa) {
$("#mydyndiv_id").html(jsa.text);
doit(jsa.data);
}});
this is rather heavy, the server should double-encode HTML&JSON the HTML fragment: it needs first to construct the <b>bold</b> fragment -with HTML encoding, and then to construct the JSON object and send it.
making an HTML AJAX which has some <script> element. The AJAX response would be of Content-type: text/html and would contain <b>bold</b><script>doit(42)</script>, and the Javascript code would be
$.ajax
({url: "/someajax",
method: "POST",
data: {"somearg": "foo"},
datatype: "html",
success: function(ht) {
$("#mydyndiv_id").html(ht);
}});
this might be wrong, since the doit(42) function could be perhaps called more than once and is kept in the DOM and I don't want that
making a Javascript AJAX; the AJAX response would be of Content-type: application-javascript and would contain:
$("#mydyndiv_id").html("<b>bold</b>");
doit(42);
with the AJAX invocation in Javascript being
$.ajax
({url: "/someajax",
method: "POST",
data: {"somearg": "foo"},
datatype: "script",
success: function(jscode) { /* empty body */ }
})
This is brittle w.r.t. errors in doit(42) (see this question; the only debugging technique I found is lots of console.log and that is painful) and also requires double encoding on server side.
Of course, any other technique is welcome!
PS. If you are curious, the code is commit a6f1dd7514e5 of the MELT monitor (alpha stage) and you would try the http://localhost.localdomain:8086/nanoedit.html URL in your browser; this software (which is also a specialized HTTP server!) would have only very few simultaneous Web users (usually one, perhaps a dozen); in that sense it is not a usual web application. In my dreams it could become a workbench for a small team of (C & C++) software developers, and the GUI of that workbench would be their browser.
These different approaches have pros and cons, but generally the first two options are more advisable, let's see:
JSON AJAX
First of all, working with templating on your server is the right approach. If you use this method you will be able to pass more flexible data from your server to your client as you can e.g. use {"text":"<b>bold</b>", "data": 42, "more_data": 43}".
You are not bound to use just the data at the moment you initially create the service but expand passed data easily.
HTML AJAX
This method is simple and if you would like to have a service for every single piece of data you need to pass, rather than a service for multiple pieces, this is the preferable choice. In difference to the JSON AJAX method, you will not be able to expand here and if needed, you'll naturally have to create a new service for passing new data.
Javascript AJAX
Altough it is possible, tis method is rather unadivsable, as you can not maintain your application in a reasonable way, as your templating is client-side. See what Peter-Paul Koch says here:
Although templating is the correct solution, doing it in the browser is fundamentally wrong. The cost of application maintenance should not be offloaded onto all their users’s browsers (we’re talking millions of hits per month here) — especially not the mobile ones. This job belongs on the server.
Further reading : Why client-side templating is wrong.
First approach looks good for me, but generally it's a little bit ugly to transfer raw HTML via AJAX, if you have to transfer raw HTML it's better to use techniques called PJAX, see jquery-pjax plugin for more information of how to use and customize it.
From my point of view best approach would start using jquery-template to avoid transferring HTML over AJAX and start transfer only object witch would be rendered to template on frontend.Call doit method within handling success is ok until it use data provided in response.
I would rather go with a variation of first approach. But, it depends on the kind of generated HTML that you are currently returning from the server-side.
If it is a simple element, then you could just return a JSON object from server with one of the properties identifying the element.
For example, the response from the web-service would be like:
{'elem': 'b', 'text': 'bold', 'value': '42'}
And you consume that in the AJAX call like this:
$.ajax({
datatype: "json",
...
success: function(response) {
// create the required element client-side
var elem = document.createElement(response.elem);
// use other properties of the response object
elem.textContent = response.text + doit(response.value);
// add the element to your div
$('#mydiv-1')[0].appendChild(elem);
}
});
Where doit is the Javascript function that is already part of your client-side code-base and you just use the arguments returned by the web-service.
Alternatively, if your generated HTML is a complex fragment, then you need to identify common patterns and use client-side templates to transform the returned data into presentation.
For example, your client-side template may look like this:
<script type='text/template' id='tmpl'>
<div><h3></h3><p></p><h5></h5></div>
</script>
Your web-service returns something like this:
{'title': 'title', 'text': 'paragraph', 'value': '42'}
And you consume that in the AJAX call like this:
$.ajax({
datatype: "json",
...
success: function(response) {
// clone the client-side template
var template = $('#tmpl').html(), $elem = $(template);
// append to your div
$('#mydiv-2').append($elem);
// populate the cloned template with returned object properties
$elem.find('h3').text(response.title);
$elem.find('p').text(response.text);
$elem.find('h5').text(doit(response.value));
}
});
This way you avoid returning generated HTML from your server and manage the presentation details at the client-side only. Your web-service needs not to know the presentational aspects and deals only with raw data (consuming or spewing). The client-side code gets data from the web-service and deals with using and/or presenting that data as part of the client-side app.
Demo for both the variations: https://jsfiddle.net/abhitalks/wuhnuv99/
Bottom-line: Don't transfer code. Transfer data. Code should then use that data.

JSON external file vs defined in JS

What are some arguments as to when to use JSON external file such as with jQuery's
$.getJSON('external.json',function(data){});
(ajax retrieving) versus defining it in javascript with
var myJson = { "someVar": { "1": ["test1","test2"], "2": ["test3","test4"]} }
What is the "proper" way of doing it? Does it depend on JSON length or are there any other factors that can tell you what approach to use?
The way I see it: choose between loading another file which is supposed to be slow as you are loading data via ajax call or adding plenty of lines into already packed javascript file which is not a good thing either. Surely there must be some distinction as to where you should use one or another ... ?
I am not interested only in speed difference (getting file from ajax is of course slower) but also in other aspects such as what is generally used when and what should be used in some case ...
The first one is a shorthand for:
$.ajax({
dataType: "json",
url: url,
data: data,
success: success
});
This is an Ajax request which will take more time than having a simple JSON object into the file.
I would prefer the second one IF it's possible. Also if you attend to have good performances the first one is longer.
time( Loading+parsing 2 files ) >> time( Read a Javascript object )
If your data is known at page creation time you're probably best to use an object literal like:
var myJson = {...}
However, as Kursion mentions,
$.getJSON(...)
is a shorthand method for retrieving json data asynchronously via ajax. You'd use it if you want to retrieve data from the server that wasn't known at the time of page load...
For example, if a user enters a search term in an input control, you might want to retrieve JSON in response to that without performing a whole page update. You couldn't simply define a javascript object up-front because you wouldn't know what the search term was in advance.

trapping and logging "bugfoot" javascript exceptions in a meaningful way

We have had some reports of problems with our checkout whereby customers get js exceptions (we assume) so they cannot checkout.
No matter how many testbenches we use, we have failed to recreate the issues but that's the point of the exercise.
I have setup a simple error trapping function which works based around:
window.onerror = function(message, url, line, chr) {
new Request({
url: "/errorTrap.php",
data: {
m: message,
u: url,
l: line,
c: chr
},
method: "get",
onComplete: function() {
// perhaps save the rendered html source via a second POST request?
alert("done");
}
}).send();
return true;
};
Sure enough, in a single week I have now received 8 emails of trapped exceptions.
Regretfully, the checkout page is very dynamic. It contains SOME inline javascript, a lot of it is external .js files and classes and some is evaluated js through ajax responses. The length of the page differs dependent on items in the shopping basket, shipping options, address book info and so forth.
This is why seeing an exception 'Object expected' on line 253 means very little as it does not help me understand which function has triggered the exception or supply the context of the script block / source code that goes with it.
I have been thinking of doing a second XHR request that can drop the innerHTML of document.body to a ajax handler and thus supply a relative line numbering and content that may have caused the problem.
Is this the only improvement in tracing I can do? Are there any solutions for this "out there"?
Here is the jsfiddle that demos the exception handling http://www.jsfiddle.net/dimitar/8hqrY/
Well, debugging a problem is always like that. Either going there, actually seeing the issue and then tackling it with debug tools or getting evidence, guesswork, getting more evidence and so on, Sherlok Holmes-style :^)
In addition to DOM tree, you can get JS stack trace: A Javascript stacktrace in any browser.

ExtJS: autoLoad does not work in IE

Using ExtJS 2.2.1, I've got a container element which is supposed to load a piece of HTML from the server using:
autoLoad: { url: 'someurl' }
This works fine in Firefox, but for IE7 this results in a syntax error in ext-all-debug.js at line 7170:
this.decode = function(json){
return eval("(" + json + ')');
};
I fixed this by turning that function into this:
this.decode = function(json){
return eval('(function(){ return json; })()');
};
Then the autoLoad works well in both browsers, but then there's some odd bugs and besides, you really don't want to fix this in the ExtJS library as it will be unmaintainable (especially in the minified ext-all.js which is like half a megabye of Javascript on a single line).
I haven't been able to find a lot about this bug.
Variations that I've tried:
// With <script> tags around all the HTML
autoLoad: { url: 'someurl', scripts: true }
// With <script> tags around all the HTML
autoLoad: { url: 'someurl', scripts: false }
And visa versa without the <script> tags. There isn't any Javascript in the HTML either, but it should be possible, because eventually we will use Javascript inside the returned HTML.
The problem isn't in the HTML because even with the simplest possible HTML, the error is the same.
UPDATE - Response to donovan:
The simplest case where this is used is this one:
changeRolesForm = new Ext.Panel({
height: 600,
items: [{ autoScroll: true, autoLoad: WMS.Routing.Route("GetRolesList", "User") + '?userID=' + id}]
});
There is no datastore involved here. The response-type is also text\html, not json, so that can't be confusing it either. And as said, it's working just fine in Firefox, and in Firefox, it also executes the same eval function, but without the error. So it's not like Firefox follows a different path of execution, it's the same, but without the error on eval.
Check your JSON. FF allow trailing commas in JSON objects while IE does not. e.g.
{foo:'bar',baz:'boz',}
would work in FF but in IE it would throw a syntax error. In order for there to not be a syntax error the JSON would need to be:
{foo:'bar',baz:'boz'}
I located the source of the problem and it was indeed not with ExtJS. There was a section in the application that listened to the Ext.Ajax 'requestcomplete' event and tried decoding the response.responseText to json, even if the response was HTML (which it only is in one or two cases). IE was not amused by this.
If you're autoLoad'ing into a Panel or Element then a JSON decode shouldn't even be involved in the process. UpdateManager just defers to Ext.Element.update(..) which takes a string of html.
The only reason I can think that your response would be parsed as JSON is if you were using a JSONStore to request it - what are you using?
You should be able to do something simple like this:
var panel = new Ext.Panel({
autoLoad: 'someurl' // this is the short form, you can still use the object config
});
OR
var element = Ext.get('element id').update({
url: 'someurl'
});
Response to Update:
That looks correct as long as something weird isn't happening with the WMS.Routing.Route(...) method. I'm actually currently working on an ExtJS application myself so I was able to quickly test some different server responses and couldn't reproduce your problem. I've also relooked at the ExtJS 2.2.1 sources and still see nothing in the related Element update and UpdateManager that would make the call to Ext.util.JSON.decode(...) that you're seeing.
I'm imagining that its from an unrelated AJAX request in another part of your application. If you're not already, I would use firebug / firebug lite to help debug this - specifically try to get a stack trace to make sure the source of your problem really is this autoLoad.
I had the same problem, excuse my english, i'm from Mejico, i hope I can help… my problem was triggered when I submit a Form to login, my PHP returns a JSON with the response in case of failure like this:
$respuesta = "{success: false, msgError: 'El usuario o contraseña son incorrectos'}";
but I wasn't send a resposne when it success, well when it has a true success, then the ExtJS it was trying to decode my JSON response, but there was nothing to decode, i guess that was, in my case again, the problem… I solved just sending back a response for the true succes, FF, Chrome, Safari, dont catch the problem, but Opera and IE8 does… I hope I help someone, goodbye
I don't know what the problem is, but I wanted to point out that your "fix" makes it simply return the json as a string instead of an eval'd object, so of course there is no error anymore -- you removed the functionality. It could just as simply be:
this.decode = function(json){
return json;
}
Generally speaking, random errors like this do not usually indicate a bug in Ext, especially not in functions used as commonly as Ext.decode. I would guess that either there is something in the JSON that IE does not like that other browsers ignore, or more likely, there is something unexpected going on in your app that is not obvious from your description. Have you tried inspecting your request log in Firebug to see what the JSON actually looks like? Have you tried getting the result of your Route call into a variable first to verify its contents before populating the panel? Also, try setting the "break on all errors" option in Firebug to true -- a lot of times when you get a random function from Ext at the top of your stack trace, the culprit is actually some application code that you weren't expecting.

Categories