Skip to content

Commit

Permalink
calculate scrollbar width correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
buschtoens committed Mar 22, 2017
1 parent 27707ed commit 8e68179
Showing 1 changed file with 43 additions and 51 deletions.
94 changes: 43 additions & 51 deletions addon/components/ember-scrollable.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Ember from 'ember';
import InboundActionsMixin from 'ember-component-inbound-actions/inbound-actions';
import DomMixin from 'ember-lifeline/mixins/dom';
import layout from '../templates/components/ember-scrollable';
import {Horizontal, Vertical} from '../classes/scrollable';
import { Horizontal, Vertical } from '../classes/scrollable';

const {
computed,
Expand Down Expand Up @@ -67,10 +67,10 @@ export default Ember.Component.extend(InboundActionsMixin, DomMixin, {
* @type Number
*/
scrollTo: computed('vertical', {
get(){
get() {
return this.get('vertical') ? this.get('scrollToY') : this.get('scrollToX');
},
set(key, value){
set(key, value) {
deprecate('Using the `scrollTo` property directly has been deprecated, please prefer being explicit by using `scrollToX` and `scrollToY`.');
const prop = this.get('vertical') ? 'scrollToY' : 'scrollToX';
this.set(prop, value);
Expand Down Expand Up @@ -215,40 +215,34 @@ export default Ember.Component.extend(InboundActionsMixin, DomMixin, {
this._contentElement = this.$(`${contentSelector}:first`);
},

/**
* Original function by Jonathan Sharp:
* http://jdsharp.us/jQuery/minute/calculate-scrollbar-width.php
*
* Modified to work with newer jQuery version.
*
* @property scrollbarThickness
* @private
* @type Number
*/
scrollbarThickness: computed(() => {
// Append a temporary scrolling element to the DOM, then measure
// the difference between between its outer and inner elements.
let tempEl = $(`
<div class="scrollbar-width-tester" style="width: 50px; position: absolute; top: 0px;">
<div style="overflow: scroll;">
<div class="scrollbar-width-tester__inner"></div>
</div>
</div>
`);
$('body').append(tempEl);
let width = $(tempEl).width();
let widthMinusScrollbars = $('.scrollbar-width-tester__inner', tempEl).width();
tempEl.remove();

return (width - widthMinusScrollbars);
}),

measureScrollbar() {

/**
* Calculate scrollbar width
*
* Original function by Jonathan Sharp:
* http://jdsharp.us/jQuery/minute/calculate-scrollbar-width.php
* Updated to work in Chrome v25.
*/
function scrollbarWidth() {
// Append a temporary scrolling element to the DOM, then measure
// the difference between between its outer and inner elements.
var tempEl = $('<div class="scrollbar-width-tester" style="width:50px;height:50px;overflow-y:scroll;position:absolute;top:-200px;left:-200px;"><div style="height:100px;"></div>');
$('body').append(tempEl);
var width = $(tempEl).innerWidth();
var widthMinusScrollbars = $('div', tempEl).innerWidth();
tempEl.remove();

// On OS X if the scrollbar is set to auto hide it will have zero width. On webkit we can still
// hide it using ::-webkit-scrollbar { width:0; height:0; } but there is no moz equivalent. So we're
// forced to sniff Firefox and return a hard-coded scrollbar width. I know, I know...

// https://github.com/alphasights/ember-scrollable/issues/34
// if (width === widthMinusScrollbars && navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
// return 17;
// }

return (width - widthMinusScrollbars);
}

return scrollbarWidth();

},

/**
* Used to create/reset scrollbar(s) if they are necessary
Expand All @@ -264,7 +258,7 @@ export default Ember.Component.extend(InboundActionsMixin, DomMixin, {
});
},

_resizeHandler(){
_resizeHandler() {
debounce(this, this.resizeScrollbar, 16);
},

Expand All @@ -275,23 +269,21 @@ export default Ember.Component.extend(InboundActionsMixin, DomMixin, {
resizeScrollContent() {
const width = this.$().width();
const height = this.$().height();
const scrollbarThickness = this.measureScrollbar();
const scrollbarThickness = this.get('scrollbarThickness');

const hasHorizontal = this.get('horizontal');
const hasVertical = this.get('vertical');

if (hasHorizontal && hasVertical) {
this.set('scrollContentWidth', width + scrollbarThickness);
this.set('scrollContentHeight', height + scrollbarThickness);
} else if (hasHorizontal) {
this.set('scrollContentWidth', width);
this.set('scrollContentHeight', height + scrollbarThickness);
this._contentElement.height(height);
} else {
if (hasHorizontal) {
this.set('scrollContentWidth', width);
this.set('scrollContentHeight', height + scrollbarThickness);
this._contentElement.height(height);
} else {
this.set('scrollContentWidth', width + scrollbarThickness);
this.set('scrollContentHeight', height);
}
this.set('scrollContentWidth', width + scrollbarThickness);
this.set('scrollContentHeight', height);
}
},

Expand Down Expand Up @@ -336,7 +328,7 @@ export default Ember.Component.extend(InboundActionsMixin, DomMixin, {
* @method mouseMove
* @private
*/
mouseMove(){
mouseMove() {
if (this.get('autoHide')) {
throttle(this, this.showScrollbar, THROTTLE_TIME_LESS_THAN_60_FPS_IN_MS);
}
Expand All @@ -349,8 +341,8 @@ export default Ember.Component.extend(InboundActionsMixin, DomMixin, {
* @param e
* @private
*/
updateMouseOffset(e){
const {pageX, pageY} = e;
updateMouseOffset(e) {
const { pageX, pageY } = e;
this.set('horizontalMouseOffset', pageX);
this.set('verticalMouseOffset', pageY);
},
Expand Down Expand Up @@ -378,7 +370,7 @@ export default Ember.Component.extend(InboundActionsMixin, DomMixin, {
* @private
*/
updateScrollbarAndSetupProperties(scrollOffset, scrollbarDirection) {
const {handleOffset, handleSize} = this.get(`${scrollbarDirection}Scrollbar`).getHandlePositionAndSize(scrollOffset);
const { handleOffset, handleSize } = this.get(`${scrollbarDirection}Scrollbar`).getHandlePositionAndSize(scrollOffset);
this.set(`${scrollbarDirection}HandleOffset`, handleOffset);
this.set(`${scrollbarDirection}HandleSize`, handleSize);
},
Expand Down Expand Up @@ -522,7 +514,7 @@ export default Ember.Component.extend(InboundActionsMixin, DomMixin, {
scrollTop() {
this.set('scrollToY', 0);
},
scrolled(){
scrolled() {
scheduleOnce('afterRender', this, 'scrolled', ...arguments);
},
horizontalDrag(dragPerc) {
Expand Down

0 comments on commit 8e68179

Please sign in to comment.