ares-ide
Version:
A browser-based code editor and UI designer for Enyo 2 projects
201 lines (198 loc) • 6.35 kB
JavaScript
/**
_enyo.ScrollStrategy_ is a helper kind that implements a default scrolling
strategy for an <a href="#enyo.Scroller">enyo.Scroller</a>.
_enyo.ScrollStrategy_ is not typically created in application code.
Instead, it is specified as the value of the `strategyKind` property of an
`enyo.Scroller` or <a href="#enyo.List">enyo.List</a>, or is used by the
framework implicitly.
*/
enyo.kind({
name: "enyo.ScrollStrategy",
tag: null,
published: {
/**
Specifies how to vertically scroll. Acceptable values are:
* "scroll": Always shows a scrollbar; sets _overflow: scroll_.
* "auto": Scrolls only if needed; sets _overflow: auto_.
* "hidden": Never scrolls; sets _overflow: hidden_.
* "default": Same as "auto".
*/
vertical: "default",
/**
Specifies how to horizontally scroll. Acceptable values are:
* "scroll": Always shows a scrollbar; sets _overflow: scroll_.
* "auto": Scrolls only if needed; sets _overflow: auto_.
* "hidden": Never scrolls; sets _overflow: hidden_.
* "default": Same as "auto".
*/
horizontal: "default",
//* Scroll position along horizontal axis
scrollLeft: 0,
//* Scroll position along vertical axis
scrollTop: 0,
//* Maximum height of scroll content
maxHeight: null,
//* Use mouse wheel to move scroller
useMouseWheel: true
},
//* @protected
handlers: {
ondragstart: "dragstart",
ondragfinish: "dragfinish",
ondown: "down",
onmove: "move",
onmousewheel: "mousewheel"
},
create: enyo.inherit(function (sup) {
return function() {
sup.apply(this, arguments);
this.horizontalChanged();
this.verticalChanged();
this.maxHeightChanged();
};
}),
rendered: enyo.inherit(function (sup) {
return function() {
sup.apply(this, arguments);
enyo.makeBubble(this.container, "scroll");
this.scrollNode = this.calcScrollNode();
};
}),
teardownRender: enyo.inherit(function (sup) {
return function() {
sup.apply(this, arguments);
this.scrollNode = null;
};
}),
calcScrollNode: function() {
return this.container.hasNode();
},
horizontalChanged: function() {
this.container.applyStyle("overflow-x", this.horizontal == "default" ? "auto" : this.horizontal);
},
verticalChanged: function() {
this.container.applyStyle("overflow-y", this.vertical == "default" ? "auto" : this.vertical);
},
maxHeightChanged: function() {
this.container.applyStyle("max-height", this.maxHeight);
},
scrollTo: function(inX, inY) {
if (this.scrollNode) {
this.setScrollLeft(inX);
this.setScrollTop(inY);
}
},
scrollToNode: function(inNode, inAlignWithTop) {
if (this.scrollNode) {
var sb = this.getScrollBounds();
var n = inNode;
var b = {height: n.offsetHeight, width: n.offsetWidth, top: 0, left: 0};
while (n && n.parentNode && n.id != this.scrollNode.id) {
b.top += n.offsetTop;
b.left += n.offsetLeft;
n = n.parentNode;
}
// By default, the element is scrolled to align with the top of the scroll area.
this.setScrollTop(Math.min(sb.maxTop, inAlignWithTop === false ? b.top - sb.clientHeight + b.height : b.top));
this.setScrollLeft(Math.min(sb.maxLeft, inAlignWithTop === false ? b.left - sb.clientWidth + b.width : b.left));
}
},
scrollIntoView: function(inControl, inAlignWithTop) {
if (inControl.hasNode()) {
inControl.node.scrollIntoView(inAlignWithTop);
}
},
isInView: function(inNode) {
var sb = this.getScrollBounds();
var ot = inNode.offsetTop;
var oh = inNode.offsetHeight;
var ol = inNode.offsetLeft;
var ow = inNode.offsetWidth;
return (ot >= sb.top && ot + oh <= sb.top + sb.clientHeight) && (ol >= sb.left && ol + ow <= sb.left + sb.clientWidth);
},
setScrollTop: function(inTop) {
this.scrollTop = inTop;
if (this.scrollNode) {
this.scrollNode.scrollTop = this.scrollTop;
}
},
setScrollLeft: function(inLeft) {
this.scrollLeft = inLeft;
if (this.scrollNode) {
this.scrollNode.scrollLeft = this.scrollLeft;
}
},
getScrollLeft: function() {
return this.scrollNode ? this.scrollNode.scrollLeft : this.scrollLeft;
},
getScrollTop: function() {
return this.scrollNode ? this.scrollNode.scrollTop : this.scrollTop;
},
_getScrollBounds: function() {
var s = this.getScrollSize(), cn = this.container.hasNode();
var b = {
left: this.getScrollLeft(),
top: this.getScrollTop(),
clientHeight: cn ? cn.clientHeight : 0,
clientWidth: cn ? cn.clientWidth : 0,
height: s.height,
width: s.width
};
b.maxLeft = Math.max(0, b.width - b.clientWidth);
b.maxTop = Math.max(0, b.height - b.clientHeight);
return b;
},
getScrollSize: function() {
var n = this.scrollNode;
return {width: n ? n.scrollWidth : 0, height: n ? n.scrollHeight : 0};
},
getScrollBounds: function() {
return this._getScrollBounds();
},
calcStartInfo: function() {
var sb = this.getScrollBounds();
var y = this.getScrollTop(), x = this.getScrollLeft();
this.canVertical = sb.maxTop > 0 && this.vertical != "hidden";
this.canHorizontal = sb.maxLeft > 0 && this.horizontal != "hidden";
this.startEdges = {
top: y === 0,
bottom: y === sb.maxTop,
left: x === 0,
right: x === sb.maxLeft
};
},
// NOTE: down, move, and drag handlers are needed only for native touch scrollers
shouldDrag: function(inEvent) {
var requestV = inEvent.vertical;
return (requestV && this.canVertical || !requestV && this.canHorizontal) /*&& !this.isOobVerticalScroll(inEvent)*/;
},
dragstart: function(inSender, inEvent) {
this.dragging = this.shouldDrag(inEvent);
if (this.dragging) {
return this.preventDragPropagation;
}
},
dragfinish: function(inSender, inEvent) {
if (this.dragging) {
this.dragging = false;
inEvent.preventTap();
}
},
// avoid allowing scroll when starting at a vertical boundary to prevent ios from window scrolling.
down: function() {
this.calcStartInfo();
},
// NOTE: mobile native scrollers need touchmove. Indicate this by
// setting the requireTouchmove property to true.
move: function(inSender, inEvent) {
if (inEvent.which && (this.canVertical && inEvent.vertical || this.canHorizontal && inEvent.horizontal)) {
inEvent.disablePrevention();
}
},
mousewheel: function(inSender, inEvent) {
//* We disable mouse wheel scrolling by preventing the default
if (!this.useMouseWheel) {
inEvent.preventDefault();
}
}
});