From 02915210f45365f53e5d90e51bf8879487de1e4e Mon Sep 17 00:00:00 2001 From: squidfunk Date: Sat, 24 Sep 2016 19:12:05 +0200 Subject: [PATCH] Fix jittery scroll bouncing --- ...ation-db87fe00d3.js => application-a233641b81.js} | 2 +- material/base.html | 2 +- src/assets/javascripts/components/sidebar.js | 12 ++++++++---- 3 files changed, 10 insertions(+), 6 deletions(-) rename material/assets/javascripts/{application-db87fe00d3.js => application-a233641b81.js} (75%) diff --git a/material/assets/javascripts/application-db87fe00d3.js b/material/assets/javascripts/application-a233641b81.js similarity index 75% rename from material/assets/javascripts/application-db87fe00d3.js rename to material/assets/javascripts/application-a233641b81.js index 5178ad9f2..e2f8bc10a 100644 --- a/material/assets/javascripts/application-db87fe00d3.js +++ b/material/assets/javascripts/application-a233641b81.js @@ -5,4 +5,4 @@ * @copyright The Financial Times Limited [All Rights Reserved] * @license MIT License (see LICENSE.txt) */ -function o(e,t){function n(e,t){return function(){return e.apply(t,arguments)}}var i;if(t=t||{},this.trackingClick=!1,this.trackingClickStart=0,this.targetElement=null,this.touchStartX=0,this.touchStartY=0,this.lastTouchIdentifier=0,this.touchBoundary=t.touchBoundary||10,this.layer=e,this.tapDelay=t.tapDelay||200,this.tapTimeout=t.tapTimeout||700,!o.notNeeded(e)){for(var r=["onMouse","onClick","onTouchStart","onTouchMove","onTouchEnd","onTouchCancel"],s=this,c=0,l=r.length;c=0,a=navigator.userAgent.indexOf("Android")>0&&!r,s=/iP(ad|hone|od)/.test(navigator.userAgent)&&!r,c=s&&/OS 4_\d(_\d)?/.test(navigator.userAgent),l=s&&/OS [6-7]_\d/.test(navigator.userAgent),u=navigator.userAgent.indexOf("BB10")>0;o.prototype.needsClick=function(e){switch(e.nodeName.toLowerCase()){case"button":case"select":case"textarea":if(e.disabled)return!0;break;case"input":if(s&&"file"===e.type||e.disabled)return!0;break;case"label":case"iframe":case"video":return!0}return/\bneedsclick\b/.test(e.className)},o.prototype.needsFocus=function(e){switch(e.nodeName.toLowerCase()){case"textarea":return!0;case"select":return!a;case"input":switch(e.type){case"button":case"checkbox":case"file":case"image":case"radio":case"submit":return!1}return!e.disabled&&!e.readOnly;default:return/\bneedsfocus\b/.test(e.className)}},o.prototype.sendClick=function(e,t){var n,i;document.activeElement&&document.activeElement!==e&&document.activeElement.blur(),i=t.changedTouches[0],n=document.createEvent("MouseEvents"),n.initMouseEvent(this.determineEventType(e),!0,!0,window,1,i.screenX,i.screenY,i.clientX,i.clientY,!1,!1,!1,!1,0,null),n.forwardedTouchEvent=!0,e.dispatchEvent(n)},o.prototype.determineEventType=function(e){return a&&"select"===e.tagName.toLowerCase()?"mousedown":"click"},o.prototype.focus=function(e){var t;s&&e.setSelectionRange&&0!==e.type.indexOf("date")&&"time"!==e.type&&"month"!==e.type?(t=e.value.length,e.setSelectionRange(t,t)):e.focus()},o.prototype.updateScrollParent=function(e){var t,n;if(t=e.fastClickScrollParent,!t||!t.contains(e)){n=e;do{if(n.scrollHeight>n.offsetHeight){t=n,e.fastClickScrollParent=n;break}n=n.parentElement}while(n)}t&&(t.fastClickLastScrollTop=t.scrollTop)},o.prototype.getTargetElementFromEventTarget=function(e){return e.nodeType===Node.TEXT_NODE?e.parentNode:e},o.prototype.onTouchStart=function(e){var t,n,i;if(e.targetTouches.length>1)return!0;if(t=this.getTargetElementFromEventTarget(e.target),n=e.targetTouches[0],s){if(i=window.getSelection(),i.rangeCount&&!i.isCollapsed)return!0;if(!c){if(n.identifier&&n.identifier===this.lastTouchIdentifier)return e.preventDefault(),!1;this.lastTouchIdentifier=n.identifier,this.updateScrollParent(t)}}return this.trackingClick=!0,this.trackingClickStart=e.timeStamp,this.targetElement=t,this.touchStartX=n.pageX,this.touchStartY=n.pageY,e.timeStamp-this.lastClickTimen||Math.abs(t.pageY-this.touchStartY)>n},o.prototype.onTouchMove=function(e){return!this.trackingClick||((this.targetElement!==this.getTargetElementFromEventTarget(e.target)||this.touchHasMoved(e))&&(this.trackingClick=!1,this.targetElement=null),!0)},o.prototype.findControl=function(e){return void 0!==e.control?e.control:e.htmlFor?document.getElementById(e.htmlFor):e.querySelector("button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea")},o.prototype.onTouchEnd=function(e){var t,n,i,o,r,u=this.targetElement;if(!this.trackingClick)return!0;if(e.timeStamp-this.lastClickTimethis.tapTimeout)return!0;if(this.cancelNextClick=!1,this.lastClickTime=e.timeStamp,n=this.trackingClickStart,this.trackingClick=!1,this.trackingClickStart=0,l&&(r=e.changedTouches[0],u=document.elementFromPoint(r.pageX-window.pageXOffset,r.pageY-window.pageYOffset)||u,u.fastClickScrollParent=this.targetElement.fastClickScrollParent),i=u.tagName.toLowerCase(),"label"===i){if(t=this.findControl(u)){if(this.focus(u),a)return!1;u=t}}else if(this.needsFocus(u))return e.timeStamp-n>100||s&&window.top!==window&&"input"===i?(this.targetElement=null,!1):(this.focus(u),this.sendClick(u,e),s&&"select"===i||(this.targetElement=null,e.preventDefault()),!1);return!(!s||c||(o=u.fastClickScrollParent,!o||o.fastClickLastScrollTop===o.scrollTop))||(this.needsClick(u)||(e.preventDefault(),this.sendClick(u,e)),!1)},o.prototype.onTouchCancel=function(){this.trackingClick=!1,this.targetElement=null},o.prototype.onMouse=function(e){return!this.targetElement||(!!e.forwardedTouchEvent||(!e.cancelable||(!(!this.needsClick(this.targetElement)||this.cancelNextClick)||(e.stopImmediatePropagation?e.stopImmediatePropagation():e.propagationStopped=!0,e.stopPropagation(),e.preventDefault(),!1))))},o.prototype.onClick=function(e){var t;return this.trackingClick?(this.targetElement=null,this.trackingClick=!1,!0):"submit"===e.target.type&&0===e.detail||(t=this.onMouse(e),t||(this.targetElement=null),t)},o.prototype.destroy=function(){var e=this.layer;a&&(e.removeEventListener("mouseover",this.onMouse,!0),e.removeEventListener("mousedown",this.onMouse,!0),e.removeEventListener("mouseup",this.onMouse,!0)),e.removeEventListener("click",this.onClick,!0),e.removeEventListener("touchstart",this.onTouchStart,!1),e.removeEventListener("touchmove",this.onTouchMove,!1),e.removeEventListener("touchend",this.onTouchEnd,!1),e.removeEventListener("touchcancel",this.onTouchCancel,!1)},o.notNeeded=function(e){var t,n,i,o;if("undefined"==typeof window.ontouchstart)return!0;if(n=+(/Chrome\/([0-9]+)/.exec(navigator.userAgent)||[,0])[1]){if(!a)return!0;if(t=document.querySelector("meta[name=viewport]")){if(t.content.indexOf("user-scalable=no")!==-1)return!0;if(n>31&&document.documentElement.scrollWidth<=window.outerWidth)return!0}}if(u&&(i=navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/),i[1]>=10&&i[2]>=3&&(t=document.querySelector("meta[name=viewport]")))){if(t.content.indexOf("user-scalable=no")!==-1)return!0;if(document.documentElement.scrollWidth<=window.outerWidth)return!0}return"none"===e.style.msTouchAction||"manipulation"===e.style.touchAction||(o=+(/Firefox\/([0-9]+)/.exec(navigator.userAgent)||[,0])[1],!!(o>=27&&(t=document.querySelector("meta[name=viewport]"),t&&(t.content.indexOf("user-scalable=no")!==-1||document.documentElement.scrollWidth<=window.outerWidth)))||("none"===e.style.touchAction||"manipulation"===e.style.touchAction))},o.attach=function(e,t){return new o(e,t)},i=function(){return o}.call(t,n,t,e),!(void 0!==i&&(e.exports=i))}()},function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;n0&&this.el_[t-1].classList.add("md-nav__link--marked"),this.index_=t}else for(var i=this.index_;i>=0;i--){var o=document.querySelector(this.el_[i].hash);if(!(o.offsetTop>window.pageYOffset)){this.index_=i;break}i>0&&this.el_[i-1].classList.remove("md-nav__link--marked")}this.offset_=window.pageYOffset}},{key:"reset",value:function(){[].forEach.call(this.el_,function(e){e.classList.remove("md-nav__link--marked")})}},{key:"listen",value:function(){var e=this;["scroll","resize","orientationchange"].forEach(function(t){window.addEventListener(t,e.handler_,!1)}),this.update()}},{key:"unlisten",value:function(){var e=this;["scroll","resize","orientationchange"].forEach(function(t){window.removeEventListener(t,e.handler_,!1)}),this.reset()}}]),e}();t["default"]=o},function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;n=0,a=navigator.userAgent.indexOf("Android")>0&&!r,s=/iP(ad|hone|od)/.test(navigator.userAgent)&&!r,c=s&&/OS 4_\d(_\d)?/.test(navigator.userAgent),l=s&&/OS [6-7]_\d/.test(navigator.userAgent),u=navigator.userAgent.indexOf("BB10")>0;o.prototype.needsClick=function(e){switch(e.nodeName.toLowerCase()){case"button":case"select":case"textarea":if(e.disabled)return!0;break;case"input":if(s&&"file"===e.type||e.disabled)return!0;break;case"label":case"iframe":case"video":return!0}return/\bneedsclick\b/.test(e.className)},o.prototype.needsFocus=function(e){switch(e.nodeName.toLowerCase()){case"textarea":return!0;case"select":return!a;case"input":switch(e.type){case"button":case"checkbox":case"file":case"image":case"radio":case"submit":return!1}return!e.disabled&&!e.readOnly;default:return/\bneedsfocus\b/.test(e.className)}},o.prototype.sendClick=function(e,t){var n,i;document.activeElement&&document.activeElement!==e&&document.activeElement.blur(),i=t.changedTouches[0],n=document.createEvent("MouseEvents"),n.initMouseEvent(this.determineEventType(e),!0,!0,window,1,i.screenX,i.screenY,i.clientX,i.clientY,!1,!1,!1,!1,0,null),n.forwardedTouchEvent=!0,e.dispatchEvent(n)},o.prototype.determineEventType=function(e){return a&&"select"===e.tagName.toLowerCase()?"mousedown":"click"},o.prototype.focus=function(e){var t;s&&e.setSelectionRange&&0!==e.type.indexOf("date")&&"time"!==e.type&&"month"!==e.type?(t=e.value.length,e.setSelectionRange(t,t)):e.focus()},o.prototype.updateScrollParent=function(e){var t,n;if(t=e.fastClickScrollParent,!t||!t.contains(e)){n=e;do{if(n.scrollHeight>n.offsetHeight){t=n,e.fastClickScrollParent=n;break}n=n.parentElement}while(n)}t&&(t.fastClickLastScrollTop=t.scrollTop)},o.prototype.getTargetElementFromEventTarget=function(e){return e.nodeType===Node.TEXT_NODE?e.parentNode:e},o.prototype.onTouchStart=function(e){var t,n,i;if(e.targetTouches.length>1)return!0;if(t=this.getTargetElementFromEventTarget(e.target),n=e.targetTouches[0],s){if(i=window.getSelection(),i.rangeCount&&!i.isCollapsed)return!0;if(!c){if(n.identifier&&n.identifier===this.lastTouchIdentifier)return e.preventDefault(),!1;this.lastTouchIdentifier=n.identifier,this.updateScrollParent(t)}}return this.trackingClick=!0,this.trackingClickStart=e.timeStamp,this.targetElement=t,this.touchStartX=n.pageX,this.touchStartY=n.pageY,e.timeStamp-this.lastClickTimen||Math.abs(t.pageY-this.touchStartY)>n},o.prototype.onTouchMove=function(e){return!this.trackingClick||((this.targetElement!==this.getTargetElementFromEventTarget(e.target)||this.touchHasMoved(e))&&(this.trackingClick=!1,this.targetElement=null),!0)},o.prototype.findControl=function(e){return void 0!==e.control?e.control:e.htmlFor?document.getElementById(e.htmlFor):e.querySelector("button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea")},o.prototype.onTouchEnd=function(e){var t,n,i,o,r,u=this.targetElement;if(!this.trackingClick)return!0;if(e.timeStamp-this.lastClickTimethis.tapTimeout)return!0;if(this.cancelNextClick=!1,this.lastClickTime=e.timeStamp,n=this.trackingClickStart,this.trackingClick=!1,this.trackingClickStart=0,l&&(r=e.changedTouches[0],u=document.elementFromPoint(r.pageX-window.pageXOffset,r.pageY-window.pageYOffset)||u,u.fastClickScrollParent=this.targetElement.fastClickScrollParent),i=u.tagName.toLowerCase(),"label"===i){if(t=this.findControl(u)){if(this.focus(u),a)return!1;u=t}}else if(this.needsFocus(u))return e.timeStamp-n>100||s&&window.top!==window&&"input"===i?(this.targetElement=null,!1):(this.focus(u),this.sendClick(u,e),s&&"select"===i||(this.targetElement=null,e.preventDefault()),!1);return!(!s||c||(o=u.fastClickScrollParent,!o||o.fastClickLastScrollTop===o.scrollTop))||(this.needsClick(u)||(e.preventDefault(),this.sendClick(u,e)),!1)},o.prototype.onTouchCancel=function(){this.trackingClick=!1,this.targetElement=null},o.prototype.onMouse=function(e){return!this.targetElement||(!!e.forwardedTouchEvent||(!e.cancelable||(!(!this.needsClick(this.targetElement)||this.cancelNextClick)||(e.stopImmediatePropagation?e.stopImmediatePropagation():e.propagationStopped=!0,e.stopPropagation(),e.preventDefault(),!1))))},o.prototype.onClick=function(e){var t;return this.trackingClick?(this.targetElement=null,this.trackingClick=!1,!0):"submit"===e.target.type&&0===e.detail||(t=this.onMouse(e),t||(this.targetElement=null),t)},o.prototype.destroy=function(){var e=this.layer;a&&(e.removeEventListener("mouseover",this.onMouse,!0),e.removeEventListener("mousedown",this.onMouse,!0),e.removeEventListener("mouseup",this.onMouse,!0)),e.removeEventListener("click",this.onClick,!0),e.removeEventListener("touchstart",this.onTouchStart,!1),e.removeEventListener("touchmove",this.onTouchMove,!1),e.removeEventListener("touchend",this.onTouchEnd,!1),e.removeEventListener("touchcancel",this.onTouchCancel,!1)},o.notNeeded=function(e){var t,n,i,o;if("undefined"==typeof window.ontouchstart)return!0;if(n=+(/Chrome\/([0-9]+)/.exec(navigator.userAgent)||[,0])[1]){if(!a)return!0;if(t=document.querySelector("meta[name=viewport]")){if(t.content.indexOf("user-scalable=no")!==-1)return!0;if(n>31&&document.documentElement.scrollWidth<=window.outerWidth)return!0}}if(u&&(i=navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/),i[1]>=10&&i[2]>=3&&(t=document.querySelector("meta[name=viewport]")))){if(t.content.indexOf("user-scalable=no")!==-1)return!0;if(document.documentElement.scrollWidth<=window.outerWidth)return!0}return"none"===e.style.msTouchAction||"manipulation"===e.style.touchAction||(o=+(/Firefox\/([0-9]+)/.exec(navigator.userAgent)||[,0])[1],!!(o>=27&&(t=document.querySelector("meta[name=viewport]"),t&&(t.content.indexOf("user-scalable=no")!==-1||document.documentElement.scrollWidth<=window.outerWidth)))||("none"===e.style.touchAction||"manipulation"===e.style.touchAction))},o.attach=function(e,t){return new o(e,t)},i=function(){return o}.call(t,n,t,e),!(void 0!==i&&(e.exports=i))}()},function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;n0&&this.el_[t-1].classList.add("md-nav__link--marked"),this.index_=t}else for(var i=this.index_;i>=0;i--){var o=document.querySelector(this.el_[i].hash);if(!(o.offsetTop>window.pageYOffset)){this.index_=i;break}i>0&&this.el_[i-1].classList.remove("md-nav__link--marked")}this.offset_=window.pageYOffset}},{key:"reset",value:function(){[].forEach.call(this.el_,function(e){e.classList.remove("md-nav__link--marked")})}},{key:"listen",value:function(){var e=this;["scroll","resize","orientationchange"].forEach(function(t){window.addEventListener(t,e.handler_,!1)}),this.update()}},{key:"unlisten",value:function(){var e=this;["scroll","resize","orientationchange"].forEach(function(t){window.removeEventListener(t,e.handler_,!1)}),this.reset()}}]),e}();t["default"]=o},function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;n - + {% for path in extra_css %} {% endfor %} diff --git a/src/assets/javascripts/components/sidebar.js b/src/assets/javascripts/components/sidebar.js index 92a2d74a9..24aa5c512 100644 --- a/src/assets/javascripts/components/sidebar.js +++ b/src/assets/javascripts/components/sidebar.js @@ -37,6 +37,10 @@ class Sidebar { constructor(el) { this.el_ = (typeof el === 'string') ? document.querySelector(el) : el; + /* Grab inner and outer container */ + this.inner_ = this.el_.parentNode; + this.outer_ = this.el_.parentNode.parentNode; + /* Initialize parameters */ this.height_ = 0; this.locked_ = false; @@ -53,8 +57,8 @@ class Sidebar { * @param {Event} ev - Event */ update(ev) { - let container = this.el_.parentNode; - let bounds = container.getBoundingClientRect(); + let bounds = this.inner_.getBoundingClientRect(); + let parent = this.outer_.offsetTop; /* Determine top and bottom offsets */ let top = bounds.top + window.pageYOffset, @@ -67,14 +71,14 @@ class Sidebar { /* Calculate new bounds */ let offset = top - upper; let height = window.innerHeight - Math.max(lower - bottom, 0) - - Math.max(offset, container.parentNode.offsetTop); + - Math.max(offset, parent); /* If height changed, update element */ if (height != this.height_) this.el_.style.height = (this.height_ = height) + 'px'; /* Sidebar should be locked, as we're below parent offset */ - if (offset < container.parentNode.offsetTop) { + if (offset < parent) { if (!this.locked_) { this.el_.classList.add('md-js__sidebar--locked'); this.locked_ = true;