Benek Lisefski
Benek Lisefski

Reputation: 159

jQuery - how to test if link goes to anchor on same page?

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?

Upvotes: 10

Views: 19642

Answers (6)

phucbm
phucbm

Reputation: 893

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
}

Upvotes: 0

Rahul Desai
Rahul Desai

Reputation: 15491

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 */

}

Upvotes: 15

Alexey Kosov
Alexey Kosov

Reputation: 3128

    /**
     * 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;
    }

Upvotes: 2

Molemann
Molemann

Reputation: 418

This is my take, much slimmer :-

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

Upvotes: 17

Rodrigo
Rodrigo

Reputation: 1253

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>

Upvotes: 8

Jonathan Joosten
Jonathan Joosten

Reputation: 1509

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');
});

Upvotes: 2

Related Questions