10

I'm trying to run an ajax function when links are clicked, but I need to exclude links to anchors on the same page so I don't try to re-load in the page content when I'm simply scrolling down to a different part of the same page.

I know I can test if the href include a hash but that's not good enough:

if (href.indexOf("#") === -1)

Because I will have links that go to another page AND scroll to a local anchor. So I need to test if the href points to the current page AND includes a hash. And in that case I would exclude it from the function. But if it points to a different page and includes a hash it should still be included.

How can I achieve this with jQuery?

Benek Lisefski
  • 159
  • 1
  • 3
  • 13

6 Answers6

17

This is my take, much slimmer :-

$('a[href*=\\#]').on('click', function (event) {
    if(this.pathname === window.location.pathname){
        // Do something 
    }
});
Molemann
  • 418
  • 5
  • 10
13

You do not need jQuery for this. Just use regex in Javascript.

if(/^#/.test(href)) { // .test() returns a boolean

    /* do not run AJAX function */ 

} else {

    /* run the AJAX function */ 

}

Explanation:

^# is the regex. // is where you wrap your regex in. ^ means at the beginning of the string and # is what you are looking for. .test() is a javascript function that executes the regex on a given string and return a boolean value.

Read up: RegExp.prototype.test() - JavaScript | MDN


Update 1:

In case if the href is not starting with a # but it still points to the same webpage, your problem is reduced to checking if a string is a substring of another string. You can make use of window.location.href and .indexOf() to achieve this:

if(href.indexOf(window.location.href) > -1) { 

    /* do not run AJAX function */ 

} else {

    /* run the AJAX function */ 

}

window.location.href returns the URL of the webpage that you are on and href.indexOf(window.location.href) checks if window.location.href is substring of href;

Example: https://www.example.com/page1 is a substring of https://www.example.com/page1#myDiv

Read up:


Update 2:

Good find by @Tib. My code in update above was not checking if the hostnames are the same. I have fixed it below:

if(<hostnames are the same>) { // make use of window.location.hostname here to get hostname of current webpage
    if(href.indexOf(window.location.href) > -1) { 

        /* do not run AJAX function */ 

    } else {

        /* run the AJAX function */ 

    }
} else {

    /* do not run AJAX function */

}
Rahul Desai
  • 15,242
  • 19
  • 83
  • 138
  • Thanks Rahul, but simply testing to see if hash is the first character in the strong is not enough. These are CMS pages and nav links will have the same URL on every page. On the homepage these links go to anchors on the same page, on other pages they go to anchors on the home page. So the hash won't be at the beginning. I need to reliably test if the href is going to the current page or to a different page. – Benek Lisefski Nov 20 '15 at 22:49
  • @BenekLisefski Please checkout **Update 1** in my answer above. – Rahul Desai Nov 21 '15 at 00:04
  • I ended up adjusting my plan and finding another workaround but thanks anyway for the detailed answer. – Benek Lisefski Nov 23 '15 at 00:43
  • That's terribly wrong! What if you have a link that points to an anchor of an external website? You should also check the hostname portion. Rodrigo pointed out the right solution – fedetibaldo Aug 21 '17 at 23:00
8

Supported in all browsers:

"use strict"; // Start of use strict
$('a').bind('click', function(event) {
  if (this.pathname == window.location.pathname &&
    this.protocol == window.location.protocol &&
    this.host == window.location.host) {
    alert('links to same page');
    event.preventDefault();
  } else {
    alert('links to a different page');
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#same-page">Same Page</a>
<br>
<a href="/users/913950#page">Other Page</a>
Rodrigo
  • 1,253
  • 16
  • 11
  • did the same thing but added `&& this.hash` to the end just to check if it had the hash part (local anchor) in the URL at all. – Ryan Taylor Feb 14 '18 at 20:09
2

Far from perfect, but works for me. Don't forget to use jQuery.

Have fun with it:

jQuery('a').on('click',function (e) {

    var current = window.location.href.split('#')[0];
    var goto = jQuery(this).attr('href').split('#')[0];

    if (current == goto && this.hash) {
        e.preventDefault();

        var target = this.hash;
        var $target = jQuery(target);

        if($target.length){
            jQuery('html,body').stop().animate({
                'scrollTop': $target.offset().top
            }, 900, 'swing');
        }
    }

});

jQuery('a[href^=#]:not([href=#])').on('click',function (e) {
    e.preventDefault();

    var target = this.hash;
    var $target = jQuery(target);

    if($target.length){
        history.pushState( null, jQuery('#title').html() , target);
        jQuery('html,body').stop().animate({
            'scrollTop': $target.offset().top }, 900, 'swing');
    }
});
jQuery('a[href=#]').on('click',function (e) {
    e.preventDefault();
    history.pushState( null, jQuery('#title').html() , location.href.replace(location.hash,""));
    jQuery('html,body').stop().animate({
        'scrollTop': 0
    }, 900, 'swing');
});
Jonathan Joosten
  • 1,499
  • 12
  • 12
2
    /**
     * Checks if the href belongs to the same page and returns the anchor if so.
     *
     * @param  {String} href
     * @returns {Boolean|String}
     */
    function getSamePageAnchor (href) {
        var link = document.createElement('a');
        link.href = href;

        /**
         * For IE compatibility
         * @see https://stackoverflow.com/a/24437713/1776901
         */
        var linkCanonical = link.cloneNode(false);

        if (
            linkCanonical.protocol !== window.location.protocol ||
            linkCanonical.host !== window.location.host ||
            linkCanonical.pathname !== window.location.pathname ||
            linkCanonical.search !== window.location.search
        ) {
            return false;
        }

        return link.hash;
    }
Alexey Kosov
  • 3,010
  • 2
  • 23
  • 32
0

Here you go,

// extract hash from URL
const hash = new URL(`https://example.com/#your-anchor`).hash; // return => #your-anchor

// if hash exists in the URL, and the anchor is also exists
if(hash.length && document.querySelectorAll(hash).length){
   // do something
}
phucbm
  • 885
  • 6
  • 13