run javascript function by url hash - javascript

I have a website which has all pages contents in one page called "pagecontents". When a menu in navbar is clicked the jQuery load function is triggered and the relevant content is loaded into the main page.
It's working fine, however I added an hash to the URL for whenever a particular content is loaded , so that users can go directly into viewing relevant content when they type or paste the url with the hash. This works fine in my local host but not on remote host I wonder What's the problem.
if(location.hash == '#web') {
$('#contentFetch').load('pagecontents.php #webC');
}if(location.hash == '#graphic') {
$('#contentFetch').load('pagecontents.php #graphicC');
}if(location.hash == '#mobile') {
//$('#testLocation').text("mobile Works");
$('#contentFetch').load('pagecontents.php #mobileC');
}if(location.hash == '#contact') {
$('#contentFetch').load('pagecontents.php #contactC');
}else{
$('#contentFetch').load('pagecontents.php #indexC');
}
Edit: About the hash in query string:
the website url ex: 'www.mywebsite.com/'. when i add the '#graphic' at the end: 'www.mywebsite.com/#graphic' it's not loading the content. I noticed that if keep on pressing enter even though is not loading, it then loads!!!? it seems very incosistent as it loads 1 time out of 5. I wonder if using this is reliable in real world, or is there another way of doing it? Thanks, Mike

Make sure to check the runtime versions that your host is using and that they comply with the ones you have locally.
Usually, a host will run a version of a software that is often outdated in order to accommodate older websites. (ex. running PHP 4 instead of PHP 5).

Related

bookmarklet that works on 2 pages

I'm using a bookmarklet to inject javascript into a webpage. I am trying to login into my gmail account(that part works) and in my gmail account automatically click Sent folder as the page loads. This is the starting page:
This is the code I am using in bookmarklet:
javascript:
document.getElementById('Email').value='myEmail#gmail.com';
document.getElementById('next').click();
setTimeout(function(){
document.getElementById('Passwd').value='myPassword';
document.getElementById('signIn').click();},1000);
setTimeout(function(){
document.getElementsByClassName("J-Ke n0 aBU")[0].click();
},6000);
J-Ke n0 aBU is the class of Sent folder. This code logins into my account, but it doesn't click Sent folder.
I noticed similar behavior on other websites; whenever a new page loads or refreshes, the bookmarklet stops working.
Why is that and what is the correct way of using the same bookmarklet on different page than it was originally clicked.
Disclaimer: I don't have gmail, so I didn't test this for gmail specifically.
This answer exists to address your comment:
What about iframes. Is theoretically possible to use gmail login in an iframe and therefore when the iframe changes to another page this doesnt have effect on the bookmarklet?
Yes, it is technically possible to have a persistent bookmarklet using iframes (or, deity forbid, a frameset).
As long as your parent window (and it's containing iframe) remain on the same domain, it should work according to cross-domain spec.
It is however possible (depending on used method) to (un-)intentionally 'counter-act' this (which, depending on used counter-action, can still be circumvented, etc..).
Navigate to website, then execute bookmarklet which:
Creates iframe.
Sets onload-handler to iframe.
Replaces current web-page content with iframe (to window's full width and height).
Set iframe's source to current url (reloading the currently open page in your injected iframe).
Then the iframe's onload-handler's job is to detect (using url/title/page-content) what page is loaded and which (if any) actions should be taken.
Example (minify (strip comments and unneeded whitespace) using Dean Edward's Packer v3):
javascript:(function(P){
var D=document
, B=D.createElement('body')
, F=D.createElement('iframe')
; //end vars
F.onload=function(){
var w=this.contentWindow //frame window
, d=w.document //frame window document
; //end vars
//BONUS: update address-bar and title.
//Use location.href instead of document.URL to include hash in FF, see https://stackoverflow.com/questions/1034621/get-current-url-in-web-browser
history.replaceState({}, D.title=d.title, w.location.href );
P(w, d); //execute handler
};
D.body.parentNode.replaceChild(B, D.body); //replace body with empty body
B.parentNode.style.cssText= B.style.cssText= (
F.style.cssText= 'width:100%;height:100%;margin:0;padding:0;border:0;'
) + 'overflow:hidden;' ; //set styles for html, body and iframe
//B.appendChild(F).src=D.URL; //doesn't work in FF if parent url === iframe url
//B.appendChild(F).setAttribute('src', D.URL); //doesn't work in FF if parent url === iframe url
B.appendChild(F).contentWindow.location.replace(D.URL); //works in FF
}(function(W, D){ //payload function. W=frame window, D=frame window document
alert('loaded');
// perform tests on D.title, W.location.href, page content, etc.
// and perform tasks accordingly
}));
Note: one of the obvious methods to minify further is to utilize bracket-access with string-variables for things like createElement, contentWindow, etc.
Here is an example function-body for the payload-function (from above bookmarklet) to be used on http://www.w3schools.com (sorry, I couldn't quickly think of another target):
var tmp;
if(D.title==='W3Schools Online Web Tutorials'){
//scroll colorpicker into view and click it after 1 sec
tmp=D.getElementById('main').getElementsByTagName('img')[0].parentNode;
tmp.focus();
tmp.scrollIntoView();
W.setTimeout(function(){tmp.click()},1000);
return;
}
if(D.title==='HTML Color Picker'){
//type color in input and click update color button 'ok'
tmp=D.getElementById('entercolorDIV');
tmp.scrollIntoView();
tmp.querySelector('input').value='yellow';
tmp.querySelector('button').click();
//click 5 colors with 3 sec interval
tmp=D.getElementsByTagName('area');
tmp[0].parentNode.parentNode.scrollIntoView();
W.setTimeout(function(){tmp[120].click()},3000);
W.setTimeout(function(){tmp[48].click()},6000);
W.setTimeout(function(){tmp[92].click()},9000);
W.setTimeout(function(){tmp[31].click()},12000);
W.setTimeout(function(){tmp[126].click()},15000);
return;
}
above example (inside bookmarklet) minified:
javascript:(function(P){var D=document,B=D.createElement('body'),F=D.createElement('iframe');F.onload=function(){var w=this.contentWindow,d=w.document;history.replaceState({},D.title=d.title,w.location.href);P(w,d)};D.body.parentNode.replaceChild(B,D.body);B.parentNode.style.cssText=B.style.cssText=(F.style.cssText='width:100%;height:100%;margin:0;padding:0;border:0;')+'overflow:hidden;';B.appendChild(F).contentWindow.location.replace(D.URL)}(function(W,D){var tmp;if(D.title==='W3Schools Online Web Tutorials'){tmp=D.getElementById('main').getElementsByTagName('img')[0].parentNode;tmp.focus();tmp.scrollIntoView();W.setTimeout(function(){tmp.click()},1000);return}if(D.title==='HTML Color Picker'){tmp=D.getElementById('entercolorDIV');tmp.scrollIntoView();tmp.querySelector('input').value='yellow';tmp.querySelector('button').click();tmp=D.getElementsByTagName('area');tmp[0].parentNode.parentNode.scrollIntoView();W.setTimeout(function(){tmp[120].click()},3000);W.setTimeout(function(){tmp[48].click()},6000);W.setTimeout(function(){tmp[92].click()},9000);W.setTimeout(function(){tmp[31].click()},12000);W.setTimeout(function(){tmp[126].click()},15000);return}}));
Hope this helps (you get started)!
As JavaScript is executed in the context of the current page only, it's not possible to execute JavaScript which spans over more than one page. So whenever a second page is loaded, execution of the JavaScript of the first page get's halted.
If it would be possible to execute JavaScript on two pages, an attacker could send you to another page, read your personal information there and send it to another server in his control with AJAX (e.g. your mails).
A solution for your issue would be to use Selenium IDE for Firefox (direct link to the extension). Originally designed for automated testing, it can also be used to automate your browser.

Auto-download behavior and back button issue

Instead of linking directly to files for download on a web site we link to a page that says "thank you for downloading". The page has tracking codes on it so we know how many people have downloaded the file. The page launches the download file using the jQuery code shown which adds a short delay after the page loads before the download begins. The download location has a content disposition header so it always downloads properly in the browser leaving the "thank you for downloading" page visible. This all works well.
The problem comes if the user carries on browsing past this page and then hits back. The download fires again.
Using window.location.replace(href); didn't seem to fix it.
The issue is further complicated by the fact that the CMS delivering the page has set it to expire immediately so it's not being cached.
Suggestions for (i) ways to avoid this problem; (ii) any better ways to handle file download / thank you pages?
jQuery Code
$(document).ready(function () {
$('a.autoDownload').each(function () {
setTimeout('navigateToDownload("' + $(this).attr('href') + '")', 4000);
});
});
function navigateToDownload(href) {
document.location.href = href;
}
One possible approach would be to set a cookie via Javascript when the page first loads. Then, if that page is ever loaded again, you can check for the presence of the cookie, and if present, do not execute the auto download?
Using the Cookie plugin for jQuery as an example:
$(document).ready(function () {
$('a.autoDownload').each(function () {
var hasDownloadedThisLink = $.cookie("site." + $(this).attr('id'));
if (!hasDownloadedThisLink) {
$.cookie("site." + $(this).attr('id'), "true");
setTimeout('navigateToDownload("' + $(this).attr('href') + '")', 4000);
}
});
});
This is just an example. If you went this way, you'd have to consider how many possible download links there might be, as there is a limit on how many cookies you can set. Also notice that I used an id attribute of the links to identify them in the cookie - I figured this would be more suitable that using some form the href attribute. I also prefixed the cookie name with site..
Well there are a couple of solutions to this. Here's an example:
function navigateToDownload(href){
var e = document.createElement("iframe");
e.src=href;
e.style.display='none';
document.body.appendChild(e);
}
Other implemenatations might exist, but I doubt they're less "hacky".

Ajax to make browser Load

1- OPEN FIREBUG, on the console tab
2- OPEN YOUR GMAIL ACCOUNT,
3- when gmail is loaded, click on one of your label (at the left under the draft box)
4- WITH FIREBUG YOU SEE THAT THE PAGE DOES NOT COMLETLY RELAOD SINCE ALL PREVIOUS ACTION STILL THERE FOR THE CURRENT DOCUMENT, BUT THE BROWSER COMPLETLY ACT LIKE THE PAGE HAVE BEEN RELOADED, stop button browser own loading effect, etc...)
5- !!!!! this is it..!!!!
Does some on have a clue on how site like Gmail can make the browser load on ajax call ( I mean show the loading icon and all, history, etc)
I already know what to check for the history navigation but how in the world they can make the browser to act like this was a simple link that load a complete new page.
from what I see with things like firebug Gmail basically retrieve mail information in JSON and than use some Javascript to render it to the user. But how they make the browser load in the while.
In gmail once it is loaded, obviously they ain't load all the data, from all your folder in background, so when you click on some of your folder and the data is not already loaded they make the browser 'load' like if it were loading a complete new page, while they retrieve the information from their server with some ajax call ( in Firefox you see the browser act like when you click on a normal link, loading icon, stop (x) button activated, and all).
Is it clear?
I came up with some 'ugly' code to achieve my goal that work quite nice in FireFox and IE (sadly it seems to not work in Chrome/WebKit and Opera).
I tell the browser to go to a url that it will not be able to reach before the ajax call end, with window.location=. The browser start to load and than when the ajax call sucess I call window.stop() (window.document.execCommand('Stop') for IE) than innerHTML the ajax data in the document
To me its look ugly and since it not work properly in Chrome/Webkit, this is apparently not the way to go.
There are many ways to utilize AJAX.
Gmail needs to load a lot of files/data before something meaningful can be displayed for the users.
E.g. showing the folder tree first doesn't make sense if it's not clickable or not ready for any interactive use.
Hence, what they do is show something lightweight like a loading graphic/progress bar while asynchronously (behind the scene), pull more data from the server until they can populate the page with a full interface for usage.
I don't know how to explain further. Maybe wiki can help: http://en.wikipedia.org/wiki/Ajax_%28programming%29
http://www.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/
Use one of the methods shown as triggering a browser busy state in the table on the page above.
document.getElementById('iframe').src = "http://www.exemple.com/browser_load.html";
They are using iFrame. By changing the source of the iFrame.
Sitepoint has a book "Build Your Own AJAX Applications" and they show some content (all?) in this tutorial:
http://articles.sitepoint.com/article/build-your-own-ajax-web-apps
They will guide you with your AJAX coding.
Think this is your answer:
http://www.obviously.com/tech_tips/slow_load_technique
Looks like gmail and facebook method (browser is showing page as "loading" with loading icons etc. - it is just simulating, because there is a background ajax request) :)
$(function($){
$('a').attr('onclick','return false;').click(function(){
var title = $(this).attr('title');
var href = $(this).attr('href');
$('title').html(title);
$('#content').load(href+' #content', function(){
history.pushState(null, null, href);
}, function(responseText) {
var title = responseText.match(/<title>([^<]*)/)[1];
document.title = title;
});
});
});
window.onpopstate = function( e ) {
var returnLocation = history.location || document.location;
var returnTitle = history.propertyName || document.title;
$('title').html(returnLocation.title)
$('#content').load(returnLocation.href+ ' #content', function(){
history.pushState(null, null, href);
}, function(responseText) {
var title = responseText.match(/<title>([^<]*)/)[1];
document.title = title;
});
}

Using JavaScript to change the URL used when a page is bookmarked

JavaScript doesn't allow you to update window.location without triggering a reload. While I agree with this policy in principle (it shouldn't be possible to visit my website and have JavaScript change the location bar to read www.yourbankingsite.com,) I believe that it should be possible to change www.foo.org/index to www.foo.org/help.
The only reason I care about this is for bookmarking. I'm working on a photo browser, and when a user is previewing a particular image, I want that image to be the default if they should bookmark that page. For example, if they are viewing foo.org/preview/images0-30 and they click on image #15, that image is expanded to a medium-sized view. If they then bookmark the page, I want the bookmark URL to be foo.org/preview/images0-30/active15.
Any thoughts, or is there a security barrier on this one as well? I can certainly understand the same policy being applied here, but one can dream.
Sounds like you should check out Really Simple History. It's how Google (for example, Gmail) allows any page to be bookmarkable (and has history) but doesn't refresh the whole page.
As for the other side of things (having people visit your site then automatically popping up the correct image), I'd try checking window.location.hash once the page loads and firing events based on that.
You can add an anchor to the URL without reloading the page and pick that up with javascript:
location.href = '.../#' + imageId;
As mentioned, generally with ajaxy sites, you manipulate/check the hash part of the URL (window.location.hash) to determine this kind of activity.
The biggest issue is making sure to check against the hash in DOM-ready/window-load, as if the user clicked on a given image. This will work with browsers and bookmarks, but may hamper search indexing.
How about detecting on page load if the URL contains a hash, and if it does, directing them to the page you want them to go to?
You can add [Add to Favorites] button on the page.
Sample:
var urlAddress = "http://www.example.com/#image1";
var pageName = "Example Page Title - Image1";
function addToFavorites() {
if (window.external) {
window.external.AddFavorite(urlAddress, pageName);
} else {
alert("Sorry! Your browser doesn't support this function.");
}
}
Or use one of these jQuery plugins:
http://plugins.jquery.com/project/bookmark
http://plugins.jquery.com/project/jqbookmark
http://plugins.jquery.com/project/AddFavourite
http://plugins.jquery.com/project/jFav
http://plugins.jquery.com/project/jBookmarkEngine
AND / OR
Use URLs with hash at the end and load your content (images etc.) based on that hash value.
function onLoad() {
if (window.location.hash == "image1") {
// load image1
}
}
There are also lots for jQuery plugins for working with URL hash events, for example:
http://plugins.jquery.com/project/hashhistory
http://plugins.jquery.com/project/hashchange
There are also lots of non jQuery JavaScript libraries for that, for example:
http://code.google.com/p/reallysimplehistory/
<html>
<head>
<script type="text/javascript">
function myHref(){
document.getElementById('myAnchor').innerHTML="Visit Google"
document.getElementById('myAnchor').href="http://www.google.com"
}
</script>
</head>
<body>
<a id="myAnchor" href="http://www.java2s.com">Visit Java2s</a>
<form>
<input type="button" onclick="myHref()" value="Change URL and text">
</form>
</body>
</html>

Remove fragment in URL with JavaScript w/out causing page reload

Background: I have an HTML page which lets you expand certain content. As only small portions of the page need to be loaded for such an expansion, it's done via JavaScript, and not by directing to a new URL/ HTML page. However, as a bonus the user is able to permalink to such expanded sections, i.e. send someone else a URL like
http://example.com/#foobar
and have the "foobar" category be opened immediately for that other user. This works using parent.location.hash = 'foobar', so that part is fine.
Now the question: When the user closes such a category on the page, I want to empty the URL fragment again, i.e. turn http://example.com/#foobar into http://example.com/ to update the permalink display. However, doing so using parent.location.hash = '' causes a reload of the whole page (in Firefox 3, for instance), which I'd like to avoid. Using window.location.href = '/#' won't trigger a page reload, but leaves the somewhat unpretty-looking "#" sign in the URL. So is there a way in popular browsers to JavaScript-remove a URL anchor including the "#" sign without triggering a page refresh?
As others have mentioned, replaceState in HTML5 can be used to remove the URL fragment.
Here is an example:
// remove fragment as much as it can go without adding an entry in browser history:
window.location.replace("#");
// slice off the remaining '#' in HTML5:
if (typeof window.history.replaceState == 'function') {
history.replaceState({}, '', window.location.href.slice(0, -1));
}
Since you are controlling the action on the hash value, why not just use a token that means "nothing", like "#_" or "#default".
You could use the shiny new HTML5 window.history.pushState and replaceState methods, as described in ASCIIcasts 246: AJAX History State and on the GitHub blog. This lets you change the entire path (within the same origin host) not just the fragment. To try out this feature, browse around a GitHub repository with a recent browser.
Put this code on head section.
<script type="text/javascript">
var uri = window.location.toString();
if (uri.indexOf("?") > 0) {
var clean_uri = uri.substring(0, uri.indexOf("?"));
window.history.replaceState({}, document.title, clean_uri);
}
</script>
There is also another option instead of using hash,
you could use javascript: void(0);
Example: Open Div
I guess it also depends on when you need that kind of link, so you better check the following links:
How to use it: http://www.brightcherry.co.uk/scribbles/2010/04/25/javascript-how-to-remove-the-trailing-hash-in-a-url/
or check debate on what is better here: Which "href" value should I use for JavaScript links, "#" or "javascript:void(0)"?
$(document).ready(function() {
$(".lnk").click(function(e) {
e.preventDefault();
$(this).attr("href", "stripped_url_via_desired_regex");
});
});
So use
parent.location.hash = '' first
then do
window.location.href=window.location.href.slice(0, -1);
As others have said, you can't do it. Plus... seriously, as the jQuery Ajaxy author - I've deployed complete ajax websites for years now - and I can guarantee no end user has ever complained or perhaps ever even noticed that there is this hash thing going on, user's don't care as long as it works and their getting what they came for.
A proper solution though is HTML5 PushState/ReplaceState/PopState ;-) Which doesn't need the fragement-identifier anymore:
https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history
For a HTML5 and HTML4 compatible project that supports this HTML5 State Functionality check out https://github.com/browserstate/History.js :-)

Categories