Files
phabricator/webroot/rsrc/js/application/diff/ScrollObjectiveList.js
epriestley aba209e999 Hide the Differential scroll objective list on trackpad systems
Summary:
Ref T12733. In the longer run I'd like to just push this out from the edge, but that currently gets us into trouble since we start bumping into content. On my system, the trackpad scrollbar also expands in size when moused over, so the minimum number of pixels we need to push it out is approximatley 15px. This hits body content and the persistent chat.

For now, just disable this element on trackpad systems.

Test Plan:
Disconnected all USB peripherals, quit and relaunched Safari, saw no objective list.

Reconnected mouse, relaunched Safari, saw objective list.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T12733

Differential Revision: https://secure.phabricator.com/D17974
2017-05-20 07:56:21 -07:00

146 lines
3.3 KiB
JavaScript

/**
* @provides phabricator-scroll-objective-list
* @requires javelin-dom
* javelin-util
* javelin-stratcom
* javelin-install
* javelin-workflow
* javelin-scrollbar
* phabricator-scroll-objective
* @javelin
*/
JX.install('ScrollObjectiveList', {
construct : function() {
this._objectives = [];
var onresize = JX.bind(this, this._dirty);
JX.Stratcom.listen('resize', null, onresize);
},
members: {
_objectives: null,
_visible: false,
_trigger: null,
newObjective: function() {
var objective = new JX.ScrollObjective()
.setObjectiveList(this);
this._objectives.push(objective);
this._getNode().appendChild(objective.getNode());
this._dirty();
return objective;
},
show: function() {
this._visible = true;
this._dirty();
return this;
},
hide: function() {
this._visible = false;
this._dirty();
return this;
},
_getNode: function() {
if (!this._node) {
var node = new JX.$N('div', {className: 'scroll-objective-list'});
this._node = node;
}
return this._node;
},
_dirty: function() {
if (this._trigger !== null) {
return;
}
this._trigger = setTimeout(JX.bind(this, this._redraw), 0);
},
_redraw: function() {
this._trigger = null;
var node = this._getNode();
var is_visible =
(this._visible) &&
(JX.Device.getDevice() == 'desktop') &&
(this._objectives.length);
if (!is_visible) {
JX.DOM.remove(node);
return;
}
document.body.appendChild(node);
// If we're on OSX without a mouse or some other system with zero-width
// trackpad-style scrollbars, adjust the display appropriately.
var aesthetic = (JX.Scrollbar.getScrollbarControlWidth() === 0);
JX.DOM.alterClass(node, 'has-aesthetic-scrollbar', aesthetic);
var d = JX.Vector.getDocument();
var list_dimensions = JX.Vector.getDim(node);
var icon_height = 16;
var list_y = (list_dimensions.y - icon_height);
var ii;
var offset;
// First, build a list of all the items we're going to show.
var items = [];
for (ii = 0; ii < this._objectives.length; ii++) {
var objective = this._objectives[ii];
var objective_node = objective.getNode();
var anchor = objective.getAnchor();
if (!anchor || !objective.isVisible()) {
JX.DOM.remove(objective_node);
continue;
}
offset = (JX.$V(anchor).y / d.y) * (list_y);
items.push({
offset: offset,
node: objective_node
});
}
// Now, sort it from top to bottom.
items.sort(function(u, v) {
return u.offset - v.offset;
});
// Lay out the items in the objective list, leaving a minimum amount
// of space between them so they do not overlap.
var min = null;
for (ii = 0; ii < items.length; ii++) {
var item = items[ii];
offset = item.offset;
if (min !== null) {
offset = Math.max(offset, min);
}
min = offset + 15;
item.node.style.top = offset + 'px';
node.appendChild(item.node);
}
}
}
});