--- /dev/null
+/*\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