Anchor Jumping by Using JavaScript

anchor jumping by using javascript

You can get the coordinate of the target element and set the scroll position to it. But this is so complicated.

Here is a lazier way to do that:

function jump(h){
var url = location.href; //Save down the URL without hash.
location.href = "#"+h; //Go to the target element.
history.replaceState(null,null,url); //Don't like hashes. Changing it back.
}

This uses replaceState to manipulate the url. If you also want support for IE, then you will have to do it the complicated way:

function jump(h){
var top = document.getElementById(h).offsetTop; //Getting Y of target element
window.scrollTo(0, top); //Go there directly or some transition
}​

Demo: http://jsfiddle.net/DerekL/rEpPA/

Another one w/ transition: http://jsfiddle.net/DerekL/x3edvp4t/

You can also use .scrollIntoView:

document.getElementById(h).scrollIntoView();   //Even IE6 supports this

(Well I lied. It's not complicated at all.)

Javascript - Jump to anchor function

Instead of

window.location.href.match(/\#more/)

you can just do

window.location.hash == '#more'

and instead of assigning to the fragment, you can use the scrollIntoView method as described at https://developer.mozilla.org/en/DOM/element.scrollIntoView

Summary

The scrollIntoView() method scrolls the element into view.

Syntax

element.scrollIntoView(alignWithTop);

alignWithTop Optional

If true, the scrolled element is aligned with the top of the scroll area. If false, it is aligned with the bottom.

Note: By default, the element is scrolled to align with the top of the scroll area.

How to go to an HTML anchor programatically in shiny?

You could use javascript for that. There are several possibilities, one way would be to get the element and use scrollIntoView(), see anchor jumping by using javascript.

An easy way to use javascript in shiny, is library(shinyjs).

You could insert the following to tell R to move the element in focus:

runjs('
document.getElementById("anchor_box").scrollIntoView();
')

In order to know, when to do so, you could wrap it within a observeEvent():

observeEvent(eventExpr = input$clck, handlerExpr = {...})

Downside would be that refreshing the page would not automatically "scroll up to the top".

Reproducible example:

library(shiny)
library(shinyjs)

ui <- fluidPage(

a("Go to Results", href = '#anchor_box'),
actionButton("clck", "Move Programmatically!"),

plotOutput("plot", height = 1300),
div(id = "anchor_box", "HERE"),
useShinyjs(),

)

server <- function(input, output, session) {

output$plot <- renderPlot({
plot(1)
})

observeEvent(eventExpr = input$clck, handlerExpr = {
runjs('
document.getElementById("anchor_box").scrollIntoView();
')
})

}

shinyApp(ui, server)

Preventing anchor from jumping on page load

You can circumvent the browser behavior by changing the anchor so that it carries some additional text that will be unique to the page visit. In the example below, I've added the first six lines to your function to set the AnchorSeed variable, and then I've used that variable where you assign the urlHash variable:

$(window).on("load", function() {
var AnchorSeed = new Date() * 1;
$( ".AnchorUpdate" ).each(
function() {
$( this ).attr( "id", this.id + AnchorSeed );
}
);
if (location.hash) { // do the test straight away
window.scrollTo(0, 0); // execute it straight away
setTimeout(function() {
window.scrollTo(0, 0); // run it a bit later also for browser compatibility
}, 1);
}
var urlHash = window.location.href.split("#")[1] + AnchorSeed;
if (urlHash && $('#' + urlHash).length)
$('html,body').animate({
scrollTop: $('#' + urlHash).offset().top - 75
}, 800, 'swing');
});

And you'll need to add the AnchorUpdate class to any page element that you might jump to, so that the jQuery routine can find it and update its id with the AnchorSeed value. In this case, we know that "portfolio" is such a link, so it would be modified as:

<div class="AnchorUpdate" id="portfolio></div>

The effect of this is that the id will change from "portfolio" to something like "portfolio1382124849780" (depending, of course, on the time stamp when the page was loaded).

Because the id "portfolio" won't exist when the page finishes loading (even though it is part of the source HTML), the browswer shouldn't bounce to it.

I used JavaScript entirely because I didn't know if you had access to server variables. If you do, I think they might be a preferable solution, as the code will be more readable. You might use a page counter variable, or simply a server-side timestamp, if possible.

Edit:

In the comments you mentioned that this was working for external links, but that it broke internal links. I don't have time to set up a test right now, but I think it would work to add a jQuery routine to update those internal links similar to what is being done above. For example, your internal link is:

<a href="#InternalLink">Jump to Internal Link</a>

You might give it a different class indicating that it needs updating:

<a class="InternalLinkUpdate" href="#InternalLink">Jump to Internal Link</a>

And then trigger a similar modification of that class using jQuery:

$( ".InternalLinkUpdate" ).each(
function() {
$( this ).attr( "href", $( this ).attr( "href" ) + AnchorSeed );
}
);

(Since I'm not able to copy from working code at the moment, I might have made a punctuation error or such in the above -- but it shouldn't take too much tinkering to get it to work properly.



Related Topics



Leave a reply



Submit