All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.smartclient.debug.public.sc.client.widgets.Scrollbar.js Maven / Gradle / Ivy

The newest version!
/*
 * Isomorphic SmartClient
 * Version SC_SNAPSHOT-2011-08-08 (2011-08-08)
 * Copyright(c) 1998 and beyond Isomorphic Software, Inc. All rights reserved.
 * "SmartClient" is a trademark of Isomorphic Software, Inc.
 *
 * [email protected]
 *
 * http://smartclient.com/license
 */

 







//>	@class Scrollbar
//
// The Scrollbar widget implements cross-platform, image-based scrollbars that control the
// scrolling of content in other widgets.  Scrollbar widgets are created and displayed
// automatically for widgets that require them, based on settings for +link{canvas.overflow}.
// 

// The scrollbar's appearance is based on a +link{StretchImg} for the "track", which consists // of two fixed size buttons and a stretchable center segment, and the +link{ScrollThumb}, // the draggable portion of the scrollbar, also a StretchImg, with an optional // +link{stretchImg.showGrip,grip}. // // @treeLocation Client Reference/Foundation // @visibility external //< isc.ClassFactory.defineClass("Scrollbar", "StretchImg"); //> @class ScrollThumb // Class used for the draggable "thumb" of a scrollbar. Do not use directly; this class is // documented only for skinning purposes. // // @treeLocation Client Reference/Foundation/ScrollBar // @visibility external //< isc.defineClass("ScrollThumb", "StretchImg").addMethods({ autoDraw:false, _generated:true, // we redraw the thumb manually, not automatically with parent or master _redrawWithMaster:false, _resizeWithMaster:false, _redrawWithParent:false, containedPeer:true, showDisabled:false, capSize:2, backgroundColor:"#EEEEEE", // don't reverse, even in RTL, (in case media is asymetric) textDirection:"ltr", skinImgDir:"images/Scrollbar/", hSrc:"[SKIN]hthumb.gif", vSrc:"[SKIN]vthumb.gif", // the thumb drags with a custom drag style canDrag:true, dragAppearance:isc.EventHandler.NONE, dragStartDistance:0, // start drag scrolling on any mouse movement dragScrollType:"parentsOnly", // stop various events from bubbling to parent of the Canvas we are scrolling click : isc.EventHandler.stopBubbling, doubleClick : isc.EventHandler.stopBubbling, mouseMove : isc.EventHandler.stopBubbling, // send special notifications for some events mouseOver : function () {return this.scrollbar.thumbOver();}, mouseOut : function () {return this.scrollbar.thumbOut();}, mouseDown : function () {return this.scrollbar.thumbDown();}, dragStart : function () {return this.scrollbar.thumbDragStart();}, dragMove : function () {return this.scrollbar.thumbMove();}, dragStop : function () {return this.scrollbar.thumbDragStop();}, mouseUp : function () {return this.scrollbar.thumbUp();}, // bubble other events to the scrollbar keyPress : function () { return this.ns.EH.bubbleEvent(this.scrollbar, this.ns.EH.eventTypes.KEY_PRESS); }, keyDown : function () { return this.ns.EH.bubbleEvent(this.scrollbar, this.ns.EH.eventTypes.KEY_DOWN); }, keyUp : function () { return this.ns.EH.bubbleEvent(this.scrollbar, this.ns.EH.eventTypes.KEY_UP); }, mouseWheel : function () { return this.ns.EH.bubbleEvent(this.scrollbar, this.ns.EH.eventTypes.MOUSE_WHEEL); }, masterMoved : function () { // on scrollbar.setRect, we'll be positioned to our final position in response to // the resize, so no need to also reposition in response to the scrollbar moving var master = this.masterElement; if (master && master._settingRect) return; this.Super("masterMoved", arguments); } }); isc.defineClass("HScrollThumb", isc.ScrollThumb).addProperties({ vertical:false }); isc.defineClass("VScrollThumb", isc.ScrollThumb); isc.Scrollbar.addProperties( { //> @attr scrollbar.btnSize (number : 16 : [IRW]) // The size of the square buttons (arrows) at the ends of this scrollbar. This // overrides the width of a vertical scrollbar or the height of a horizontal scrollbar // to set the scrollbar's thickness. // @group track // @visibility external //< btnSize:16, //> @attr scrollbar.state (ImgState : isc.StatefulCanvas.STATE_UP : IRWA) // Default to the "up" state, other states are "down" and isc.StatefulCanvas.STATE_DISABLED // @group appearance //< state:isc.StatefulCanvas.STATE_UP, //> @attr scrollbar.autoEnable (boolean : true : [IRWA]) // If true, this scrollbar will automatically enable when the scrollTarget is // scrollable (i.e., when the contents of the scrollTarget exceed its clip size in the // direction relevant to this scrollbar), and automatically disable when the // scrollTarget is not scrollable. Set this property to false for full manual control // over a scrollbar's enabled state. // @visibility external //< autoEnable:true, //> @attr scrollbar.showCorner (boolean : false : IRA) // If true, displays a corner piece at the bottom end of a vertical scrollbar, or the // right end of a horizontal scrollbar. This is typically set only when both horizontal // and vertical scrollbars are displayed and about the same corner. // @group corner // @visibility external //< //showCorner:false, //> @attr scrollbar.allowThumbDownState (boolean : false : IRA) // If true, the thumb's appearance changes when it's clicked on. // @group thumb // @visibility external //< allowThumbDownState:false, //> @attr scrollbar.allowThumbOverState (boolean : false : IRA) // If true, the thumb's appearance changes when the user rolls over it. // @group thumb // @visibility external //< allowThumbOverState:false, //> @attr scrollbar.showTrackEnds (boolean : false : IRA) // If true, the scrollbar uses a 5-segment rather than 3-segment image representation, // where the 3 interior image segments have the same state (Down, Over, etc), independent // of the two outermost image segments. //

// This allows certain advanced skinning designs where the track-as-such (space in which // the thumb may be dragged) has curved endcaps, and is also visually stateful (that is, // changes when the mouse goes down, without affecting the appearance of the outermost // segments). // // @group track // @visibility external //< showTrackEnds:false, //> @attr scrollbar.thumbMinSize (number : 12 : IRA) // The minimum pixel size of the draggable thumb regardless of how large the scrolling // region becomes. // @group thumb // @visibility external //< thumbMinSize : 12, //> @attr scrollbar.trackEndWidth (number : 12 : IRA) // The minimum pixel width of the track end segments (if enabled with showTrackEnds). // @group track // @visibility external //< trackEndWidth : 12, //> @attr scrollbar.trackEndHeight (number : 12 : IRA) // The minimum pixel height of the track end segments (if enabled with showTrackEnds). // @group track // @visibility external //< trackEndHeight : 12, //> @attr scrollbar.thumbOverlap (number : 1 : IRA) // Number of pixels the thumb is allowed to overlap the buttons at each end of the track. // Default prevents doubling of 1px borders. Set higher to allow media that shows curved // joins between the track button and ScrollThumb. // @group thumb // @visibility external //< thumbOverlap : 1, //> @attr scrollbar.startThumbOverlap (number : null : IRA) // Number of pixels the thumb is allowed to overlap the buttons at the start of the track. // Default prevents doubling of 1px borders. Set higher to allow media that shows curved // joins between the track button and ScrollThumb. // @group thumb // @visibility external //< //> @attr scrollbar.endThumbOverlap (number : null : IRA) // Number of pixels the thumb is allowed to overlap the buttons at the end of the track. // Default prevents doubling of 1px borders. Set higher to allow media that shows curved // joins between the track button and ScrollThumb. // @group thumb // @visibility external //< //> @attr scrollbar.thumbInset (number : null : IRA) // Inset of the thumb relative to the track. An inset of N pixels means the thumb is 2N // pixels smaller in breadth than the track. // @group thumb // @visibility external //< thumbInset:0, overflow:isc.Canvas.HIDDEN, //> @attr scrollbar.skinImgDir (URL : "images/Scrollbar/" : IRA) // Where are the skin images for the Scrollbar. This is local to the +link{Page.getSkinDir(), // overall skin directory}. // @group images // @visibility external //< skinImgDir:"images/Scrollbar/", //> @attr scrollbar.cornerSrc (SCImgURL : "[SKIN]corner.gif" : IR) // URL for the corner image, a singular image that appears in the corner when both h and v // scrollbars are showing. // @group images // @visibility external //< cornerSrc : "[SKIN]corner.gif", //> @attr scrollbar.cornerSize (integer : null : IR) // Allows the size of the corner segment to be set independently of the +link{btnSize}. // @group corner // @visibility external //< //> @attr scrollbar.hSrc (SCImgURL : "[SKIN]hscroll.gif" : IR) // Base URL for the images used for the horizontal scrollbar track and end buttons. //

// See +link{StretchImg.items} for a general explanation of how this base URL is // transformed into various pieces and states. //

// For a normal 3-segment track, the suffixes "_start", "_track" and "_end" are added to // this URL. The "start" and "end" images should appear to be buttons (the user can click // on these segments to scroll slowly). The "track" segment provides a background for the // space in which the thumb can be dragged, and can also be clicked on to scroll quickly. //

// For a 5-segment track (+link{showTrackEnds}:true), the suffixes are "_start", "_track_start", // "_track", "_track_end" and "_end". // // @group images // @visibility external //< hSrc:"[SKIN]hscroll.gif", //> @attr scrollbar.vSrc (SCImgURL : "[SKIN]vscroll.gif" : IR) // Base URL for the images used for the vertical scrollbar track and end buttons. See // +link{hSrc} for usage. // // @group images // @visibility external //< vSrc:"[SKIN]vscroll.gif", // internal attributes to allow instance level skinning of scrollbars // do not expose - thumb should be implemented as autoChild instead hThumbClass: isc.HScrollThumb, vThumbClass: isc.VScrollThumb, // Images for parts of the scrollbar, initialized in scrollbar.initWidget // ---------------------------------------------------------------------------------------- startImg : {name:"start", width:"btnSize", height:"btnSize"}, trackStartImg: {name:"track_start", width:"trackStartSize", height:"trackStartSize"}, trackImg : {name:"track", width:"*", height:"*"}, trackEndImg: {name:"track_end", width:"trackEndSize", height:"trackEndSize"}, endImg : {name:"end", width:"btnSize", height:"btnSize"}, //_cornerImg:null, //> @attr scrollbar.scrollTarget (Canvas : null : [IRWA]) // The widget whose contents should be scrolled by this scrollbar. The scrollbar thumb // is sized according to the amount of visible vs. scrollable content in this widget. // @visibility external //< // don't reverse, even in RTL, since otherwise track-end arrows would point inwards textDirection:"ltr", // flag for whether or not the scrollBar should be managing its own scrollTarget. // set to false if a scrollTarget actually creates the scrollBar itself. _selfManaged:true, // undocumented flag scrollbar.showThumb: set to false to disable displaying thumb. // eventually this will also disable the track. showThumb:true // undocumented flag scrollbar.disableButtonsOnEdges: if beginning or end of scrolling // is reached, show either the start or end buttons as disabled, respectively. //disableButtonsOnEdges:false }); isc.Scrollbar.addMethods({ //> @method scrollbar.initWidget() (A) // creates the thumb and adds it as a peer // calls setScrollTarget() to set us up with the target to be scrolled // // @param [all arguments] (object) objects with properties to override from default //< initWidget : function () { this.invokeSuper(isc.Scrollbar,"initWidget"); var size = this.cornerSize || this.getID() + ".btnSize-1"; this._cornerImg = {name:"corner", width:size, height:size}; if (null == this.startThumbOverlap) this.startThumbOverlap = this.thumbOverlap; if (null == this.endThumbOverlap) this.endThumbOverlap = this.thumbOverlap; // set up the image list for this scrollbar this.setItems(); // must be after setItems() because updateButtonsOnEdges() may trigger setState. // If setItems() hasn't been called yet, setState() changes the global StretchImg items. if (this.vertical) this.setWidth(this.btnSize); else this.setHeight(this.btnSize); // create our thumb this.makeThumb(); // add the thumb as a peer this.addPeer(this.thumb); // initialize us for our scrollTarget this.setScrollTarget(); // call setThumb to figure out how big and where the scrollbar thumb should be // note: this will enable and disable the scrollbar if autoEnable is true this.setThumb(); }, //> @method scrollbar.setItems() // @group appearance // set up the list of images for this scrollbar // the image list changes depending on whether we're showing a corner piece or not //< setItems : function () { // create the items if (this.showTrackEnds == true) { this.items = [ this.startImg, this.trackStartImg, this.trackImg, this.trackEndImg, this.endImg ]; } else { this.items = [ this.startImg, this.trackImg, this.endImg ]; } if (this.showCorner) this.items.add(this._cornerImg); }, //> @method scrollbar.setShowCorner() (A) // Start showing the corner piece. //

// Marks the scrollbar for redraw. // // @param newState (boolean) true == show the corner piece //< setShowCorner : function (newState) { newState = newState != false; // if the newState is not the same as the old state if (this.showCorner != newState) { // set the newState this.showCorner = newState; // change the image list this.setItems(); // resize the images in preparation for the redraw this.resizeImages(); // mark this object as dirty to be redrawn later this.markForRedraw("showCorner") } return newState; }, //> @method scrollbar.setScrollTarget() ([]) // Sets or clears the scrollbar's scrollTarget. If no argument is provided, then the // scrollTarget will be set to the scrollbar itself. // // @visibility external // @group scroll // @param [newTarget] (Canvas) target canvas to be scrolled //< // Make sure we have a scrollTarget defined -- use us if nothing was ever specified. // Also, make sure the observation relationship between the scrollbar and the scrollTarget // is set up. setScrollTarget : function (newTarget) { // If we have been given a newTarget, stop observing the current scrollTarget that we're // observing. if (this._selfManaged && this.scrollTarget != null && this.isObserving(this.scrollTarget, "scrollTo")) { //stop observing (current) this.scrollTarget this.ignore(this.scrollTarget, "scrollTo"); } // If a newTarget was specified, set the scrollTarget to it. // If a newTarget was not specified, we'll use the current scrollTarget. If the // current scrollTarget isn't set, we use the scrollBar itself to avoid // null pointers if (newTarget != null) this.scrollTarget = newTarget; // if a target was not specified, use ourself for the target just so stuff doesn't break if (this.scrollTarget == null) this.scrollTarget = this; // We now are sure that we have a scrollTarget. If the scrollTarget has been changed // then we re-observe it. Otherwise, we're done. // if we've got a scrollTarget and we weren't created by adjustOverflow in the target, // we should observe the _adjustOverflow method of the target to make sure the // size of the thumb matches the visible portion of the target. if (this._selfManaged && this.scrollTarget != this && this.scrollTarget != newTarget) { this.observe(this.scrollTarget, "scrollTo", "observer.setThumb()"); } }, //> @method scrollbar.setHandleDisabled() (A) // Extend setHandleDisabled to hide the thumb and show disabled styling when disabled. // @group enable // // @param disabled (boolean) true if disabling //< setHandleDisabled : function (disabled) { // clear out the auto-enabled property - if we were auto disabled, we don't want to // auto enable. // call the superclass method this.Super("setHandleDisabled",arguments); // hide the thumb if necessary, and set it's _showWithMaster flag to avoid it showing // when the scrollbar is shown, if the scrollbar is disabled. if (this.thumb) { if (this.scrollTarget && this.scrollTarget._delayThumbVisibility) { if (disabled) this.thumb.delayCall("setVisibility", [isc.Canvas.HIDDEN]); else this.thumb.delayCall("setVisibility", [this.visibility]); } else { if (disabled) this.thumb.setVisibility(isc.Canvas.HIDDEN); else this.thumb.setVisibility(this.visibility); } this.thumb._showWithMaster = !disabled; } // make sure our drawn state matches the enabled state if (disabled == (this.state == isc.StatefulCanvas.STATE_UP)) { this.setState(disabled ? isc.StatefulCanvas.STATE_DISABLED: isc.StatefulCanvas.STATE_UP ); } }, //> @method scrollbar.setVisibility() (A) // Extended to ensure thumb is placed correctly when this scrollbar is shown. // @group visibility // // @param newState (boolean) new visible state //< setVisibility : function (newState,b,c,d) { this.invokeSuper(isc.Scrollbar, "setVisibility", newState,b,c,d); if (this.isVisible()) this.setThumb(); }, //> @method scrollbar.parentVisibilityChanged() (A) // Extended to ensure thumb is placed correctly when this scrollbar is shown due to a hidden // ancestor being shown. // @group visibility // // @param newState (boolean) new visible state //< parentVisibilityChanged : function (newState,b,c,d) { this.invokeSuper(isc.Scrollbar, "parentVisibilityChanged", newState,b,c,d); if (this.isVisible()) this.setThumb(); }, //> @method scrollbar.drawPeers() (A) // custom drawPeers routine to size the thumb before it's drawn // // @param document (document) // // @return () //< drawPeers : function (a,b,c,d) { // call the routine to resize the thumb this.setThumb(); // call the superclass method to actually do the drawing this.invokeSuper(isc.Scrollbar, "drawPeers", a,b,c,d); }, //> @method scrollbar.resizePeersBy() (A) // Overridden to size the thumb // // @param deltaX (number) change in width // @param deltaY (number) change in height //< resizePeersBy : function (deltaX, deltaY) { this.setThumb(); }, makeThumb : function () { if (!this.showThumb) return; // figure out derived attributes var classObject = this.vertical ? this.vThumbClass : this.hThumbClass; this.thumb = classObject.create({ ID:this.getID()+"_thumb", scrollbar:this, state:this.state, visibility:this.visibility, width : this.vertical ? this.getWidth() : 1, height : !this.vertical ? this.getHeight() : 1, dragScrollDirection : this.vertical ? isc.Canvas.VERTICAL : isc.Canvas.HORIZONTAL }); // Down / Over styling // - by default when a statefulCanvas starts to be dragged we clear any down / over state // on the item. // - we handle scrollbar thumb down / over styling independently via the allowThumbDownState // allowThumbOverState attributes, and avoid clearing these states when the user starts // dragging the thumb // - If showDown / showRollOver was set explicitly on the thumb, have those setting override // allowThumbDown / allowThumbOver so a skin can set these attributes on the scrollbar thumb // class and we'll react to them as expected. if (this.thumb.showRollOver) { this.allowThumbOverState = true this.thumb.showRollOver = false; } if (this.thumb.showDown) { this.allowThumbDownState = true; this.thumb.showDown = false; } }, updateButtonsOnEdges : function () { // if at start/end of track, optionally disable start/end buttons if (this.disableButtonsOnEdges) { var scrollRatio = this.scrollTarget.getScrollRatio(this.vertical); var vpRatio = this.scrollTarget.getViewportRatio(this.vertical); // Because setState() also occurs on button clicks, we can't be clever and // store the previous ratio to optimize out duplicate setState() calls if (scrollRatio == 0) { this.setState(isc.StatefulCanvas.STATE_DISABLED, this._$start); } else { this.setState(isc.StatefulCanvas.STATE_UP, this._$start); } if (scrollRatio == 1 || vpRatio >= 1) { this.setState(isc.StatefulCanvas.STATE_DISABLED, this._$end); } else { this.setState(isc.StatefulCanvas.STATE_UP, this._$end); } } }, //> @method scrollbar.setThumb() (A) // Resize the thumb so that the thumb's size relative to the track reflects the viewport size // relative to the overall scrollable area. // @param forceResize (boolean) if true, resize regardless of whether it is necessary //< setThumb : function () { // every time thumb is updated, check to see if buttons need disabling this.updateButtonsOnEdges(); // Bail if the thumb hasn't been created yet. This happens on setWidth() / setHeight() // during initWidget() if (this.thumb == null || this._suppressSetThumb) return; var thumb = this.thumb, trackSize = this.trackSize(); // make sure the thumb is above us (we avoid automatically redrawing the thumb, so it can // end up underneath the zIndex of the latest draw of the track/buttons) if (this.isDrawn() && thumb.isDrawn()) thumb.moveAbove(this); // calculate size for thumb var size = Math.round(this.scrollTarget.getViewportRatio(this.vertical) * trackSize); // don't go below a minimum thumb size (too hard to grab) if (!isc.isA.Number(size) || size < this.thumbMinSize) size = this.thumbMinSize; // don't let it exceed trackSize if (size > trackSize) size = trackSize; // always ensure the thumb's thickness matches the available space for it var thickness = Math.max(1, (this.vertical ? this.getWidth() : this.getHeight()) - (2*this.thumbInset)); // resize the thumb this.vertical ? thumb.resizeTo(thickness, size) : thumb.resizeTo(size, thickness); // now move the thumb according to the scroll this.moveThumb(); }, // Override 'setZIndex' to ensure the thumb stays above us when our z-index changes. setZIndex : function (newIndex) { this.Super("setZIndex", arguments); if (this.thumb) this.thumb.moveAbove(this); }, //> @method scrollbar.moveThumbTo() (A) // move the thumb to a particular coordinate // // @param coord (number) new x or y coordinate to move to //< moveThumbTo : function (coord) { if (!this.thumb) return; if (this.vertical) return this.thumb.moveTo(this.getLeft() + this.thumbInset, coord); else return this.thumb.moveTo(coord, this.getTop() + this.thumbInset); }, //> @method scrollbar.thumbSize() (A) // @group sizing // return the size of the thumb in the direction of the scroll // @return (number) the size of the thumb in the direction of the scroll //< thumbSize : function () { if (!this.thumb) return; return (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth()); }, //> @method scrollbar.moveThumb() (A) // Move the thumb to the right place for the scroll of the target //

// May enable/disable the scrollbar if scrolling is no longer necessary because everything is // visible. // @group sizing //< moveThumb : function () { var scrollingOn = (this._selfManaged || this.scrollTarget.canScroll(this.vertical)); if (!scrollingOn) { if (this.autoEnable) this.disable(); this.moveThumbTo(this.trackStart()); return; } if (this.autoEnable && !this.scrollTarget.isDisabled()) this.enable(); var scrollRatio = this.scrollTarget.getScrollRatio(this.vertical), maxThumbPosition = this.trackSize() - this.thumbSize(), thumbCoord = Math.round(scrollRatio * maxThumbPosition); this.moveThumbTo(thumbCoord + this.trackStart()); // If the thumb moved due to the user holding the mouse down over our track, this kills // repeatTrackScrolling var EH = isc.EH; if (EH.mouseIsDown() && (EH.mouseDownTarget() == this) && this.thumb.containsEvent()) this.doneTrackScrolling(); }, _$start:"start", _$end:"end", _$track:"track", _$track_start:"track_start", _$track_end:"track_end", _$thumb:"thumb", _$corner:"corner", //> @method scrollbar.trackSize() (A) // @group sizing // return the size of the scroll track // @return (number) size of the scroll track //< trackSize : function () { // that's the size of the 'track' object + 2, // since the thumb overlaps the top and bottom buttons by 1 pixel if (this.showTrackEnds == true) return this.getSize(this.getPartNum(this._$track)) + this.getSize(this.getPartNum(this._$track_start)) + this.getSize(this.getPartNum(this._$track_end)) + this.startThumbOverlap + this.endThumbOverlap; else return this.getSize(this.getPartNum(this._$track)) + this.startThumbOverlap + this.endThumbOverlap; }, //> @method scrollbar.trackStart() (A) // Return where the scroll track starts // @group sizing // // @return (number) relative pixel where the scroll track starts //< trackStart : function () { if (this.vertical) return this.getTop() + this.btnSize - this.startThumbOverlap; else return this.getLeft() + this.btnSize - this.startThumbOverlap; }, //> @method scrollbar.directionRelativeToThumb() (A) // Return where an x,y coordinate is in relation to the scroll thumb, accounting for direction // // @return (number) // negative == before thumb // 0 == inside thumb // positive == after thumb //< directionRelativeToThumb : function () { if (!this.thumb) { // no thumb means no track: buttons only if (this.clickPart == this._$start) return -1; else return 1; } var coord, thumb = this.thumb, thumbEdge, thumbSize; if (this.vertical) { coord = isc.EH.getY(); thumbEdge = thumb.getPageTop(); thumbSize = thumb.getHeight(); } else { coord = isc.EH.getX(); thumbEdge = thumb.getPageLeft(); thumbSize = thumb.getWidth(); } if (coord < thumbEdge) return -1; else if (coord > thumbEdge + thumbSize) return 1; return 0; }, //> @method scrollbar.mouseDown() (A) // mouseDown handler -- figures out what was clicked on and what to do // @group event handling // // @return (boolean) false == cancel event processing //< mouseDown : function () { // figure out which part they clicked in and remember it this.clickPart = this.inWhichPart(); // if the click is in a corner, clear the clickPart if (this.clickPart == this._$corner) { this.clickPart = null; return isc.EH.STOP_BUBBLING; } // show that clickPart as down visually this._updateItemStates(isc.StatefulCanvas.STATE_DOWN, this.clickPart); // remember the 'direction' of the click relative to the thumb // -1 = before thumb, 0 = inside thumb, 1 = after thumb this.startDirection = this.directionRelativeToThumb(); // return false so we cancel event processing return isc.EH.STOP_BUBBLING; }, //> @method scrollbar.mouseStillDown() (A) // mouseStillDown handler // @group event handling // // @return (boolean) false == cancel event processing //< mouseStillDown : function () { // scroll the target according to where the mouse went down if (this.clickPart == this._$track || this.showTrackEnds == true && (this.clickPart == this._$track_start || this.clickPart == this._$track_end)) { // avoid continuing to page scroll if the thumb passes the cursor // direction will be zero the the thumb is actually underneath the cursor var direction = this.directionRelativeToThumb(); if (direction != 0 && direction == this.startDirection) { // Make a note of the fact that we're doing repeated track scrolls // Note: do this on the 2nd track scroll only - we don't want a single click in the // track to count as this kind of rapid scrolling if (this._initialTrackScroll) { delete this._initialTrackScroll; this._repeatTrackScrolling = true; } else if (!this._repeatTrackScrolling) this._initialTrackScroll = true; this.scrollTarget.scrollByPage(this.vertical, this.startDirection, "trackClick"); } } else { // button click this.scrollTarget.scrollByDelta(this.vertical, this.startDirection, "trackButtonClick"); } // return true that mouseStillDown should continue //return isc.EventHandler.STOP_BUBBLING; return true; }, doubleClick : function () { //this.logWarn("scrollbar double click"); if (isc.Browser.isIE) return this.mouseStillDown(); // return isc.EventHandler.STOP_BUBBLING so we cancel event processing return isc.EH.STOP_BUBBLING; }, _$corner:"corner", _updateItemStates : function (newState, part) { if (part == null) return this.setState(newState); var defaultState = isc.StatefulCanvas.STATE_UP, track = (part == this._$track || part == this._$track_start || part == this._$track_end), start = !track && part == this._$start, end = !track && !start && part == this._$end, corner = !track && !start && !end, trackState = track ? newState : defaultState; this.setState(start ? newState : defaultState, this._$start); this.setState(trackState,this._$track); if (this.showTrackEnds) this.setState(trackState,this._$track_start); if (this.showTrackEnds) this.setState(trackState,this._$track_end); this.setState(end ? newState : defaultState, this._$end); if (this.showCorner) this.setState(corner ? newState : defaultState, this._$corner); }, //> @method scrollbar.mouseUp() (A) // @group event handling // mouseUp handler for the main scrollbar // // @return (boolean) false == cancel event processing //< mouseUp : function () { // show the clickPart as up again visually if (this.clickPart) { var newState = this.showRollOver ? isc.StatefulCanvas.STATE_OVER : isc.StatefulCanvas.STATE_UP; this._updateItemStates(newState, this.clickPart); } this.clickPart = null; this.doneTrackScrolling(); this.updateButtonsOnEdges(); // return isc.EventHandler.STOP_BUBBLING so we cancel event processing return isc.EventHandler.STOP_BUBBLING; }, // Stop various events from propagating to the parent of the Canvas we are scrolling. click : isc.EventHandler.stopBubbling, mouseOver:isc.EH.stopBubbling, // MouseMove - respect showRollOver - implemented to show partwise rollOver mouseMove : function () { // clickPart should be defined if the mouse went down over this item - otherwise // we don't want to show a down state at all if (this.ns.EH.mouseIsDown() && this.clickPart) { // appropriate item down state should have been set already - no need to re-set //this._updateItemStates(isc.StatefulCanvas.STATE_DOWN, this.clickPart); } else if (this.showRollOver) { this._updateItemStates(isc.StatefulCanvas.STATE_OVER, this.inWhichPart()); } return isc.EH.STOP_BUBBLING; }, //> @method scrollbar.mouseOut() (A) // mouseOut event handler -- clear the button hilite, if appropriate // may redraw the button // @group events //< mouseOut : function () { if (this.ns.EH.mouseIsDown()) return isc.EH.STOP_BUBBLING; if (this.showRollOver) { this.setState(isc.StatefulCanvas.STATE_UP); } return isc.EH.STOP_BUBBLING; }, // avoid triggering drag interactions on the track (possible if any of our master's parents are // canDrag:true and aren't coded to explicitly avoid drag interactions on scrollbars) prepareForDragging : function () { return false; }, // is the user currently scrolling by dragging the scroll thumb? isDragScrolling : function () { return this._dragScrolling; }, // is the user scrolling by holding the mouse down over the track? isRepeatTrackScrolling : function () { return this._repeatTrackScrolling; }, doneTrackScrolling : function () { // We're no longer repeat track scrolling delete this._initialTrackScroll; if (this.isRepeatTrackScrolling()) { delete this._repeatTrackScrolling; // notify the target we're done with 'track scrolling' if (this.scrollTarget && this.scrollTarget.doneFastScrolling) this.scrollTarget.doneFastScrolling(); } }, // Implement custom mouseOver / mouseOut handlers for the thumb to show and clear over state // We do this rather than relying on the standard StatefulCanvas.showRollOver behavior since // when the user starts dragging the thumb we get mouseOut event and we don't want to clear the // state in that case - instead wait for drag stop / mouseUp //> @method scrollbar.thumbOver() (A) // Handle mouse over the thumb // @group event handling // // @return (boolean) false == cancel event processing //< thumbOver : function () { // show the thumb as down if (this.allowThumbOverState) { this.thumb.setState(isc.StatefulCanvas.STATE_OVER); } }, //> @method scrollbar.thumbOut() (A) // Handle mouse out over the thumb // @group event handling // // @return (boolean) false == cancel event processing //< thumbOut : function () { if (!isc.EH.mouseIsDown()) { this.thumb.setState(isc.StatefulCanvas.STATE_UP); } }, //> @method scrollbar.thumbDown() (A) // Handle mouse down in the thumb // @group event handling // // @return (boolean) false == cancel event processing //< thumbDown : function () { this.clickPart = this._$thumb; // show the thumb as down if (this.allowThumbDownState) { this.thumb.setState(isc.StatefulCanvas.STATE_DOWN); } return isc.EventHandler.STOP_BUBBLING; }, //> @method scrollbar.thumbDragStart() (A) // Handle drag start in the thumb // @group event handling // // @return (boolean) false == cancel event processing //< thumbDragStart : function () { // set the offsetX and offsetY so the thumb moves with the mouse properly var EH = isc.EH; EH.dragOffsetX = this.thumb.getOffsetX(EH.mouseDownEvent); EH.dragOffsetY = this.thumb.getOffsetY(EH.mouseDownEvent); this._dragScrolling = true; return EH.STOP_BUBBLING; }, //> @method scrollbar.getEventCoord() (A) // return the event coordinate we care about, in the relevant direction // @return (number) x or y coordinate, relative to our coordinate system //< getEventCoord : function () { var EH = isc.EH; if (this.vertical) return EH.getY() - this.getPageTop() - this.btnSize + this.startThumbOverlap - EH.dragOffsetY; else return EH.getX() - this.getPageLeft() - this.btnSize + this.startThumbOverlap - EH.dragOffsetX; }, masterMoved : function (dX,dY,a,b,c,d) { if (this.masterElement._settingRect) return; return this.invokeSuper(isc.Scrollbar, "masterMoved", dX, dY, a,b,c,d); }, //> @method scrollbar.thumbMove() (A) // mouse move in the thumb // // @return (boolean) false == cancel event processing //< thumbMove : function () { // get the total amount of the track that's scrollable var trackSize = this.trackSize() - this.thumbSize(), // get the Y coordinate of the event, less the track start and the offsetY from mouseDown eventCoord = this.getEventCoord(), // get ratio to scroll to ratio = eventCoord / trackSize; ratio = Math.max(0, Math.min(ratio, 1)); this.scrollTarget.scrollToRatio(this.vertical, ratio, "thumbMove"); return isc.EventHandler.STOP_BUBBLING; }, //> @method scrollbar.thumbUp() (A) // mouse up in the thumb // // @return (boolean) false == cancel event processing //< thumbUp : function () { // The thumb can catch the mouse up events that really should be going to // the track, because the thumb winds up occluding the track when the button is // held down long enough to move the thumb to where the mouse pointer is. If we're // currently servicing a non-thumb click, bail out and call mouseUp. if (this.clickPart != this._$thumb) return this.mouseUp(); // show the thumb as up var newState = this.allowThumbOverState && this.thumb.containsEvent() ? isc.StatefulCanvas.STATE_OVER : isc.StatefulCanvas.STATE_UP; this.thumb.setState(newState); return isc.EventHandler.STOP_BUBBLING; }, //> @method scrollbar.thumbDragStop() // Event fired when the user stops dragging the scrollbar thumb //< thumbDragStop : function () { delete this._dragScrolling; // doneFastScrolling() - notifies the target that the user is no longer performing // rapid scrolls on the widget if (this.scrollTarget && this.scrollTarget.doneFastScrolling) this.scrollTarget.doneFastScrolling(); // thumbUp will handle clearing the down state, etc. return this.thumbUp(); }, // pass key and mousewheel events through keyPress : function () { return this.ns.EH.bubbleEvent(this.scrollTarget, this.ns.EH.eventTypes.KEY_PRESS); }, keyDown : function () { return this.ns.EH.bubbleEvent(this.scrollTarget, this.ns.EH.eventTypes.KEY_DOWN); }, keyUp : function () { return this.ns.EH.bubbleEvent(this.scrollTarget, this.ns.EH.eventTypes.KEY_UP); }, mouseWheel : function () { return this.ns.EH.bubbleEvent(this.scrollTarget, this.ns.EH.eventTypes.MOUSE_WHEEL); }, // If this scrollbar was created by a widget automatically, always hide by shifting to // top/left and sizing to smallest possible size of the target. hide : function (a,b,c,d) { this.invokeSuper("Scrollbar", "hide", a,b,c,d); if (!this._selfManaged && this.scrollTarget != null) { this.moveTo(this.scrollTarget.getLeft(), this.scrollTarget.getTop()); this.resizeTo(1,1); } } });





© 2015 - 2024 Weber Informatics LLC | Privacy Policy