diff --git a/README.md b/README.md
index 9d27edfb9..ea97bba14 100644
--- a/README.md
+++ b/README.md
@@ -121,6 +121,7 @@ List of Definitions
* [Vimeo](http://developer.vimeo.com/player/js-api) (by [Daz Wilkin](https://github.com/DazWilkin/))
* [WebRTC](http://dev.w3.org/2011/webrtc/editor/webrtc.html) (by [Ken Smith](https://github.com/smithkl42))
* [YouTube](https://developers.google.com/youtube/) (by [Daz Wilkin](https://github.com/DazWilkin/))
+* [Zynga Scroller](https://github.com/zynga/scroller) (by [Boris Yankov](https://github.com/borisyankov))
Requested Definitions
---------------------
diff --git a/scroller/easyscroller.d.ts b/scroller/easyscroller.d.ts
new file mode 100644
index 000000000..5b6477fe5
--- /dev/null
+++ b/scroller/easyscroller.d.ts
@@ -0,0 +1,15 @@
+// Type definitions for Zynga EasyScroller
+// Project: https://github.com/zynga/scroller
+// Definitions by: Boris Yankov https://github.com/borisyankov
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+
+///
+
+class EasyScroller {
+ constructor (content: any, options: ScrollerOptions);
+
+ render(): void;
+ reflow(): void;
+ bindEvents(): void;
+}
\ No newline at end of file
diff --git a/scroller/scroller-tests.ts b/scroller/scroller-tests.ts
new file mode 100644
index 000000000..9daaab498
--- /dev/null
+++ b/scroller/scroller-tests.ts
@@ -0,0 +1,254 @@
+///
+
+function test_basic() {
+ var scrollerObj = new Scroller(function (left, top, zoom) {
+ }, {
+ scrollingY: false
+ });
+ scrollerObj.setDimensions(1000, 1000, 3000, 3000);
+}
+
+function test_canvas() {
+ var contentWidth = 2000;
+ var contentHeight = 2000;
+ var cellWidth = 100;
+ var cellHeight = 100;
+ var content = document.getElementById('content');
+ var context = content.getContext('2d');
+ var tiling = new Tiling();
+ var render = function (left, top, zoom) {
+ content.width = clientWidth;
+ content.height = clientHeight;
+ context.clearRect(0, 0, clientWidth, clientHeight);
+ tiling.setup(clientWidth, clientHeight, contentWidth, contentHeight, cellWidth, cellHeight);
+ tiling.render(left, top, zoom, paint);
+ };
+ var paint = function (row, col, left, top, width, height, zoom) {
+ context.fillStyle = row % 2 + col % 2 > 0 ? "#ddd" : "#fff";
+ context.fillRect(left, top, width, height);
+ context.fillStyle = "black";
+ context.font = (14 * zoom).toFixed(2) + 'px "Helvetica Neue", Helvetica, Arial, sans-serif';
+ context.fillText(row + "," + col, left + (6 * zoom), top + (18 * zoom));
+ };
+}
+
+function test_domlist() {
+ var container = document.getElementById("container");
+ var content = document.getElementById("content");
+ var refreshElem = content.getElementsByTagName("div")[0];
+ var scroller = new Scroller(render, {
+ scrollingX: false
+ });
+ scroller.activatePullToRefresh(50, function () {
+ refreshElem.className += " active";
+ refreshElem.innerHTML = "Release to Refresh";
+ }, function () {
+ refreshElem.className = refreshElem.className.replace(" active", "");
+ refreshElem.innerHTML = "Pull to Refresh";
+ }, function () {
+ refreshElem.className += " running";
+ refreshElem.innerHTML = "Refreshing...";
+ setTimeout(function () {
+ refreshElem.className = refreshElem.className.replace(" running", "");
+ insertItems();
+ scroller.finishPullToRefresh();
+ }, 2000);
+ });
+ var rect = container.getBoundingClientRect();
+ scroller.setPosition(rect.left + container.clientLeft, rect.top + container.clientTop);
+ var insertItems = function () {
+ for (var i = 0; i < 15; i++) {
+ var row = document.createElement("div");
+ row.className = "row";
+ row.style.backgroundColor = i % 2 > 0 ? "#ddd" : "";
+ row.innerHTML = Math.random();
+ if (content.firstChild == content.lastChild) {
+ content.appendChild(row);
+ } else {
+ content.insertBefore(row, content.childNodes[1])
+ }
+ }
+ scroller.setDimensions(container.clientWidth, container.clientHeight, content.offsetWidth, content.offsetHeight - 50);
+ };
+ insertItems();
+ if ('ontouchstart' in window) {
+ container.addEventListener("touchstart", function (e) {
+ // Don't react if initial down happens on a form element
+ if (e.target.tagName.match(/input|textarea|select/i)) {
+ return;
+ }
+ scroller.doTouchStart(e.touches, e.timeStamp);
+ e.preventDefault();
+ }, false);
+ document.addEventListener("touchmove", function (e) {
+ scroller.doTouchMove(e.touches, e.timeStamp);
+ }, false);
+ document.addEventListener("touchend", function (e) {
+ scroller.doTouchEnd(e.timeStamp);
+ }, false);
+ } else {
+ var mousedown = false;
+ container.addEventListener("mousedown", function (e) {
+ if (e.target.tagName.match(/input|textarea|select/i)) {
+ return;
+ }
+ scroller.doTouchStart([{
+ pageX: e.pageX,
+ pageY: e.pageY
+ }], e.timeStamp);
+ mousedown = true;
+ }, false);
+ document.addEventListener("mousemove", function (e) {
+ if (!mousedown) {
+ return;
+ }
+ scroller.doTouchMove([{
+ pageX: e.pageX,
+ pageY: e.pageY
+ }], e.timeStamp);
+ mousedown = true;
+ }, false);
+ document.addEventListener("mouseup", function (e) {
+ if (!mousedown) {
+ return;
+ }
+ scroller.doTouchEnd(e.timeStamp);
+ mousedown = false;
+ }, false);
+ }
+}
+
+function test_dompaging() {
+ var container = document.getElementById("container");
+ var content = document.getElementById("content");
+ var size = 400;
+ var frag = document.createDocumentFragment();
+ for (var cell = 0, cl = content.clientWidth / size; cell < cl; cell++) {
+ elem = document.createElement("div");
+ elem.className = "cell";
+ elem.style.backgroundColor = cell % 2 > 0 ? "#ddd" : "";
+ elem.innerHTML = cell;
+ frag.appendChild(elem);
+ }
+ content.appendChild(frag);
+ var scroller = new Scroller(render, {
+ scrollingY: false,
+ paging: true
+ });
+ var rect = container.getBoundingClientRect();
+ scroller.setPosition(rect.left + container.clientLeft, rect.top + container.clientTop);
+ scroller.setDimensions(container.clientWidth, container.clientHeight, content.offsetWidth, content.offsetHeight);
+ if ('ontouchstart' in window) {
+ container.addEventListener("touchstart", function (e) {
+ if (e.target.tagName.match(/input|textarea|select/i)) {
+ return;
+ }
+ scroller.doTouchStart(e.touches, e.timeStamp);
+ e.preventDefault();
+ }, false);
+ document.addEventListener("touchmove", function (e) {
+ scroller.doTouchMove(e.touches, e.timeStamp);
+ }, false);
+ document.addEventListener("touchend", function (e) {
+ scroller.doTouchEnd(e.timeStamp);
+ }, false);
+ } else {
+ var mousedown = false;
+ container.addEventListener("mousedown", function (e) {
+ if (e.target.tagName.match(/input|textarea|select/i)) {
+ return;
+ }
+ scroller.doTouchStart([{
+ pageX: e.pageX,
+ pageY: e.pageY
+ }], e.timeStamp);
+ mousedown = true;
+ }, false);
+ document.addEventListener("mousemove", function (e) {
+ if (!mousedown) {
+ return;
+ }
+ scroller.doTouchMove([{
+ pageX: e.pageX,
+ pageY: e.pageY
+ }], e.timeStamp);
+ mousedown = true;
+ }, false);
+
+ document.addEventListener("mouseup", function (e) {
+ if (!mousedown) {
+ return;
+ }
+ scroller.doTouchEnd(e.timeStamp);
+ mousedown = false;
+ }, false);
+ }
+}
+
+function test_domsnapping() {
+ var container = document.getElementById("container");
+ var content = document.getElementById("content");
+ var size = 100;
+ var frag = document.createDocumentFragment();
+ for (var row = 0, rl = content.clientHeight / size; row < rl; row++) {
+ for (var cell = 0, cl = content.clientWidth / size; cell < cl; cell++) {
+ elem = document.createElement("div");
+ elem.className = "cell";
+ elem.style.backgroundColor = row % 2 + cell % 2 > 0 ? "#ddd" : "";
+ elem.innerHTML = row + "," + cell;
+ frag.appendChild(elem);
+ }
+ }
+ content.appendChild(frag);
+ var scroller = new Scroller(render, {
+ snapping: true
+ });
+ var rect = container.getBoundingClientRect();
+ scroller.setPosition(rect.left + container.clientLeft, rect.top + container.clientTop);
+ scroller.setDimensions(container.clientWidth, container.clientHeight, content.offsetWidth, content.offsetHeight);
+ scroller.setSnapSize(100, 100);
+ if ('ontouchstart' in window) {
+ container.addEventListener("touchstart", function (e) {
+ if (e.target.tagName.match(/input|textarea|select/i)) {
+ return;
+ }
+ scroller.doTouchStart(e.touches, e.timeStamp);
+ e.preventDefault();
+ }, false);
+ document.addEventListener("touchmove", function (e) {
+ scroller.doTouchMove(e.touches, e.timeStamp);
+ }, false);
+ document.addEventListener("touchend", function (e) {
+ scroller.doTouchEnd(e.timeStamp);
+ }, false);
+ } else {
+ var mousedown = false;
+ container.addEventListener("mousedown", function (e) {
+ if (e.target.tagName.match(/input|textarea|select/i)) {
+ return;
+ }
+ scroller.doTouchStart([{
+ pageX: e.pageX,
+ pageY: e.pageY
+ }], e.timeStamp);
+ mousedown = true;
+ }, false);
+ document.addEventListener("mousemove", function (e) {
+ if (!mousedown) {
+ return;
+ }
+ scroller.doTouchMove([{
+ pageX: e.pageX,
+ pageY: e.pageY
+ }], e.timeStamp);
+ mousedown = true;
+ }, false);
+ document.addEventListener("mouseup", function (e) {
+ if (!mousedown) {
+ return;
+ }
+ scroller.doTouchEnd(e.timeStamp);
+ mousedown = false;
+ }, false);
+ }
+}
\ No newline at end of file
diff --git a/scroller/scroller.d.ts b/scroller/scroller.d.ts
new file mode 100644
index 000000000..72bf30d2f
--- /dev/null
+++ b/scroller/scroller.d.ts
@@ -0,0 +1,50 @@
+// Type definitions for Zynga Scroller
+// Project: https://github.com/zynga/scroller
+// Definitions by: Boris Yankov https://github.com/borisyankov
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+
+interface ScrollerOptions {
+ scrollingX?: bool;
+ scrollingY?: bool;
+ animating?: bool;
+ animationDuration?: number;
+ bouncing?: bool;
+ locking?: bool;
+ paging?: bool;
+ snapping?: bool;
+ zooming?: bool;
+ minZoom?: number;
+ maxZoom?: number;
+ speedMultiplier?: number;
+}
+
+interface ScrollValues {
+ left: number;
+ top: number;
+}
+
+interface ScrollValuesWithZoom extends ScrollValues {
+ zoom: number;
+}
+
+class Scroller {
+ constructor (callback: (left: number, top: number, zoom: number) => void , options: ScrollerOptions);
+
+ setDimensions(clientWidth: number, clientHeight: number, contentWidth: number, contentHeight: number): void;
+ setPosition(left: number, top: number): void;
+ setSnapSize(width: number, height: number): void;
+ activatePullToRefresh(height: number, activateCallback: Function, deactivateCallback: Function, startCallback: Function): void;
+ finishPullToRefresh(): void;
+ getValues(): ScrollValuesWithZoom;
+ getScrollMax(): ScrollValues;
+ zoomTo(level: number, animate?: bool, originLeft?: bool, originTop?: bool): void;
+ zoomBy(factor: number, animate?: bool, originLeft?: bool, originTop?: bool): void;
+ scrollTo(left?: number, top?: number, animate?: number, zoom?: number): void;
+ scrollBy(left?: number, top?: number, animate?: number): void;
+
+ doMouseZoom(wheelDelta: number, timeStamp: number, pageX: number, pageY: number): void;
+ doTouchStart(touches: any[], timeStamp: number): void;
+ doTouchMove(touches: any[], timeStamp: number, scale?: number): void;
+ doTouchEnd(timeStamp: number): void;
+}
\ No newline at end of file