gecko-dev/toolkit/content/widgets/scrollbox.xml

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

774 строки
27 KiB
XML
Исходник Обычный вид История

2002-10-14 02:44:10 +04:00
<?xml version="1.0"?>
2012-05-21 15:12:37 +04:00
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
2002-10-14 02:44:10 +04:00
<bindings id="arrowscrollboxBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="arrowscrollbox" extends="chrome://global/content/bindings/general.xml#basecontrol">
2002-10-14 02:44:10 +04:00
<content>
<xul:toolbarbutton class="scrollbutton-up"
anonid="scrollbutton-up"
xbl:inherits="orient,collapsed=notoverflowing,disabled=scrolledtostart"
onclick="_onButtonClick(event);"
onmousedown="_onButtonMouseDown(event, -1);"
onmouseup="_onButtonMouseUp(event);"
onmouseover="_onButtonMouseOver(-1);"
onmouseout="_onButtonMouseOut();"/>
<xul:spacer class="arrowscrollbox-overflow-start-indicator"
xbl:inherits="collapsed=scrolledtostart"/>
<xul:scrollbox class="arrowscrollbox-scrollbox"
anonid="scrollbox"
flex="1"
xbl:inherits="orient,align,pack,dir,smoothscroll">
2002-10-14 02:44:10 +04:00
<children/>
</xul:scrollbox>
<xul:spacer class="arrowscrollbox-overflow-end-indicator"
xbl:inherits="collapsed=scrolledtoend"/>
<xul:toolbarbutton class="scrollbutton-down"
anonid="scrollbutton-down"
xbl:inherits="orient,collapsed=notoverflowing,disabled=scrolledtoend"
onclick="_onButtonClick(event);"
onmousedown="_onButtonMouseDown(event, 1);"
onmouseup="_onButtonMouseUp(event);"
onmouseover="_onButtonMouseOver(1);"
onmouseout="_onButtonMouseOut();"/>
2002-10-14 02:44:10 +04:00
</content>
<implementation>
<constructor><![CDATA[
if (!this.hasAttribute("smoothscroll")) {
this.smoothScroll = this._prefBranch
.getBoolPref("toolkit.scrollbox.smoothScroll", true);
}
this.setAttribute("notoverflowing", "true");
this._updateScrollButtonsDisabledState();
]]></constructor>
<destructor><![CDATA[
// Release timer to avoid reference cycles.
if (this._scrollTimer) {
this._scrollTimer.cancel();
this._scrollTimer = null;
}
]]></destructor>
<field name="scrollbox">
document.getAnonymousElementByAttribute(this, "anonid", "scrollbox");
</field>
<field name="_scrollButtonUp">
document.getAnonymousElementByAttribute(this, "anonid", "scrollbutton-up");
</field>
<field name="_scrollButtonDown">
document.getAnonymousElementByAttribute(this, "anonid", "scrollbutton-down");
</field>
<field name="_scrollIndex">0</field>
<field name="_arrowScrollAnim"><![CDATA[({
scrollbox: this,
requestHandle: 0, /* 0 indicates there is no pending request */
start: function arrowSmoothScroll_start() {
this.lastFrameTime = window.performance.now();
if (!this.requestHandle)
this.requestHandle = window.requestAnimationFrame(this.sample.bind(this));
},
stop: function arrowSmoothScroll_stop() {
window.cancelAnimationFrame(this.requestHandle);
this.requestHandle = 0;
},
sample: function arrowSmoothScroll_handleEvent(timeStamp) {
const scrollIndex = this.scrollbox._scrollIndex;
const timePassed = timeStamp - this.lastFrameTime;
this.lastFrameTime = timeStamp;
const scrollDelta = 0.5 * timePassed * scrollIndex;
this.scrollbox.scrollByPixels(scrollDelta, true);
this.requestHandle = window.requestAnimationFrame(this.sample.bind(this));
},
})]]></field>
<property name="_clickToScroll" readonly="true">
<getter><![CDATA[
return this.hasAttribute("clicktoscroll");
]]></getter>
</property>
<property name="_scrollDelay" readonly="true">
<getter><![CDATA[
if (this._clickToScroll) {
return this._prefBranch.getIntPref(
"toolkit.scrollbox.clickToScroll.scrollDelay", 150);
}
// Use the same REPEAT_DELAY as "nsRepeatService.h".
return /Mac/.test(navigator.platform) ? 25 : 50;
]]></getter>
</property>
<field name="__prefBranch">null</field>
<property name="_prefBranch" readonly="true">
<getter><![CDATA[
if (this.__prefBranch === null) {
this.__prefBranch = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);
}
return this.__prefBranch;
]]></getter>
</property>
<field name="_scrollIncrement">null</field>
<property name="scrollIncrement" readonly="true">
<getter><![CDATA[
if (this._scrollIncrement === null) {
this._scrollIncrement = this._prefBranch
.getIntPref("toolkit.scrollbox.scrollIncrement", 20);
}
return this._scrollIncrement;
]]></getter>
</property>
<property name="smoothScroll">
<getter><![CDATA[
return this.getAttribute("smoothscroll") == "true";
]]></getter>
<setter><![CDATA[
this.setAttribute("smoothscroll", !!val);
return val;
]]></setter>
</property>
<property name="scrollClientRect" readonly="true">
<getter><![CDATA[
return this.scrollbox.getBoundingClientRect();
]]></getter>
</property>
<property name="scrollClientSize" readonly="true">
<getter><![CDATA[
return this.orient == "vertical" ?
this.scrollbox.clientHeight :
this.scrollbox.clientWidth;
]]></getter>
</property>
<property name="scrollSize" readonly="true">
<getter><![CDATA[
return this.orient == "vertical" ?
this.scrollbox.scrollHeight :
this.scrollbox.scrollWidth;
]]></getter>
</property>
<property name="lineScrollAmount" readonly="true">
<getter><![CDATA[
// line scroll amout should be the width (at horizontal scrollbox) or
// the height (at vertical scrollbox) of the scrolled elements.
// However, the elements may have different width or height. So,
// for consistent speed, let's use avalage with of the elements.
var elements = this._getScrollableElements();
return elements.length && (this.scrollSize / elements.length);
]]></getter>
</property>
<property name="scrollPosition" readonly="true">
<getter><![CDATA[
return this.orient == "vertical" ?
this.scrollbox.scrollTop :
this.scrollbox.scrollLeft;
]]></getter>
</property>
<field name="_startEndProps"><![CDATA[
this.orient == "vertical" ? ["top", "bottom"] : ["left", "right"];
]]></field>
<field name="_isRTLScrollbox"><![CDATA[
this.orient != "vertical" &&
document.defaultView.getComputedStyle(this.scrollbox).direction == "rtl";
]]></field>
<method name="_onButtonClick">
<parameter name="event"/>
<body><![CDATA[
if (this._clickToScroll) {
this._distanceScroll(event);
}
]]></body>
</method>
<method name="_onButtonMouseDown">
<parameter name="event"/>
<parameter name="index"/>
<body><![CDATA[
if (this._clickToScroll && event.button == 0) {
this._startScroll(index);
}
]]></body>
</method>
<method name="_onButtonMouseUp">
<parameter name="event"/>
<body><![CDATA[
if (this._clickToScroll && event.button == 0) {
this._stopScroll();
}
]]></body>
</method>
<method name="_onButtonMouseOver">
<parameter name="index"/>
<body><![CDATA[
if (this._clickToScroll) {
this._continueScroll(index);
} else {
this._startScroll(index);
}
]]></body>
</method>
<method name="_onButtonMouseOut">
<parameter name="index"/>
<body><![CDATA[
if (this._clickToScroll) {
this._pauseScroll();
} else {
this._stopScroll();
}
]]></body>
</method>
<method name="_boundsWithoutFlushing">
<parameter name="element"/>
<body><![CDATA[
if (!("_DOMWindowUtils" in this)) {
this._DOMWindowUtils = window.windowUtils;
}
return this._DOMWindowUtils ?
this._DOMWindowUtils.getBoundsWithoutFlushing(element) :
element.getBoundingClientRect();
]]></body>
</method>
<method name="_canScrollToElement">
<parameter name="element"/>
<body><![CDATA[
if (element.hidden) {
return false;
}
// See if the element is hidden via CSS without the hidden attribute.
// If we get only zeros for the client rect, this means the element
// is hidden. As a performance optimization, we don't flush layout
// here which means that on the fly changes aren't fully supported.
let rect = this._boundsWithoutFlushing(element);
return !!(rect.top || rect.left || rect.width || rect.height);
]]></body>
</method>
<field name="_ensureElementIsVisibleAnimationFrame">0</field>
<method name="ensureElementIsVisible">
<parameter name="element"/>
<parameter name="aInstant"/>
<body><![CDATA[
if (!this._canScrollToElement(element))
return;
if (this._ensureElementIsVisibleAnimationFrame) {
window.cancelAnimationFrame(this._ensureElementIsVisibleAnimationFrame);
}
this._ensureElementIsVisibleAnimationFrame = window.requestAnimationFrame(() => {
element.scrollIntoView({ block: "nearest",
behavior: aInstant ? "instant" : "auto" });
this._ensureElementIsVisibleAnimationFrame = 0;
});
]]></body>
</method>
<method name="scrollByIndex">
<parameter name="index"/>
<parameter name="aInstant"/>
<body><![CDATA[
if (index == 0)
return;
var rect = this.scrollClientRect;
var [start, end] = this._startEndProps;
var x = index > 0 ? rect[end] + 1 : rect[start] - 1;
var nextElement = this._elementFromPoint(x, index);
if (!nextElement)
return;
var targetElement;
if (this._isRTLScrollbox)
index *= -1;
while (index < 0 && nextElement) {
if (this._canScrollToElement(nextElement))
targetElement = nextElement;
nextElement = nextElement.previousElementSibling;
index++;
}
while (index > 0 && nextElement) {
if (this._canScrollToElement(nextElement))
targetElement = nextElement;
nextElement = nextElement.nextElementSibling;
index--;
}
if (!targetElement)
return;
this.ensureElementIsVisible(targetElement, aInstant);
]]></body>
</method>
<method name="_getScrollableElements">
<body><![CDATA[
var nodes = this.children;
if (nodes.length == 1 &&
nodes[0].localName == "children" &&
nodes[0].namespaceURI == "http://www.mozilla.org/xbl") {
nodes = document.getBindingParent(this).children;
}
return Array.prototype.filter.call(nodes, this._canScrollToElement, this);
]]></body>
</method>
<method name="_elementFromPoint">
<parameter name="aX"/>
<parameter name="aPhysicalScrollDir"/>
<body><![CDATA[
var elements = this._getScrollableElements();
if (!elements.length)
return null;
if (this._isRTLScrollbox)
elements.reverse();
var [start, end] = this._startEndProps;
var low = 0;
var high = elements.length - 1;
if (aX < elements[low].getBoundingClientRect()[start] ||
aX > elements[high].getBoundingClientRect()[end])
return null;
var mid, rect;
while (low <= high) {
mid = Math.floor((low + high) / 2);
rect = elements[mid].getBoundingClientRect();
if (rect[start] > aX)
high = mid - 1;
else if (rect[end] < aX)
low = mid + 1;
else
return elements[mid];
}
// There's no element at the requested coordinate, but the algorithm
// from above yields an element next to it, in a random direction.
// The desired scrolling direction leads to the correct element.
if (!aPhysicalScrollDir)
return null;
if (aPhysicalScrollDir < 0 && rect[start] > aX)
mid = Math.max(mid - 1, 0);
else if (aPhysicalScrollDir > 0 && rect[end] < aX)
mid = Math.min(mid + 1, elements.length - 1);
return elements[mid];
]]></body>
</method>
<method name="_startScroll">
<parameter name="index"/>
<body><![CDATA[
if (this._isRTLScrollbox) {
index *= -1;
}
if (this._clickToScroll) {
this._scrollIndex = index;
this._mousedown = true;
if (this.smoothScroll) {
this._arrowScrollAnim.start();
return;
}
}
if (!this._scrollTimer) {
this._scrollTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
} else {
this._scrollTimer.cancel();
}
let callback;
if (this._clickToScroll) {
callback = () => {
if (!document && this._scrollTimer) {
this._scrollTimer.cancel();
}
this.scrollByIndex(this._scrollIndex);
};
} else {
callback = () => this.scrollByPixels(this.scrollIncrement * index);
}
this._scrollTimer.initWithCallback(callback, this._scrollDelay,
Ci.nsITimer.TYPE_REPEATING_SLACK);
callback();
]]>
</body>
</method>
<method name="_stopScroll">
<body><![CDATA[
if (this._scrollTimer)
this._scrollTimer.cancel();
if (this._clickToScroll) {
this._mousedown = false;
if (!this._scrollIndex || !this.smoothScroll)
return;
this.scrollByIndex(this._scrollIndex);
this._scrollIndex = 0;
this._arrowScrollAnim.stop();
}
]]></body>
</method>
<method name="_pauseScroll">
<body><![CDATA[
if (this._mousedown) {
this._stopScroll();
this._mousedown = true;
document.addEventListener("mouseup", this);
document.addEventListener("blur", this, true);
}
]]></body>
</method>
<method name="_continueScroll">
<parameter name="index"/>
<body><![CDATA[
if (this._mousedown)
this._startScroll(index);
]]></body>
</method>
<method name="_distanceScroll">
<parameter name="aEvent"/>
<body><![CDATA[
if (aEvent.detail < 2 || aEvent.detail > 3)
return;
var scrollBack = (aEvent.originalTarget == this._scrollButtonUp);
var scrollLeftOrUp = this._isRTLScrollbox ? !scrollBack : scrollBack;
var targetElement;
if (aEvent.detail == 2) {
// scroll by the size of the scrollbox
let [start, end] = this._startEndProps;
let x;
if (scrollLeftOrUp)
x = this.scrollClientRect[start] - this.scrollClientSize;
else
x = this.scrollClientRect[end] + this.scrollClientSize;
targetElement = this._elementFromPoint(x, scrollLeftOrUp ? -1 : 1);
// the next partly-hidden element will become fully visible,
// so don't scroll too far
if (targetElement)
targetElement = scrollBack ?
targetElement.nextElementSibling :
targetElement.previousElementSibling;
}
if (!targetElement) {
// scroll to the first resp. last element
let elements = this._getScrollableElements();
targetElement = scrollBack ?
elements[0] :
elements[elements.length - 1];
}
this.ensureElementIsVisible(targetElement);
]]></body>
</method>
<method name="handleEvent">
<parameter name="aEvent"/>
<body><![CDATA[
if (aEvent.type == "mouseup" ||
aEvent.type == "blur" && aEvent.target == document) {
this._mousedown = false;
document.removeEventListener("mouseup", this);
document.removeEventListener("blur", this, true);
}
]]></body>
</method>
<method name="scrollByPixels">
<parameter name="aPixels"/>
<parameter name="aInstant"/>
<body><![CDATA[
let scrollOptions = { behavior: aInstant ? "instant" : "auto" };
scrollOptions[this._startEndProps[0]] = aPixels;
this.scrollbox.scrollBy(scrollOptions);
]]></body>
</method>
<field name="_prevMouseScrolls">[null, null]</field>
<field name="_touchStart">-1</field>
<field name="_scrollButtonUpdatePending">false</field>
<method name="_updateScrollButtonsDisabledState">
<body><![CDATA[
if (this.hasAttribute("notoverflowing")) {
this.setAttribute("scrolledtoend", "true");
this.setAttribute("scrolledtostart", "true");
return;
}
if (this._scrollButtonUpdatePending) {
return;
}
this._scrollButtonUpdatePending = true;
// Wait until after the next paint to get current layout data from
// getBoundsWithoutFlushing.
window.requestAnimationFrame(() => {
setTimeout(() => {
if (!this._startEndProps) {
// We've been destroyed in the meantime.
return;
}
this._scrollButtonUpdatePending = false;
let scrolledToStart = false;
let scrolledToEnd = false;
if (this.hasAttribute("notoverflowing")) {
scrolledToStart = true;
scrolledToEnd = true;
} else {
let [leftOrTop, rightOrBottom] = this._startEndProps;
let leftOrTopEdge = ele => Math.round(this._boundsWithoutFlushing(ele)[leftOrTop]);
let rightOrBottomEdge = ele => Math.round(this._boundsWithoutFlushing(ele)[rightOrBottom]);
let elements = this._getScrollableElements();
let [leftOrTopElement, rightOrBottomElement] = [elements[0], elements[elements.length - 1]];
if (this._isRTLScrollbox) {
[leftOrTopElement, rightOrBottomElement] = [rightOrBottomElement, leftOrTopElement];
}
if (leftOrTopElement &&
leftOrTopEdge(leftOrTopElement) >= leftOrTopEdge(this.scrollbox)) {
scrolledToStart = !this._isRTLScrollbox;
scrolledToEnd = this._isRTLScrollbox;
} else if (rightOrBottomElement &&
rightOrBottomEdge(rightOrBottomElement) <= rightOrBottomEdge(this.scrollbox)) {
scrolledToStart = this._isRTLScrollbox;
scrolledToEnd = !this._isRTLScrollbox;
}
}
if (scrolledToEnd) {
this.setAttribute("scrolledtoend", "true");
} else {
this.removeAttribute("scrolledtoend");
}
if (scrolledToStart) {
this.setAttribute("scrolledtostart", "true");
} else {
this.removeAttribute("scrolledtostart");
}
}, 0);
});
]]></body>
</method>
<field name="_isScrolling">false</field>
<field name="_destination">0</field>
<field name="_direction">0</field>
</implementation>
2002-10-14 02:44:10 +04:00
<handlers>
<handler event="wheel"><![CDATA[
// Don't consume the event if we can't scroll.
if (this.hasAttribute("notoverflowing")) {
return;
}
Bug 1320609 part.1 wheel event handler of <scrollbox> should use |_smoothScrollByPixels| instead of |scrollByPixels| when the deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE r=mstange <scrollbox> should scroll its contents smoothly even if wheel device doesn't support high resolution scroll. This patch makes the wheel event handler use |_smoothScrollByPixels| when deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE. The reason why ignoring DOM_DELTA_PIXEL is, such devices are typically supports high resolution scroll. Therefore, <scrollbox> doesn't need to animate its scroll by itself. However, |_smoothScrollByPixels| doesn't work fine without some additional fixes. First, this patch doesn't stop pending scroll from |_smoothScrollByPixels| because discarding some pending scroll causes slower scroll. Actually, when you turn mouse wheel faster, scroll amount becomes smaller without this fix. Next, this patch adds continous scroll mode to |_scrollAnim| object. If it's requested new animation during processing previous scroll, it keeps previous scroll amount and restart animation with new destination. Additionally, accumulating the scroll distance as fractional value. Therefore, it scrolls 3px when 1.5px scroll is requested twice. Finally, this patch discards pending scrolls when user tries to scroll to reverse direction. When user tries to scroll to reserse direction, the user must want to scroll the contents from current position rather than actual scroll destination. Therefore, this patch discards pending scrolls in |_smoothScrollByPixels|. Although, it might be better to handle this in |_scrollAnim|. However, |_isScrolling| is not managed by it and changing the behavior in private method is safer than changing utility object (i.e., |_scrollAnim|). Additionally, this patch fixes timestamp issue at callback of requestAnimationFrame(). Sometimes, the given timestamp is older than start time. In that case, current code scrolls to reverse diretion. Therefore, we should treat such old timestamp as same as start time. MozReview-Commit-ID: DluWUN2VhVw --HG-- extra : rebase_source : 067467444c7a0aee4d551410c50de3a8a97601c5
2016-12-22 14:04:35 +03:00
let doScroll = false;
let instant;
Bug 1320609 part.1 wheel event handler of <scrollbox> should use |_smoothScrollByPixels| instead of |scrollByPixels| when the deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE r=mstange <scrollbox> should scroll its contents smoothly even if wheel device doesn't support high resolution scroll. This patch makes the wheel event handler use |_smoothScrollByPixels| when deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE. The reason why ignoring DOM_DELTA_PIXEL is, such devices are typically supports high resolution scroll. Therefore, <scrollbox> doesn't need to animate its scroll by itself. However, |_smoothScrollByPixels| doesn't work fine without some additional fixes. First, this patch doesn't stop pending scroll from |_smoothScrollByPixels| because discarding some pending scroll causes slower scroll. Actually, when you turn mouse wheel faster, scroll amount becomes smaller without this fix. Next, this patch adds continous scroll mode to |_scrollAnim| object. If it's requested new animation during processing previous scroll, it keeps previous scroll amount and restart animation with new destination. Additionally, accumulating the scroll distance as fractional value. Therefore, it scrolls 3px when 1.5px scroll is requested twice. Finally, this patch discards pending scrolls when user tries to scroll to reverse direction. When user tries to scroll to reserse direction, the user must want to scroll the contents from current position rather than actual scroll destination. Therefore, this patch discards pending scrolls in |_smoothScrollByPixels|. Although, it might be better to handle this in |_scrollAnim|. However, |_isScrolling| is not managed by it and changing the behavior in private method is safer than changing utility object (i.e., |_scrollAnim|). Additionally, this patch fixes timestamp issue at callback of requestAnimationFrame(). Sometimes, the given timestamp is older than start time. In that case, current code scrolls to reverse diretion. Therefore, we should treat such old timestamp as same as start time. MozReview-Commit-ID: DluWUN2VhVw --HG-- extra : rebase_source : 067467444c7a0aee4d551410c50de3a8a97601c5
2016-12-22 14:04:35 +03:00
let scrollAmount = 0;
if (this.orient == "vertical") {
Bug 1320609 part.1 wheel event handler of <scrollbox> should use |_smoothScrollByPixels| instead of |scrollByPixels| when the deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE r=mstange <scrollbox> should scroll its contents smoothly even if wheel device doesn't support high resolution scroll. This patch makes the wheel event handler use |_smoothScrollByPixels| when deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE. The reason why ignoring DOM_DELTA_PIXEL is, such devices are typically supports high resolution scroll. Therefore, <scrollbox> doesn't need to animate its scroll by itself. However, |_smoothScrollByPixels| doesn't work fine without some additional fixes. First, this patch doesn't stop pending scroll from |_smoothScrollByPixels| because discarding some pending scroll causes slower scroll. Actually, when you turn mouse wheel faster, scroll amount becomes smaller without this fix. Next, this patch adds continous scroll mode to |_scrollAnim| object. If it's requested new animation during processing previous scroll, it keeps previous scroll amount and restart animation with new destination. Additionally, accumulating the scroll distance as fractional value. Therefore, it scrolls 3px when 1.5px scroll is requested twice. Finally, this patch discards pending scrolls when user tries to scroll to reverse direction. When user tries to scroll to reserse direction, the user must want to scroll the contents from current position rather than actual scroll destination. Therefore, this patch discards pending scrolls in |_smoothScrollByPixels|. Although, it might be better to handle this in |_scrollAnim|. However, |_isScrolling| is not managed by it and changing the behavior in private method is safer than changing utility object (i.e., |_scrollAnim|). Additionally, this patch fixes timestamp issue at callback of requestAnimationFrame(). Sometimes, the given timestamp is older than start time. In that case, current code scrolls to reverse diretion. Therefore, we should treat such old timestamp as same as start time. MozReview-Commit-ID: DluWUN2VhVw --HG-- extra : rebase_source : 067467444c7a0aee4d551410c50de3a8a97601c5
2016-12-22 14:04:35 +03:00
doScroll = true;
if (event.deltaMode == event.DOM_DELTA_PIXEL)
Bug 1320609 part.1 wheel event handler of <scrollbox> should use |_smoothScrollByPixels| instead of |scrollByPixels| when the deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE r=mstange <scrollbox> should scroll its contents smoothly even if wheel device doesn't support high resolution scroll. This patch makes the wheel event handler use |_smoothScrollByPixels| when deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE. The reason why ignoring DOM_DELTA_PIXEL is, such devices are typically supports high resolution scroll. Therefore, <scrollbox> doesn't need to animate its scroll by itself. However, |_smoothScrollByPixels| doesn't work fine without some additional fixes. First, this patch doesn't stop pending scroll from |_smoothScrollByPixels| because discarding some pending scroll causes slower scroll. Actually, when you turn mouse wheel faster, scroll amount becomes smaller without this fix. Next, this patch adds continous scroll mode to |_scrollAnim| object. If it's requested new animation during processing previous scroll, it keeps previous scroll amount and restart animation with new destination. Additionally, accumulating the scroll distance as fractional value. Therefore, it scrolls 3px when 1.5px scroll is requested twice. Finally, this patch discards pending scrolls when user tries to scroll to reverse direction. When user tries to scroll to reserse direction, the user must want to scroll the contents from current position rather than actual scroll destination. Therefore, this patch discards pending scrolls in |_smoothScrollByPixels|. Although, it might be better to handle this in |_scrollAnim|. However, |_isScrolling| is not managed by it and changing the behavior in private method is safer than changing utility object (i.e., |_scrollAnim|). Additionally, this patch fixes timestamp issue at callback of requestAnimationFrame(). Sometimes, the given timestamp is older than start time. In that case, current code scrolls to reverse diretion. Therefore, we should treat such old timestamp as same as start time. MozReview-Commit-ID: DluWUN2VhVw --HG-- extra : rebase_source : 067467444c7a0aee4d551410c50de3a8a97601c5
2016-12-22 14:04:35 +03:00
scrollAmount = event.deltaY;
else if (event.deltaMode == event.DOM_DELTA_PAGE)
Bug 1320609 part.1 wheel event handler of <scrollbox> should use |_smoothScrollByPixels| instead of |scrollByPixels| when the deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE r=mstange <scrollbox> should scroll its contents smoothly even if wheel device doesn't support high resolution scroll. This patch makes the wheel event handler use |_smoothScrollByPixels| when deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE. The reason why ignoring DOM_DELTA_PIXEL is, such devices are typically supports high resolution scroll. Therefore, <scrollbox> doesn't need to animate its scroll by itself. However, |_smoothScrollByPixels| doesn't work fine without some additional fixes. First, this patch doesn't stop pending scroll from |_smoothScrollByPixels| because discarding some pending scroll causes slower scroll. Actually, when you turn mouse wheel faster, scroll amount becomes smaller without this fix. Next, this patch adds continous scroll mode to |_scrollAnim| object. If it's requested new animation during processing previous scroll, it keeps previous scroll amount and restart animation with new destination. Additionally, accumulating the scroll distance as fractional value. Therefore, it scrolls 3px when 1.5px scroll is requested twice. Finally, this patch discards pending scrolls when user tries to scroll to reverse direction. When user tries to scroll to reserse direction, the user must want to scroll the contents from current position rather than actual scroll destination. Therefore, this patch discards pending scrolls in |_smoothScrollByPixels|. Although, it might be better to handle this in |_scrollAnim|. However, |_isScrolling| is not managed by it and changing the behavior in private method is safer than changing utility object (i.e., |_scrollAnim|). Additionally, this patch fixes timestamp issue at callback of requestAnimationFrame(). Sometimes, the given timestamp is older than start time. In that case, current code scrolls to reverse diretion. Therefore, we should treat such old timestamp as same as start time. MozReview-Commit-ID: DluWUN2VhVw --HG-- extra : rebase_source : 067467444c7a0aee4d551410c50de3a8a97601c5
2016-12-22 14:04:35 +03:00
scrollAmount = event.deltaY * this.scrollClientSize;
else
Bug 1320609 part.1 wheel event handler of <scrollbox> should use |_smoothScrollByPixels| instead of |scrollByPixels| when the deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE r=mstange <scrollbox> should scroll its contents smoothly even if wheel device doesn't support high resolution scroll. This patch makes the wheel event handler use |_smoothScrollByPixels| when deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE. The reason why ignoring DOM_DELTA_PIXEL is, such devices are typically supports high resolution scroll. Therefore, <scrollbox> doesn't need to animate its scroll by itself. However, |_smoothScrollByPixels| doesn't work fine without some additional fixes. First, this patch doesn't stop pending scroll from |_smoothScrollByPixels| because discarding some pending scroll causes slower scroll. Actually, when you turn mouse wheel faster, scroll amount becomes smaller without this fix. Next, this patch adds continous scroll mode to |_scrollAnim| object. If it's requested new animation during processing previous scroll, it keeps previous scroll amount and restart animation with new destination. Additionally, accumulating the scroll distance as fractional value. Therefore, it scrolls 3px when 1.5px scroll is requested twice. Finally, this patch discards pending scrolls when user tries to scroll to reverse direction. When user tries to scroll to reserse direction, the user must want to scroll the contents from current position rather than actual scroll destination. Therefore, this patch discards pending scrolls in |_smoothScrollByPixels|. Although, it might be better to handle this in |_scrollAnim|. However, |_isScrolling| is not managed by it and changing the behavior in private method is safer than changing utility object (i.e., |_scrollAnim|). Additionally, this patch fixes timestamp issue at callback of requestAnimationFrame(). Sometimes, the given timestamp is older than start time. In that case, current code scrolls to reverse diretion. Therefore, we should treat such old timestamp as same as start time. MozReview-Commit-ID: DluWUN2VhVw --HG-- extra : rebase_source : 067467444c7a0aee4d551410c50de3a8a97601c5
2016-12-22 14:04:35 +03:00
scrollAmount = event.deltaY * this.lineScrollAmount;
} else {
// We allow vertical scrolling to scroll a horizontal scrollbox
// because many users have a vertical scroll wheel but no
// horizontal support.
// Because of this, we need to avoid scrolling chaos on trackpads
// and mouse wheels that support simultaneous scrolling in both axes.
// We do this by scrolling only when the last two scroll events were
// on the same axis as the current scroll event.
// For diagonal scroll events we only respect the dominant axis.
let isVertical = Math.abs(event.deltaY) > Math.abs(event.deltaX);
let delta = isVertical ? event.deltaY : event.deltaX;
let scrollByDelta = isVertical && this._isRTLScrollbox ? -delta : delta;
if (this._prevMouseScrolls.every(prev => prev == isVertical)) {
Bug 1320609 part.1 wheel event handler of <scrollbox> should use |_smoothScrollByPixels| instead of |scrollByPixels| when the deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE r=mstange <scrollbox> should scroll its contents smoothly even if wheel device doesn't support high resolution scroll. This patch makes the wheel event handler use |_smoothScrollByPixels| when deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE. The reason why ignoring DOM_DELTA_PIXEL is, such devices are typically supports high resolution scroll. Therefore, <scrollbox> doesn't need to animate its scroll by itself. However, |_smoothScrollByPixels| doesn't work fine without some additional fixes. First, this patch doesn't stop pending scroll from |_smoothScrollByPixels| because discarding some pending scroll causes slower scroll. Actually, when you turn mouse wheel faster, scroll amount becomes smaller without this fix. Next, this patch adds continous scroll mode to |_scrollAnim| object. If it's requested new animation during processing previous scroll, it keeps previous scroll amount and restart animation with new destination. Additionally, accumulating the scroll distance as fractional value. Therefore, it scrolls 3px when 1.5px scroll is requested twice. Finally, this patch discards pending scrolls when user tries to scroll to reverse direction. When user tries to scroll to reserse direction, the user must want to scroll the contents from current position rather than actual scroll destination. Therefore, this patch discards pending scrolls in |_smoothScrollByPixels|. Although, it might be better to handle this in |_scrollAnim|. However, |_isScrolling| is not managed by it and changing the behavior in private method is safer than changing utility object (i.e., |_scrollAnim|). Additionally, this patch fixes timestamp issue at callback of requestAnimationFrame(). Sometimes, the given timestamp is older than start time. In that case, current code scrolls to reverse diretion. Therefore, we should treat such old timestamp as same as start time. MozReview-Commit-ID: DluWUN2VhVw --HG-- extra : rebase_source : 067467444c7a0aee4d551410c50de3a8a97601c5
2016-12-22 14:04:35 +03:00
doScroll = true;
if (event.deltaMode == event.DOM_DELTA_PIXEL) {
Bug 1320609 part.1 wheel event handler of <scrollbox> should use |_smoothScrollByPixels| instead of |scrollByPixels| when the deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE r=mstange <scrollbox> should scroll its contents smoothly even if wheel device doesn't support high resolution scroll. This patch makes the wheel event handler use |_smoothScrollByPixels| when deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE. The reason why ignoring DOM_DELTA_PIXEL is, such devices are typically supports high resolution scroll. Therefore, <scrollbox> doesn't need to animate its scroll by itself. However, |_smoothScrollByPixels| doesn't work fine without some additional fixes. First, this patch doesn't stop pending scroll from |_smoothScrollByPixels| because discarding some pending scroll causes slower scroll. Actually, when you turn mouse wheel faster, scroll amount becomes smaller without this fix. Next, this patch adds continous scroll mode to |_scrollAnim| object. If it's requested new animation during processing previous scroll, it keeps previous scroll amount and restart animation with new destination. Additionally, accumulating the scroll distance as fractional value. Therefore, it scrolls 3px when 1.5px scroll is requested twice. Finally, this patch discards pending scrolls when user tries to scroll to reverse direction. When user tries to scroll to reserse direction, the user must want to scroll the contents from current position rather than actual scroll destination. Therefore, this patch discards pending scrolls in |_smoothScrollByPixels|. Although, it might be better to handle this in |_scrollAnim|. However, |_isScrolling| is not managed by it and changing the behavior in private method is safer than changing utility object (i.e., |_scrollAnim|). Additionally, this patch fixes timestamp issue at callback of requestAnimationFrame(). Sometimes, the given timestamp is older than start time. In that case, current code scrolls to reverse diretion. Therefore, we should treat such old timestamp as same as start time. MozReview-Commit-ID: DluWUN2VhVw --HG-- extra : rebase_source : 067467444c7a0aee4d551410c50de3a8a97601c5
2016-12-22 14:04:35 +03:00
scrollAmount = scrollByDelta;
instant = true;
} else if (event.deltaMode == event.DOM_DELTA_PAGE) {
Bug 1320609 part.1 wheel event handler of <scrollbox> should use |_smoothScrollByPixels| instead of |scrollByPixels| when the deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE r=mstange <scrollbox> should scroll its contents smoothly even if wheel device doesn't support high resolution scroll. This patch makes the wheel event handler use |_smoothScrollByPixels| when deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE. The reason why ignoring DOM_DELTA_PIXEL is, such devices are typically supports high resolution scroll. Therefore, <scrollbox> doesn't need to animate its scroll by itself. However, |_smoothScrollByPixels| doesn't work fine without some additional fixes. First, this patch doesn't stop pending scroll from |_smoothScrollByPixels| because discarding some pending scroll causes slower scroll. Actually, when you turn mouse wheel faster, scroll amount becomes smaller without this fix. Next, this patch adds continous scroll mode to |_scrollAnim| object. If it's requested new animation during processing previous scroll, it keeps previous scroll amount and restart animation with new destination. Additionally, accumulating the scroll distance as fractional value. Therefore, it scrolls 3px when 1.5px scroll is requested twice. Finally, this patch discards pending scrolls when user tries to scroll to reverse direction. When user tries to scroll to reserse direction, the user must want to scroll the contents from current position rather than actual scroll destination. Therefore, this patch discards pending scrolls in |_smoothScrollByPixels|. Although, it might be better to handle this in |_scrollAnim|. However, |_isScrolling| is not managed by it and changing the behavior in private method is safer than changing utility object (i.e., |_scrollAnim|). Additionally, this patch fixes timestamp issue at callback of requestAnimationFrame(). Sometimes, the given timestamp is older than start time. In that case, current code scrolls to reverse diretion. Therefore, we should treat such old timestamp as same as start time. MozReview-Commit-ID: DluWUN2VhVw --HG-- extra : rebase_source : 067467444c7a0aee4d551410c50de3a8a97601c5
2016-12-22 14:04:35 +03:00
scrollAmount = scrollByDelta * this.scrollClientSize;
} else {
Bug 1320609 part.1 wheel event handler of <scrollbox> should use |_smoothScrollByPixels| instead of |scrollByPixels| when the deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE r=mstange <scrollbox> should scroll its contents smoothly even if wheel device doesn't support high resolution scroll. This patch makes the wheel event handler use |_smoothScrollByPixels| when deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE. The reason why ignoring DOM_DELTA_PIXEL is, such devices are typically supports high resolution scroll. Therefore, <scrollbox> doesn't need to animate its scroll by itself. However, |_smoothScrollByPixels| doesn't work fine without some additional fixes. First, this patch doesn't stop pending scroll from |_smoothScrollByPixels| because discarding some pending scroll causes slower scroll. Actually, when you turn mouse wheel faster, scroll amount becomes smaller without this fix. Next, this patch adds continous scroll mode to |_scrollAnim| object. If it's requested new animation during processing previous scroll, it keeps previous scroll amount and restart animation with new destination. Additionally, accumulating the scroll distance as fractional value. Therefore, it scrolls 3px when 1.5px scroll is requested twice. Finally, this patch discards pending scrolls when user tries to scroll to reverse direction. When user tries to scroll to reserse direction, the user must want to scroll the contents from current position rather than actual scroll destination. Therefore, this patch discards pending scrolls in |_smoothScrollByPixels|. Although, it might be better to handle this in |_scrollAnim|. However, |_isScrolling| is not managed by it and changing the behavior in private method is safer than changing utility object (i.e., |_scrollAnim|). Additionally, this patch fixes timestamp issue at callback of requestAnimationFrame(). Sometimes, the given timestamp is older than start time. In that case, current code scrolls to reverse diretion. Therefore, we should treat such old timestamp as same as start time. MozReview-Commit-ID: DluWUN2VhVw --HG-- extra : rebase_source : 067467444c7a0aee4d551410c50de3a8a97601c5
2016-12-22 14:04:35 +03:00
scrollAmount = scrollByDelta * this.lineScrollAmount;
}
}
if (this._prevMouseScrolls.length > 1)
this._prevMouseScrolls.shift();
this._prevMouseScrolls.push(isVertical);
}
Bug 1320609 part.1 wheel event handler of <scrollbox> should use |_smoothScrollByPixels| instead of |scrollByPixels| when the deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE r=mstange <scrollbox> should scroll its contents smoothly even if wheel device doesn't support high resolution scroll. This patch makes the wheel event handler use |_smoothScrollByPixels| when deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE. The reason why ignoring DOM_DELTA_PIXEL is, such devices are typically supports high resolution scroll. Therefore, <scrollbox> doesn't need to animate its scroll by itself. However, |_smoothScrollByPixels| doesn't work fine without some additional fixes. First, this patch doesn't stop pending scroll from |_smoothScrollByPixels| because discarding some pending scroll causes slower scroll. Actually, when you turn mouse wheel faster, scroll amount becomes smaller without this fix. Next, this patch adds continous scroll mode to |_scrollAnim| object. If it's requested new animation during processing previous scroll, it keeps previous scroll amount and restart animation with new destination. Additionally, accumulating the scroll distance as fractional value. Therefore, it scrolls 3px when 1.5px scroll is requested twice. Finally, this patch discards pending scrolls when user tries to scroll to reverse direction. When user tries to scroll to reserse direction, the user must want to scroll the contents from current position rather than actual scroll destination. Therefore, this patch discards pending scrolls in |_smoothScrollByPixels|. Although, it might be better to handle this in |_scrollAnim|. However, |_isScrolling| is not managed by it and changing the behavior in private method is safer than changing utility object (i.e., |_scrollAnim|). Additionally, this patch fixes timestamp issue at callback of requestAnimationFrame(). Sometimes, the given timestamp is older than start time. In that case, current code scrolls to reverse diretion. Therefore, we should treat such old timestamp as same as start time. MozReview-Commit-ID: DluWUN2VhVw --HG-- extra : rebase_source : 067467444c7a0aee4d551410c50de3a8a97601c5
2016-12-22 14:04:35 +03:00
if (doScroll) {
let direction = scrollAmount < 0 ? -1 : 1;
let startPos = this.scrollPosition;
if (!this._isScrolling || this._direction != direction) {
this._destination = startPos + scrollAmount;
this._direction = direction;
} else {
// We were already in the process of scrolling in this direction
this._destination = this._destination + scrollAmount;
scrollAmount = this._destination - startPos;
}
this.scrollByPixels(scrollAmount, instant);
Bug 1320609 part.1 wheel event handler of <scrollbox> should use |_smoothScrollByPixels| instead of |scrollByPixels| when the deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE r=mstange <scrollbox> should scroll its contents smoothly even if wheel device doesn't support high resolution scroll. This patch makes the wheel event handler use |_smoothScrollByPixels| when deltaMode is DOM_DELTA_LINE or DOM_DELTA_PAGE. The reason why ignoring DOM_DELTA_PIXEL is, such devices are typically supports high resolution scroll. Therefore, <scrollbox> doesn't need to animate its scroll by itself. However, |_smoothScrollByPixels| doesn't work fine without some additional fixes. First, this patch doesn't stop pending scroll from |_smoothScrollByPixels| because discarding some pending scroll causes slower scroll. Actually, when you turn mouse wheel faster, scroll amount becomes smaller without this fix. Next, this patch adds continous scroll mode to |_scrollAnim| object. If it's requested new animation during processing previous scroll, it keeps previous scroll amount and restart animation with new destination. Additionally, accumulating the scroll distance as fractional value. Therefore, it scrolls 3px when 1.5px scroll is requested twice. Finally, this patch discards pending scrolls when user tries to scroll to reverse direction. When user tries to scroll to reserse direction, the user must want to scroll the contents from current position rather than actual scroll destination. Therefore, this patch discards pending scrolls in |_smoothScrollByPixels|. Although, it might be better to handle this in |_scrollAnim|. However, |_isScrolling| is not managed by it and changing the behavior in private method is safer than changing utility object (i.e., |_scrollAnim|). Additionally, this patch fixes timestamp issue at callback of requestAnimationFrame(). Sometimes, the given timestamp is older than start time. In that case, current code scrolls to reverse diretion. Therefore, we should treat such old timestamp as same as start time. MozReview-Commit-ID: DluWUN2VhVw --HG-- extra : rebase_source : 067467444c7a0aee4d551410c50de3a8a97601c5
2016-12-22 14:04:35 +03:00
}
event.stopPropagation();
event.preventDefault();
]]></handler>
<handler event="touchstart"><![CDATA[
if (event.touches.length > 1) {
// Multiple touch points detected, abort. In particular this aborts
// the panning gesture when the user puts a second finger down after
// already panning with one finger. Aborting at this point prevents
// the pan gesture from being resumed until all fingers are lifted
// (as opposed to when the user is back down to one finger).
this._touchStart = -1;
} else {
this._touchStart = (this.orient == "vertical"
? event.touches[0].screenY
: event.touches[0].screenX);
}
]]></handler>
<handler event="touchmove"><![CDATA[
if (event.touches.length == 1 &&
this._touchStart >= 0) {
var touchPoint = (this.orient == "vertical"
? event.touches[0].screenY
: event.touches[0].screenX);
var delta = this._touchStart - touchPoint;
if (Math.abs(delta) > 0) {
this.scrollByPixels(delta, true);
this._touchStart = touchPoint;
}
event.preventDefault();
}
]]></handler>
<handler event="touchend"><![CDATA[
this._touchStart = -1;
]]></handler>
<handler event="underflow" phase="capturing"><![CDATA[
// Ignore underflow events:
// - from nested scrollable elements
// - corresponding to an overflow event that we ignored
if (event.target != this ||
this.hasAttribute("notoverflowing")) {
return;
}
// Ignore events that doesn't match our orientation.
// Scrollport event orientation:
// 0: vertical
// 1: horizontal
// 2: both
if (this.orient == "vertical") {
if (event.detail == 1)
return;
} else if (event.detail == 0) {
// horizontal scrollbox
return;
}
this.setAttribute("notoverflowing", "true");
this._updateScrollButtonsDisabledState();
2002-10-14 02:44:10 +04:00
]]></handler>
<handler event="overflow" phase="capturing"><![CDATA[
// Ignore overflow events:
// - from nested scrollable elements
if (event.target != this) {
return;
}
// Ignore events that doesn't match our orientation.
// Scrollport event orientation:
// 0: vertical
// 1: horizontal
// 2: both
if (this.orient == "vertical") {
if (event.detail == 1)
return;
} else if (event.detail == 0) {
// horizontal scrollbox
return;
}
this.removeAttribute("notoverflowing");
this._updateScrollButtonsDisabledState();
2002-10-14 02:44:10 +04:00
]]></handler>
<handler event="scroll"><![CDATA[
this._isScrolling = true;
this._updateScrollButtonsDisabledState();
]]></handler>
<handler event="scrollend"><![CDATA[
this._isScrolling = false;
this._destination = 0;
this._direction = 0;
]]></handler>
2002-10-14 02:44:10 +04:00
</handlers>
</binding>
</bindings>