I am using the following plug in for cookies in jQuery:
https://code.google.com/p/cookies/
The issue i am having is not with the plugin but when and how to delete the cookie at the end of a quoting process.
The site i am using this on is a six step online quote and buy process.
There is Omniture event serialisation sitestat tracking applied to some of the pages. This event serialisation has to include the name of the event and a random number of which i create.
I have a generic function for this which i call at the bottom of the page like so:
serialEvent('event21:', 'payment');
Here is the function:
function serialEvent(eventNumber, eventName) {
var sessionID = jaaulde.utils.cookies.get('sessionID');
var remLength = 20 - eventName.length;
var remSession = sessionID.substr(sessionID.length - remLength, remLength);
var eventName = eventName + remSession;
s.events = eventNumber + eventName;
}
I need to delete the cookie at the end of the process, the Thank you page but i also need the cookie 'sessionID' for the 'serialEvent' function.
As the function is called at the bottom of the page should i just write the cookie delete after it? Is that robust enough?
I need to be sure that the function has successfully been called before the cookie is deleted.
The code for deleting the cookie is quite simple:
jaaulde.utils.cookies.del('sessionID');
Thanks :)
There's no asynchronous or timer-delayed callback functions called in serialEvent function so you can either
Put it at the end of the function before the closing bracket,
or
Put it after serialEvent('event21:', 'payment');.
Javascript executes synchronously, so you can be sure that the cookie is only deleted when you are finished with it.
you can delete the cookie at the end of the process as well as in window.onUnload event to make sure that the cookie is cleared even if you are closing the window before the process completes.
function serialEvent(eventNumber, eventName)
{
var ok = false;
try
{
var sessionID = jaaulde.utils.cookies.get('sessionID');
var remLength = 20 - eventName.length;
var remSession = sessionID.substr(sessionID.length - remLength, remLength);
var eventName = eventName + remSession;
s.events = eventNumber + eventName;
ok = true;
}
catch(e)
{
// todo: error handling (what has gone wrong?)
ok = false;
}
return ok;
}
This way you can find out if the function is called correctly. ok will only be true if the whole function is executed correctly.
Related
My objective - and I want to do this w/out jQuery:
retrieve data from a json file (ajax GET)
use data therein to generate a list of links
when one of these links is clicked, get the value of its id (or perhaps another attribute), use it to load corresponding data (from the same json file, also via ajax GET)
Having rewritten this code to employ a callback, I'm getting the json data & creating links. However, I'm confused about two things regarding how the addEventListener works: first, why is the showProj function invoked as the event listeners are added in the for loop (so far, only alerting each link's id)? And second, why do the links not respond to clicks afterwards? I thought adding event listeners merely enables the generated links to be clickable?
function ajaxReq() {
var request = new XMLHttpRequest();
return request;
}
function getJsonData(makeLinks) { // makeLinks = the callback
var request = ajaxReq();
request.open("GET", "/json/projects.json", true);
request.setRequestHeader("content-type", "application/json");
request.send(null);
request.onreadystatechange = function() {
if (request.readyState === 4) {
if (request.status === 200) {
makeLinks(request.responseText);
}
}
} // onreadystatechange
} // getJsonData
getJsonData(makeLinks);
function makeLinks(result) { // result = request.responseText
var projects = JSON.parse(result);
var projects = projects["Projects"];
var projectList = document.getElementById("project-list"); // ul#project-list
for (var project in projects) {
var projectId = projects[project].id;
var listItem = "<li><a class=\"project-link\" id=\""+projects[project].project+"\" href=\"#\">" + projects[project].project + "</a></li>";
projectList.innerHTML += listItem;
}
var projLink = document.getElementsByClassName("project-link");
for (var i = 0; i < projLink.length; i++) {
var projId = projLink[i].id;
projLink[i].addEventListener("click", showProject(projId), false); // ** ?? **
}
} // makeLinks
function showProject(projId) {
/*
function showProject will load data corresponding to the link's id (or another attribute);
presently there are only alerts until the links are working
*/
alert("projId is: " + projId);
} // showProject
Again, what I'm ultimately after is simply to click on a .project-link class link, get its id (or some other attribute) and then load corresponding data, e.g. (pseudo-code):
projLink.onclick = function(){
var projId = this.id;
showProject(projId);
}
... and I realize I could do it with this:
$(document).ready(function() {
$("#project-list").on("click", 'li a', function() {
var projId = this.id;
showProject(projId);
})
})
... but I want to know why the event listeners aren't working in the first place (that is, without the jQuery bit).
And lastly: would it be considered evil bad practice in this scenario to preclude a scope issue by defining var projLink globally, so that I don't have to redefine it e.g., inside showProj?
Many thanks in advance for any corrections, suggestions, insights.
svs
You're correct that var projLink is scoped to the makeLinks() function, but more importantly it's also inside the Ajax callback, which is a separate asynchronous scope.
While that Ajax code is running asynchronously, the rest of your JS continues to run as well.
So if you call another function to also getElementsByClassName("project-link"), most likely there aren't any yet because the Ajax callback hasn't finished doing its thing.
Possible options include:
Put everything in the Ajax request.onreadystatechange() within makeLinks() (not ideal)
Adjust the code to use a separate callback function, and pass your JSON data to it. You may have to mess w/timeouts & checks to ensure the data is defined & complete before you try to act on it.
Take a look at this previous question about Ajax response.
Having read up a little further on event listeners, I have discovered the answer to my initial two questions and solved my current issue so if it's of interest to anyone:
projLink[i].addEventListener("click", showProject(projId), false);
The 'showProj' function is invoked in the above statement because i) it's (also) a callback, and - if I understand correctly - ii) because an argument is provided; therefore it's invoked as each of the elements in the for loop has the click event added. Evidently if no argument is provided to the addEventListener callback, then the callback function will indeed be invoked on click. [ more insight on this would be welcome ]
Furthermore, I learn that the third argument (boolean) pertains to capture & bubbling, however I shall not presently sidetrack myself on the finer points of capture & bubbling. Suffice to say that in my case, I'm fairly certain I can achieve my needs thusly:
projLink[i].addEventListener("click", showProject, false);
... (and perhaps even without the optional boolean altogether, though my understanding is that it's better practice to include it (?)
svs, over & out.
i am trying to figure out how to pass an element id to a popup window that executes only php code. when the link is clicked, it grabs the link id, the opens the popup, how do i get the id to be passed?
JS:
$(document).on('click', '.char_inventory', function (e) {
c = true;
var id = e.currentTarget.id;
//alert(id);
if (id == "close_inventory") {
$("#console").html("<div id=\"placeholder\"></div>");
c = false;
} else {
/* $.post('input_commands/inventory_show.php',{id:id}, function(data) {
text=data;
elem = $("#console");
//delay=100;
elem.html(text);
}); */
function popUp(target, id) {
//var id = parent.document.getElementById('id').value;
popWin = window.open(target, "windowName", "width=400,height=250,status=yes");
}
popUp("input_commands/inventory_show.php", id);
}
load();
//setTimeout(function(){c=false;},4000);
});
you mean like:
function popUp(target, id) {
window.some_id = id;
window.open(target, "windowName", "width=400,height=250,status=yes");
}
and in child window:
//get some_id
var id = window.opener.some_id;
if you want to access the element with id from child window, do:
var id = window.opener.some_id;
var clickedElement = window.opener.$("#" +id)
Edit the line popUp("input_commands/inventory_show.php", id); to popUp("input_commands/inventory_show.php?id="+id); and on the page inventory_show.php you can use $_REQUEST['id'] or $_GET['id'] to get the value.
if you want to pass more parameters you can do :
popUp("input_commands/inventory_show.php?id="+id+"¶m1="+param1_value+"¶m2="+param2_value);
It's a very good educational issue: you will understand that the "narrative" or the "story" of the program execution breaks when you pass anyting to the server (PHP in this case).
Interpret the situation as two separate action:
User selects an item, the data is fowarded to server side for further processing.
When the server completes a processing, it sends the data to the client for displaying it.
In JavaScript, there is no single-line of program execution. There are listeners, and when an event occurs, like user action or timeout or arrival of an AJAX response, the appropiate handler executes and processes it (and may do things which will be generate further events in the future, e.g. set up a timer or initiate AJAX).
When you initiate something, which will cause event in the future, it's your responsibility that the event should contain all the information for the handler. Most of cases there is a simple way to do it: you can set up separate handler for each event, other cases you should use a mechanism to put ID or "target address" into the event, which the handler can recognise.
I am trying to use $.post to send form data to a server side script to be saved if the user tries to leave the page without submitting the form. I am using the same function attached to a save button and on setInterval set to every 2 minutes, and it works fine. But when I attach the function to document.onbeforeunload it does not work. In firebug, I see the request is being sent, but it looks like it is being stopped before a status code is returned and the page continues to unload. I am still pretty new to Javascript and Jquery and I am not sure if maybe $.post is one of those functions that might not work on the onbeforeunload event. If that is true, is there another way I can send the data if the user tries to leave the page without saving?
This is the function I am calling from the onbeforeunload event:
function ajaxSubmit(){
var blogtitle = $("#title").val();
var publishedstate = 0;
var blogid = $("#blogID").val();
var blogbody = CKEDITOR.instances['body'].getData();
var postdata = {ajaxSubmit:true,title:blogtitle,body:blogbody,published:publishedstate,blog_id:blogid};
$.post('ajaxblog.php',postdata,function(data){
$("#autosaveMessage").html(data);
$("#autosaveMessage").show();
setTimeout(function(){$("#autosaveMessage").hide();},5000);
});
}
and this is how I am calling the function:
var post_clicked = false;
$("#postButton").click(function(){
post_clicked = true;
});
function leaveEditor(){
if(post_clicked==false){
ajaxSubmit();
}
else{
//Do Nothing
}
}
window.onbeforeunload = leaveEditor;
No, and this is by design. It would be remarkably troublesome if a page could use onbeforeunload to indefinitely delay browsing away, persist its presence somehow, etc. One of the most important abilities for a user of a web browser to have is the ability to leave.
Just use the stringy return value—the whole point of it is to remind the user that s/he made changes that will be lost. Like on SO :)
I call
window.location.reload(false)
in a javascript method to update the page. I have additional javascript calls after this call. Is there a way to know when window.location.reload(false) has completed running before calling the additional javascript calls?
You simply have to provide a function to onload : a reload isn't different from a load.
window.onload = function() { // ...
Your line of code window.location.reload(false) causes the browser to reload the current page - no script after this statement will be executed ....
You could set a cookie on first load - then on subsequent loads check for the existence of the cookie and perform an action ... pseudo code :
onload = check cookie
if cookie is present
run function
else
set cookie
reload
You could check the time on the cookie and choose to execute the function after a period of time (1 hour for example) has passed ....
I use the hashtag to set variables that tells me if the page is reloaded or not. You could do something like this:
// Get the hash of the page
var hashstring = window.location.hash.substring(1);
var found = false;
// Do a hash exist?
if (hashstring.length > 0)
{
// Split the hash by '&'-sign (in case you have more variables in the hash, as I have)
var a = hashstring.split("&");
// Loop through the values
for (i = 0; i < a.length; i++)
{
// Split the string by '=' (key=value format)
var b = a[i].split("=");
// If the key is 'reloaded' (which tells us if the page is reloaded)
if(b[0] == 'reloaded')
{
found = true;
}
}
}
if(!found)
{
location.hash = 'reloaded=true';
window.location.reload();
}
// Do other stuff, this will only be executed if the page has been reloaded
I've put the code that finds a variable in the hash in a seperate function in my project, but fot simplicity I just added it here above. This makes it possible to determine if the page has been reloaded, and run code only if it has.
hi this all started when i ran a function (lets call it loadround) that altered the innerHTML of an iframe. now once loadframe was loaded there were links in the iframe that once clicked would change the iframe page. the only problem is when i click the back button the loadround page was gone. i've thought about this numerous times to no avail. so i tried this code.
loadround
then
function loadround(a,b){
window.location.hash = "#loadround('"+a+"','"+b+"')";
var code = "<(h2)>"+a+"</(h2)><(h2)>"+b+"</(h2)>"
var iFrame = document.getElementById('iframe');
var iFrameBody;
iFrameBody = iFrame.contentDocument.getElementsByTagName('body')[0]
iFrameBody.innerHTML = code;
}
(the brackets in the h2 are intentional)
then i would try to reload the function by possibly an onload function but for now i was testing with a simple href as followed.
function check(){
var func = location.hash.replace(/#/, '')
void(func);
}
check
unfortunately the check code doesn't work and im almost certain there is an easier way of doing this. i tried changing the src of the iframe instead of the innerhtml and there was the same problem. thanks in advance
The modern browsers are starting to support the event window.onhashchange
In the meantime you can use the workaround proposed by Lekensteyn or maybe you can find something useful here: JavaScript/jQuery - onhashchange event workaround
You are misunderstanding the function void, which just make sure the return value is undefined. That prevents the browser from navigating away when you put it in a link. You can test that yourself by pasting the next addresses in your browser:
javascript:1 // note: return value 1, browser will print "1" on screen
javascript:void(1) // note: undefined return value, browser won't navigate away
It's strongly discouraged to execute the hash part as Javascript, as it's vulnerable to XSS without proper validating it. You should watch the hash part, and on modification, do something.
An example; watch every 50 milliseconds for modifications in the hash part, and insert in a element with ID targetElement an heading with the hash part. If the hash part is not valid, replace the current entry with home.
var oldHash = '';
function watchHash(){
// strip the first character (#) from location.hash
var newHash = location.hash.substr(1);
if (oldHash != newHash) {
// assume that the parameter are alphanumeric characters or digits
var validated = newHash.match(/^(\w+)$/);
// make sure the hash is valid
if (validated) {
// usually, you would do a HTTP request and use the parameter
var code = "<h1>" + validated[1] + "</h1>";
var element = document.getElementById("targetElement");
element.innerHTML = code;
} else {
// invalid hash, redirect to #home, without creating a new history entry
location.replace("#home");
}
// and set the new state
oldHash = newHash;
}
}
// periodically (every 50 ms) watch for modification in the hash part
setInterval(watchHash, 50);
HTML code:
Home
About Me
Contact
<div id="targetElement">
<!-- HTML will be inserted here -->
</div>