I've created a page using JQuery and Ajax that helps a user filter through a series of options and ultimately displays a filtered list of products meeting their specification.
This all works fine.
The problem i'm having is the "Back Button" problem with Ajax, i know how to get around this with anchors on static content (i.e. Filter.php#Step2).
However, the page works by returning a list of product specifications, when a spec link is clicked, Ajax loads the same page again applying the links parameters, this is repeated up to six times, after which, the user is redirected to the filtered product URL.
If the user then clicks "Back", then of course, the filter page reloads from step 1 rather than the last step (step 6).
Does anyone know if this is even possible?
Every time you want to be able to go back to the previous step, change window.location.hash.
Ie.
window.location.hash = 'step1';
This changes the #foo part in the URL. You will also need a timer in JavaScript which checks if the hash was changed, as there is no way to reliably detect hitting the back button. Something along the lines of...
var oldHash = window.location.hash;
setInterval(function(){
if(window.location.hash != oldHash) {
//the hash was changed, do something
}
}, 50);
I hope this helps
I can't say I've implemented this before personally, but I remember the jQuery Tools tab component doing something similar. I'm not sure if it will work for your particular situation, but it may be worth looking at their approach as a starting point.
jQuery Tools AJAX:ed tabs with History support
Related
I have a website that loads its content by the user clicking a button, then the clicks calls a javascript function that updates just the content of a central <div> element by changing its inner html with AJAX and jQuery.
So for example, when the visitor wants to go to my contact page, they click the contact button, and the div's content is updated to the contact form by pulling that content from an external file and using it to replace the div's innerHTML. The actual address of the entire page doesnt change, as the entire page isnt being reloaded, just the innerHTML of the div.
Further to this, my site uses PHP, and I've coded it such that various content can be populated in the div on page load by passing variables in the url. For example, index.php?page=home will tell the PHP script to load the home page content from an external file, while index.php?page=contact will load the contact form. This way search engines can find each page and their content by following these links in my sitemap.
My problem is that if a visitor clicks a button and loads different content into the div, then clicks the reload button of their browser or presses CTRL+R, the entire page reloads and the div of course reverts to its original content.
My question is, is there a way to load a particular page when the browser refreshes? For example, if the visitor has loaded the page index.php?page=home then clicked on the contact button and updated the div content, then pressed the refresh button of their browser, can i somehow write a script that will load index.php?page=contact instead, preserving the look of the page and the content?
Option 1: location.hash
Easier, but not as robust. Worth taking a look at, but if you want to store the states of multiple elements, you probably want option 2.
Here's a demonstration of the code below.
Example:
function onHashChange() {
var hash = window.location.hash;
// Load the appropriate content based on the hash.
}
$(window).on('hashchange', onHashChange);
$(document).on('load', onHashChange);
$('#button').click(function(){
window.location.hash = "home";
});
This way, all you need to do is change the hash on button change and handle the page load using the hashchange event.
Option 2: History API using History.js
A little harder to implement (but not much!), but infinitely more robust. Relies on a widely used framework.
Another, and perhaps a cleaner way of doing this would be to use the History API. It allows you to change window.location without refreshing the page, allowing you to handle those changes using JavaScript.
Not all browsers support the API yet though, but you could use History.js, which provides location.hash fallbacks if needed. Here's a demo.
From History.js's github page:
History.js gracefully supports the HTML5 History/State APIs
(pushState, replaceState, onPopState) in all browsers. Including
continued support for data, titles, replaceState. Supports jQuery,
MooTools and Prototype. For HTML5 browsers this means that you can
modify the URL directly, without needing to use hashes anymore. For
HTML4 browsers it will revert back to using the old onhashchange
functionality.
Example of History.js:
function onStateChange() {
var state = window.History.getState();
// Handle state accordingly.
// Fetch the data passed with pushState.
var data = state.data;
var title = state.title;
var url = state.url;
}
// Check the initial state.
$('document').on('load', onStateChange);
// Listen for state changes.
window.History.Adapter.bind(window, 'statechange', onStateChange);
// Any data you want to be passed with the state change.
var stateObj = { variable : 'value' }
// Change state using pushState()
window.History.pushState(stateObj, "State name", "/page.html");
The state name is ignored by most browsers. The third parameter is the bit that gets added to the URL.
Weeks ago I've released a jQuery plugin for this situations, when the developer wants to add ajax content to a page, and dynamically change the URL.
The plugin is jQuery Dynamic URL https://github.com/promatik/jQuery-Dynamic-URL
There is a demo here: http://promatik.pt/github/dynamic-url/
When you load ajax content, you can push a path to the URL, ex:
$.pushPath( 0 /*level*/, "contact" )
Your site instantly turns to: example.com/contact
Or in your case, you can use:
$.pushVar( "page", "contact" )
Your site instantly turns to: example.com/?page=contact
This plugin also allows you to do this:
Imagine that you give me a link for: example.com/?page=contact
In the index page, $.getVars( ) will return: {"page" : "contact"}
So with this info you can build your page based on the this queries.
There's more thigs you can do with the plugin, like listening to event onPopState (that means user went back or forward in browser, so you can rebuild your pages based on that) just try out the demo...
Important information: This plugin works in all modern browsers except IE9, witch works partially, you still can access url data like example.com/?page=contact (and build your page based on this queries) but not modify dynamically the URL during the user experience.
So I have this site that dynamically posts content using jquery and php. I would like to know how to generate permalinks. I think I could do it, but I dont even know what I should be searching for on google. You can see the site at www.eataustineat.com.
For example, I would like a link like eataustineat.com/claypit to that would go directly to the video review, instead of having to to search for it and then click the link.
I will describe the how the site works on a basic level:
first the user selects the "All Restaurants tab" in the content slider, then jquery slides to the third frame.
Next, a user selects a link from a list. This list is generated by sql queries in php, while javascript pushes the result of the php to a specific div.
When a user selects a link, jquery slides to the second slide. Once again, php runs a query while javascript pushes the content to a specific div. As a result, the user never leaves the index page.
I think it depends on how your website works. The ideal thing that I have in my mind at the moment is:
Decide a unique way to find your video (could be a title, a file name, an id: must not change), if you are using a database it's a column with a value different for each entry
Create a webpage that accept as a parameter (not optional) (possibly a $_GET parameter, not a post) that unique key and fills it's content with entry's data (the video review hopefully)
Now the permalink will be yourwebsite/yourwebpage?myparam=myvalue
Normally the permalink is the numerical id referred to that entry (thinking about databases in this case)
Edit 1: If what you mean is "moving the webpage to the link" (and not creating it), maybe you should ignore my answer, I didn't understand the question so.
What suggested Tadeck, if this is the case, is good
Edit 2: What about if, following the keylines I given you to create a permalink, you pass this value to the homepage and on page load you fire the event through the click() function (so it's like if the user clicks on the link, fires everything that you need, even the scroller thing)
Obviusly you need to give an ID to each tag, but I don't think it's a big problem (just use directly your "permalink value" as an id
The alternative in using click() method, is: give to the slider function a name so you can call it instead of waiting the click event only, expecially this part
$('.cross-link').live("click", function(){
You'll have to replace function() with a named function
then you will call, on page load, that function + ajaxpage('result.php?id=9', 'results2') + ajaxpage('videoloader.php?id=9') completely emulating the click event in this case.
You still need however an id in the a tag to find out which is the link
You should search for one (or both) of the following points:
pushState and onStateChange - preferred, nicest and probably what you are looking for,
location.hash and onhashchange - probably easier to implement (does not require you to support it on server side and works in older browsers too), but in this case you would get URL like http://eataustineat.com/#!claypit instead of http://eataustineat.com/claypit.
In this first case you would need to make sure server side scripting / configuration will invoke proper state within JS, when visited eg. by entering URL (http://eataustineat.com/claypit).
I need to implement a links-click counter, that will count the number of clicks on the link...
Right now what i am doing is, i am linking the href to redir.php, which will increase the counter in DB and then using header('Location:'); I am redirecting it to the correct URL.
This works but it is certainly not the best approach. In an effort to make my code efficient, how can I make this link counter better? AJAX?
Not much exp with ajax so I wondering how to do in ajax or is there any other better method...
I do not want someone to write a bot script that would make multiple requests to the redir.php and mess up the stats.
You can use
Javascript to make a Ajax call to your "counter.php"
Add a Javascript code (like Google Analytic) on each page to post on the database
Create a "cron job" to analyse the "access_log" (if you count the link in the same domain, server)
Add a PHP code to update the database when each page is generate.
But I think the first javascript method is the best one.
Add a class on the link to spy
Add a "Event handler" to create a AJAX post
Create a simple PHP script to update the database.
Aka
If you links are generated from a source like a CMS instead of by hand, you could pass the link ID to your URL and on the loading of the next page count increment that the link has been clicked. Going this way would require that you reload (without the link ID) the page after that step to make sure that someone copying the link would not make the counter increment needlessly.
This method is bulletproof if your user has javascript enabled, but if your user does have javascript enabled, you could still do the method stated above and through a client side layer, bypass the whole thing and send it through AJAX.
This might seems like redundancy, but this way, you accelerate your process for most of your visitors (without the redirect since you do it through AJAX) and in the case that the javascript doesn't work or is disabled, you have a fail proof system that would avoid missing any click
Building off of #Akarun's answer, here is sample code (in jQuery) for adding a "listener" onto link clicks with "spy" class. Note that I load an image instead of attempting a $.post or other AJAX event -- this is because those won't complete by the time the person navigates away from the page (which clicking on a link is bound to do in most cases), whereas the browser will get off a request for the image in time. It's still a normal PHP script, the browser just thinks it's loading an image.
$(document).ready(function() {
$('a.spy').mousedown(function(event) {
var page_url = "<?=$_SERVER['PHP_SELF']?>";
var target_url = $(this).attr('href');
if(target_url != "#" && target_url != "javascript:void(0);")
new Image().src= "/welcome/track_link/?page_url=" + escape(page_url) + "&target_url=" + escape(target_url);
return true;
});
});
Have you thought of mobile users and other devices?
I believe your first implementation is completely adequate and secure.
You completely control the counting and there is no issue of user manipulation.
It works predictably also.
After all, the ajax will just do the samething in counter.php; Read and update the database. Stay with your present implementation.
Do it the way Google does it:
Waterfront Rentals
A javascript function. The passed code aids security.
Actually looking at the Google source they load an image with the URL as a parameter
window.clk=function(e,b,a,k,i,c,j)
{
if(document.images) {
b=encodeURIComponent||escape;a=new Image;var f=window.google.cri++;window.google.crm[f]=a;a.onerror=a.onload=a.onabort=function() {
delete window.google.crm[f]
};
var d,g,h;if(google.v6) {
d=google.v6.src;g=google.v6.complete||google.v6s?2:1;h=(new Date).getTime()-google.v6t;delete google.v6
}if(c&&c.substring(0,6)!="&sig2=")c="&sig2="+c;a.src=["/url?sa=T&source=",google.sn,"&cd=",b(i),google.j&&google.j.pf?"&sqi=2":"","&ved=",b(j),e?"&url="+b(e.replace(/#.*/,
"")).replace(/\+/g,"%2B"):"","&ei=",google.kEI,d?"&v6u="+b(d)+"&v6s="+g+"&v6t="+h:"",c].join("")
}
return true
};
currently I have the a basic jQuery gallery:
<ul>
<li>IMAGE</li>
<li>IMAGE</li>
</ul>
// with NAV stuff
I cycle through the images with animations and everything works great.
However, my client "NEEDS" another setup, whereby there will be a new page per slide. GQ.com is a good example of this. Click the link to check it out.
If you will notice, each time you click 'Previous' or 'Next' a new page is loaded, creating more pageviews for the site.
My Question:
Is it possible to have this with my current setup (b/c it can't change)? Or is it only possible through the server-side programming? How are they doing this?
Take a look at what's actually happening there. The URL for the "next" button looks like this:
Next
But when you click on it, where does it take you? You get here:
http://www.gq.com/style/wear-it-now/201010/best-jean-jackets-denim#slide=2
Notice the difference? It's a hash # instead of a question mark ?. They aren't reloading the entire page, they are making an HTTP request asynchronously in Javascript and using some form of hijax to change the browser's hash value (that which appears after the #...the only part that javascript can change), thereby allow the user to cycle backward and forward with the regular browser controls. The way to do this is to build in methods in your javascript to detect the value of what's after the hash both on page load and after a page's hash value has changed. Then you can have another javascript function actually control changing it when you click the "next" or "previous" buttons, and return false to kill the normal anchor href execution.
The reason this is called "hijax" is because your site still has perfectly-valid hrefs (e.g. you can go to that link above but replace the # with a ? and get to the exact same application state). This allows search engines to crawl your site and users without javascript to effectively use your site, while also providing all the AJAXery that people expect in fully-featured browsers. The trick here is to make sure that what comes after the # can be passed via AJAX to your server, have the server understand that it's an AJAX call, and process a return value that your javascript can understand. The easiest way is to use the extra bit after the # as the URL of your AJAX request and let the server interpret everything properly.
Is it possible to detect when the user clicks on the browser's back button?
I have an Ajax application and if I can detect when the user clicks on the back button I can display the appropriate data back
Any solution using PHP, JavaScript is preferable. Hell a solution in any language is fine, just need something that I can translate to PHP/JavaScript
Edit: Cut and paste from below:
Wow, all excellent answers. I'd like to use Yahoo but I already use Prototype and Scriptaculous libraries and don't want to add more ajax libraries. But it uses iFrames which gives me a good pointer to write my own code.
One of my favorite frameworks for doing this is Yahoo!'s Browser History Manager. You register events and it calls you back when the user returns Back to that state. And if you want to learn how it works, here's a fun blog entry about the decisions Yahoo! made when designing it.
There are multiple ways of doing it, though some will only work in certain browsers. One that I know off the top of my head is to embed a tiny near-invisible iframe on the page. When the user hits the back button the iframe is navigated back which you can detect and then update your page. Here is another solution.
You might also want to go view source on something like gmail and see how they do it.
Here's a library for the sort of thing you're looking for by the way
There's no way to tell when a user clicks the back button of presses the backspace key to go back in the browser, however there are other events that happen in a certain order which are detectable. This example javascript has a reasonably good method for detecting back commands:
The traditional way, however, is to track user movement through your site using cookies or referrer pages. When the user goes to page A, then page B, then appears at page A again (especially when there's no link on B to A) then you know they went back - A can detect this and redirect them or otherwise.
The Yahoo User Interface Library, my personal favorite client-side JS library, has an excellent Browser History Manager that does exactly what you're asking for.
The simplest way to check if you came back to a cached version of your page, which needs to be refreshed, is to add a hidden input element that will be cached, and you can check if it still has its default value.
Just place the following inside your body tag. I place mine right before the end tag.
<input type="hidden" id="needs-refresh" value="no">
<script>
onload=function(){
var e = document.getElementById("needs-refresh");
if (e.value === "yes")
location.reload();
e.value = "yes";
}
</script>
I set a variable $wasPosted in $_SESSION with value false.
All my posts go via the same php file, and set $wasPosted to true.
All header(location:) requests are preceded by setting $wasPosted to true.
If $wasPosted is false then the page was loaded after use of the backward or forward buttons.
The dojo toolkit has functionality to deal with this in javascript. I don't think there is any good way to handle it in pure PHP.
Here is the docs page they have: http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/back-button-undo