How to prevent jQuery from changing href attriute on click? - javascript

I have a collection of anchor tags, which look like so:
<a href='#123'></a>
I use the #123 as an id, which I supply to an AJAX call. I make the call on click of a link. After a link is clicked, besides the displaying of the results of the AJAX call, two things happen:
the url in the address bar gets the hash like so: www.localhost.com/foo#123.
The href attribute of the clicked link gets changed from #123 to the AJAX address www.localhost.com/bar#123. If I don't make an AJAX call (for test purposes), then it changes to the current url in the address bar: www.localhost.com/foo#123.
If I use event.preventDefault, than both of these things don't happen. I want to keep 1. (changing of the hash value in the address bar), but I don't won't to keep the value of the href, as otherwise, a subsequent click on the same link results in an error.
How can I do this?
My code
I will include a simplified version of my code, which still produces the same effect.
makeAjaxCall = (brandId) ->
alert 'OK'
$ ->
$('.box-trigger').on 'click', (e) ->
makeAjaxCall($(this).attr('href'))
This code gets loaded on page www.localhost.com/foo. If I click on the link, than I gen an alert with 'OK', the address changes to www.localhost.com/foo#123 and the href of the link also changes to www.localhost.com/foo#123.
Clarification regarding foo and bar
In the makeAjaxCall function, if I really make an ajax call to the url www.localhost.com/bar, then the href changes to www.localhost.com/bar#123. However, I removed the Ajax call to try to debug the problem. In that case the href changes to the current url, in this case www.localhost.com/foo#123.
Solution
I ended up using event.prevenDefault + manually appending the hash to the address bar url like so:
$ ->
$('.lightbox-trigger').on 'click', (e) ->
e.preventDefault()
makeAjaxCall $(this).attr('href')
window.location.hash = $(this).attr('href')

Solution suggestion 1
I would use the data parameter, as suggested by Optimus in the comments. Like this:
HTML
<a class="box-trigger" data-id="#123"></a>
Note: I don't have the href parameter at all, this is because we don't want the URL to be affected at all, right? It's an AJAX call after all. (This will, however make most browsers not recognise the <a> tag as a link. It will lose its "link styling" as it where. You can easily simulate this by simply styling it using CSS.)
CoffeeScript
makeAjaxCall = (brandId) ->
alert 'OK'
$ ->
$('.box-trigger').on 'click', (e) ->
makeAjaxCall($(this).data('id'))
Note: I have never used CoffeeScript, so this is just a guess.
Solution suggestion 2
If you, for some reason wish to have the ID as an anchor inside the href, you could have a look at the JQuery event.preventDefault() function. This might just stop the URL from changing and all other behaviour you're experiencing.

Related

History API (Dive Into HTML 5 / CH. 11)

I am trying to wrap my head around the history API. I am reading this along with this: http://diveintohtml5.info/history.html. It is relevant to me because, I am creating a single-page-application. There are two areas of the chapter's code that I don't understand:
function addClicker(link) {
....
swapPhoto(link.href);
history.pushState(null, null, link.href);
....
}
In the above code - what is link.href? I think I understand that the href is referring to the link attribute, and the link is being passed to the addClicker method. Is this just the way in which you have to refer to the href attribute of the link that is being passed in?
Secondly:
function swapPhoto(href) {
....
req.open("GET","http://diveintohtml5.info/examples/history/gallery/" + href.split("/").pop(), false);
....
}
What is happening with the above line? I've been trying to figure out what the open() function does with that second parameter...
I am trying to make it so that when a user logs in through a login form (and submit button) - the profile page gets brought up (I am making an SPA) - and then the user could go back to the main page configuration after logging in. So I think I am trying to do something like:
addClicker(document.getElementById("[SUBMIT BUTTON]"));
However, the submit button doesn't have a href attribute...so I am not sure how to proceed.

perform href before onClick

I've the following link:
I
And this use the following javascript:
function showGallery(){
if(window.location.hash) {
$('#gallery').fadeIn('fast');
var hash = window.location.hash.substring(1);
alert(hash);
} else {
}
}
So it only show the gallery when in the URL is a hashtag. But when i click on the link, nothing happens. When i click it twice, the gallery fade in.
So the link first make the javascript, and i doesn't work 'cause there is no hashtag in the URL and after that, it perform the href and insert the Hashtag in the URL.
How can i do that?
My Target:
When i click on a link, it open a gallery. To know which gallery i must open, i insert in the URL a Hashtag. Here i want to display the HDR album. And i also want, if my site get opend with a hashtag, it should display the gallery.!
Is there also a another, easier or cleaner way to make it?
Hope you understand what i want.
For modern browsers, you can bind your Javascript code to the onhashchange event. Links will be without Javascript:
I
And the Javascript is run whenever the hash has changed:
function locationHashChanged() {
if (location.hash === "#HDR") {
$('#gallery').fadeIn('fast');
}
}
window.onhashchange = locationHashChanged;
Have you tried a setTimeout call to delay the onclick event?
Like this:
I
You can simplify this quite considerably, it is not good practice to use the href for other things than pure navigation.
<a onClick="showGallery('HDR')">I</a>
And then:
function showGallery(name){
if(name) {
$('#gallery').fadeIn('fast');
alert(name);
} else {
}
}
If you want to run showGallery() without following the link, the correct code is this:
I
By keeping the href the user still sees the destination in the status bar and navigation still works for clients without Javascript (i.e. Google). By returning false in the event handler, you prevent the browser from following the link.
In showGallery(), you can then show the gallery and add '#HDR' to the location.hash.
You don't need to verify the window's hash, because on first click you don't have any hash in the address bar. The functionality will only apply on the second click.
What you can do is this:
gallery 1
function showGallery(galid){
var linkhash = $('#' + galid).attr('href').substring(1);
alert(linkhash);
$('#gallery' + linkhash).fadeIn('fast');
}

Best way to distinguish links for internal action and ajax request?

Because this topic turn out to interdisciplinary (but still is about user experience) I'm curiuos what think about this an javacript developers.
My site handling a tags with href starting with # as ajax request. If request was successfully then it's change document hash to appropiate. Now I want to implement action links that call internal js function like going to site top, but I don't want javascript:myAction() reference, because most browsers is showing hint with referencing url when you're over the link. Probably I can use and successfully handle own url schema like action:myAction, but it's not enough solution - user was still hinted about magic url. Another option is using custom attribute like action="myAction" with href as custom string e.g. href="Go to top", but what with browsers compatibility? Last solution is to using a span styled as link to perfom action - user is not hinted about any url, but this is a part of link functionality what suggest that perform an action (going to url default).
What is better and why?
<script>
if(window.addEventListener)//Chrome, Firefox and Safari
document.getElementById('myLink').addEventListener('click',function(e){
var e = e || event;
e.preventDefault();
window.location = destiny;
});
else//IE and Opera
document.getElementById('myLink').attachEvent('onclick',function(e){
var e = e || event;
e.preventDefault();
window.location = destiny;
});
</script>
Link
You should make your links work first without JavaScript. Then you don't have to worry about someone clicking <a href='/customers'>Customers!</a>. It works nicely and is accessible. Once you've reached this point you put the JavaScript on top to enhance the user experience. How you hook all of these up is up to you - say you want to handle deletes in a generic way, you might have links that look like this:
<a href='/customers/2' class='delete'>Delete customer</a>
<a href='/customers/2' data-action='delete'>Delete customer</a>
Or if it's specific per link, you set the id and wire it up that way:
<a href='/customers/2' id='delete'>Delete customer</a>
All of this wiring up should be done in an external JavaScript file.
I would do this by first writing everything in a way users without JS can use it, like
Go to top
Then I would take JS to enhance it immediatly after the DOM is loaded. First by adding the onclick event, then removing the href, to avoid any link hint (any other content than links probably not pass any validator) and finally a new style attribute that the cursor becomes a pointer on hover.
It is part of the very useful programmatic progressive enhancement structure. This way I get valid and compatible code as well as a comfortable behaviour.

Javascript protocol and events

What does the following code mean -
some link
My basic doubt is which script is run when we click on the link
The onclick will run first. If onclick doesn't return false (in this case it doesn't), then href will be processed.
The javascript part in the href attribute is the protocol (you know, like http, ftp or mailto). What it does is it tells the browser that the URL is actually JavaScript code.
Normally, when you click on a link, the browser will execute whatever it finds in the href attribute. However, the browser will also trigger the onclick event before it handles the href thing. So, setting an onclick handler will override the normal behavior.
Thus, the event handler becomes king and it has the possibility to allow or prevent the default browser behavior by returning true (allow) or false (prevent).
So, in your example, when you click on that link, the browser will trigger addItem. If it returns false, nothing happens. If it returns true, the browser will execute the code in the href attribute. But since it finds no statement in there (i.e. empty statement), nothing happens.
Try the following code:
won't go to google.com
will go to google.com
Does that make sense to you?
Note that when the browser interprets the "javascript:" value of an "href", if the return value is not empty then it is interpreted as the document content desired for the <a> tag! Here is a test page for you to enjoy:
http://gutfullofbeer.net/jslink.html
The source for that page (look at it; it's really short) includes the following link:
<a href='javascript:getLink()'>Click to go there!</a>
The function "getLink()" is defined as follows:
function getLink() {
var sel = document.getElementById('sel');
return sel.options[sel.selectedIndex].value;
}
As you see, the function grabs the current selected value of the <select> element on the page and returns that. What does the <select> element look like?
<select id='sel'>
<option value='<html><head><meta http-equiv="refresh" content="2;http://cnn.com"/></head><body>Redirecting to CNN ...</body></html>'>CNN</option>
<option value='<html><head><meta http-equiv="refresh" content="2;http://zombo.com"/><head><body>Redirecting to Zombocom ...</body></html>'>Zombocom</option>
<option value='<html><head><meta http-equiv="refresh" content="2;http://reddit.com"/></head><body>Redirecting to Reddit ...</body></html>'>Reddit</option>
</select>
The values of those options are complete HTML markup for a page with a redirect to the requested site. Because the URL returns a value, that value is understood by the browser to be the new page content.
It's pretty mind-blowing. I'm not sure why you'd ever do this.
your doubt is true !, you must find "function addItem(x)" in a javascript file that linked by script tag from the page.(usually in head tag)
The "javascript:" inside href is a way to tell the browser to execute javascript instead of going to a different page.
This line, for example will show a message box with "testing" message.
Click me
and this one will execute an empty javascript statement that will do nothing
Click me
The onclick is an event that also fires when a link is clicked. In contrast to href it does not allow you to put in a link to a different page; it accepts only javascript.
Browsers will first fire onclick event and then process href attribute. If it's an URL (empty href means current URL; click will just refresh the page) it will follow it, if it's javascript it will execute it.
Putting "javascript:;" or "javascript:void(null);" inside href is old and wrong technique to ensure browser does not not refresh the page after onclick is processed.
To answer your question; both scripts will execute, but the href script will do nothing.

Force page reload with html anchors (#) - HTML & JS

Say I'm on a page called /example#myanchor1 where myanchor is an anchor in the page.
I'd like to link to /example#myanchor2, but force the page to reload while doing so.
The reason is that I run js to detect the anchor from the url at the page load.
The problem (normally expected behavior) here though, is that the browser just sends me to that specific anchor on the page without reloading the page.
How would I go about doing so? JS is OK.
I would suggest monitoring the anchor in the URL to avoid a reload, that's pretty much the point of using anchors for control-flow. But still here goes. I'd say the easiest way to force a reload using a simple anchor-link would be to use
where in place of $random insert a random number (assuming "dummy" is not interpreted server side). I'm sure there's a way to reload the page after setting the anchor, but it's probably more difficult then simply reacting to the anchor being set and do the stuff you need at that point.
Then again, if you reload the page this way, you can just put myanchor2 as a query parameter instead, and render your stuff server side.
Edit
Note that the link above will reload in all circumstances, if you only need to reload if you're not already on the page, you need to have the dummy variable be more predictable, like so
I would still recommend just monitoring the hash though.
Simple like that
#hardcore
an example
Another way to do that is to set the url, and use window.location.reload() to force the reload.
<a href="/example#myanchor2"
onclick="setTimeout(location.reload.bind(location), 1)">
</a>
Basically, the setTimeout delays the reload. As there is no return false in the onclick, the href is performed. The url is then changed by the href and only after that is the page reloaded.
No need for jQuery, and it is trivial.
My favorite solution, inspired by another answer is:
myanchor2
href link will not be followed so you can use your own preference, for example: "" or "#".
Even though I like the accepted answer I find this more elegant as it doesn't introduce a foreign parameter. And both #Qwerty's and #Stilltorik's answers were causing the hash to disappear after reload for me.
What's the point of using client-side JS if you're going to keep reloading the page all the time anyways? It might be a better idea to monitor the hash for changes even when the page is not reloading.
This page has a hash monitor library and a jQuery plugin to go with it.
If you really want to reload the page, why not use a query string (?foo) instead of a hash?
Another option that hasn't been mentioned yet is to bind event listeners (using jQuery for example) to the links that you care about (might be all of them, might not be) and get the listener to call whatever function you use.
Edit after comment
For example, you might have this code in your HTML:
example1
example2
example3
Then, you could add the following code to bind and respond to the links:
<script type="text/javascript">
$('a.myHash').click(function(e) {
e.preventDefault(); // Prevent the browser from handling the link normally, this stops the page from jumping around. Remove this line if you do want it to jump to the anchor as normal.
var linkHref = $(this).attr('href'); // Grab the URL from the link
if (linkHref.indexOf("#") != -1) { // Check that there's a # character
var hash = linkHref.substr(linkHref.indexOf("#") + 1); // Assign the hash to a variable (it will contain "myanchor1" etc
myFunctionThatDoesStuffWithTheHash(hash); // Call whatever javascript you use when the page loads and pass the hash to it
alert(hash); // Just for fun.
}
});
</script>
Note that I'm using the jQuery class selector to select the links I want to 'monitor', but you can use whatever selector you want.
Depending on how your existing code works, you may need to either modify how/what you pass to it (perhaps you will need to build a full URL including the new hash and pass that across - eg. http://www.example.com/example#myanchor1), or modify the existing code to accept what you pass to it from you new code.
Here's something like what I did (where "anc" isn't used for anything else):
And onload:
window.onload = function() {
var hash = document.location.hash.substring(1);
if (hash.length == 0) {
var anc = getURLParameter("anc");
if (anc != null) {
hash = document.location.hash = anc;
}
}
}
The getURLParameter function is from here
If you need to reload the page using the same anchor and expect the browser to return to that anchor, it won't. It will return to the user's previous scroll position.
Setting a random anchor, overwriting it and then reloading seems to fix it. Not entirely sure why.
var hash = window.location.hash;
window.location.hash = Math.random();
window.location.hash = hash;
window.location.reload();
Try this its help for me
<a onclick="location.href='link.html'">click me</a>
In your anchor tag instead of
click me
As suggested in another answer, monitoring the hash is also an option. I ended up solving it like this so it required minimal code changes. If I had asked the original question, I believe I would have loved to see this option fully explained.
The added benefit is that it allows for additional code for either of the situations (hash changed or page loaded). It also allows you to call the hash change code manually with a custom hash. I used jQuery because it makes the hash change detection a piece of cake.
Here goes!
Move all the code that fires when a hash is detected into a separate independent function:
function openHash(hash) {
// hashy code goes here
return false; // optional: prevents triggering href for onclick calls
}
Then detect your hash for both scenarios like so:
// page load
$(function () {
if(typeof location.hash != typeof undefined) {
// here you can add additional code to trigger only on page load
openHash(location.hash);
}
});
// hash change
$(window).on('hashchange', function() {
// here you can add additional code to trigger only on hash change
openHash(location.hash);
});
And you can also call the code manually now like
Magic
Hope this helps anyone!
Try this by adding simple question mark:
Going to Anchor2 with Refresh

Categories