Changed zouba directory heirarchy.
[ptas] / zouba / wrt / WRTKit / UI / Scrollbar.js
diff --git a/zouba/wrt/WRTKit/UI/Scrollbar.js b/zouba/wrt/WRTKit/UI/Scrollbar.js
new file mode 100644 (file)
index 0000000..88e2a56
--- /dev/null
@@ -0,0 +1,173 @@
+/*\r
+� Copyright 2008 Nokia Corporation. All rights reserved.\r
+\r
+IMPORTANT:  The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia\r
+Corporation (�Nokia�) in consideration of your agreement to the following terms. Your use, installation\r
+and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If\r
+you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example\r
+Widget files.\r
+\r
+In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia\r
+grants you a personal, non-exclusive license, under Nokia�s copyrights in the WRTKit and Example\r
+Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,\r
+CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60\r
+Widgets.\r
+\r
+If you redistribute the WRTKit and Example files, you must retain this entire notice in all such\r
+redistributions of the WRTKit and Example files.\r
+\r
+You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products\r
+that include the WRTKit and Example files without the prior written explicit agreement with Nokia.\r
+Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by\r
+Nokia herein, including but not limited to any patent rights that may be infringed by your products that\r
+incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files\r
+may be incorporated.\r
+\r
+The WRTKit and Example files are provided on an "AS IS" basis.  NOKIA MAKES NO\r
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\r
+WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A\r
+PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION\r
+ALONE OR IN COMBINATION WITH YOUR PRODUCTS.\r
+\r
+IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\r
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR\r
+DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY\r
+OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,\r
+EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+*/\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+// The Scrollbar class is an implementation of a user interface element that\r
+// indicates the current viewport position in a document.\r
+\r
+// Constructor.\r
+function Scrollbar(parentElement) {\r
+    uiLogger.debug("Scrollbar(" + parentElement + ")");\r
+    \r
+    // get the parent element\r
+    this.parentElement = parentElement;\r
+    \r
+    // create the root element\r
+    this.rootElement = document.createElement("div");\r
+    this.rootElement.className = "Scrollbar";\r
+    this.rootElement.style.visibility = "hidden";\r
+    \r
+    // create the scrollbar\r
+    // the scrollbar consists of a root element with six children\r
+    // (three track elements and three thumb elements)\r
+    \r
+    // track\r
+    this.trackTopElement = document.createElement("div");\r
+    this.trackTopElement.className = "ScrollbarTrackTop";\r
+    this.trackMiddleElement = document.createElement("div");\r
+    this.trackMiddleElement.className = "ScrollbarTrackMiddle";\r
+    this.trackBottomElement = document.createElement("div");\r
+    this.trackBottomElement.className = "ScrollbarTrackBottom";\r
+    \r
+    // thumb\r
+    this.thumbTopElement = document.createElement("div");\r
+    this.thumbTopElement.className = "ScrollbarThumbTop";\r
+    this.thumbMiddleElement = document.createElement("div");\r
+    this.thumbMiddleElement.className = "ScrollbarThumbMiddle";\r
+    this.thumbBottomElement = document.createElement("div");\r
+    this.thumbBottomElement.className = "ScrollbarThumbBottom";\r
+    \r
+    // assemble and attach the scrollbar\r
+    this.rootElement.appendChild(this.trackTopElement);\r
+    this.rootElement.appendChild(this.trackMiddleElement);\r
+    this.rootElement.appendChild(this.trackBottomElement);\r
+    this.rootElement.appendChild(this.thumbTopElement);\r
+    this.rootElement.appendChild(this.thumbMiddleElement);\r
+    this.rootElement.appendChild(this.thumbBottomElement);\r
+    this.parentElement.appendChild(this.rootElement);\r
+    \r
+    // bring the scrollbar up to date\r
+    this.update(0, 100, 100);\r
+}\r
+\r
+// Parent element for the scrollbar.\r
+Scrollbar.prototype.parentElement = null;\r
+\r
+// Root HTML element in the scrollbar.\r
+Scrollbar.prototype.rootElement = null;\r
+\r
+// Scrollbar track top element.\r
+Scrollbar.prototype.trackTopElement = null;\r
+\r
+// Scrollbar track middle element.\r
+Scrollbar.prototype.trackMiddleElement = null;\r
+\r
+// Scrollbar track bottom element.\r
+Scrollbar.prototype.trackBottomElement = null;\r
+\r
+// Scrollbar thumb top element.\r
+Scrollbar.prototype.thumbTopElement = null;\r
+\r
+// Scrollbar thumb middle element.\r
+Scrollbar.prototype.thumbMiddleElement = null;\r
+\r
+// Scrollbar thumb bottom element.\r
+Scrollbar.prototype.thumbBottomElement = null;\r
+\r
+// Is the scrollbar needed?\r
+Scrollbar.prototype.scrollbarNeeded = false;\r
+\r
+// Updates the scrollbar.\r
+Scrollbar.prototype.update = function(scrollY, viewportHeight, documentHeight) {\r
+    // figure out current heights\r
+    var scrollbarHeight = this.rootElement.clientHeight;\r
+    var trackTopHeight = this.trackTopElement.clientHeight;\r
+    var trackBottomHeight = this.trackBottomElement.clientHeight;\r
+    var thumbTopHeight = this.thumbTopElement.clientHeight;\r
+    var thumbBottomHeight = this.thumbBottomElement.clientHeight;\r
+    \r
+    // scrollable height is the larger of document and viewport heights\r
+    var scrollableHeight = documentHeight;\r
+    var scrollbarNeeded = true;\r
+    if (viewportHeight >= documentHeight) {\r
+        scrollableHeight = viewportHeight;\r
+        scrollbarNeeded = false;\r
+    }\r
+    \r
+    // show or hide scrollbar?\r
+    if (scrollbarNeeded != this.scrollbarNeeded) {\r
+        this.scrollbarNeeded = scrollbarNeeded;\r
+        this.rootElement.style.visibility = scrollbarNeeded ? "visible" : "hidden";\r
+    }\r
+    \r
+    // calculate thumb top position...\r
+    var thumbTopPct = scrollY / scrollableHeight;\r
+    var thumbTop = scrollbarHeight * thumbTopPct;\r
+    // ...and bottom position...\r
+    var thumbBottomPct = (scrollY + viewportHeight) / scrollableHeight;\r
+    var thumbBottom = scrollbarHeight * thumbBottomPct;\r
+    \r
+    // ...and thumb height\r
+    var thumbHeight = thumbBottom - thumbTop;\r
+    \r
+    // ensure that the thumb is not too small\r
+    var thumbMinHeight = thumbTopHeight + thumbBottomHeight;\r
+    if (thumbHeight < thumbMinHeight) {\r
+        var underflow = thumbMinHeight - thumbHeight;\r
+        // adjust thumb top pos assuming a shorter scrollbar track\r
+        var thumbMid = (scrollbarHeight - underflow) * ((thumbTopPct + thumbBottomPct) / 2) + (underflow / 2);\r
+        thumbTop = thumbMid - (thumbMinHeight / 2);\r
+        thumbBottom = thumbTop + thumbMinHeight;\r
+        thumbHeight = thumbBottom - thumbTop;\r
+    }\r
+    \r
+    // position and size track element (add 1 to the middle section height for rounding errors)\r
+    this.trackTopElement.style.top = "0px";\r
+    this.trackMiddleElement.style.top = Math.round(trackTopHeight) + "px";\r
+    this.trackMiddleElement.style.height = Math.round(scrollbarHeight - trackTopHeight - trackBottomHeight + 1) + "px";\r
+    this.trackBottomElement.style.top = Math.round(scrollbarHeight - trackTopHeight) + "px";\r
+    \r
+    // position and size thumb element (add 1 to the middle section height for rounding errors)\r
+    this.thumbTopElement.style.top = Math.round(thumbTop) + "px";\r
+    this.thumbMiddleElement.style.top = Math.round(thumbTop + thumbTopHeight) + "px";\r
+    this.thumbMiddleElement.style.height = Math.round(thumbHeight - thumbTopHeight - thumbBottomHeight + 1) + "px";\r
+    this.thumbBottomElement.style.top = Math.round(thumbBottom - thumbBottomHeight) + "px";\r
+}\r