Linking within the page - javascript

I have seen a lot of websites where they are linking in the same page.
(demo)
The problem in this system is, when you reload the page after clicking the link (which refers you to the selected area), the page immediately scrolled to the selected area, because the click on the link leaves a #name on the URL page (even when reloading), for example:
www.example.com/#down
I have seen also websites, where they don't add #name to the URL line but you still referred to the linked area.
I guessed this has been made by jQuery or Javascript but I couldn't find (inspect element and page's source) the code (I found this system in high-tech sites, where they have a lot of js files and it was complicated to find).
My real question is: how can I link within my website, without using the hash-tag|name system?

The behaviour you describe is the intended, desired behaviour of anchors. As has been said...
Websites aren't broken by default, they are functional, high-performing, and accessible. You break them.
You can have an event listener detect clicks on links and scroll accordingly. jQuery would be something like this:
$(document).on("click", "a[href*='#']", function(evt) {
evt.preventDefault();
var target = this.href.split("#")[1];
var elm = document.getElementById(target);
if( elm) elm.scrollIntoView(); // or replace with fancy scrollTo plugin
});
However, be aware that doing this decreases usability. From xkcd...

Working DEMO
HTML:
GO SEE THE DEMO
jQuery:
$("a").click(function(event) {
event.preventDefault();
var divId = $(this).attr('href');
$('html, body').animate({
scrollTop: $(divId).offset().top
}, 500);
});

Related

jquery go to anchor on page load

i have a WordPress site and problems with anchors. i have a page with several anchors which are linked to in the main menu. when i am on the page itself, all anchors work fine, but if I'am on any other page, they don't work, at least not in all browsers and the anchors are ignored.
As being informed it is a chrome bug, ive found this solution:
<script type="text/javascript">
jQuery(window).load(function(){
var hashNum = 0;
if (window.location.hash != ''){
hashNum = window.location.hash.replace("#oneofmanyanchors", "");
console.log('hashNum: ' + hashNum);
};
hashMenu = jQuery('[data-q_id="#oneofmanyanchors"]').offset().top;
jQuery('html,body').animate({
scrollTop: hashMenu
}, 0);
});
</script>
above code is working and fixes the issues i had in chrome and ff.
however i need this added functionality: At the moment it is addressing only one specific anchor, but i need it to work with any anchors in the page url, not just the one above (anchors are referenced with the data-q_id attribute).
so the code needs to be updated that it grabs any given anchor from the page URL and go to / scroll to that anchor (once) via jquery after first page load.
How do i achieve this?
Thanks in advance!
PS: The problem is caused by theme incompatibility with a certain plugin i need...
I think this should work in every browser - what happens to be the problem?
In order to achieve this in jquery you should scroll to the element/anchor with javascript as soon as the document is loaded.
So like this:
$(function() {
location.hash = "#" + hash;
});
I still think you should find out what went wrong and why the linken from another page doesn't work in some browser before using a workaround for the problem. Your code will just ged more and more messy like that.
How to scroll HTML page to given anchor using jQuery or Javascript?
and here
$(document).ready shorthand

ScrollTo: targeting specific buttons in a navbar

Got an issue with a navbar I'm creating for a WordPress site. Some of the links are meant to scroll down to different places on the homepage and some are outside links to other places on the site. Something like this:
<div class="main-navigation">
<ul>
<li class="link1">Link 1
<li class="link2">Link 2
</ul>
</div>
Basic stuff.
So if I add the following Javascript in the footer....
jQuery(document).ready(function() {
jQuery('.main-navigation a' ).click(function(){
jQuery.scrollTo( this.hash, 1000, { easing:'swing' });
return false;
});
Link 2 will scroll down but since Link 1 isn't supposed to scroll, if you click on it, nothing happens like it's a null link.
I thought I could change the reference to something like
jQuery('.main-navigation a.link2' ).click(function(){
So only link 2 does the scrolling, but that just makes it jump to the page like an old anchor tag trick in the 1990's.
Tried a few variations of the same idea, and nothing clicked. Anyone know what the right code would be to target just the buttons that need to have the scrolling?
Building from itsgoingdown's answer. The animation is ignored because the default link event still fires. If you pass the event and also prevent the default, you'll be set. See below.
$(document).ready(function() {
$('.main-navigation a[href^="#"]' ).click(function(event) {
// Prevent default link action
event.preventDefault();
// Grab location to send to
var href = $(this).attr('href');
// Scroll the page, animated
$('html, body').animate({
scrollTop: $(href).offset().top
}, 700);
});
});
Here is a live JSFiddle to show as well.
https://jsfiddle.net/y3nutj22/5/
Thanks to the both of you. I finally figured it out and in a sense, you're both right. However, neither of your codes produced the scrollTo effect. While '.main-navigation a[href^="#"]' was partially correct, my issue....and I finally realized it this morning....was I hard coded in the URL's in WordPress' menu feature as a complete URL. So just using '#' wouldn't work. Also, since it's WP, I can't use $'s in the code, Have ot use jQuery, of course.
This is the code that did the trick.
jQuery(document).ready(function() {
jQuery('.main-navigation a[href^="http://path.to.url/#"]' ).click(function(){
jQuery.scrollTo( this.hash, 1000, { easing:'swing' });
return false;
});
with path.to.url representing the actual URL, of course.
Thanks again!

How to make this grid work

I purchased a html5 theme that I am customizing for my church website. It has two cool features:
A tab script that allows for multiple items to displayed on one page.
a grid that will allow me to display sermons in a series in a neat and orderly way.
Both of these work well when used alone, but when I try to use the grid inside the tabs, no dice.
I am a design guy and know very little about Javascript functions and need help. Here is what the developer, who has not got back with me said to do:
"The grid function is built to run on page load and when you put it inside a tab it doesn’t initialize on page load so don’t work when you change tabs. A custom function needs to be built for this which will run the isotope grid on tabs change. Like:"
$(".nav-tabs li")click(function(e){
ADORE.IsoTope();
e.preventDefault();
}
I do not know where to add this or even if something else needs to be added. I have also attached a link where you can download my code (html/php and .js file) so you can see what is going on. Any help would be appreciated. Remember, I know very little about Javascript.
https://www.dropbox.com/s/jypfjz3a89soxh7/example.zip?dl=0
Add:
$(".nav-tabs li a").click(function(e){
$('a[href="' + $(this).attr('href') + '"]').tab('show');
var IsoTopeCont = $(".isotope-grid");
IsoTopeCont.isotope({
itemSelector: ".grid-item",
layoutMode: 'sloppyMasonry'
});
});
at Line 469 of your init.js and it should work for you. Thanks
You can try the following: inside your init.js add the following:
$(".nav-tabs li").click(function(e){
e.preventDefault();
ADORE.IsoTope();
});
e.g. in the first line after var ADORE = window.ADORE || {};
As you mentioned that you don't know much about javascript: the first line starts with
jQuery(function($){ ...
This takes care about that everything inside the { will get executed when jQuery is loaded.
I'm not sure if the e.preventDefault(); is necessary - this is used e.g. to prevent links from getting executed and attach a different function to the click() event, so it could be possible that Isotope is working when a tab is clicked, but the tab is not working anymore.
If this won't work, you can check with web dev tools if there are any script errors. In case you're unfamiliar with web dev tools, find some details for Firefox here: https://developer.mozilla.org/en-US/docs/Tools/Web_Console and for Chrome here: https://developer.chrome.com/devtools/docs/console

How can I tell if a page has jumped to the anchor (#) in JavaScript?

I have some JavaScript that can appear on many different pages. Sometimes those pages have been accessed via a URL containing an anchor reference (#comment-100, for instance). In those cases I want the JavaScript to delay executing until after the window has jumped. Right now I'm just using a delay but that's pretty hackish and obviously doesn't work in all cases. I can't seem to find any sort of DOM event that corresponds to the window "jump".
Aside from the simple delay, the only solution I've come up with is to have the JS look for the anchor in the URL and, if it finds one, watch for changes in scrollTop. But that seems buggy, and I'm not 100% sure that my script will always get fired before the scrolling happens so then it would only run if the user manually scrolled the page. Anyhow, I don't really like the solution and would prefer something more event driven. Any suggestions?
Edit to clarify:
I'm not trying to detect a hash change. Take the following example:
Page index.php contains a link to post.php#comment-1
User clicks the link to post.php#comment-1
post.php#comment-1 loads
$(document).ready fires
Not long later the browser scrolls down to #comment-1
I'm trying to reliably detect when step 5 happens.
You can check window.onhashchange in modern browsers. If you want cross compatible, check out http://benalman.com/projects/jquery-hashchange-plugin/
This page has more info on window.onhashchange as well.
EDIT: You basically replace all anchor names with a similar linking convention, and then use .scrollTo to handle the scrolling:
$(document).ready(function () {
// replace # with #_ in all links containing #
$('a[href*=#]').each(function () {
$(this).attr('href', $(this).attr('href').replace('#', '#_'));
});
// scrollTo if #_ found
hashname = window.location.hash.replace('#_', '');
// find element to scroll to (<a name=""> or anything with particular id)
elem = $('a[name="' + hashname + '"],#' + hashname);
if(elem) {
$(document).scrollTo(elem, 800,{onAfter:function(){
//put after scroll code here }});
}
});
See jQuery: Scroll to anchor when calling URL, replace browsers behaviour for more info.
Seems like you could use window.onscroll. I tested this code just now:
<a name="end" />
<script type="text/javascript">
window.onscroll = function (e) {
alert("scrolled");
}
</script>
which seems to work.
Edit: Hm, it doesn't work in IE8. It works in both Firefox and Chrome though.
Edit: jQuery has a .scroll() handler, but it fires before scrolling on IE and doesn't seem to work for Chrome or Firefox.
To detect when the element appears on the screen, use the appear plugin:
$('#comment-1').appear(function() {
$(this).text('scrolled');
});

jQuery - Could use a little help with a content loader

I'm not very elite when it comes to JavaScript, especially the syntax. So I'm trying to learn. And in this process I'm trying to implement a content loader that basically removes all content from a div and inserts content from another div from a different document.
I've tried to do this on this site:
www.matkalenderen.no - Check the butt ugly link there. See what happens?
I've taken the example from this site:
http://nettuts.s3.cdn.plus.org/011_jQuerySite/sample/index.html#index
But I'm not sure this example actually works the way I think it does. I mean, if the code just wipes out existing content from a div and inserts content from another div, why does the other webpages in this example include doctype and heading etc etc? Wouldn't you just need the div and it's content? Without all the other stuff "around"? Maybe I don't get how this works though. Thought it worked mosly like include really.
This is my code however:
$(document).ready(function() {
var hash = window.location.hash.substr(1);
var href = $('#dynloader a').each(function(){
var href = $(this).attr('href');
if(hash==href.substr(0,href.length-5)){
var toLoad = hash+'.html #container';
$('#container').load(toLoad)
}
});
$('#dynloader a').click(function(){
var toLoad = $(this).attr('href')+' #container';
$('#container').hide('fast',loadcontainer);
$('#load').remove();
$('#wrapper').append('<span id="load">LOADING...</span>');
$('#load').fadeIn('normal');
window.location.hash = $(this).attr('href').substr(0,$(this).attr('href').length-5);
function loadcontainer() {
$('#container').load(toLoad,'',showNewcontainer())
}
function showNewcontainer() {
$('#container').show('normal',hideLoader());
}
function hideLoader() {
$('#load').fadeOut('normal');
}
return false;
});
});
The jQuery .load() has some extra functionality in it to support this.
You can see it in the docs here (look at `Loading Page Fragments')
In your example here's the important part: hash+'.html #container' the space before the #container means that jQuery will grab that URL, look for the element with id="container" and fetch only that element's content's discarding the rest of the page. This lets .load() work in a more generic way without what you're fetching being specifically designed for only ajax loading.
In your case I think you just need to remove #content from the end unless you're looking for that element. It's not saying "look for content" that's just the ID they used for the element they wanted to look for. It could have been #divToLoad which would be a clearer example IMO.

Categories