Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix for "scroll to page anchor" #68

Merged
merged 1 commit into from Jun 23, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
134 changes: 78 additions & 56 deletions js/common.js
Expand Up @@ -10,40 +10,6 @@ String.prototype.toInt = function()
return parseInt(this);
}

/* {{{ Hash Scroll */
var jHtmlBody = $('html, body');
function scroll(target, interval)
{
if (typeof interval == 'undefined') {
interval = 400;
}

var hash = target;
target = $('[id="' + target.substring(1) + '"]');

var offsetTop =
target.offset().top
- 52
- target.css('margin-top').toInt()
;

jHtmlBody.animate(
{scrollTop: offsetTop},
interval,
function()
{
if (window.location.hash != hash)
{
window.location.hash = hash;
window.scrollTo(0, offsetTop);
}
}
);

return false;
}
/* }}} */

/** {{{
* jQuery.ScrollTo - Easy element scrolling using jQuery.
* Copyright (c) 2007-2013 Ariel Flesler - aflesler<a>gmail<d>com | http://flesler.blogspot.com
Expand All @@ -54,6 +20,83 @@ function scroll(target, interval)
(function($){var h=$.scrollTo=function(a,b,c){$(window).scrollTo(a,b,c)};h.defaults={axis:'xy',duration:parseFloat($.fn.jquery)>=1.3?0:1,limit:true};h.window=function(a){return $(window)._scrollable()};$.fn._scrollable=function(){return this.map(function(){var a=this,isWin=!a.nodeName||$.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!isWin)return a;var b=(a.contentWindow||a).document||a.ownerDocument||a;return/webkit/i.test(navigator.userAgent)||b.compatMode=='BackCompat'?b.body:b.documentElement})};$.fn.scrollTo=function(e,f,g){if(typeof f=='object'){g=f;f=0}if(typeof g=='function')g={onAfter:g};if(e=='max')e=9e9;g=$.extend({},h.defaults,g);f=f||g.duration;g.queue=g.queue&&g.axis.length>1;if(g.queue)f/=2;g.offset=both(g.offset);g.over=both(g.over);return this._scrollable().each(function(){if(e==null)return;var d=this,$elem=$(d),targ=e,toff,attr={},win=$elem.is('html,body');switch(typeof targ){case'number':case'string':if(/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)){targ=both(targ);break}targ=$(targ,this);if(!targ.length)return;case'object':if(targ.is||targ.style)toff=(targ=$(targ)).offset()}$.each(g.axis.split(''),function(i,a){var b=a=='x'?'Left':'Top',pos=b.toLowerCase(),key='scroll'+b,old=d[key],max=h.max(d,a);if(toff){attr[key]=toff[pos]+(win?0:old-$elem.offset()[pos]);if(g.margin){attr[key]-=parseInt(targ.css('margin'+b))||0;attr[key]-=parseInt(targ.css('border'+b+'Width'))||0}attr[key]+=g.offset[pos]||0;if(g.over[pos])attr[key]+=targ[a=='x'?'width':'height']()*g.over[pos]}else{var c=targ[pos];attr[key]=c.slice&&c.slice(-1)=='%'?parseFloat(c)/100*max:c}if(g.limit&&/^\d+$/.test(attr[key]))attr[key]=attr[key]<=0?0:Math.min(attr[key],max);if(!i&&g.queue){if(old!=attr[key])animate(g.onAfterFirst);delete attr[key]}});animate(g.onAfter);function animate(a){$elem.animate(attr,f,g.easing,a&&function(){a.call(this,targ,g)})}}).end()};h.max=function(a,b){var c=b=='x'?'Width':'Height',scroll='scroll'+c;if(!$(a).is('html,body'))return a[scroll]-$(a)[c.toLowerCase()]();var d='client'+c,html=a.ownerDocument.documentElement,body=a.ownerDocument.body;return Math.max(html[scroll],body[scroll])-Math.min(html[d],body[d])};function both(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);
/*}}}*/


var PHP_NET = {};

PHP_NET.HEADER_HEIGHT = 52;

/**
* Scrolls the page so that the given element will be shown into view.
*
* @param HTMLElement element The element to show.
* @param Number animationDuration Animation duration in milliseconds. Defaults to 400ms.
* @param Function callback Function to execute after the animation is complete.
* @return void
*/
PHP_NET.scrollElementIntoView = function(element, animationDuration, callback){
animationDuration = animationDuration || 400;
var destTop = $(element).offset().top - PHP_NET.HEADER_HEIGHT;
var callbackCalled = false;
$('html, body').animate(
{scrollTop: destTop},
animationDuration,
function(){
// prevents the callback to be called twice. temporary
// solution until further investigation is done
if(!callbackCalled) callback();
callbackCalled = true;
}
);
};

/**
* Enables "smooth scrolling to page anchor" for page <a> links.
*/
$(document).ready(function(){
$('a[href*=#]').click(function(e){
var urlTester = document.createElement("a");
urlTester.href = this.href;
urlTester.hash = location.hash;
var targetElement = document.getElementById(this.hash.substr(1));
// this <a> targets an id="" on this very page
// (the current URL and the target URL
// are identic not considering their #hash fragments)
if(urlTester.href == location.href && targetElement){
// temporarily disable the id="" attribute from such element
// so that UA's default scrolling is prevented
var wasID = targetElement.id;
targetElement.id = "";
PHP_NET.scrollElementIntoView(targetElement, null, function(){
// restore the id="" attribute to the element
targetElement.id = wasID;
});
}
});
});

/**
* Enables "smooth scrolling to page anchor" when page was just loaded.
*/
$(document).ready(function(){
var targetElm = location.hash ? document.getElementById(location.hash.substr(1)) : null;
// if the location.hash points to an element that is actually in the document
if(targetElm){
// temporarily disable the id="" attribute from such element so that UA's default scrolling is prevented
var wasID = targetElm.id;
targetElm.id = "";
// so when page is fully loaded and after some delay for a smoother result
$(window).load(function(){
setTimeout(function(){
// animate the scrolling so that the element is shown into viewport
PHP_NET.scrollElementIntoView(targetElm, null, function(){
// finally restore the id="" attribute to the element
targetElm.id = wasID;
});
}, 300);
});
}
});

Mousetrap.bind('up up down down left right left right b a enter', function() {
$(".brand img").attr("src", "/images/php_konami.gif");
});
Expand Down Expand Up @@ -313,15 +356,6 @@ Mousetrap.bind("l o g o enter", function(e) {
$(".brand img").attr("src", "/images/logo.php?refresh&time=" + time);
});

$(window).load(function()
{
// Fire our scroll, webkit needs onload
if (window.location.hash)
{
scroll(window.location.hash, 0);
}
});

function fixTimeout() {
Mousetrap.trigger("m i r r o r enter");
setTimeout(function() {
Expand Down Expand Up @@ -376,19 +410,7 @@ $(document).ready(function() {
var $this = $(this);
$this.append("<a class='genanchor' href='#" + $this.attr('id') + "'> ¶</a>");
});

// Bind events for #[id]
$(window).on('hashchange', function(e) {
e.preventDefault();
return false;
});

$('a[href^=#]').click(function(e) {
e.preventDefault();
scroll($.attr(this, 'href'), 400);
return false;
});


/* Don't load elephpants on browsers that don't support data: URIs.
* Unfortunately, the Modernizr test is asynchronous, so we have to spin
* until it actually gives us a yes or a no. */
Expand Down