diff --git a/js/common.js b/js/common.js index 84f739bbbd..c4f7b82b55 100755 --- a/js/common.js +++ b/js/common.js @@ -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 - afleslergmailcom | http://flesler.blogspot.com @@ -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 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 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"); }); @@ -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() { @@ -376,19 +410,7 @@ $(document).ready(function() { var $this = $(this); $this.append(" ΒΆ"); }); - - // 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. */