I'm looking at putting together a good way of caching results of AJAX queries so that the same user doesn't have to repeat the same query on the same page twice. I've put something together using a Hash which works fine but i'm not sure if there's a better method i could be using. This is a rough snippet of what i've come up with which should give you a general idea:
var ajaxresults;
document.observe("dom:loaded", function() {
ajaxresults = new Hash();
doAjaxQuery();
});
function doAjaxQuery(){
var qs = '?mode=getSomething&id='+$('something').value;
if(ajaxresults.get(qs)){
var vals = (ajaxresults.get(qs)).evalJSON();
doSomething(vals);
}else{
new Ajax.Request('/ajaxfile.php'+qs,{
evalJSON: true,
onSuccess: function(transport){
var vals = transport.responseText.evalJSON();
ajaxresults.set(qs,transport.responseText);
},
onComplete: function(){
doSomething(vals);
}
});
}
}
Did you try caching the AJAX requests by defining the cache content headers. Its another way and your browser will take care of caching. You dont have to create any hash inside your libraray to maintaing cache data.
High performance websites discussed lot about this. I dont know much about the PHP, but there is a way in .Net world to setting cache headers before writing the response to stream. I am sure there should be a similar way in PHP too.
If you start building a results tree with JSON you can check of a particular branch (or entry) exists in the tree. If it doesn't you can go fetch it from the server.
You can then serialize your JSON data and store it in window.name. Then you can persist the data from page to page as well.
Edit:
Here's a simple way to use JSON for this type of task:
var clientData = {}
clientData.dataset1 = [
{name:'Dave', age:'41', userid:2345},
{name:'Vera', age:'32', userid:9856}
]
if(clientData.dataset2) {
alert("dataset 2 loaded")
}
else {
alert("dataset 2 must be loaded from server")
}
if(clientData.dataset1) {
alert(clientData.dataset1[0].name)
}
else {
alert("dataset 1 must be loaded from server")
}
Well, I guess you could abstract it some more (e.g. extend Ajax by a cachedRequest() method that hashes a combination of all parameters to make it universally usable in any Ajax request) but the general approach looks fine to me, and I can't think of a better/faster solution.
Related
I'd like to perform a redirect, but I also wish to send additional information along with it.
I've tried to change the value of window.location.href but that doesn't seem to pass along the extra information.
I also get how I can do
$.get(
new_url,
{data : "mydata"},
function(data) {
alert('page content: ' + data);
}
);
and that will display the html content of the new page, but that doesn't help with actually getting there.
How can I achieve this?
Edit: I feel as if I must be phrasing this terribly because I'm pretty sure this is an easy/common task. This shouldn't be something that would require cookies - it should basically be like a post request (I think).
You have a few different options for this:
URI Variables - You can append extra data to the URL by appending a question mark (?) followed by a set of key-value separated by an ampersand (=) with each variable being separated by an ampersand (&). For instance, http://www.google.com/search?q=javascript+url+variables&ie=UTF-8 gives you a link to a Google search for "javascript url variables" using UTF-8 encoding. Your PHP code or JavaScript would need to handle passing along and processing these variables. If using JavaScript a nice library for processing URLs is URI.js or using PHP you can use the parse_url and http_build_query functions. You can use this with window.location.href; for instance: window.location.href = "http://www.google.com/search?q=javascript+url+variables&ie=UTF-8" (replace the Google URL with the one you created or set in a variable).
Storage API - You can use the localStorage or sessionStorage properties to store and retrieve information using JavaScript (information is stored in the user's browser - supported by IE 8 and newer and all other major browsers). Note that this is JavaScript only unless you grab the data with JavaScript and pass it to your PHP server through URL variables, form, AJAX request, etc.
Cookie - You can store additional information inside a cookie - however this is more difficult since you have to setup your variables as a parsable string (possibly JSON) and remember to encode/decode the string when setting/getting the cookie. I don't recommend this method.
IndexedDB API - This is a more advanced client-side/browser storage mechanism and currently only supported in IE 10 and newer (and nearly all other browsers). There are also still changes being made to the standard which means newer versions of browsers could break current implementations or be buggy. If all you need is simple key-value storage (not an SQL-like database) then you should stick with one of the above options.
You can use the window open method to redirect your user,and remember to use "_self"
window.open('url','_self');
Preferably you'd store the data in localStorage and fall back to a cookie (I really like js-cookie).
Here are the two helper functions you need to store and retrieve data:
function setMultiPageData(itemName, data) {
var dataStr = JSON.stringify(data);
var hasLocalStorage = typeof localStorage !== 'undefined';
if (hasLocalStorage) {
localStorage.setItem(itemName, dataStr);
}
else {
Cookies.set(itemName, dataStr, { path: '/' }); // path set to root to make cookie available on any page
}
}
function getMultiPageData(itemName) {
var data = null;
var hasLocalStorage = typeof localStorage !== 'undefined';
if (hasLocalStorage) {
data = localStorage.getItem(itemName);
}
if (!hasLocalStorage || data === null) {
data = Cookies.get(itemName);
}
var parsedObject = null;
try {
parsedObject = JSON.parse(data);
}
catch (ex) {
console.log(ex); // remove in production
}
return parsedObject;
}
usage:
var data = { first: 'this is the first thing', second: 'this is the second thing' };
setMultiPageData('stackoverflow-test', data);
// go to a new page
var retrievedData = getMultiPageData('stackoverflow-test');
if (retrievedData === null) {
console.log('something went wrong')
}
else {
console.log(retrievedData); // { first: 'this is the first thing', second: 'this is the second thing' }
}
for (var i = 3848450; i > 3848400; i--) {
var query = {
url: 'http://classifieds.rennug.com/classifieds/viewad.cgi?adindex=' + i,
type: 'html',
selector: 'tr',
extract: 'text'
}
,
uriQuery = encodeURIComponent(JSON.stringify(query)),
request = 'http://127.0.0.1:8888//?q=' +
uriQuery + '&callback=?';
jQuery.getJSON(request, function (data) {
var datastring = data[0].results;
var datasplit = datastring.toString().split('Sign');
$('#inner-content').append(datasplit[0]);
});
}
I want to listen for new URLs of ads that are posted without writing some kind of arbitrary code that takes up a lot of memory looping through new URLs, etc. I can do that but it seems redundant and such as my code listed above. Im using noodle.js to get the info from the pages. Now I would like a way to listen for new urls instead of looping through every possible url from a to z. Since I don't know z it's a safe bet I'll be using an if statement but how would one go about incorporating this nth URL without ending up with undefined iterations. Im still learning and find this place has many helpful people. This is simply a fun project I'm doing to learn something new.
If I understand you correcly, you want an external thing to inform your javascript when there's new a URL or JSON data
Unfortunately the web is not built for servers to contact clients, with one exception to my knowleadge: WebSockets
You already seem to have a local server so you meet the requirements plus node ships with them ready for use (also available on the browser). To use noodlejs with websockets you'd have to require the package and set up the WebSocket to send data to your client
Other than pointing you towards that direction, I don't think I can do better than the internet at giving you a tutorial. Hope this helps, Have fun! Also thanks for telling me about noodle, that thing is awesome!
I have a server side function which returns content of HTML page:
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
Meteor.methods({
sayHello: function() {
var response = Meteor.http.call("GET", "http://google.com");
return response;
}
});
});
And I have client code where I am trying to get title from this HTML page:
'click .add_tag' : function(e,t) {
//Session.set('editing_tag_id', e.target.id);
Meteor.call("sayHello", function(err, response) {
var title = $(response.content).find("title").text();
var title2 = $(response).find("title").text();
var title3 = response.content.match(/<title[^>]*>([^<]+)<\/title>/)[1];
alert(title3);
});
I would like to get jQuery version ('title' or 'title2'), but it doesn't works. It returns empty string.
'Title3' - version works fine, but I don't like regexps. :)
Is there any way to make 'jQuery'-versions works ?
As requested, I will reiterate my comment as an answer...
I would stick with the regex, even though you don't like it. There is a huge overhead of constructing a DOM element that is essentially an entire page, purely for the purpose of parsing a small amount of text. The regex is more lightweight and will perform adequately in slower browsers or on slower machines.
Wrap response.content in a <div> and then do a selection off of that. This way you have a proper structure to start from rather than an array that you might actually be getting.
var $wrap = $("<div></div>").html(response.content);
$wrap.find("title").text();
An example of what is probably going on: http://jsfiddle.net/UFtJV/
Don't forget one thing : you should never return HTML to client. You should return Json (or even Xml) that your client will transform into Html using Template.
You are doing like a lot of dev doing Bad Ajax.
Don't forget : "only data on wire, not display".
So there should not be any problem coz, on response you just have to take data from Json formatted response and inject it inside your Template.
I'm very, very new to Javascript, and to web programming in general. I think that I'm misunderstanding something fundamental, but I've been unable to figure out what.
I have the following code:
function checkUserAuth(){
var userAuthHttpObject = new XMLHttpRequest();
var url = baseURL + "/userAuth";
userAuthHttpObject.open("POST",url,true);
userAuthHttpObject.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
userAuthHttpObject.onload=function(){
if (userAuthHttpObject.readyState == 4) {
var response = json.loads(userAuthHttpObject.responseText);
return response; //This is the part that doesn't work!
}
};
userAuthHttpObject.send(params);
}
I would love to call it from my page with something like:
var authResponse = checkUserAuth();
And then just do what I want with that data.
Returning a variable, however, just returns it to the userAuthObject, and not all the way back to the function that was originally called.
Is there a way to get the data out of the HttpObject, and into the page that called the function?
Working with AJAX requires wrapping your head around asynchronous behavior, which is different than other types of programming. Rather than returning values directly, you want to set up a callback function.
Create another JavaScript function which accepts the AJAX response as a parameter. This function, let's call it "takeAction(response)", should do whatever it needs to, perhaps print a failure message or set a value in a hidden field and submit a form, whatever.
then where you have "return response" put "takeAction(response)".
So now, takeAction will do whatever it was you would have done after you called "var authResponse = checkUserAuth();"
There are a couple of best practices you should start with before you continue to write the script you asked about
XMLHTTTPRequest() is not browser consistent. I would recommend you use a library such as mootools or the excellent jquery.ajax as a starting point. it easier to implement and works more consistently. http://api.jquery.com/jQuery.ajax/
content type is important. You will have have problems trying to parse json data if you used a form content type. use "application/json" if you want to use json.
true user authorization should be done on the server, never in the browser. I'm not sure how you are using this script, but I suggest you may want to reconsider.
Preliminaries out of the way, Here is one way I would get information from an ajax call into the page with jquery:
$.ajax({
//get an html chunk
url: 'ajax/test.html',
// do something with the html chunk
success: function(htmlData) {
//replace the content of <div id="auth">
$('#auth').html(htmlData);
//replace content of #auth with only the data in #message from
//the data we recieved in our ajax call
$('#auth').html( function() {
return $(htmlData).find('#message').text();
});
}
});
I have an ExtJS based application. When editing an object, an ExtJS window appears with a number of tabs. Three of these tabs have Ext GridPanels, each showing a different type of data. Currently each GridPanel has it's own JsonStore, meaning four total AJAX requests to the server -- one for the javascript to create the window, and one for each of the JsonStores. Is there any way all three JsonStores could read from one AJAX call? I can easily combine all the JSON data, each one currently has a different root property.
Edit: This is Ext 2.2, not Ext 3.
The javascript object created from the JSON response is available in yourStore.reader.jsonData when the store's load event is fired. For example:
yourStore.on('load', function(firstStore) {
var data = firstStore.reader.jsonData;
otherStore.loadData(data);
thirdStore.loadData(data);
}
EDIT:
To clarify, each store would need a separate root property (which you are already doing) so they'd each get the data intended.
{
"firstRoot": [...],
"secondRoot": [...],
"thirdRoot": [...]
}
You could get the JSON directly with an AjaxRequest, and then pass it to the loadData() method of each JSONStore.
You may be able to do this using Ext.Direct, where you can make multiple requests during a single connection.
Maybe HTTP caching can help you out. Combine your json data, make sure your JsonStores are using GET, and watch Firebug to be sure the 2nd and 3rd requests are not going to the server. You may need to set a far-future expires header in that json response, which may be no good if you expect that data to change often.
Another fantastic way is to use Ext.Data.Connection() as shown below :
var conn = new Ext.data.Connection();
conn.request({
url: '/myserver/allInOneAjaxCall',
method: 'POST',
params: {
// if you wish too
},
success: function(responseObj) {
var json = Ext.decode(responseObj.responseText);
yourStore1.loadData(json.dataForStore1);
yourStore2.loadData(json.dataForStore2);
},
failure: function(responseObj) {
var message = Ext.decode(responseObj.responseText).message;
alert(message);
}
});
It worked for me.