| Index: sky/framework/sky-scrollable.sky
|
| diff --git a/sky/framework/sky-scrollable.sky b/sky/framework/sky-scrollable.sky
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f950c8b470aafc548b8751a405597c2186d4bb7e
|
| --- /dev/null
|
| +++ b/sky/framework/sky-scrollable.sky
|
| @@ -0,0 +1,101 @@
|
| +<!--
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +-->
|
| +<import src="/sky/framework/sky-element/sky-element.sky" as="SkyElement" />
|
| +
|
| +<sky-element
|
| + name="sky-scrollable"
|
| + on-gesturescrollstart="handleScrollStart_"
|
| + on-gesturescrollend="handleScrollEnd_"
|
| + on-gesturescrollupdate="handleScrollUpdate_"
|
| + on-gestureflingstart="handleFlingStart_"
|
| + on-gestureflingcancel="handleFlingCancel_">
|
| +<template>
|
| + <style>
|
| + :host {
|
| + overflow: hidden;
|
| + }
|
| + #scrollable {
|
| + transform: translateY(0);
|
| + }
|
| + </style>
|
| + <div id="scrollable">
|
| + <content />
|
| + </div>
|
| +</template>
|
| +<script>
|
| +// TODO(abarth): Move the fling curve to a separate module.
|
| +var kFlingFriction = 0.9;
|
| +var kFlingVelocityMin = 1;
|
| +
|
| +module.exports = class extends SkyElement {
|
| + created() {
|
| + this.scrollable_ = null;
|
| + this.scrollOffset_ = 0;
|
| + this.flingVelocity_ = 0;
|
| + this.flingAnimationId_ = null;
|
| + }
|
| +
|
| + shadowRootReady() {
|
| + this.scrollable_ = this.shadowRoot.getElementById('scrollable');
|
| + }
|
| +
|
| + scrollBy(scrollDelta) {
|
| + var offset = Math.max(0, Math.min(this.scrollable_.offsetHeight, this.scrollOffset_ + scrollDelta));
|
| + if (offset == this.scrollOffset_)
|
| + return false;
|
| + this.scrollOffset_ = offset;
|
| + this.applyScrollOffset_();
|
| + return true;
|
| + }
|
| +
|
| + applyScrollOffset_() {
|
| + var transform = 'translateY(' + -this.scrollOffset_.toFixed(2) + 'px)';
|
| + this.scrollable_.style.transform = transform;
|
| + }
|
| +
|
| + scheduleFlingTick_() {
|
| + this.flingAnimationId_ = requestAnimationFrame(this.tickFling_.bind(this));
|
| + }
|
| +
|
| + tickFling_() {
|
| + this.flingAnimationId_ = null;
|
| + if (!this.scrollBy(this.flingVelocity_)) {
|
| + this.flingVelocity_ = 0;
|
| + return;
|
| + }
|
| + var velocity = this.flingVelocity_ * kFlingFriction;
|
| + if (velocity < kFlingVelocityMin)
|
| + velocity = 0;
|
| + this.flingVelocity_ = velocity;
|
| + if (velocity)
|
| + this.scheduleFlingTick_();
|
| + }
|
| +
|
| + handleScrollStart_(event) {
|
| + }
|
| +
|
| + handleScrollEnd_(event) {
|
| + }
|
| +
|
| + handleScrollUpdate_(event) {
|
| + this.scrollBy(-event.dy);
|
| + }
|
| +
|
| + handleFlingStart_(event) {
|
| + this.flingVelocity_ = -event.velocityY;
|
| + this.scheduleFlingTick_();
|
| + }
|
| +
|
| + handleFlingCancel_(event) {
|
| + if (!this.flingAnimationId_)
|
| + return;
|
| + cancelAnimationFrame(this.flingAnimationId_);
|
| + this.flingVelocity_ = 0;
|
| + this.flingAnimationId_ = null;
|
| + }
|
| +}.register();
|
| +</script>
|
| +</sky-element>
|
|
|