14

I use e.preventDefault(); to disable default anchor behaviour.

Is there a way to prevent only jump action to a target on click?

I tried:

  var hash = window.location.hash;
  var link = $('a');
  $('a').click(function() {
    e.preventDefault();
    hash = "#"+link.attr("href");
  });

But it doesn't work: http://jsfiddle.net/ynts/LgcmB/.

A. Z.
  • 728
  • 1
  • 11
  • 28

8 Answers8

27
$(document).ready(function() {
  var hash = window.location.hash;
  var link = $('a');
  $('a').click(function(e) {
    e.preventDefault();
    hash = link.attr("href");
    window.location = hash;
  });
});

You also have to specify event argument in the function. By naming it as e or event and then you can manipulate it.

Muhammad Talha Akbar
  • 9,952
  • 6
  • 38
  • 62
  • Was just about to comment on the lack of explanation for the missing event, but there it was, +1. – adeneo Jan 06 '13 at 19:44
  • heheheh :P I will never miss descriptions in my answers :D – Muhammad Talha Akbar Jan 06 '13 at 19:44
  • Unfortunately, there is no jump action and no url update. I want to have `jsfiddle.net/ynts/Jgkmt/embedded/result/#anchor` after click. – A. Z. Jan 06 '13 at 19:57
  • edited my answer :D It may not work in the jsFiddle because they use iframes! – Muhammad Talha Akbar Jan 06 '13 at 20:09
  • 8
    Once `window.location` is set, a jump to `#anchor` happens :(. – A. Z. Jan 06 '13 at 20:49
  • can you explain a little more? – Muhammad Talha Akbar Jan 07 '13 at 12:38
  • @AspiringAqib I put this example from jsFiddle to [test_1.html](http://dl.dropbox.com/u/983140/@/stackoverflow.com/14185974/test_1.html). The link is clicked → url in adress bar is added with `#anchor` (on `window.location = hash;`) → jump to `p#anchor` happens. So all steps of default click action on an anchor link are here. My idea was to get only `#anchor` added to page adress in adress bar and no page scroll to `p#anchor`. – A. Z. Jan 07 '13 at 19:32
  • well you can use, this plugin: http://benalman.com/projects/jquery-hashchange-plugin/ and add this code to jQuery: `$(window).hashchange( function(e) { e.preventDefault(); });` I think it will work and if worked then don't forget to do something ;) – Muhammad Talha Akbar Jan 07 '13 at 19:39
  • @AspiringAqib still no luck: [test_2.html](http://dl.dropbox.com/u/983140/@/stackoverflow.com/14185974/test_2.html). – A. Z. Jan 07 '13 at 21:40
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/22347/discussion-between-aspiring-aqib-and-ynt) – Muhammad Talha Akbar Jan 07 '13 at 21:42
  • `` You were adding that function in other event which occurs on click! – Muhammad Talha Akbar Jan 08 '13 at 05:00
  • @AspiringAqib I tried this variant, too. [It doesn't resolve the issue.](https://dl.dropbox.com/u/983140/%40/stackoverflow.com/14185974/test_3.html) – A. Z. Jan 09 '13 at 01:50
  • oh buddy then I have also never tried these things but can you explain why you wanna stop it to do that? – Muhammad Talha Akbar Jan 09 '13 at 07:38
  • @AspiringAqib I use a script for tabs that works with anchors. It works smooth. But I want to add `#href-value` to a page adress in adress bar when a tab is clicked. However, once URL is updated, a page jumps to `div#href-value`. So I lose "smoothness" of tabs behavior. – A. Z. Jan 09 '13 at 20:20
  • `window.location.hash = hash` is more safe than `window.location = hash` isn't it? – dtrunk Jul 29 '14 at 14:57
  • Seems like an obtrusive script behavior to intercept the click event and prevent it, then fish the href value out of the attribute and assign it the to the window location. Perhaps a better way: http://stackoverflow.com/a/34544031/1467810 – TaeKwonJoe Dec 31 '15 at 09:26
15

This is the only solution I could come up with that works consistently across all desktop and mobile browsers or webviews with various client UI libraries and frameworks. By getting the window coordinates before scrolling occurs we can revert and maintain the current scroll position.

$('a').click(function (e) {
    var x = window.pageXOffset,
        y = window.pageYOffset;
    $(window).one('scroll', function () {
        window.scrollTo(x, y);
    })
});
TaeKwonJoe
  • 1,077
  • 11
  • 24
  • 1
    I tried different solutions but your solution is very good. it worked on searching also – Mirza Obaid Jul 02 '19 at 11:11
  • 1
    This had same affect for me as just using e.preventDefault(); – Daniel Jan 03 '20 at 03:54
  • 1
    This will not cause wierd behavior within a WKWebView! – ANGOmarcello Dec 06 '21 at 21:38
  • @Daniel and @ANGOmarcello that's the idea : "Is there a way to prevent only jump action to a target on click?" The event default behavior is not prevented via `e.preventDefault()` nor is `e.stopPropagation()` occurring. Only the UI jump behavior is prevented via scroll position value revert before painting as asked. – TaeKwonJoe Jul 07 '23 at 04:34
5

To only prevent the "jump" you have to use different id for the target element than what is specified in the anchor.

e.g. for a link to a new tab use,

<a href="#new" />

and for the target element mask the id

<div id="new-tab"></div>

Then in your script append the mask to the real hash, and use it to get the element.

$(window).on("hashchange", function(){
    var hash = this.location.hash;
    var mytab = $(hash + "-tab");
});

This preserves the hash location changes in browser history that can be controlled by the back/forward buttons, and detected on page load with the hashchange event if user enters the page with hash specified.

jumois
  • 87
  • 1
  • 4
  • 1
    Thanks so much for this comment. I did this long ago and couldn't figure out for the life of me remember what I did to solve the stupid cross-page reload scrolling issues. Your answer reminded me of the good ol' masking method! – Tallboy Aug 18 '16 at 15:32
  • Very helpful in different circumstances. E.g. define a boolean on page load, change the anchor, prevent the jump. After page load handle clicks on inner anchors as usual. – Avatar May 28 '18 at 07:31
3

You should bind an onclick event to anchor and specify return false; as a result. The return false; statement causes default click behaviour (jump) would not work. You can find more info here: How to disable anchor "jump" when loading a page?

Community
  • 1
  • 1
Sergei Smirnov
  • 151
  • 1
  • 3
2

You need to pass the event on the function.

var hash = window.location.hash;
var link = $('a');
//pass event here
$('a').click(function(e) {
    e.preventDefault();
    hash = "#"+link.attr("href");
});
Dexter
  • 7,911
  • 4
  • 41
  • 40
AgnosticDev
  • 1,843
  • 2
  • 20
  • 36
1

After first trying the other answers on this page, this was all I needed:

  $('a').click(function (e) {
    e.preventDefault();
  });
Daniel
  • 515
  • 4
  • 13
0

You can use match with ^ to detect starting with #

$("a:link").on("click", function(e){
    if($(this).attr("href").match("^#")) {
        e.preventDefault();
        //some other stuff you want to do with the hash, like smooth scroll to anchor
        $('html, body').animate({ scrollTop: $($(this).attr("href")).offset().top }, 'fast');
    }
});
Fanky
  • 1,673
  • 1
  • 18
  • 20
0

Add any string after the hash:

<a href="#anystring">
TV-C-1-5
  • 680
  • 2
  • 13
  • 19