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
OptionalIf 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
Html5 Canvas Ctx.Filltext Won't Do Line Breaks
Anchor Jumping by Using JavaScript
How to Remove Tinymce and Then Re-Add It
How to Add Drop-Down List (<Select>) Programmatically
How to Access Shadow Dom Elements Through the Parent Document
Scroll with Anchor Without # in Url
Want HTML Form Submit to Do Nothing
Replace Innerhtml in Contenteditable Div
Setting CSS Value Limits of the Window Scrolling Animation
HTML Input Type="Number" Still Returning a String When Accessed from JavaScript
Integrating Dropzone.Js into Existing HTML Form with Other Fields
Why Element.Style Always Return Empty in Js
Print Specific Part of Webpage
How Filereader.Readastext in HTML5 File API Works
How to Auto-Submit an Upload Form When a File Is Selected