Deep-linking with individual names

Stef's Avatar


23 Aug, 2012 08:11 AM

I would love a possibility to add individual hashes to each slide, e.g. "/#design-project-xyz", "/#something-to-see", "/#another-project"… complementing the option of a fixed prefix.

The attached screenshot shows something i have done until recently that used to work perfectly. I was hoping that i could get it to work with v9 if i replace the "currentSlideId" property with the new "currSlide"… but the "afterSlideChange" function has changed if i am not mistaken and i can not wrap my head around a different implementation it yet…

Best regards + have a brilliant day!


Showing page 2 out of 3. View the first page

  1. 31 Posted by gdu on 25 Mar, 2013 09:25 AM

    gdu's Avatar

    I am looking for the same thing i.e. a way to customize the links of my different slides.
    Dmtry, is there a chance to implement such feature any time soon?
    Thanks in advance!

  2. 32 Posted by daveclay on 05 Apr, 2013 05:44 AM

    daveclay's Avatar

    I edited the royalslider deeplinking module that uses custom image names in the hash instead of indexes. I used a separate, hidden span associated with the image to specify the name. The caption wouldn't work for me, since I have longer caption text. I believe this falls back to using indexes if there isn't a custom rsImgHash element.

    I've attached the diff that makes changes to the 9.4.8 "dev" files used to implement this.

    <div class="rsContent">
        <span class="rsImgHash hidden">someImageName</span>
        <a class="rsImg" data-rsTmb="/path/to/thumb.png" href="/path/to/image.png"/>

    The patch changes to set up the custom hash, and jquery.royalslider.js in order to read the custom image hash that the deeplinking module sets up.

    FYI, to apply the diff, use patch to apply the diff in the "dev" root directory.

    $ patch -p0 < custom_hash.diff

  3. 33 Posted by gdu on 08 Apr, 2013 08:18 AM

    gdu's Avatar

    Looks promising Dave! Could you give more details on how to apply the diff file? Or even better could you provide a simple step-by-step?
    Basically what I would like is the ability to customize the URL of each tab instead of having /#home-1, /#home-2 etc. on this page:

  4. 34 Posted by daveclay on 08 Apr, 2013 03:17 PM

    daveclay's Avatar

    If you'd like the files themselves for optimal quickness, you can grab the modified files directly from my site:

    To use a diff file to make changes, you use the "patch" command (which is a unix-y command available on linux or mac). Grab the development zip file from:

    Once that's unzipped, you should have a "dev" directory. Now you need to run "patch" to apply the diff file's changes to the current directory of files.

    cd dev
    patch -p0 < custom_hash.diff

    And then use those files. There's a quick explanation of using patch here:

  5. 35 Posted by miguelsansegund... on 09 Apr, 2013 11:34 AM

    miguelsansegundo's Avatar

    Great work @daveclay, thanks! My goal now is to use post slug in WordPress with a custom Mustache variable in a template of this awesome Royal Slider .

    See you Bros!

  6. 36 Posted by gdu on 10 Apr, 2013 07:55 AM

    gdu's Avatar

    Thanks Dave, it works like a charm. Cheers !

  7. 37 Posted by gdu on 15 Apr, 2013 12:05 PM

    gdu's Avatar

    @Dave or @anynone: I do have an issue and I think it's related to the find() method you used in your custom deeplinking script. var imgHashElems = slide.content.find('.rsImgHash'); After clicking on a thumbnail, it makes the page jump right to the top of the slider making the header of the website hidden. How can I override that?
    I tried to replace find() by select() and I no longer have this page jump however with this method instead of having only the hash tag I've set up in the <span> it displays all the slide content ! Any help appreciated !

  8. 38 Posted by gdu on 15 Apr, 2013 12:12 PM

    gdu's Avatar

    I've attached screenshots for you to better understand my issue. Thanks!

  9. 39 Posted by Mitch on 15 Oct, 2013 09:58 AM

    Mitch's Avatar

    I too would also like to see individual names implemented. has this gone any further?

  10. 40 Posted by gdu on 21 Oct, 2013 06:25 AM

    gdu's Avatar

    @mitch: yep, I got this working a while ago. You can visit the page below to see it in action:

  11. 41 Posted by Mitch on 21 Oct, 2013 11:33 AM

    Mitch's Avatar

    Hi gdu

    Thanks for the pointer.

    So would I just save then add to my site and reference it in the head?

  12. 42 Posted by gdu on 22 Oct, 2013 12:41 PM

    gdu's Avatar

    Mitch, also don't forget to call the custom name at the beginning of each slide as such: <span class="rsImgHash hidden">yourCustomHashTagName</span>

    And you have to activate the deep linking iniside Royalslider initialization script:
    deeplinking: {
    // deep linking options go gere
    enabled: true,
    change: true
    Good luck!

  13. 43 Posted by rob on 02 Dec, 2013 01:42 AM

    rob's Avatar

    gdu thanks so much for this. I've tried using your custom royalslider javascript -custom hashnames work!


    Your custom royalslider.js seems to be missing the part which adds .rsActiveSlide to the current slide - which I need for the functionality of my site also. Any ideas?

    Would be great if I can get both working.

  14. 44 Posted by bmccormick on 22 Apr, 2014 02:31 AM

    bmccormick's Avatar

    Just a comment to anyone who's having trouble implementing this.... Your custom hash tag cannot start with a digit. I was trying this with Youtube Video ID's and finally realized the one's that were not working began with numbers.

  15. 45 Posted by 3stripe on 29 Apr, 2014 09:23 PM

    3stripe's Avatar

    Any plan to incorporate this into the core?

    For albums whose contents/order changes, it makes the url structure a lot more future-proof :)

  16. 46 Posted by hvb on 30 Jun, 2014 04:51 PM

    hvb's Avatar

    I, for one, could really use this in my isotope implementation here: indeed, any plans on implementing this?

  17. 47 Posted by whit on 26 Aug, 2014 08:52 PM

    whit's Avatar

    Thank you for making an awesome slider.

    This feature that everyone is asking for would come in super-handy though. Having old links that reference the wrong slide every time I change the slide order is not ideal. I haven't been able to get these code examples that others have provided to work on my site.

  18. 48 Posted by elena.mascolo on 28 Aug, 2014 10:15 AM

    elena.mascolo's Avatar

    Hi whit, I read all the thread and I was able to use custom names looking the source code of the site posted by gdu.

    I attach the deeplinking JS file modified.

    It works with a span with rsImgHash class:

    <div class="rsContent">
    <span class="rsImgHash hidden">yourcustomname</span>
    <img class="rsImg" src="image.jpg">

    and the deeplinking option enabled in the royalslider script:

    deeplinking: { 
    // deep linking options go gere 
    enabled: true, 
    change: true 

    I hope I helped you


  19. 49 Posted by whit on 29 Aug, 2014 08:25 PM

    whit's Avatar

    Hi Elena,

    I really appreciate you helping me out with this. I'm having the same problem with your code that I had with gdu's code. When I use this new code, the names of the slides display up in the URL as I move from slide to slide, but my video slides will no longer play the videos.

    Also, if I paste the address of one of my slides into a browser, it always goes to the first slide instead of the slide listed in the URL.

    Here's an example of my page using the named slides that's not quite working right:

    Here's an example of how the video slider looks now using deep-linking with an index number:

    I understand if you can't look into this further, but I thought I'd go ahead and post it just in case someone knows what might be happening.

  20. Support Staff 50 Posted by Dmytro Semenov on 30 Aug, 2014 05:22 PM

    Dmytro Semenov's Avatar

    @whit, try getting unimified version of slider JS file from build tool, and include it. As currently you have a mixed code blocks, which are minified in different methods.

  21. 51 Posted by mothership on 04 Sep, 2014 09:51 AM

    mothership's Avatar

    I tried utilizing the "fixed" deeplinking.js file provided by Elena and it failed miserably (with deeplinking options on and hidden spans in place). This is a bit frustrating given hash changes on slides are a fairly common feature and with a mandatory suffix in place it pretty much destroys the entire use for it.

  22. 52 Posted by mothership on 04 Sep, 2014 07:37 PM

    mothership's Avatar

    We ended up running with this based off another thread:

    (function($) {
      "use strict";
         * RoyalSlider Deep Linking Module
         * @version 1.0.6 + jQuery hashchange plugin v1.3 Copyright (c) 2010 Ben Alman:
       * 1.0.1:
       * - Added timeout before hash changes to 750ms to avoid reloading animation.
       * 1.0.2:
       * - Added multiple slider with hash support
       * 1.0.3
       * - Removed hashchange listener on destroy()
       * 1.0.4
       * - Decreased timeout from 750 to 400ms
       * 1.0.5
       * - History state is now replaced instead of pushing to avoid back button confusion
       * - jQuery 1.9.0 compability
       * 1.0.6
       * - Namespaced hashchange event
       * 1.0.7
       * - Multiple sliders on one page
        $.extend($.rsProto, {
            _initDeeplinking: function() {
                var self = this,
                self._hashDefaults = {
                    enabled: false,
                    change: false,
                    prefix: ''
       = $.extend({}, self._hashDefaults,;
                if( {
                    var hashChange =;
            var getSlideIdByHash = function() {
              var h,
                hash = window.location.hash,
                hashes = {},
                index = 0;
              $('.royalSlider .rsImage').each(function(i) {
                h = $(this).attr('alt');
                hashes[h] = i;
              if(hash) {
                index = hashes[hash.substring(1)] || index;
                return index;
              return -1;
                    var id = getSlideIdByHash();
                    if(id !== -1) {
               = id;
                    if(hashChange) {
                        $(window).on('hashchange'+self.ns, function(e){
                            if(!isBlocked) {
                                var id = getSlideIdByHash();
                  if(id < 0) {
                  if(id > self.numSlides - 1)
                    id = self.numSlides - 1;
                  self.goTo( id );
              self.ev.on('rsBeforeAnimStart', function() {
                if(hashTimeout) {
                if(hashChangeTimeout) {
                    self.ev.on('rsAfterSlideChange', function() {
                        if(hashTimeout) {
                if(hashChangeTimeout) {
                hashChangeTimeout = setTimeout(function() {
                  isBlocked = true;
                  var currentSlide = self.currSlide
                  window.location.hash = $(currentSlide.content).find('.rsImage').attr('alt');
                  hashTimeout = setTimeout(function() {
                    isBlocked = false;
                    hashTimeout = null;
                  }, 60);
                }, 400);
            self.ev.on('rsBeforeDestroy', function() {
              hashChangeTimeout = null;
              hashTimeout = null;
              if(hashChange) {
                $(window).off('hashchange' + self.ns);
        $.rsModules.deeplinking = $.rsProto._initDeeplinking;
     * jQuery hashchange event - v1.3 - 7/21/2010
     * Copyright (c) 2010 "Cowboy" Ben Alman
     * Dual licensed under the MIT and GPL licenses.
      '$:nomunge'; // Used by YUI compressor.
      // Reused string.
      var str_hashchange = 'hashchange',
        // Method / object references.
        doc = document,
        special = $.event.special,
        // Does the browser support window.onhashchange? Note that IE8 running in
        // IE7 compatibility mode reports true for 'onhashchange' in window, even
        // though the event isn't supported, so also test document.documentMode.
        doc_mode = doc.documentMode,
        supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 );
      // Get location.hash (or what you'd expect location.hash to be) sans any
      // leading #. Thanks for making this necessary, Firefox!
      function get_fragment( url ) {
        url = url || location.href;
        return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' );
      $.fn[ str_hashchange ] = function( fn ) {
        return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange );
      $.fn[ str_hashchange ].delay = 50;
      special[ str_hashchange ] = $.extend( special[ str_hashchange ], {
        // Called only when the first 'hashchange' event is bound to window.
        setup: function() {
          // If window.onhashchange is supported natively, there's nothing to do..
          if ( supports_onhashchange ) { return false; }
          // Otherwise, we need to create our own. And we don't want to call this
          // until the user binds to the event, just in case they never do, since it
          // will create a polling loop and possibly even a hidden Iframe.
          $( fake_onhashchange.start );
        // Called only when the last 'hashchange' event is unbound from window.
        teardown: function() {
          // If window.onhashchange is supported natively, there's nothing to do..
          if ( supports_onhashchange ) { return false; }
          // Otherwise, we need to stop ours (if possible).
          $( fake_onhashchange.stop );
      // fake_onhashchange does all the work of triggering the window.onhashchange
      // event for browsers that don't natively support it, including creating a
      // polling loop to watch for hash changes and in IE 6/7 creating a hidden
      // Iframe to enable back and forward.
      fake_onhashchange = (function(){
        var self = {},
          // Remember the initial hash so it doesn't get triggered immediately.
          last_hash = get_fragment(),
          fn_retval = function(val){ return val; },
          history_set = fn_retval,
          history_get = fn_retval;
        // Start the polling loop.
        self.start = function() {
          timeout_id || poll();
        // Stop the polling loop.
        self.stop = function() {
          timeout_id && clearTimeout( timeout_id );
          timeout_id = undefined;
        // This polling loop checks every $.fn.hashchange.delay milliseconds to see
        // if location.hash has changed, and triggers the 'hashchange' event on
        // window when necessary.
        function poll() {
          var hash = get_fragment(),
            history_hash = history_get( last_hash );
          if ( hash !== last_hash ) {
            history_set( last_hash = hash, history_hash );
            $(window).trigger( str_hashchange );
          } else if ( history_hash !== last_hash ) {
            location.href = location.href.replace( /#.*/, '' ) + history_hash;
          timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay );
        window.attachEvent && !window.addEventListener && !supports_onhashchange && (function(){
          // Not only do IE6/7 need the "magical" Iframe treatment, but so does IE8
          // when running in "IE7 compatibility" mode.
          var iframe,
          // When the event is bound and polling starts in IE 6/7, create a hidden
          // Iframe for history handling.
          self.start = function(){
            if ( !iframe ) {
              iframe_src = $.fn[ str_hashchange ].src;
              iframe_src = iframe_src && iframe_src + get_fragment();
              // Create hidden Iframe. Attempt to make Iframe as hidden as possible
              // by using techniques from
              iframe = $('<iframe tabindex="-1" title="empty"/>').hide()
                // When Iframe has completely loaded, initialize the history and
                // start polling.
                .one( 'load', function(){
                  iframe_src || history_set( get_fragment() );
                // Load Iframe src if specified, otherwise nothing.
                .attr( 'src', iframe_src || 'javascript:0' )
                // Append Iframe after the end of the body to prevent unnecessary
                // initial page scrolling (yes, this works).
                .insertAfter( 'body' )[0].contentWindow;
              // Whenever `document.title` changes, update the Iframe's title to
              // prettify the back/next history menu entries. Since IE sometimes
              // errors with "Unspecified error" the very first time this is set
              // (yes, very useful) wrap this with a try/catch block.
              doc.onpropertychange = function(){
                try {
                  if ( event.propertyName === 'title' ) {
                    iframe.document.title = doc.title;
                } catch(e) {}
          // Override the "stop" method since an IE6/7 Iframe was created. Even
          // if there are no longer any bound event handlers, the polling loop
          // is still necessary for back/next to work at all!
          self.stop = fn_retval;
          // Get history by looking at the hidden Iframe's location.hash.
          history_get = function() {
            return get_fragment( iframe.location.href );
          // Set a new history item by opening and then closing the Iframe
          // document, *then* setting its location.hash. If document.domain has
          // been set, update that as well.
          history_set = function( hash, history_hash ) {
            var iframe_doc = iframe.document,
              domain = $.fn[ str_hashchange ].domain;
            if ( hash !== history_hash ) {
              // Update Iframe with any initial `document.title` that might be set.
              iframe_doc.title = doc.title;
              // Opening the Iframe's document after it has been closed is what
              // actually adds a history entry.
              // Set document.domain for the Iframe document as well, if necessary.
              domain && iframe_doc.write( '<script>document.domain="' + domain + '"</script>' );
              // Update the Iframe's hash, for great justice.
              iframe.location.hash = hash;
        return self;

    This allowed us to not have to use .rsImg (gave weird results for our setup) and instead use .rsImage inside of our #slideshow (typically, this is .rsSlider by default).

    It needs to be optimized but for now, it works and returns the full .rsImage's alt attribute.

  23. 53 Posted by emi.rolland on 01 May, 2015 09:00 PM

    emi.rolland's Avatar

    Hello guys

    I'm trying and trying to install the custom deep linking,
    I read with a lot of attention the topic :,
    it works perfectly in the url but when I tried to put the url in another browser, I always go on the first slide.
    here an exemple :

    It should take you to the second slide, but it is not working, does anayone had any idea...

    Thank you very much for your help

    (connexion code : curator / demo)



  24. Support Staff 54 Posted by Dmytro Semenov on 03 May, 2015 09:08 AM

    Dmytro Semenov's Avatar

    @Emillie, you'll need to debug by yourself what might wrong, open deeplinking js and take a look if this part works correctly:

    var id = getSlideIdByHash();
                    if(id !== -1) {
               = id;
  25. 55 Posted by emi.rolland on 04 May, 2015 10:21 AM

    emi.rolland's Avatar

    Hello Dmitry thank you for your help, the problem was a line just above :

     $('#slideshow .rsImage').each(function(i) {
                h = $(this).attr('alt');
                hashes[h] = i;

    I had to replace #slideshow by my correct id.

    It works perfectly now.
    So I maybe it could help other people, be carefull in the deeplinking js file, you have to repalce #slideshow by the id you use.

  26. 56 Posted by alan on 03 Jun, 2015 04:45 PM

    alan's Avatar

    For some reason I can't seem to get the linking to a specific slide to work i.e.

    <a class="show-thumbnails" href="#fade-to-blue">Fade to Blue</a>
    Should then go to that specific slide in the slider, correct?

    For some reason it doesn't. It changes the url but then doesn't go to that slide.

    I'm using the deeplinking script as per the above comment by @mothership, above, and that's working perfectly i.e. adding the correct end to the url and I can also directly link to a slide by entering the full url in a new browser window.

    Any help or ideas would be much appreciated as I can't figure out why this wouldn't be working.

  27. Support Staff 57 Posted by Dmytro Semenov on 03 Jun, 2015 07:56 PM

    Dmytro Semenov's Avatar

    @alan, can you please open new private discussion and link to the page that you're working on? Just HTML file isn't enough. If you want URL to change dynamically (not just on page load), make sure that deeplinking.change is true

  28. 58 Posted by alan on 04 Jun, 2015 08:38 AM

    alan's Avatar

    @Dmitry Semenov - Thanks, I've opened a new discussion here

  29. 59 Posted by detlef on 02 May, 2017 10:55 AM

    detlef's Avatar

    The link above is removed, however I have another question. I would like to pull the perm-hash out of a data attribute. What would me the easiest way to do this ? I am using RS in this case as an image-slider only.

  30. Support Staff 60 Posted by Dmytro Semenov on 02 May, 2017 11:55 AM

    Dmytro Semenov's Avatar

    @detlef, you can access content of the current slide via $('.royalSlider').data('royalSlider').currSlide.content. In event like rsAfterSlideChange

Reply to this discussion

Internal reply

Formatting help / Preview (switch to plain text) No formatting (switch to Markdown)

Attaching KB article:


Already uploaded files

  • Bildschirmfoto_2012-08-23_um_10.07.21.png 63.1 KB

Attached Files

You can attach files up to 10MB

If you don't have an account yet, we need to confirm you're human and not a machine trying to post spam.

Keyboard shortcuts


? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac