From b3fa8f11844fec1fe5b3601c62e627ccda7102d8 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Thu, 5 Sep 2013 17:20:17 -0700 Subject: [PATCH 01/15] MouseTracker original events in handlers Implemented "Expose original event in handlers" (#23) for MouseTracker Added OpenSeadragon.getElementOffset() method. Element-relative mouse coordinates should be correct even if the element and/or page is scrolled (#131) --- src/button.js | 38 +- src/buttongroup.js | 20 +- src/eventhandler.js | 2 +- src/mousetracker.js | 1065 ++++++++++++++++++++++++----------------- src/navigator.js | 16 +- src/openseadragon.js | 42 ++ src/referencestrip.js | 862 ++++++++++++++++----------------- src/viewer.js | 88 ++-- 8 files changed, 1166 insertions(+), 967 deletions(-) diff --git a/src/button.js b/src/button.js index 7eead5da..4524234e 100644 --- a/src/button.js +++ b/src/button.js @@ -175,57 +175,59 @@ $.Button = function( options ) { clickTimeThreshold: this.clickTimeThreshold, clickDistThreshold: this.clickDistThreshold, - enterHandler: function( tracker, position, buttonDownElement, buttonDownAny ) { - if ( buttonDownElement ) { + enterHandler: function( tracker, eventData ) { + if ( eventData.buttonDownElement ) { inTo( _this, $.ButtonState.DOWN ); _this.raiseEvent( "onEnter", _this ); - } else if ( !buttonDownAny ) { + } else if ( !eventData.buttonDownAny ) { inTo( _this, $.ButtonState.HOVER ); } }, - focusHandler: function( tracker, position, buttonDownElement, buttonDownAny ) { - this.enterHandler( tracker, position, buttonDownElement, buttonDownAny ); + // TODO: This didn't match handler signature in MouseTracker. Investigate! + focusHandler: function ( tracker, eventData ) { //position, buttonDownElement, buttonDownAny + //this.enterHandler( tracker, eventData ); //position, buttonDownElement, buttonDownAny _this.raiseEvent( "onFocus", _this ); }, - exitHandler: function( tracker, position, buttonDownElement, buttonDownAny ) { + exitHandler: function( tracker, eventData ) { outTo( _this, $.ButtonState.GROUP ); - if ( buttonDownElement ) { + if ( eventData.buttonDownElement ) { _this.raiseEvent( "onExit", _this ); } }, - blurHandler: function( tracker, position, buttonDownElement, buttonDownAny ) { - this.exitHandler( tracker, position, buttonDownElement, buttonDownAny ); + // TODO: This didn't match handler signature in MouseTracker. Investigate! + blurHandler: function ( tracker, eventData ) { //position, buttonDownElement, buttonDownAny + //this.exitHandler( tracker, eventData ); //position, buttonDownElement, buttonDownAny _this.raiseEvent( "onBlur", _this ); }, - pressHandler: function( tracker, position ) { + pressHandler: function ( tracker, eventData ) { inTo( _this, $.ButtonState.DOWN ); _this.raiseEvent( "onPress", _this ); }, - releaseHandler: function( tracker, position, insideElementPress, insideElementRelease ) { - if ( insideElementPress && insideElementRelease ) { + releaseHandler: function( tracker, eventData ) { + if ( eventData.insideElementPress && eventData.insideElementRelease ) { outTo( _this, $.ButtonState.HOVER ); _this.raiseEvent( "onRelease", _this ); - } else if ( insideElementPress ) { + } else if ( eventData.insideElementPress ) { outTo( _this, $.ButtonState.GROUP ); } else { inTo( _this, $.ButtonState.HOVER ); } }, - clickHandler: function( tracker, position, quick, shift ) { - if ( quick ) { + clickHandler: function( tracker, eventData ) { + if ( eventData.quick ) { _this.raiseEvent("onClick", _this); } }, - keyHandler: function( tracker, key ){ - //console.log( "%s : handling key %s!", _this.tooltip, key); - if( 13 === key ){ + keyHandler: function( tracker, eventData ){ + //console.log( "%s : handling key %s!", _this.tooltip, eventData.keyCode); + if( 13 === eventData.keyCode ){ _this.raiseEvent( "onClick", _this ); _this.raiseEvent( "onRelease", _this ); return false; diff --git a/src/buttongroup.js b/src/buttongroup.js index 17c08267..550a2ac1 100644 --- a/src/buttongroup.js +++ b/src/buttongroup.js @@ -85,29 +85,23 @@ $.ButtonGroup = function( options ) { element: this.element, clickTimeThreshold: this.clickTimeThreshold, clickDistThreshold: this.clickDistThreshold, - enterHandler: function() { + enterHandler: function ( tracker, eventData ) { var i; for ( i = 0; i < _this.buttons.length; i++ ) { _this.buttons[ i ].notifyGroupEnter(); } }, - exitHandler: function() { - var i, - buttonDownElement = arguments.length > 2 ? - arguments[ 2 ] : - null; - if ( !buttonDownElement ) { + exitHandler: function ( tracker, eventData ) { + var i; + if ( !eventData.buttonDownElement ) { for ( i = 0; i < _this.buttons.length; i++ ) { _this.buttons[ i ].notifyGroupExit(); } } }, - releaseHandler: function() { - var i, - insideElementRelease = arguments.length > 3 ? - arguments[ 3 ] : - null; - if ( !insideElementRelease ) { + releaseHandler: function ( tracker, eventData ) { + var i; + if ( !eventData.insideElementRelease ) { for ( i = 0; i < _this.buttons.length; i++ ) { _this.buttons[ i ].notifyGroupExit(); } diff --git a/src/eventhandler.js b/src/eventhandler.js index 56fbf080..1595bd54 100644 --- a/src/eventhandler.js +++ b/src/eventhandler.js @@ -55,7 +55,7 @@ $.EventHandler.prototype = { * @function * @param {String} eventName - Name of event to register. * @param {Function} handler - Function to call when event is triggered. - * @param {Object} optional userData - Arbitrary object to be passed to the handler. + * @param {Object} optional userData - Arbitrary object to be passed unchanged to the handler. */ addHandler: function ( eventName, handler, userData ) { var events = this.events[ eventName ]; diff --git a/src/mousetracker.js b/src/mousetracker.js index f2dd53f8..36492d6a 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -32,72 +32,82 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -(function( $ ){ +(function ( $ ) { - // is any button currently being pressed while mouse events occur - var IS_BUTTON_DOWN = false, - // is any tracker currently capturing? - IS_CAPTURING = false, - // dictionary from hash to MouseTracker - ACTIVE = {}, - // list of trackers interested in capture - CAPTURING = [], - // dictionary from hash to private properties - THIS = {}; + // is any button currently being pressed while mouse events occur + var IS_BUTTON_DOWN = false, + // is any tracker currently capturing? + IS_CAPTURING = false, + // dictionary from hash to MouseTracker + ACTIVE = {}, + // list of trackers interested in capture + CAPTURING = [], + // dictionary from hash to private properties + THIS = {}; /** - * The MouseTracker allows other classes to set handlers for common mouse - * events on a specific element like, 'enter', 'exit', 'press', 'release', - * 'scroll', 'click', and 'drag'. - * @class - * @param {Object} options - * Allows configurable properties to be entirely specified by passing - * an options object to the constructor. The constructor also supports - * the original positional arguments 'elements', 'clickTimeThreshold', - * and 'clickDistThreshold' in that order. - * @param {Element|String} options.element - * A reference to an element or an element id for which the mouse - * events will be monitored. - * @param {Number} options.clickTimeThreshold - * The number of milliseconds within which mutliple mouse clicks - * will be treated as a single event. - * @param {Number} options.clickDistThreshold - * The distance between mouse click within multiple mouse clicks - * will be treated as a single event. - * @param {Function} options.enterHandler - * An optional handler for mouse enter. - * @param {Function} options.exitHandler - * An optional handler for mouse exit. - * @param {Function} options.pressHandler - * An optional handler for mouse press. - * @param {Function} options.releaseHandler - * An optional handler for mouse release. - * @param {Function} options.scrollHandler - * An optional handler for mouse scroll. - * @param {Function} options.clickHandler - * An optional handler for mouse click. - * @param {Function} options.dragHandler - * An optional handler for mouse drag. - * @property {Number} hash - * An unique hash for this tracker. - * @property {Element} element - * The element for which mouse event are being monitored. - * @property {Number} clickTimeThreshold - * The number of milliseconds within which mutliple mouse clicks - * will be treated as a single event. - * @property {Number} clickDistThreshold - * The distance between mouse click within multiple mouse clicks - * will be treated as a single event. - */ + * The MouseTracker allows other classes to set handlers for common mouse + * events on a specific element like, 'enter', 'exit', 'press', 'release', + * 'scroll', 'click', and 'drag'. + * @class + * @param {Object} options + * Allows configurable properties to be entirely specified by passing + * an options object to the constructor. The constructor also supports + * the original positional arguments 'elements', 'clickTimeThreshold', + * and 'clickDistThreshold' in that order. + * @param {Element|String} options.element + * A reference to an element or an element id for which the mouse + * events will be monitored. + * @param {Number} options.clickTimeThreshold + * The number of milliseconds within which mutliple mouse clicks + * will be treated as a single event. + * @param {Number} options.clickDistThreshold + * The distance between mouse click within multiple mouse clicks + * will be treated as a single event. + * @param {Function} options.enterHandler + * An optional handler for mouse enter. + * @param {Function} options.exitHandler + * An optional handler for mouse exit. + * @param {Function} options.pressHandler + * An optional handler for mouse press. + * @param {Function} options.releaseHandler + * An optional handler for mouse release. + * @param {Function} options.moveHandler + * An optional handler for mouse move. + * @param {Function} options.scrollHandler + * An optional handler for mouse scroll. + * @param {Function} options.clickHandler + * An optional handler for mouse click. + * @param {Function} options.dragHandler + * An optional handler for mouse drag. + * @param {Function} options.keyHandler + * An optional handler for keypress. + * @param {Function} options.focusHandler + * An optional handler for focus. + * @param {Function} options.blurHandler + * An optional handler for blur. + * @property {Number} hash + * An unique hash for this tracker. + * @property {Element} element + * The element for which mouse event are being monitored. + * @property {Number} clickTimeThreshold + * The number of milliseconds within which mutliple mouse clicks + * will be treated as a single event. + * @property {Number} clickDistThreshold + * The distance between mouse click within multiple mouse clicks + * will be treated as a single event. + * @property {Object} optional userData + * Arbitrary object to be passed unchanged to any attached handler methods. + */ $.MouseTracker = function ( options ) { - var args = arguments; + var args = arguments; - if( !$.isPlainObject( options ) ){ + if ( !$.isPlainObject( options ) ) { options = { - element: args[ 0 ], - clickTimeThreshold: args[ 1 ], - clickDistThreshold: args[ 2 ] + element: args[0], + clickTimeThreshold: args[1], + clickDistThreshold: args[2] }; } @@ -105,66 +115,68 @@ this.element = $.getElement( options.element ); this.clickTimeThreshold = options.clickTimeThreshold; this.clickDistThreshold = options.clickDistThreshold; + this.userData = options.userData || null; - - this.enterHandler = options.enterHandler || null; - this.exitHandler = options.exitHandler || null; - this.pressHandler = options.pressHandler || null; + this.enterHandler = options.enterHandler || null; + this.exitHandler = options.exitHandler || null; + this.pressHandler = options.pressHandler || null; this.releaseHandler = options.releaseHandler || null; - this.scrollHandler = options.scrollHandler || null; - this.clickHandler = options.clickHandler || null; - this.dragHandler = options.dragHandler || null; - this.keyHandler = options.keyHandler || null; - this.focusHandler = options.focusHandler || null; - this.blurHandler = options.blurHandler || null; + this.moveHandler = options.moveHandler || null; + this.scrollHandler = options.scrollHandler || null; + this.clickHandler = options.clickHandler || null; + this.dragHandler = options.dragHandler || null; + this.keyHandler = options.keyHandler || null; + this.focusHandler = options.focusHandler || null; + this.blurHandler = options.blurHandler || null; //Store private properties in a scope sealed hash map var _this = this; /** - * @private - * @property {Boolean} tracking - * Are we currently tracking mouse events. - * @property {Boolean} capturing - * Are we curruently capturing mouse events. - * @property {Boolean} buttonDown - * True if the left mouse button is currently being pressed and was - * initiated inside the tracked element, otherwise false. - * @property {Boolean} insideElement - * Are we currently inside the screen area of the tracked element. - * @property {OpenSeadragon.Point} lastPoint - * Position of last mouse down/move - * @property {Number} lastMouseDownTime - * Time of last mouse down. - * @property {OpenSeadragon.Point} lastMouseDownPoint - * Position of last mouse down - */ - THIS[ this.hash ] = { - mouseover: function( event ){ onMouseOver( _this, event ); }, - mouseout: function( event ){ onMouseOut( _this, event ); }, - mousedown: function( event ){ onMouseDown( _this, event ); }, - mouseup: function( event ){ onMouseUp( _this, event ); }, - click: function( event ){ onMouseClick( _this, event ); }, - DOMMouseScroll: function( event ){ onMouseWheelSpin( _this, event ); }, - mousewheel: function( event ){ onMouseWheelSpin( _this, event ); }, - mouseupie: function( event ){ onMouseUpIE( _this, event ); }, - mousemoveie: function( event ){ onMouseMoveIE( _this, event ); }, - mouseupwindow: function( event ){ onMouseUpWindow( _this, event ); }, - mousemove: function( event ){ onMouseMove( _this, event ); }, - touchstart: function( event ){ onTouchStart( _this, event ); }, - touchmove: function( event ){ onTouchMove( _this, event ); }, - touchend: function( event ){ onTouchEnd( _this, event ); }, - keypress: function( event ){ onKeyPress( _this, event ); }, - focus: function( event ){ onFocus( _this, event ); }, - blur: function( event ){ onBlur( _this, event ); }, - tracking: false, - capturing: false, - buttonDown: false, - insideElement: false, - lastPoint: null, - lastMouseDownTime: null, + * @private + * @property {Boolean} tracking + * Are we currently tracking mouse events. + * @property {Boolean} capturing + * Are we curruently capturing mouse events. + * @property {Boolean} buttonDownElement + * True if the left mouse button is currently being pressed and was + * initiated inside the tracked element, otherwise false. + * @property {Boolean} insideElement + * Are we currently inside the screen area of the tracked element. + * @property {OpenSeadragon.Point} lastPoint + * Position of last mouse down/move + * @property {Number} lastMouseDownTime + * Time of last mouse down. + * @property {OpenSeadragon.Point} lastMouseDownPoint + * Position of last mouse down + */ + THIS[this.hash] = { + mouseover: function ( event ) { onMouseOver( _this, event, false ); }, + mouseout: function ( event ) { onMouseOut( _this, event, false ); }, + mousedown: function ( event ) { onMouseDown( _this, event ); }, + mouseup: function ( event ) { onMouseUp( _this, event, false ); }, + mousemove: function ( event ) { onMouseMove( _this, event ); }, + click: function ( event ) { onMouseClick( _this, event ); }, + DOMMouseScroll: function ( event ) { onMouseWheelSpin( _this, event, false ); }, + mousewheel: function ( event ) { onMouseWheelSpin( _this, event, false ); }, + mouseupie: function ( event ) { onMouseUpIE( _this, event ); }, + mousemoveie: function ( event ) { onMouseMoveIE( _this, event ); }, + mouseupwindow: function ( event ) { onMouseUpWindow( _this, event ); }, + mousemovewindow: function ( event ) { onMouseMoveWindow( _this, event, false ); }, + touchstart: function ( event ) { onTouchStart( _this, event ); }, + touchmove: function ( event ) { onTouchMove( _this, event ); }, + touchend: function ( event ) { onTouchEnd( _this, event ); }, + keypress: function ( event ) { onKeyPress( _this, event ); }, + focus: function ( event ) { onFocus( _this, event ); }, + blur: function ( event ) { onBlur( _this, event ); }, + tracking: false, + capturing: false, + buttonDownElement: false, + insideElement: false, + lastPoint: null, + lastMouseDownTime: null, lastMouseDownPoint: null, - lastPinchDelta: 0 + lastPinchDelta: 0 }; }; @@ -172,30 +184,30 @@ $.MouseTracker.prototype = { /** - * Clean up any events or objects created by the mouse tracker. - * @function - */ - destroy: function() { + * Clean up any events or objects created by the mouse tracker. + * @function + */ + destroy: function () { stopTracking( this ); this.element = null; }, /** - * Are we currently tracking events on this element. - * @deprecated Just use this.tracking - * @function - * @returns {Boolean} Are we currently tracking events on this element. - */ + * Are we currently tracking events on this element. + * @deprecated Just use this.tracking + * @function + * @returns {Boolean} Are we currently tracking events on this element. + */ isTracking: function () { - return THIS[ this.hash ].tracking; + return THIS[this.hash].tracking; }, /** - * Enable or disable whether or not we are tracking events on this element. - * @function - * @param {Boolean} track True to start tracking, false to stop tracking. - * @returns {OpenSeadragon.MouseTracker} Chainable. - */ + * Enable or disable whether or not we are tracking events on this element. + * @function + * @param {Boolean} track True to start tracking, false to stop tracking. + * @returns {OpenSeadragon.MouseTracker} Chainable. + */ setTracking: function ( track ) { if ( track ) { startTracking( this ); @@ -207,213 +219,276 @@ }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {OpenSeadragon.Point} position - * The poistion of the event on the screen. - * @param {Boolean} buttonDown - * True if the left mouse button is currently being pressed and was - * initiated inside the tracked element, otherwise false. - * @param {Boolean} buttonDownAny - * Was the button down anywhere in the screen during the event. - */ - enterHandler: function(){}, + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * buttonDownElement: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. + * buttonDownAny: Was the button down anywhere in the screen during the event. + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ + enterHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {OpenSeadragon.Point} position - * The poistion of the event on the screen. - * @param {Boolean} buttonDown - * True if the left mouse button is currently being pressed and was - * initiated inside the tracked element, otherwise false. - * @param {Boolean} buttonDownAny - * Was the button down anywhere in the screen during the event. - */ - exitHandler: function(){}, + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * buttonDownElement: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. + * buttonDownAny: Was the button down anywhere in the screen during the event. + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ + exitHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {OpenSeadragon.Point} position - * The poistion of the event on the screen. - */ - pressHandler: function(){}, + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ + pressHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {OpenSeadragon.Point} position - * The poistion of the event on the screen. - * @param {Boolean} buttonDown - * True if the left mouse button is currently being pressed and was - * initiated inside the tracked element, otherwise false. - * @param {Boolean} insideElementRelease - * Was the mouse still inside the tracked element when the button - * was released. - */ - releaseHandler: function(){}, + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * insideElementPress: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. + * insideElementRelease: Was the mouse still inside the tracked element when the button was released. + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ + releaseHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {OpenSeadragon.Point} position - * The poistion of the event on the screen. - * @param {Number} scroll - * The scroll delta for the event. - * @param {Boolean} shift - * Was the shift key being pressed during this event? - */ - scrollHandler: function(){}, + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ + moveHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {OpenSeadragon.Point} position - * The poistion of the event on the screen. - * @param {Boolean} quick - * True only if the clickDistThreshold and clickDeltaThreshold are - * both pased. Useful for ignoring events. - * @param {Boolean} shift - * Was the shift key being pressed during this event? - */ - clickHandler: function(){}, + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * scroll: The scroll delta for the event. + * shift: Was the shift key being pressed during this event? + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ + scrollHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {OpenSeadragon.Point} position - * The poistion of the event on the screen. - * @param {OpenSeadragon.Point} delta - * The x,y components of the difference between start drag and - * end drag. Usefule for ignoring or weighting the events. - * @param {Boolean} shift - * Was the shift key being pressed during this event? - */ - dragHandler: function(){}, + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * quick: True only if the clickDistThreshold and clickDeltaThreshold are both pased. Useful for ignoring events. + * shift: Was the shift key being pressed during this event? + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ + clickHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {Number} keyCode - * The key code that was pressed. - * @param {Boolean} shift - * Was the shift key being pressed during this event? - */ - keyHandler: function(){}, + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * delta: The x,y components of the difference between start drag and end drag. Usefule for ignoring or weighting the events. + * shift: Was the shift key being pressed during this event? + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ + dragHandler: function () { }, - focusHandler: function(){}, + /** + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * keyCode: The key code that was pressed. + * shift: Was the shift key being pressed during this event? + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ + keyHandler: function () { }, - blurHandler: function(){} + /** + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ + focusHandler: function () { }, + + /** + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ + blurHandler: function () { } }; /** - * Starts tracking mouse events on this element. - * @private - * @inner - */ + * Starts tracking mouse events on this element. + * @private + * @inner + */ function startTracking( tracker ) { var events = [ - "mouseover", "mouseout", "mousedown", "mouseup", + "mouseover", "mouseout", "mousedown", "mouseup", "mousemove", "click", "DOMMouseScroll", "mousewheel", "touchstart", "touchmove", "touchend", "keypress", "focus", "blur" ], - delegate = THIS[ tracker.hash ], + delegate = THIS[tracker.hash], event, i; if ( !delegate.tracking ) { - for( i = 0; i < events.length; i++ ){ - event = events[ i ]; + for ( i = 0; i < events.length; i++ ) { + event = events[i]; $.addEvent( tracker.element, event, - delegate[ event ], + delegate[event], false ); } delegate.tracking = true; - ACTIVE[ tracker.hash ] = tracker; + ACTIVE[tracker.hash] = tracker; } } /** - * Stops tracking mouse events on this element. - * @private - * @inner - */ + * Stops tracking mouse events on this element. + * @private + * @inner + */ function stopTracking( tracker ) { var events = [ - "mouseover", "mouseout", "mousedown", "mouseup", + "mouseover", "mouseout", "mousedown", "mouseup", "mousemove", "click", "DOMMouseScroll", "mousewheel", "touchstart", "touchmove", "touchend", "keypress", "focus", "blur" ], - delegate = THIS[ tracker.hash ], + delegate = THIS[tracker.hash], event, i; if ( delegate.tracking ) { - for( i = 0; i < events.length; i++ ){ - event = events[ i ]; + for ( i = 0; i < events.length; i++ ) { + event = events[i]; $.removeEvent( tracker.element, event, - delegate[ event ], + delegate[event], false ); } releaseMouse( tracker ); delegate.tracking = false; - delete ACTIVE[ tracker.hash ]; + delete ACTIVE[tracker.hash]; } } /** - * @private - * @inner - */ + * @private + * @inner + */ function hasMouse( tracker ) { - return THIS[ tracker.hash ].insideElement; + return THIS[tracker.hash].insideElement; } /** - * Begin capturing mouse events on this element. - * @private - * @inner - */ + * Begin capturing mouse events on this element. + * @private + * @inner + */ function captureMouse( tracker ) { - var delegate = THIS[ tracker.hash ]; + var delegate = THIS[tracker.hash]; if ( !delegate.capturing ) { if ( $.Browser.vendor == $.BROWSERS.IE && $.Browser.version < 9 ) { @@ -445,7 +520,7 @@ $.addEvent( window, "mousemove", - delegate.mousemove, + delegate.mousemovewindow, true ); } @@ -455,12 +530,12 @@ /** - * Stop capturing mouse events on this element. - * @private - * @inner - */ + * Stop capturing mouse events on this element. + * @private + * @inner + */ function releaseMouse( tracker ) { - var delegate = THIS[ tracker.hash ]; + var delegate = THIS[tracker.hash]; if ( delegate.capturing ) { if ( $.Browser.vendor == $.BROWSERS.IE && $.Browser.version < 9 ) { @@ -486,7 +561,7 @@ $.removeEvent( window, "mousemove", - delegate.mousemove, + delegate.mousemovewindow, true ); $.removeEvent( @@ -502,32 +577,36 @@ /** - * @private - * @inner - */ - function triggerOthers( tracker, handler, event ) { + * @private + * @inner + */ + function triggerOthers( tracker, handler, event, isTouch ) { var otherHash; for ( otherHash in ACTIVE ) { if ( ACTIVE.hasOwnProperty( otherHash ) && tracker.hash != otherHash ) { - handler( ACTIVE[ otherHash ], event ); + handler( ACTIVE[otherHash], event, isTouch ); } } } /** - * @private - * @inner - */ - function onFocus( tracker, event ){ + * @private + * @inner + */ + function onFocus( tracker, event ) { //console.log( "focus %s", event ); var propagate; if ( tracker.focusHandler ) { propagate = tracker.focusHandler( tracker, - event + { + isTouchEvent: false, + originalEvent: event, + userData: tracker.userData + } ); - if( propagate === false ){ + if ( propagate === false ) { $.cancelEvent( event ); } } @@ -535,18 +614,22 @@ /** - * @private - * @inner - */ - function onBlur( tracker, event ){ + * @private + * @inner + */ + function onBlur( tracker, event ) { //console.log( "blur %s", event ); var propagate; if ( tracker.blurHandler ) { propagate = tracker.blurHandler( tracker, - event + { + isTouchEvent: false, + originalEvent: event, + userData: tracker.userData + } ); - if( propagate === false ){ + if ( propagate === false ) { $.cancelEvent( event ); } } @@ -554,19 +637,25 @@ /** - * @private - * @inner - */ - function onKeyPress( tracker, event ){ + * @private + * @inner + */ + function onKeyPress( tracker, event ) { //console.log( "keypress %s %s %s %s %s", event.keyCode, event.charCode, event.ctrlKey, event.shiftKey, event.altKey ); var propagate; if ( tracker.keyHandler ) { propagate = tracker.keyHandler( tracker, - event.keyCode ? event.keyCode : event.charCode, - event.shiftKey + { + position: getMouseRelative( event, tracker.element ), + keyCode: event.keyCode ? event.keyCode : event.charCode, + shift: event.shiftKey, + isTouchEvent: false, + originalEvent: event, + userData: tracker.userData + } ); - if( !propagate ){ + if ( !propagate ) { $.cancelEvent( event ); } } @@ -574,14 +663,16 @@ /** - * @private - * @inner - */ - function onMouseOver( tracker, event ) { + * @private + * @inner + */ + function onMouseOver( tracker, event, isTouch ) { - var delegate = THIS[ tracker.hash ], + var delegate = THIS[tracker.hash], propagate; + isTouch = ( isTouch !== undefined ) ? isTouch : false; + event = $.getEvent( event ); if ( $.Browser.vendor == $.BROWSERS.IE && @@ -589,7 +680,7 @@ delegate.capturing && !isChild( event.srcElement, tracker.element ) ) { - triggerOthers( tracker, onMouseOver, event ); + triggerOthers( tracker, onMouseOver, event, isTouch ); } var to = event.target ? @@ -609,11 +700,16 @@ if ( tracker.enterHandler ) { propagate = tracker.enterHandler( tracker, - getMouseRelative( event, tracker.element ), - delegate.buttonDown, - IS_BUTTON_DOWN + { + position: getMouseRelative( event, tracker.element ), + buttonDownElement: delegate.buttonDownElement, + buttonDownAny: IS_BUTTON_DOWN, + isTouchEvent: isTouch, + originalEvent: event, + userData: tracker.userData + } ); - if( propagate === false ){ + if ( propagate === false ) { $.cancelEvent( event ); } } @@ -621,13 +717,15 @@ /** - * @private - * @inner - */ - function onMouseOut( tracker, event ) { - var delegate = THIS[ tracker.hash ], + * @private + * @inner + */ + function onMouseOut( tracker, event, isTouch ) { + var delegate = THIS[tracker.hash], propagate; + isTouch = ( isTouch !== undefined ) ? isTouch : false; + event = $.getEvent( event ); if ( $.Browser.vendor == $.BROWSERS.IE && @@ -635,7 +733,7 @@ delegate.capturing && !isChild( event.srcElement, tracker.element ) ) { - triggerOthers( tracker, onMouseOut, event ); + triggerOthers( tracker, onMouseOut, event, isTouch ); } @@ -656,12 +754,17 @@ if ( tracker.exitHandler ) { propagate = tracker.exitHandler( tracker, - getMouseRelative( event, tracker.element ), - delegate.buttonDown, - IS_BUTTON_DOWN + { + position: getMouseRelative( event, tracker.element ), + buttonDownElement: delegate.buttonDownElement, + buttonDownAny: IS_BUTTON_DOWN, + isTouchEvent: isTouch, + originalEvent: event, + userData: tracker.userData + } ); - if( propagate === false ){ + if ( propagate === false ) { $.cancelEvent( event ); } } @@ -669,20 +772,22 @@ /** - * @private - * @inner - */ - function onMouseDown( tracker, event, noCapture ) { - var delegate = THIS[ tracker.hash ], + * @private + * @inner + */ + function onMouseDown( tracker, event, noCapture, isTouch ) { + var delegate = THIS[tracker.hash], propagate; + isTouch = ( isTouch !== undefined ) ? isTouch : false; + event = $.getEvent( event ); if ( event.button == 2 ) { return; } - delegate.buttonDown = true; + delegate.buttonDownElement = true; delegate.lastPoint = getMouseAbsolute( event ); delegate.lastMouseDownPoint = delegate.lastPoint; @@ -691,9 +796,14 @@ if ( tracker.pressHandler ) { propagate = tracker.pressHandler( tracker, - getMouseRelative( event, tracker.element ) + { + position: getMouseRelative( event, tracker.element ), + isTouchEvent: isTouch, + originalEvent: event, + userData: tracker.userData + } ); - if( propagate === false ){ + if ( propagate === false ) { $.cancelEvent( event ); } } @@ -705,47 +815,47 @@ if ( noCapture ) { return; } - + if ( !( $.Browser.vendor == $.BROWSERS.IE && $.Browser.version < 9 ) || !IS_CAPTURING ) { captureMouse( tracker ); IS_CAPTURING = true; // reset to empty & add us - CAPTURING = [ tracker ]; - } else if ( $.Browser.vendor == $.BROWSERS.IE && $.Browser.version < 9 ) { + CAPTURING = [tracker]; + } else if ( $.Browser.vendor == $.BROWSERS.IE && $.Browser.version < 9 ) { // add us to the list CAPTURING.push( tracker ); } } /** - * @private - * @inner - */ + * @private + * @inner + */ function onTouchStart( tracker, event ) { var touchA, touchB; - if( event.touches.length == 1 && + if ( event.touches.length == 1 && event.targetTouches.length == 1 && - event.changedTouches.length == 1 ){ + event.changedTouches.length == 1 ) { - THIS[ tracker.hash ].lastTouch = event.touches[ 0 ]; - onMouseOver( tracker, event.changedTouches[ 0 ] ); - // call with no capture as the onMouseMove will + THIS[tracker.hash].lastTouch = event.touches[0]; + onMouseOver( tracker, event.changedTouches[0], true ); + // call with no capture as the onMouseMoveWindow will // be triggered by onTouchMove - onMouseDown( tracker, event.touches[ 0 ], true ); + onMouseDown( tracker, event.touches[0], true, true ); } - if( event.touches.length == 2 ){ + if ( event.touches.length == 2 ) { - touchA = getMouseAbsolute( event.touches[ 0 ] ); - touchB = getMouseAbsolute( event.touches[ 1 ] ); - THIS[ tracker.hash ].lastPinchDelta = + touchA = getMouseAbsolute( event.touches[0] ); + touchB = getMouseAbsolute( event.touches[1] ); + THIS[tracker.hash].lastPinchDelta = Math.abs( touchA.x - touchB.x ) + Math.abs( touchA.y - touchB.y ); - THIS[ tracker.hash ].pinchMidpoint = new $.Point( - ( touchA.x + touchB.x ) / 2 , + THIS[tracker.hash].pinchMidpoint = new $.Point( + ( touchA.x + touchB.x ) / 2, ( touchA.y + touchB.y ) / 2 ); //$.console.debug("pinch start : "+THIS[ tracker.hash ].lastPinchDelta); @@ -756,33 +866,40 @@ /** - * @private - * @inner - */ - function onMouseUp( tracker, event ) { - var delegate = THIS[ tracker.hash ], - //were we inside the tracked element when we were pressed - insideElementPress = delegate.buttonDown, - //are we still inside the tracked element when we released + * @private + * @inner + */ + function onMouseUp( tracker, event, isTouch ) { + var delegate = THIS[tracker.hash], + //were we inside the tracked element when we were pressed + insideElementPress = delegate.buttonDownElement, + //are we still inside the tracked element when we released insideElementRelease = delegate.insideElement, propagate; + isTouch = ( isTouch !== undefined ) ? isTouch : false; + event = $.getEvent( event ); if ( event.button == 2 ) { return; } - delegate.buttonDown = false; + delegate.buttonDownElement = false; if ( tracker.releaseHandler ) { propagate = tracker.releaseHandler( tracker, - getMouseRelative( event, tracker.element ), - insideElementPress, - insideElementRelease + { + position: getMouseRelative( event, tracker.element ), + insideElementPress: insideElementPress, + insideElementRelease: insideElementRelease, + isTouchEvent: isTouch, + originalEvent: event, + userData: tracker.userData + } ); - if( propagate === false ){ + if ( propagate === false ) { $.cancelEvent( event ); } } @@ -794,25 +911,25 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onTouchEnd( tracker, event ) { - if( event.touches.length === 0 && + if ( event.touches.length === 0 && event.targetTouches.length === 0 && - event.changedTouches.length == 1 ){ + event.changedTouches.length == 1 ) { + + THIS[tracker.hash].lastTouch = null; - THIS[ tracker.hash ].lastTouch = null; - // call with no release, as the mouse events are // not registered in onTouchStart - onMouseUpWindow( tracker, event.changedTouches[ 0 ], true ); - onMouseOut( tracker, event.changedTouches[ 0 ] ); + onMouseUpWindow( tracker, event.changedTouches[0], true ); + onMouseOut( tracker, event.changedTouches[0], true ); } - if( event.touches.length + event.changedTouches.length == 2 ){ - THIS[ tracker.hash ].lastPinchDelta = null; - THIS[ tracker.hash ].pinchMidpoint = null; + if ( event.touches.length + event.changedTouches.length == 2 ) { + THIS[tracker.hash].lastPinchDelta = null; + THIS[tracker.hash].pinchMidpoint = null; //$.console.debug("pinch end"); } event.preventDefault(); @@ -820,15 +937,15 @@ /** - * Only triggered once by the deepest element that initially received - * the mouse down event. We want to make sure THIS event doesn't bubble. - * Instead, we want to trigger the elements that initially received the - * mouse down event (including this one) only if the mouse is no longer - * inside them. Then, we want to release capture, and emulate a regular - * mouseup on the event that this event was meant for. - * @private - * @inner - */ + * Only triggered once by the deepest element that initially received + * the mouse down event. We want to make sure THIS event doesn't bubble. + * Instead, we want to trigger the elements that initially received the + * mouse down event (including this one) only if the mouse is no longer + * inside them. Then, we want to release capture, and emulate a regular + * mouseup on the event that this event was meant for. + * @private + * @inner + */ function onMouseUpIE( tracker, event ) { var othertracker, i; @@ -840,9 +957,9 @@ } for ( i = 0; i < CAPTURING.length; i++ ) { - othertracker = CAPTURING[ i ]; + othertracker = CAPTURING[i]; if ( !hasMouse( othertracker ) ) { - onMouseUp( othertracker, event ); + onMouseUp( othertracker, event, false ); } } @@ -858,20 +975,20 @@ /** - * Only triggered in W3C browsers by elements within which the mouse was - * initially pressed, since they are now listening to the window for - * mouseup during the capture phase. We shouldn't handle the mouseup - * here if the mouse is still inside this element, since the regular - * mouseup handler will still fire. - * @private - * @inner - */ + * Only triggered in W3C browsers by elements within which the mouse was + * initially pressed, since they are now listening to the window for + * mouseup during the capture phase. We shouldn't handle the mouseup + * here if the mouse is still inside this element, since the regular + * mouseup handler will still fire. + * @private + * @inner + */ function onMouseUpWindow( tracker, event, noRelease ) { - if ( ! THIS[ tracker.hash ].insideElement ) { - onMouseUp( tracker, event ); + if ( !THIS[tracker.hash].insideElement ) { + onMouseUp( tracker, event, false ); } - if (noRelease) { + if ( noRelease ) { return; } @@ -880,9 +997,33 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ + function onMouseMove( tracker, event ) { + if ( tracker.moveHandler ) { + event = $.getEvent( event ); + + var propagate = tracker.moveHandler( + tracker, + { + position: getMouseRelative( event, tracker.element ), + isTouchEvent: false, + originalEvent: event, + userData: tracker.userData + } + ); + if ( propagate === false ) { + $.cancelEvent( event ); + } + } + } + + + /** + * @private + * @inner + */ function onMouseClick( tracker, event ) { if ( tracker.clickHandler ) { $.cancelEvent( event ); @@ -891,13 +1032,15 @@ /** - * @private - * @inner - */ - function onMouseWheelSpin( tracker, event ) { + * @private + * @inner + */ + function onMouseWheelSpin( tracker, event, isTouch ) { var nDelta = 0, propagate; + isTouch = ( isTouch !== undefined ) ? isTouch : false; + if ( !event ) { // For IE, access the global (window) event object event = window.event; } @@ -907,7 +1050,7 @@ if ( window.opera ) { // Opera has the values reversed nDelta = -nDelta; } - } else if (event.detail) { // Mozilla FireFox + } else if ( event.detail ) { // Mozilla FireFox nDelta = -event.detail; } //The nDelta variable is gated to provide smooth z-index scrolling @@ -918,11 +1061,16 @@ if ( tracker.scrollHandler ) { propagate = tracker.scrollHandler( tracker, - getMouseRelative( event, tracker.element ), - nDelta, - event.shiftKey + { + position: getMouseRelative( event, tracker.element ), + scroll: nDelta, + shift: event.shiftKey, + isTouchEvent: isTouch, + originalEvent: event, + userData: tracker.userData + } ); - if( propagate === false ){ + if ( propagate === false ) { $.cancelEvent( event ); } } @@ -930,11 +1078,11 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function handleMouseClick( tracker, event ) { - var delegate = THIS[ tracker.hash ], + var delegate = THIS[tracker.hash], propagate; event = $.getEvent( event ); @@ -943,20 +1091,25 @@ return; } - var time = $.now() - delegate.lastMouseDownTime, - point = getMouseAbsolute( event ), + var time = $.now() - delegate.lastMouseDownTime, + point = getMouseAbsolute( event ), distance = delegate.lastMouseDownPoint.distanceTo( point ), - quick = time <= tracker.clickTimeThreshold && + quick = time <= tracker.clickTimeThreshold && distance <= tracker.clickDistThreshold; if ( tracker.clickHandler ) { propagate = tracker.clickHandler( tracker, - getMouseRelative( event, tracker.element ), - quick, - event.shiftKey + { + position: getMouseRelative( event, tracker.element ), + quick: quick, + shift: event.shiftKey, + isTouchEvent: false, + originalEvent: event, + userData: tracker.userData + } ); - if( propagate === false ){ + if ( propagate === false ) { $.cancelEvent( event ); } } @@ -964,15 +1117,17 @@ /** - * @private - * @inner - */ - function onMouseMove( tracker, event ) { - var delegate = THIS[ tracker.hash ], + * @private + * @inner + */ + function onMouseMoveWindow( tracker, event, isTouch ) { + var delegate = THIS[tracker.hash], delta, propagate, point; + isTouch = ( isTouch !== undefined ) ? isTouch : false; + event = $.getEvent( event ); point = getMouseAbsolute( event ); delta = point.minus( delegate.lastPoint ); @@ -982,11 +1137,16 @@ if ( tracker.dragHandler ) { propagate = tracker.dragHandler( tracker, - getMouseRelative( event, tracker.element ), - delta, - event.shiftKey + { + position: getMouseRelative( event, tracker.element ), + delta: delta, + shift: event.shiftKey, + isTouchEvent: isTouch, + originalEvent: event, + userData: tracker.userData + } ); - if( propagate === false ){ + if ( propagate === false ) { $.cancelEvent( event ); } } @@ -994,74 +1154,75 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onTouchMove( tracker, event ) { var touchA, touchB, pinchDelta; - if ( !THIS[ tracker.hash ].lastTouch ) { - return; + if ( !THIS[tracker.hash].lastTouch ) { + return; } - if( event.touches.length === 1 && + if ( event.touches.length === 1 && event.targetTouches.length === 1 && event.changedTouches.length === 1 && - THIS[ tracker.hash ].lastTouch.identifier === event.touches[ 0 ].identifier){ + THIS[tracker.hash].lastTouch.identifier === event.touches[0].identifier ) { - onMouseMove( tracker, event.touches[ 0 ] ); + onMouseMoveWindow( tracker, event.touches[0], true ); - } else if ( event.touches.length === 2 ){ + } else if ( event.touches.length === 2 ) { - touchA = getMouseAbsolute( event.touches[ 0 ] ); - touchB = getMouseAbsolute( event.touches[ 1 ] ); + touchA = getMouseAbsolute( event.touches[0] ); + touchB = getMouseAbsolute( event.touches[1] ); pinchDelta = Math.abs( touchA.x - touchB.x ) + Math.abs( touchA.y - touchB.y ); //TODO: make the 75px pinch threshold configurable - if( Math.abs( THIS[ tracker.hash ].lastPinchDelta - pinchDelta ) > 75 ){ + if ( Math.abs( THIS[tracker.hash].lastPinchDelta - pinchDelta ) > 75 ) { //$.console.debug( "pinch delta : " + pinchDelta + " | previous : " + THIS[ tracker.hash ].lastPinchDelta); onMouseWheelSpin( tracker, { shift: false, - pageX: THIS[ tracker.hash ].pinchMidpoint.x, - pageY: THIS[ tracker.hash ].pinchMidpoint.y, - detail:( - THIS[ tracker.hash ].lastPinchDelta > pinchDelta + shiftKey: false, + pageX: THIS[tracker.hash].pinchMidpoint.x, + pageY: THIS[tracker.hash].pinchMidpoint.y, + detail: ( + THIS[tracker.hash].lastPinchDelta > pinchDelta ) ? 1 : -1 - }); + }, true ); - THIS[ tracker.hash ].lastPinchDelta = pinchDelta; + THIS[tracker.hash].lastPinchDelta = pinchDelta; } } event.preventDefault(); } /** - * Only triggered once by the deepest element that initially received - * the mouse down event. Since no other element has captured the mouse, - * we want to trigger the elements that initially received the mouse - * down event (including this one). The the param tracker isn't used - * but for consistency with the other event handlers we include it. - * @private - * @inner - */ + * Only triggered once by the deepest element that initially received + * the mouse down event. Since no other element has captured the mouse, + * we want to trigger the elements that initially received the mouse + * down event (including this one). The the param tracker isn't used + * but for consistency with the other event handlers we include it. + * @private + * @inner + */ function onMouseMoveIE( tracker, event ) { var i; for ( i = 0; i < CAPTURING.length; i++ ) { - onMouseMove( CAPTURING[ i ], event ); + onMouseMoveWindow( CAPTURING[i], event, false ); } $.stopEvent( event ); } /** - * @private - * @inner - */ + * @private + * @inner + */ function getMouseAbsolute( event ) { return $.getMousePosition( event ); } @@ -1071,8 +1232,8 @@ * @inner */ function getMouseRelative( event, element ) { - var mouse = $.getMousePosition( event ), - offset = $.getElementPosition( element ); + var mouse = $.getMousePosition( event ), + offset = $.getElementOffset( element ); return mouse.minus( offset ); } @@ -1087,7 +1248,7 @@ while ( elementB && elementA != elementB && body != elementB ) { try { elementB = elementB.parentNode; - } catch (e) { + } catch ( e ) { return false; } } @@ -1119,6 +1280,6 @@ $.addEvent( window, "mousedown", onGlobalMouseDown, true ); $.addEvent( window, "mouseup", onGlobalMouseUp, true ); } - })(); + } )(); -}( OpenSeadragon )); +} ( OpenSeadragon ) ); diff --git a/src/navigator.js b/src/navigator.js index cd64f953..f1999831 100644 --- a/src/navigator.js +++ b/src/navigator.js @@ -251,13 +251,13 @@ $.extend( $.Navigator.prototype, $.EventHandler.prototype, $.Viewer.prototype, { * @inner * @function */ -function onCanvasClick( tracker, position, quick, shift ) { +function onCanvasClick( tracker, eventData ) { var newBounds, viewerPosition, dimensions; if (! this.drag) { if ( this.viewer.viewport ) { - viewerPosition = this.viewport.deltaPointsFromPixels(position); + viewerPosition = this.viewport.deltaPointsFromPixels( eventData.position ); dimensions = this.viewer.viewport.getBounds().getSize(); newBounds = new $.Rect( viewerPosition.x - dimensions.x/2, @@ -285,18 +285,18 @@ function onCanvasClick( tracker, position, quick, shift ) { * @inner * @function */ -function onCanvasDrag( tracker, position, delta, shift ) { +function onCanvasDrag( tracker, eventData ) { if ( this.viewer.viewport ) { this.drag = true; if( !this.panHorizontal ){ - delta.x = 0; + eventData.delta.x = 0; } if( !this.panVertical ){ - delta.y = 0; + eventData.delta.y = 0; } this.viewer.viewport.panBy( this.viewport.deltaPointsFromPixels( - delta + eventData.delta ) ); } @@ -308,8 +308,8 @@ function onCanvasDrag( tracker, position, delta, shift ) { * @inner * @function */ -function onCanvasRelease( tracker, position, insideElementPress, insideElementRelease ) { - if ( insideElementPress && this.viewer.viewport ) { +function onCanvasRelease( tracker, eventData ) {//position, insideElementPress, insideElementRelease + if ( eventData.insideElementPress && this.viewer.viewport ) { this.viewer.viewport.applyConstraints(); } } diff --git a/src/openseadragon.js b/src/openseadragon.js index e5913772..6da43be9 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -699,6 +699,48 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ }, + /** + * Determines the position of the upper-left corner of the element adjusted for current page and/or element scroll. + * @function + * @name OpenSeadragon.getElementOffset + * @param {Element|String} element - the element we want the position for. + * @returns {Point} - the position of the upper left corner of the element adjusted for current page and/or element scroll. + * Inspired by jQuery.fn.offset() (jquery 1.10.1) + */ + getElementOffset: function( element ) { + var doc = element && element.ownerDocument, + docElement, + win, + boundingRect = { top: 0, left: 0 }; + + if ( !doc ) { + return new $.Point(); + } + + docElement = doc.documentElement; + + // Make sure it's not a disconnected DOM node + //if ( !jQuery.contains( docElement, element ) ) { + // return new $.Point(); + //} + + if ( typeof element.getBoundingClientRect !== typeof undefined ) { + boundingRect = element.getBoundingClientRect(); + } + + win = ( doc == doc.window ) ? + doc : + ( doc.nodeType === 9 ) ? + doc.defaultView || doc.parentWindow : + false; + + return new $.Point( + boundingRect.left + ( win.pageXOffset || docElement.scrollLeft ) - ( docElement.clientLeft || 0 ), + boundingRect.top + ( win.pageYOffset || docElement.scrollTop ) - ( docElement.clientTop || 0 ) + ); + }, + + /** * Determines the height and width of the given element. * @function diff --git a/src/referencestrip.js b/src/referencestrip.js index cfa053da..f822e98a 100644 --- a/src/referencestrip.js +++ b/src/referencestrip.js @@ -32,511 +32,511 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -(function( $ ){ +(function ( $ ) { -// dictionary from id to private properties -var THIS = {}; + // dictionary from id to private properties + var THIS = {}; -/** - * The CollectionDrawer is a reimplementation if the Drawer API that - * focuses on allowing a viewport to be redefined as a collection - * of smaller viewports, defined by a clear number of rows and / or - * columns of which each item in the matrix of viewports has its own - * source. - * - * This idea is a reexpression of the idea of dzi collections - * which allows a clearer algorithm to reuse the tile sources already - * supported by OpenSeadragon, in heterogenious or homogenious - * sequences just like mixed groups already supported by the viewer - * for the purpose of image sequnces. - * - * TODO: The difficult part of this feature is figuring out how to express - * this functionality as a combination of the functionality already - * provided by Drawer, Viewport, TileSource, and Navigator. It may - * require better abstraction at those points in order to effeciently - * reuse those paradigms. - */ -$.ReferenceStrip = function( options ){ + /** + * The CollectionDrawer is a reimplementation if the Drawer API that + * focuses on allowing a viewport to be redefined as a collection + * of smaller viewports, defined by a clear number of rows and / or + * columns of which each item in the matrix of viewports has its own + * source. + * + * This idea is a reexpression of the idea of dzi collections + * which allows a clearer algorithm to reuse the tile sources already + * supported by OpenSeadragon, in heterogenious or homogenious + * sequences just like mixed groups already supported by the viewer + * for the purpose of image sequnces. + * + * TODO: The difficult part of this feature is figuring out how to express + * this functionality as a combination of the functionality already + * provided by Drawer, Viewport, TileSource, and Navigator. It may + * require better abstraction at those points in order to effeciently + * reuse those paradigms. + */ + $.ReferenceStrip = function ( options ) { - var _this = this, - viewer = options.viewer, - viewerSize = $.getElementSize( viewer.element ), + var _this = this, + viewer = options.viewer, + viewerSize = $.getElementSize( viewer.element ), element, style, i; - //We may need to create a new element and id if they did not - //provide the id for the existing element - if( !options.id ){ - options.id = 'referencestrip-' + $.now(); - this.element = $.makeNeutralElement( "div" ); - this.element.id = options.id; - this.element.className = 'referencestrip'; - } - - options = $.extend( true, { - sizeRatio: $.DEFAULT_SETTINGS.referenceStripSizeRatio, - position: $.DEFAULT_SETTINGS.referenceStripPosition, - scroll: $.DEFAULT_SETTINGS.referenceStripScroll, - clickTimeThreshold: $.DEFAULT_SETTINGS.clickTimeThreshold - }, options, { - //required overrides - element: this.element, - //These need to be overridden to prevent recursion since - //the navigator is a viewer and a viewer has a navigator - showNavigator: false, - mouseNavEnabled: false, - showNavigationControl: false, - showSequenceControl: false - }); - - $.extend( this, options ); - //Private state properties - THIS[ this.id ] = { - "animating": false - }; - - this.minPixelRatio = this.viewer.minPixelRatio; - - style = this.element.style; - style.marginTop = '0px'; - style.marginRight = '0px'; - style.marginBottom = '0px'; - style.marginLeft = '0px'; - style.left = '0px'; - style.bottom = '0px'; - style.border = '0px'; - style.background = '#000'; - style.position = 'relative'; - - $.setElementOpacity( this.element, 0.8 ); - - this.viewer = viewer; - this.innerTracker = new $.MouseTracker({ - element: this.element, - dragHandler: $.delegate( this, onStripDrag ), - scrollHandler: $.delegate( this, onStripScroll ), - enterHandler: $.delegate( this, onStripEnter ), - exitHandler: $.delegate( this, onStripExit ), - keyHandler: $.delegate( this, onKeyPress ) - }).setTracking( true ); - - //Controls the position and orientation of the reference strip and sets the - //appropriate width and height - if( options.width && options.height ){ - this.element.style.width = options.width + 'px'; - this.element.style.height = options.height + 'px'; - viewer.addControl( - this.element, - {anchor: $.ControlAnchor.BOTTOM_LEFT} - ); - } else { - if( "horizontal" == options.scroll ){ - this.element.style.width = ( - viewerSize.x * - options.sizeRatio * - viewer.tileSources.length - ) + ( 12 * viewer.tileSources.length ) + 'px'; - - this.element.style.height = ( - viewerSize.y * - options.sizeRatio - ) + 'px'; - - viewer.addControl( - this.element, - {anchor: $.ControlAnchor.BOTTOM_LEFT} - ); - }else { - this.element.style.height = ( - viewerSize.y * - options.sizeRatio * - viewer.tileSources.length - ) + ( 12 * viewer.tileSources.length ) + 'px'; - - this.element.style.width = ( - viewerSize.x * - options.sizeRatio - ) + 'px'; - - viewer.addControl( - this.element, - {anchor: $.ControlAnchor.TOP_LEFT} - ); - + //We may need to create a new element and id if they did not + //provide the id for the existing element + if ( !options.id ) { + options.id = 'referencestrip-' + $.now(); + this.element = $.makeNeutralElement( "div" ); + this.element.id = options.id; + this.element.className = 'referencestrip'; } - } - this.panelWidth = ( viewerSize.x * this.sizeRatio ) + 8; - this.panelHeight = ( viewerSize.y * this.sizeRatio ) + 8; - this.panels = []; + options = $.extend( true, { + sizeRatio: $.DEFAULT_SETTINGS.referenceStripSizeRatio, + position: $.DEFAULT_SETTINGS.referenceStripPosition, + scroll: $.DEFAULT_SETTINGS.referenceStripScroll, + clickTimeThreshold: $.DEFAULT_SETTINGS.clickTimeThreshold + }, options, { + //required overrides + element: this.element, + //These need to be overridden to prevent recursion since + //the navigator is a viewer and a viewer has a navigator + showNavigator: false, + mouseNavEnabled: false, + showNavigationControl: false, + showSequenceControl: false + } ); - /*jshint loopfunc:true*/ - for( i = 0; i < viewer.tileSources.length; i++ ){ + $.extend( this, options ); + //Private state properties + THIS[this.id] = { + "animating": false + }; - element = $.makeNeutralElement('div'); - element.id = this.element.id + "-" + i; + this.minPixelRatio = this.viewer.minPixelRatio; - element.style.width = _this.panelWidth + 'px'; - element.style.height = _this.panelHeight + 'px'; - element.style.display = 'inline'; - element.style.float = 'left'; //Webkit - element.style.cssFloat = 'left'; //Firefox - element.style.styleFloat = 'left'; //IE - element.style.padding = '2px'; + style = this.element.style; + style.marginTop = '0px'; + style.marginRight = '0px'; + style.marginBottom = '0px'; + style.marginLeft = '0px'; + style.left = '0px'; + style.bottom = '0px'; + style.border = '0px'; + style.background = '#000'; + style.position = 'relative'; - element.innerTracker = new $.MouseTracker({ - element: element, - clickTimeThreshold: this.clickTimeThreshold, - clickDistThreshold: this.clickDistThreshold, - pressHandler: function( tracker ){ - tracker.dragging = $.now(); - }, - releaseHandler: function( tracker, position, insideElementPress, insideElementRelease ){ - var id = tracker.element.id, - page = Number( id.split( '-' )[ 2 ] ), + $.setElementOpacity( this.element, 0.8 ); + + this.viewer = viewer; + this.innerTracker = new $.MouseTracker( { + element: this.element, + dragHandler: $.delegate( this, onStripDrag ), + scrollHandler: $.delegate( this, onStripScroll ), + enterHandler: $.delegate( this, onStripEnter ), + exitHandler: $.delegate( this, onStripExit ), + keyHandler: $.delegate( this, onKeyPress ) + } ).setTracking( true ); + + //Controls the position and orientation of the reference strip and sets the + //appropriate width and height + if ( options.width && options.height ) { + this.element.style.width = options.width + 'px'; + this.element.style.height = options.height + 'px'; + viewer.addControl( + this.element, + { anchor: $.ControlAnchor.BOTTOM_LEFT } + ); + } else { + if ( "horizontal" == options.scroll ) { + this.element.style.width = ( + viewerSize.x * + options.sizeRatio * + viewer.tileSources.length + ) + ( 12 * viewer.tileSources.length ) + 'px'; + + this.element.style.height = ( + viewerSize.y * + options.sizeRatio + ) + 'px'; + + viewer.addControl( + this.element, + { anchor: $.ControlAnchor.BOTTOM_LEFT } + ); + } else { + this.element.style.height = ( + viewerSize.y * + options.sizeRatio * + viewer.tileSources.length + ) + ( 12 * viewer.tileSources.length ) + 'px'; + + this.element.style.width = ( + viewerSize.x * + options.sizeRatio + ) + 'px'; + + viewer.addControl( + this.element, + { anchor: $.ControlAnchor.TOP_LEFT } + ); + + } + } + + this.panelWidth = ( viewerSize.x * this.sizeRatio ) + 8; + this.panelHeight = ( viewerSize.y * this.sizeRatio ) + 8; + this.panels = []; + + /*jshint loopfunc:true*/ + for ( i = 0; i < viewer.tileSources.length; i++ ) { + + element = $.makeNeutralElement( 'div' ); + element.id = this.element.id + "-" + i; + + element.style.width = _this.panelWidth + 'px'; + element.style.height = _this.panelHeight + 'px'; + element.style.display = 'inline'; + element.style.float = 'left'; //Webkit + element.style.cssFloat = 'left'; //Firefox + element.style.styleFloat = 'left'; //IE + element.style.padding = '2px'; + + element.innerTracker = new $.MouseTracker( { + element: element, + clickTimeThreshold: this.clickTimeThreshold, + clickDistThreshold: this.clickDistThreshold, + pressHandler: function ( tracker, eventData ) { + tracker.dragging = $.now(); + }, + releaseHandler: function ( tracker, eventData ) { + var id = tracker.element.id, + page = Number( id.split( '-' )[2] ), now = $.now(); - if ( insideElementPress && - insideElementRelease && + if ( eventData.insideElementPress && + eventData.insideElementRelease && tracker.dragging && - ( now - tracker.dragging ) < tracker.clickTimeThreshold ){ - tracker.dragging = null; - viewer.goToPage( page ); + ( now - tracker.dragging ) < tracker.clickTimeThreshold ) { + tracker.dragging = null; + viewer.goToPage( page ); + } } - } - }).setTracking( true ); + } ).setTracking( true ); - this.element.appendChild( element ); + this.element.appendChild( element ); - element.activePanel = false; + element.activePanel = false; - this.panels.push( element ); + this.panels.push( element ); - } - loadPanels( this, this.scroll == 'vertical' ? viewerSize.y : viewerSize.y, 0); - this.setFocus( 0 ); + } + loadPanels( this, this.scroll == 'vertical' ? viewerSize.y : viewerSize.y, 0 ); + this.setFocus( 0 ); -}; + }; -$.extend( $.ReferenceStrip.prototype, $.EventHandler.prototype, $.Viewer.prototype, { + $.extend( $.ReferenceStrip.prototype, $.EventHandler.prototype, $.Viewer.prototype, { - setFocus: function( page ){ - var element = $.getElement( this.element.id + '-' + page ), + setFocus: function ( page ) { + var element = $.getElement( this.element.id + '-' + page ), viewerSize = $.getElementSize( this.viewer.canvas ), - scrollWidth = Number(this.element.style.width.replace('px','')), - scrollHeight = Number(this.element.style.height.replace('px','')), - offsetLeft = -Number(this.element.style.marginLeft.replace('px','')), - offsetTop = -Number(this.element.style.marginTop.replace('px','')), + scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), + scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), + offsetLeft = -Number( this.element.style.marginLeft.replace( 'px', '' ) ), + offsetTop = -Number( this.element.style.marginTop.replace( 'px', '' ) ), offset; - if ( this.currentSelected !== element ){ - if( this.currentSelected ){ - this.currentSelected.style.background = '#000'; - } - this.currentSelected = element; - this.currentSelected.style.background = '#999'; - - if( 'horizontal' == this.scroll ){ - //right left - offset = (Number(page)) * ( this.panelWidth + 3 ); - if( offset > offsetLeft + viewerSize.x - this.panelWidth){ - offset = Math.min(offset, (scrollWidth - viewerSize.x)); - this.element.style.marginLeft = -offset + 'px'; - loadPanels( this, viewerSize.x, -offset ); - }else if( offset < offsetLeft ){ - offset = Math.max(0, offset - viewerSize.x / 2); - this.element.style.marginLeft = -offset + 'px'; - loadPanels( this, viewerSize.x, -offset ); + if ( this.currentSelected !== element ) { + if ( this.currentSelected ) { + this.currentSelected.style.background = '#000'; } - }else{ - offset = (Number(page) ) * ( this.panelHeight + 3 ); - if( offset > offsetTop + viewerSize.y - this.panelHeight){ - offset = Math.min(offset, (scrollHeight - viewerSize.y)); - this.element.style.marginTop = -offset + 'px'; - loadPanels( this, viewerSize.y, -offset ); - }else if( offset < offsetTop ){ - offset = Math.max(0, offset - viewerSize.y / 2); - this.element.style.marginTop = -offset + 'px'; - loadPanels( this, viewerSize.y, -offset ); - } - } + this.currentSelected = element; + this.currentSelected.style.background = '#999'; - this.currentPage = page; - $.getElement( element.id + '-displayregion' ).focus(); - onStripEnter.call( this, this.innerTracker ); + if ( 'horizontal' == this.scroll ) { + //right left + offset = ( Number( page ) ) * ( this.panelWidth + 3 ); + if ( offset > offsetLeft + viewerSize.x - this.panelWidth ) { + offset = Math.min( offset, ( scrollWidth - viewerSize.x ) ); + this.element.style.marginLeft = -offset + 'px'; + loadPanels( this, viewerSize.x, -offset ); + } else if ( offset < offsetLeft ) { + offset = Math.max( 0, offset - viewerSize.x / 2 ); + this.element.style.marginLeft = -offset + 'px'; + loadPanels( this, viewerSize.x, -offset ); + } + } else { + offset = ( Number( page ) ) * ( this.panelHeight + 3 ); + if ( offset > offsetTop + viewerSize.y - this.panelHeight ) { + offset = Math.min( offset, ( scrollHeight - viewerSize.y ) ); + this.element.style.marginTop = -offset + 'px'; + loadPanels( this, viewerSize.y, -offset ); + } else if ( offset < offsetTop ) { + offset = Math.max( 0, offset - viewerSize.y / 2 ); + this.element.style.marginTop = -offset + 'px'; + loadPanels( this, viewerSize.y, -offset ); + } + } + + this.currentPage = page; + $.getElement( element.id + '-displayregion' ).focus(); + onStripEnter.call( this, this.innerTracker, {} ); + } + }, + /** + * @function + * @name OpenSeadragon.ReferenceStrip.prototype.update + */ + update: function () { + if ( THIS[this.id].animating ) { + $.console.log( 'image reference strip update' ); + return true; + } + return false; } - }, + + } ); + + + + /** - * @function - * @name OpenSeadragon.ReferenceStrip.prototype.update - */ - update: function() { - if ( THIS[ this.id ].animating ) { - $.console.log('image reference strip update'); - return true; + * @private + * @inner + * @function + */ + function onStripDrag( tracker, eventData ) { + + var offsetLeft = Number( this.element.style.marginLeft.replace( 'px', '' ) ), + offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ), + scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), + scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), + viewerSize = $.getElementSize( this.viewer.canvas ); + this.dragging = true; + if ( this.element ) { + if ( 'horizontal' == this.scroll ) { + if ( -eventData.delta.x > 0 ) { + //forward + if ( offsetLeft > -( scrollWidth - viewerSize.x ) ) { + this.element.style.marginLeft = ( offsetLeft + ( eventData.delta.x * 2 ) ) + 'px'; + loadPanels( this, viewerSize.x, offsetLeft + ( eventData.delta.x * 2 ) ); + } + } else if ( -eventData.delta.x < 0 ) { + //reverse + if ( offsetLeft < 0 ) { + this.element.style.marginLeft = ( offsetLeft + ( eventData.delta.x * 2 ) ) + 'px'; + loadPanels( this, viewerSize.x, offsetLeft + ( eventData.delta.x * 2 ) ); + } + } + } else { + if ( -eventData.delta.y > 0 ) { + //forward + if ( offsetTop > -( scrollHeight - viewerSize.y ) ) { + this.element.style.marginTop = ( offsetTop + ( eventData.delta.y * 2 ) ) + 'px'; + loadPanels( this, viewerSize.y, offsetTop + ( eventData.delta.y * 2 ) ); + } + } else if ( -eventData.delta.y < 0 ) { + //reverse + if ( offsetTop < 0 ) { + this.element.style.marginTop = ( offsetTop + ( eventData.delta.y * 2 ) ) + 'px'; + loadPanels( this, viewerSize.y, offsetTop + ( eventData.delta.y * 2 ) ); + } + } + } } return false; + + } + + + + /** + * @private + * @inner + * @function + */ + function onStripScroll( tracker, eventData ) { + var offsetLeft = Number( this.element.style.marginLeft.replace( 'px', '' ) ), + offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ), + scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), + scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), + viewerSize = $.getElementSize( this.viewer.canvas ); + if ( this.element ) { + if ( 'horizontal' == this.scroll ) { + if ( eventData.scroll > 0 ) { + //forward + if ( offsetLeft > -( scrollWidth - viewerSize.x ) ) { + this.element.style.marginLeft = ( offsetLeft - ( eventData.scroll * 60 ) ) + 'px'; + loadPanels( this, viewerSize.x, offsetLeft - ( eventData.scroll * 60 ) ); + } + } else if ( eventData.scroll < 0 ) { + //reverse + if ( offsetLeft < 0 ) { + this.element.style.marginLeft = ( offsetLeft - ( eventData.scroll * 60 ) ) + 'px'; + loadPanels( this, viewerSize.x, offsetLeft - ( eventData.scroll * 60 ) ); + } + } + } else { + if ( eventData.scroll < 0 ) { + //scroll up + if ( offsetTop > viewerSize.y - scrollHeight ) { + this.element.style.marginTop = ( offsetTop + ( eventData.scroll * 60 ) ) + 'px'; + loadPanels( this, viewerSize.y, offsetTop + ( eventData.scroll * 60 ) ); + } + } else if ( eventData.scroll > 0 ) { + //scroll dowm + if ( offsetTop < 0 ) { + this.element.style.marginTop = ( offsetTop + ( eventData.scroll * 60 ) ) + 'px'; + loadPanels( this, viewerSize.y, offsetTop + ( eventData.scroll * 60 ) ); + } + } + } + } + //cancels event + return false; } -}); - - - -/** - * @private - * @inner - * @function - */ -function onStripDrag( tracker, position, delta, shift ) { - - var offsetLeft = Number(this.element.style.marginLeft.replace('px','')), - offsetTop = Number(this.element.style.marginTop.replace('px','')), - scrollWidth = Number(this.element.style.width.replace('px','')), - scrollHeight = Number(this.element.style.height.replace('px','')), - viewerSize = $.getElementSize( this.viewer.canvas ); - this.dragging = true; - if ( this.element ) { - if( 'horizontal' == this.scroll ){ - if ( -delta.x > 0 ) { - //forward - if( offsetLeft > -(scrollWidth - viewerSize.x)){ - this.element.style.marginLeft = ( offsetLeft + (delta.x * 2) ) + 'px'; - loadPanels( this, viewerSize.x, offsetLeft + (delta.x * 2) ); - } - } else if ( -delta.x < 0 ) { - //reverse - if( offsetLeft < 0 ){ - this.element.style.marginLeft = ( offsetLeft + (delta.x * 2) ) + 'px'; - loadPanels( this, viewerSize.x, offsetLeft + (delta.x * 2) ); - } - } - }else{ - if ( -delta.y > 0 ) { - //forward - if( offsetTop > -(scrollHeight - viewerSize.y)){ - this.element.style.marginTop = ( offsetTop + (delta.y * 2) ) + 'px'; - loadPanels( this, viewerSize.y, offsetTop + (delta.y * 2) ); - } - } else if ( -delta.y < 0 ) { - //reverse - if( offsetTop < 0 ){ - this.element.style.marginTop = ( offsetTop + (delta.y * 2) ) + 'px'; - loadPanels( this, viewerSize.y, offsetTop + (delta.y * 2) ); - } - } - } - } - return false; - -} - - - -/** - * @private - * @inner - * @function - */ -function onStripScroll( tracker, position, scroll, shift ) { - var offsetLeft = Number(this.element.style.marginLeft.replace('px','')), - offsetTop = Number(this.element.style.marginTop.replace('px','')), - scrollWidth = Number(this.element.style.width.replace('px','')), - scrollHeight = Number(this.element.style.height.replace('px','')), - viewerSize = $.getElementSize( this.viewer.canvas ); - if ( this.element ) { - if( 'horizontal' == this.scroll ){ - if ( scroll > 0 ) { - //forward - if( offsetLeft > -(scrollWidth - viewerSize.x)){ - this.element.style.marginLeft = ( offsetLeft - (scroll * 60) ) + 'px'; - loadPanels( this, viewerSize.x, offsetLeft - (scroll * 60) ); - } - } else if ( scroll < 0 ) { - //reverse - if( offsetLeft < 0 ){ - this.element.style.marginLeft = ( offsetLeft - (scroll * 60) ) + 'px'; - loadPanels( this, viewerSize.x, offsetLeft - (scroll * 60) ); - } - } - }else{ - if ( scroll < 0 ) { - //scroll up - if( offsetTop > viewerSize.y - scrollHeight ){ - this.element.style.marginTop = ( offsetTop + (scroll * 60) ) + 'px'; - loadPanels( this, viewerSize.y, offsetTop + (scroll * 60) ); - } - } else if ( scroll > 0 ) { - //scroll dowm - if( offsetTop < 0 ){ - this.element.style.marginTop = ( offsetTop + (scroll * 60) ) + 'px'; - loadPanels( this, viewerSize.y, offsetTop + (scroll * 60) ); - } - } - } - } - //cancels event - return false; -} - - -function loadPanels(strip, viewerSize, scroll){ - var panelSize, + function loadPanels( strip, viewerSize, scroll ) { + var panelSize, activePanelsStart, activePanelsEnd, miniViewer, style, i, element; - if( 'horizontal' == strip.scroll ){ - panelSize = strip.panelWidth; - }else{ - panelSize = strip.panelHeight; - } - activePanelsStart = Math.ceil( viewerSize / panelSize ) + 5; - activePanelsEnd = Math.ceil( (Math.abs(scroll) + viewerSize ) / panelSize ) + 1; - activePanelsStart = activePanelsEnd - activePanelsStart; - activePanelsStart = activePanelsStart < 0 ? 0 : activePanelsStart; + if ( 'horizontal' == strip.scroll ) { + panelSize = strip.panelWidth; + } else { + panelSize = strip.panelHeight; + } + activePanelsStart = Math.ceil( viewerSize / panelSize ) + 5; + activePanelsEnd = Math.ceil( ( Math.abs( scroll ) + viewerSize ) / panelSize ) + 1; + activePanelsStart = activePanelsEnd - activePanelsStart; + activePanelsStart = activePanelsStart < 0 ? 0 : activePanelsStart; - for( i = activePanelsStart; i < activePanelsEnd && i < strip.panels.length; i++ ){ - element = strip.panels[ i ]; - if ( !element.activePanel ){ - miniViewer = new $.Viewer( { - id: element.id, - tileSources: [ strip.viewer.tileSources[ i ] ], - element: element, - navigatorSizeRatio: strip.sizeRatio, - showNavigator: false, - mouseNavEnabled: false, - showNavigationControl: false, - showSequenceControl: false, - immediateRender: true, - blendTime: 0, - animationTime: 0 - } ); + for ( i = activePanelsStart; i < activePanelsEnd && i < strip.panels.length; i++ ) { + element = strip.panels[i]; + if ( !element.activePanel ) { + miniViewer = new $.Viewer( { + id: element.id, + tileSources: [strip.viewer.tileSources[i]], + element: element, + navigatorSizeRatio: strip.sizeRatio, + showNavigator: false, + mouseNavEnabled: false, + showNavigationControl: false, + showSequenceControl: false, + immediateRender: true, + blendTime: 0, + animationTime: 0 + } ); - miniViewer.displayRegion = $.makeNeutralElement( "textarea" ); - miniViewer.displayRegion.id = element.id + '-displayregion'; - miniViewer.displayRegion.className = 'displayregion'; + miniViewer.displayRegion = $.makeNeutralElement( "textarea" ); + miniViewer.displayRegion.id = element.id + '-displayregion'; + miniViewer.displayRegion.className = 'displayregion'; - style = miniViewer.displayRegion.style; - style.position = 'relative'; - style.top = '0px'; - style.left = '0px'; - style.fontSize = '0px'; - style.overflow = 'hidden'; - style.float = 'left'; //Webkit - style.cssFloat = 'left'; //Firefox - style.styleFloat = 'left'; //IE - style.zIndex = 999999999; - style.cursor = 'default'; - style.width = ( strip.panelWidth - 4 ) + 'px'; - style.height = ( strip.panelHeight - 4 ) + 'px'; + style = miniViewer.displayRegion.style; + style.position = 'relative'; + style.top = '0px'; + style.left = '0px'; + style.fontSize = '0px'; + style.overflow = 'hidden'; + style.float = 'left'; //Webkit + style.cssFloat = 'left'; //Firefox + style.styleFloat = 'left'; //IE + style.zIndex = 999999999; + style.cursor = 'default'; + style.width = ( strip.panelWidth - 4 ) + 'px'; + style.height = ( strip.panelHeight - 4 ) + 'px'; - miniViewer.displayRegion.innerTracker = new $.MouseTracker({ - element: miniViewer.displayRegion - }); + miniViewer.displayRegion.innerTracker = new $.MouseTracker( { + element: miniViewer.displayRegion + } ); - element.getElementsByTagName('form')[ 0 ].appendChild( + element.getElementsByTagName( 'form' )[0].appendChild( miniViewer.displayRegion ); - element.activePanel = true; + element.activePanel = true; + } } } -} -/** - * @private - * @inner - * @function - */ -function onStripEnter( tracker ) { + /** + * @private + * @inner + * @function + */ + function onStripEnter( tracker, eventData ) { - //$.setElementOpacity(tracker.element, 0.8); + //$.setElementOpacity(tracker.element, 0.8); - //tracker.element.style.border = '1px solid #555'; - //tracker.element.style.background = '#000'; + //tracker.element.style.border = '1px solid #555'; + //tracker.element.style.background = '#000'; - if( 'horizontal' == this.scroll ){ + if ( 'horizontal' == this.scroll ) { - //tracker.element.style.paddingTop = "0px"; - tracker.element.style.marginBottom = "0px"; + //tracker.element.style.paddingTop = "0px"; + tracker.element.style.marginBottom = "0px"; - } else { + } else { - //tracker.element.style.paddingRight = "0px"; - tracker.element.style.marginLeft = "0px"; + //tracker.element.style.paddingRight = "0px"; + tracker.element.style.marginLeft = "0px"; + } + return false; } - return false; -} -/** - * @private - * @inner - * @function - */ -function onStripExit( tracker ) { - if ( 'horizontal' == this.scroll ) { + /** + * @private + * @inner + * @function + */ + function onStripExit( tracker, eventData ) { + if ( 'horizontal' == this.scroll ) { - //tracker.element.style.paddingTop = "10px"; - tracker.element.style.marginBottom = "-" + ( $.getElementSize( tracker.element ).y / 2 ) + "px"; + //tracker.element.style.paddingTop = "10px"; + tracker.element.style.marginBottom = "-" + ( $.getElementSize( tracker.element ).y / 2 ) + "px"; - } else { + } else { - //tracker.element.style.paddingRight = "10px"; - tracker.element.style.marginLeft = "-" + ( $.getElementSize( tracker.element ).x / 2 )+ "px"; + //tracker.element.style.paddingRight = "10px"; + tracker.element.style.marginLeft = "-" + ( $.getElementSize( tracker.element ).x / 2 ) + "px"; + } + return false; } - return false; -} -/** - * @private - * @inner - * @function - */ -function onKeyPress( tracker, keyCode, shiftKey ){ - //console.log( keyCode ); + /** + * @private + * @inner + * @function + */ + function onKeyPress( tracker, eventData ) { + //console.log( eventData.keyCode ); - switch( keyCode ){ - case 61://=|+ - onStripScroll.call(this, this.tracker, null, 1, null); - return false; - case 45://-|_ - onStripScroll.call(this, this.tracker, null, -1, null); - return false; - case 48://0|) - case 119://w - case 87://W - case 38://up arrow - onStripScroll.call(this, this.tracker, null, 1, null); - return false; - case 115://s - case 83://S - case 40://down arrow - onStripScroll.call(this, this.tracker, null, -1, null); - return false; - case 97://a - case 37://left arrow - onStripScroll.call(this, this.tracker, null, -1, null); - return false; - case 100://d - case 39://right arrow - onStripScroll.call(this, this.tracker, null, 1, null); - return false; - default: - //console.log( 'navigator keycode %s', keyCode ); - return true; + switch ( eventData.keyCode ) { + case 61: //=|+ + onStripScroll.call( this, this.tracker, { position: null, scroll: 1, shift: null } ); + return false; + case 45: //-|_ + onStripScroll.call( this, this.tracker, { position: null, scroll: -1, shift: null } ); + return false; + case 48: //0|) + case 119: //w + case 87: //W + case 38: //up arrow + onStripScroll.call( this, this.tracker, { position: null, scroll: 1, shift: null } ); + return false; + case 115: //s + case 83: //S + case 40: //down arrow + onStripScroll.call( this, this.tracker, { position: null, scroll: -1, shift: null } ); + return false; + case 97: //a + case 37: //left arrow + onStripScroll.call( this, this.tracker, { position: null, scroll: -1, shift: null } ); + return false; + case 100: //d + case 39: //right arrow + onStripScroll.call( this, this.tracker, { position: null, scroll: 1, shift: null } ); + return false; + default: + //console.log( 'navigator keycode %s', eventData.keyCode ); + return true; + } } -} -}( OpenSeadragon )); +} ( OpenSeadragon ) ); diff --git a/src/viewer.js b/src/viewer.js index f1880afc..7c374daa 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -265,8 +265,8 @@ $.Viewer = function( options ) { window.scrollTo( 0, point.y ); }, - keyHandler: function(tracker, keyCode, shiftKey){ - switch( keyCode ){ + keyHandler: function( tracker, eventData ){ + switch( eventData.keyCode ){ case 61://=|+ _this.viewport.zoomBy(1.1); _this.viewport.applyConstraints(); @@ -282,7 +282,7 @@ $.Viewer = function( options ) { case 119://w case 87://W case 38://up arrow - if (shiftKey) { + if ( eventData.shift ) { _this.viewport.zoomBy(1.1); } else { _this.viewport.panBy(new $.Point(0, -0.05)); @@ -292,7 +292,7 @@ $.Viewer = function( options ) { case 115://s case 83://S case 40://down arrow - if (shiftKey) { + if ( eventData.shift ) { _this.viewport.zoomBy(0.9); } else { _this.viewport.panBy(new $.Point(0, 0.05)); @@ -310,7 +310,7 @@ $.Viewer = function( options ) { _this.viewport.applyConstraints(); return false; default: - //console.log( 'navigator keycode %s', keyCode ); + //console.log( 'navigator keycode %s', eventData.keyCode ); return true; } } @@ -1426,37 +1426,37 @@ function onBlur(){ } -function onCanvasClick( tracker, position, quick, shift ) { +function onCanvasClick( tracker, eventData ) { var zoomPerClick, factor; - if ( this.viewport && quick ) { // ignore clicks where mouse moved + if ( this.viewport && eventData.quick ) { // ignore clicks where mouse moved zoomPerClick = this.zoomPerClick; - factor = shift ? 1.0 / zoomPerClick : zoomPerClick; + factor = eventData.shift ? 1.0 / zoomPerClick : zoomPerClick; this.viewport.zoomBy( factor, - this.viewport.pointFromPixel( position, true ) + this.viewport.pointFromPixel( eventData.position, true ) ); this.viewport.applyConstraints(); } this.raiseEvent( 'canvas-click', { tracker: tracker, - position: position, - quick: quick, - shift: shift + position: eventData.position, + quick: eventData.quick, + shift: eventData.shift }); } -function onCanvasDrag( tracker, position, delta, shift ) { +function onCanvasDrag( tracker, eventData ) { if ( this.viewport ) { if( !this.panHorizontal ){ - delta.x = 0; + eventData.delta.x = 0; } if( !this.panVertical ){ - delta.y = 0; + eventData.delta.y = 0; } this.viewport.panBy( this.viewport.deltaPointsFromPixels( - delta.negate() + eventData.delta.negate() ) ); if( this.constrainDuringPan ){ @@ -1465,46 +1465,46 @@ function onCanvasDrag( tracker, position, delta, shift ) { } this.raiseEvent( 'canvas-drag', { tracker: tracker, - position: position, - delta: delta, - shift: shift + position: eventData.position, + delta: eventData.delta, + shift: eventData.shift }); } -function onCanvasRelease( tracker, position, insideElementPress, insideElementRelease ) { - if ( insideElementPress && this.viewport ) { +function onCanvasRelease( tracker, eventData ) { + if ( eventData.insideElementPress && this.viewport ) { this.viewport.applyConstraints(); } this.raiseEvent( 'canvas-release', { tracker: tracker, - position: position, - insideElementPress: insideElementPress, - insideElementRelease: insideElementRelease + position: eventData.position, + insideElementPress: eventData.insideElementPress, + insideElementRelease: eventData.insideElementRelease }); } -function onCanvasScroll( tracker, position, scroll, shift ) { +function onCanvasScroll( tracker, eventData ) { var factor; if ( this.viewport ) { - factor = Math.pow( this.zoomPerScroll, scroll ); + factor = Math.pow( this.zoomPerScroll, eventData.scroll ); this.viewport.zoomBy( factor, - this.viewport.pointFromPixel( position, true ) + this.viewport.pointFromPixel( eventData.position, true ) ); this.viewport.applyConstraints(); } this.raiseEvent( 'canvas-scroll', { tracker: tracker, - position: position, - scroll: scroll, - shift: shift + position: eventData.position, + scroll: eventData.scroll, + shift: eventData.shift }); //cancels event return false; } -function onContainerExit( tracker, position, buttonDownElement, buttonDownAny ) { - if ( !buttonDownElement ) { +function onContainerExit( tracker, eventData ) { + if ( !eventData.buttonDownElement ) { THIS[ this.hash ].mouseInside = false; if ( !THIS[ this.hash ].animating ) { beginControlsAutoHide( this ); @@ -1512,14 +1512,14 @@ function onContainerExit( tracker, position, buttonDownElement, buttonDownAny ) } this.raiseEvent( 'container-exit', { tracker: tracker, - position: position, - buttonDownElement: buttonDownElement, - buttonDownAny: buttonDownAny + position: eventData.position, + buttonDownElement: eventData.buttonDownElement, + buttonDownAny: eventData.buttonDownAny }); } -function onContainerRelease( tracker, position, insideElementPress, insideElementRelease ) { - if ( !insideElementRelease ) { +function onContainerRelease( tracker, eventData ) { + if ( !eventData.insideElementRelease ) { THIS[ this.hash ].mouseInside = false; if ( !THIS[ this.hash ].animating ) { beginControlsAutoHide( this ); @@ -1527,20 +1527,20 @@ function onContainerRelease( tracker, position, insideElementPress, insideElemen } this.raiseEvent( 'container-release', { tracker: tracker, - position: position, - insideElementPress: insideElementPress, - insideElementRelease: insideElementRelease + position: eventData.position, + insideElementPress: eventData.insideElementPress, + insideElementRelease: eventData.insideElementRelease }); } -function onContainerEnter( tracker, position, buttonDownElement, buttonDownAny ) { +function onContainerEnter( tracker, eventData ) { THIS[ this.hash ].mouseInside = true; abortControlsAutoHide( this ); this.raiseEvent( 'container-enter', { tracker: tracker, - position: position, - buttonDownElement: buttonDownElement, - buttonDownAny: buttonDownAny + position: eventData.position, + buttonDownElement: eventData.buttonDownElement, + buttonDownAny: eventData.buttonDownAny }); } From 56f5b9fb74c1c7c0b570851d54b83e1a5ae3d693 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 6 Sep 2013 10:43:39 -0700 Subject: [PATCH 02/15] MouseTracker Original Events in handlers Comment & Formatting fixes --- src/button.js | 10 +- src/mousetracker.js | 782 +++++++++++++++++------------------ src/openseadragon.js | 6 - src/referencestrip.js | 918 +++++++++++++++++++++--------------------- 4 files changed, 854 insertions(+), 862 deletions(-) diff --git a/src/button.js b/src/button.js index 4524234e..c1f711bd 100644 --- a/src/button.js +++ b/src/button.js @@ -184,9 +184,8 @@ $.Button = function( options ) { } }, - // TODO: This didn't match handler signature in MouseTracker. Investigate! - focusHandler: function ( tracker, eventData ) { //position, buttonDownElement, buttonDownAny - //this.enterHandler( tracker, eventData ); //position, buttonDownElement, buttonDownAny + focusHandler: function ( tracker, eventData ) { + this.enterHandler( tracker, eventData ); _this.raiseEvent( "onFocus", _this ); }, @@ -197,9 +196,8 @@ $.Button = function( options ) { } }, - // TODO: This didn't match handler signature in MouseTracker. Investigate! - blurHandler: function ( tracker, eventData ) { //position, buttonDownElement, buttonDownAny - //this.exitHandler( tracker, eventData ); //position, buttonDownElement, buttonDownAny + blurHandler: function ( tracker, eventData ) { + this.exitHandler( tracker, eventData ); _this.raiseEvent( "onBlur", _this ); }, diff --git a/src/mousetracker.js b/src/mousetracker.js index 36492d6a..c765b3d1 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -34,78 +34,78 @@ (function ( $ ) { - // is any button currently being pressed while mouse events occur + // is any button currently being pressed while mouse events occur var IS_BUTTON_DOWN = false, - // is any tracker currently capturing? - IS_CAPTURING = false, - // dictionary from hash to MouseTracker - ACTIVE = {}, - // list of trackers interested in capture - CAPTURING = [], - // dictionary from hash to private properties - THIS = {}; + // is any tracker currently capturing? + IS_CAPTURING = false, + // dictionary from hash to MouseTracker + ACTIVE = {}, + // list of trackers interested in capture + CAPTURING = [], + // dictionary from hash to private properties + THIS = {}; /** - * The MouseTracker allows other classes to set handlers for common mouse - * events on a specific element like, 'enter', 'exit', 'press', 'release', - * 'scroll', 'click', and 'drag'. - * @class - * @param {Object} options - * Allows configurable properties to be entirely specified by passing - * an options object to the constructor. The constructor also supports - * the original positional arguments 'elements', 'clickTimeThreshold', - * and 'clickDistThreshold' in that order. - * @param {Element|String} options.element - * A reference to an element or an element id for which the mouse - * events will be monitored. - * @param {Number} options.clickTimeThreshold - * The number of milliseconds within which mutliple mouse clicks - * will be treated as a single event. - * @param {Number} options.clickDistThreshold - * The distance between mouse click within multiple mouse clicks - * will be treated as a single event. - * @param {Function} options.enterHandler - * An optional handler for mouse enter. - * @param {Function} options.exitHandler - * An optional handler for mouse exit. - * @param {Function} options.pressHandler - * An optional handler for mouse press. - * @param {Function} options.releaseHandler - * An optional handler for mouse release. - * @param {Function} options.moveHandler - * An optional handler for mouse move. - * @param {Function} options.scrollHandler - * An optional handler for mouse scroll. - * @param {Function} options.clickHandler - * An optional handler for mouse click. - * @param {Function} options.dragHandler - * An optional handler for mouse drag. - * @param {Function} options.keyHandler - * An optional handler for keypress. - * @param {Function} options.focusHandler - * An optional handler for focus. - * @param {Function} options.blurHandler - * An optional handler for blur. - * @property {Number} hash - * An unique hash for this tracker. - * @property {Element} element - * The element for which mouse event are being monitored. - * @property {Number} clickTimeThreshold - * The number of milliseconds within which mutliple mouse clicks - * will be treated as a single event. - * @property {Number} clickDistThreshold - * The distance between mouse click within multiple mouse clicks - * will be treated as a single event. - * @property {Object} optional userData - * Arbitrary object to be passed unchanged to any attached handler methods. - */ + * The MouseTracker allows other classes to set handlers for common mouse + * events on a specific element like, 'enter', 'exit', 'press', 'release', + * 'scroll', 'click', and 'drag'. + * @class + * @param {Object} options + * Allows configurable properties to be entirely specified by passing + * an options object to the constructor. The constructor also supports + * the original positional arguments 'elements', 'clickTimeThreshold', + * and 'clickDistThreshold' in that order. + * @param {Element|String} options.element + * A reference to an element or an element id for which the mouse + * events will be monitored. + * @param {Number} options.clickTimeThreshold + * The number of milliseconds within which mutliple mouse clicks + * will be treated as a single event. + * @param {Number} options.clickDistThreshold + * The distance between mouse click within multiple mouse clicks + * will be treated as a single event. + * @param {Function} options.enterHandler + * An optional handler for mouse enter. + * @param {Function} options.exitHandler + * An optional handler for mouse exit. + * @param {Function} options.pressHandler + * An optional handler for mouse press. + * @param {Function} options.releaseHandler + * An optional handler for mouse release. + * @param {Function} options.moveHandler + * An optional handler for mouse move. + * @param {Function} options.scrollHandler + * An optional handler for mouse scroll. + * @param {Function} options.clickHandler + * An optional handler for mouse click. + * @param {Function} options.dragHandler + * An optional handler for mouse drag. + * @param {Function} options.keyHandler + * An optional handler for keypress. + * @param {Function} options.focusHandler + * An optional handler for focus. + * @param {Function} options.blurHandler + * An optional handler for blur. + * @property {Number} hash + * An unique hash for this tracker. + * @property {Element} element + * The element for which mouse event are being monitored. + * @property {Number} clickTimeThreshold + * The number of milliseconds within which mutliple mouse clicks + * will be treated as a single event. + * @property {Number} clickDistThreshold + * The distance between mouse click within multiple mouse clicks + * will be treated as a single event. + * @property {Object} optional userData + * Arbitrary object to be passed unchanged to any attached handler methods. + */ $.MouseTracker = function ( options ) { var args = arguments; if ( !$.isPlainObject( options ) ) { options = { - element: args[0], + element: args[0], clickTimeThreshold: args[1], clickDistThreshold: args[2] }; @@ -115,68 +115,68 @@ this.element = $.getElement( options.element ); this.clickTimeThreshold = options.clickTimeThreshold; this.clickDistThreshold = options.clickDistThreshold; - this.userData = options.userData || null; + this.userData = options.userData || null; - this.enterHandler = options.enterHandler || null; - this.exitHandler = options.exitHandler || null; - this.pressHandler = options.pressHandler || null; + this.enterHandler = options.enterHandler || null; + this.exitHandler = options.exitHandler || null; + this.pressHandler = options.pressHandler || null; this.releaseHandler = options.releaseHandler || null; - this.moveHandler = options.moveHandler || null; - this.scrollHandler = options.scrollHandler || null; - this.clickHandler = options.clickHandler || null; - this.dragHandler = options.dragHandler || null; - this.keyHandler = options.keyHandler || null; - this.focusHandler = options.focusHandler || null; - this.blurHandler = options.blurHandler || null; + this.moveHandler = options.moveHandler || null; + this.scrollHandler = options.scrollHandler || null; + this.clickHandler = options.clickHandler || null; + this.dragHandler = options.dragHandler || null; + this.keyHandler = options.keyHandler || null; + this.focusHandler = options.focusHandler || null; + this.blurHandler = options.blurHandler || null; //Store private properties in a scope sealed hash map var _this = this; /** - * @private - * @property {Boolean} tracking - * Are we currently tracking mouse events. - * @property {Boolean} capturing - * Are we curruently capturing mouse events. - * @property {Boolean} buttonDownElement - * True if the left mouse button is currently being pressed and was - * initiated inside the tracked element, otherwise false. - * @property {Boolean} insideElement - * Are we currently inside the screen area of the tracked element. - * @property {OpenSeadragon.Point} lastPoint - * Position of last mouse down/move - * @property {Number} lastMouseDownTime - * Time of last mouse down. - * @property {OpenSeadragon.Point} lastMouseDownPoint - * Position of last mouse down - */ + * @private + * @property {Boolean} tracking + * Are we currently tracking mouse events. + * @property {Boolean} capturing + * Are we curruently capturing mouse events. + * @property {Boolean} buttonDownElement + * True if the left mouse button is currently being pressed and was + * initiated inside the tracked element, otherwise false. + * @property {Boolean} insideElement + * Are we currently inside the screen area of the tracked element. + * @property {OpenSeadragon.Point} lastPoint + * Position of last mouse down/move + * @property {Number} lastMouseDownTime + * Time of last mouse down. + * @property {OpenSeadragon.Point} lastMouseDownPoint + * Position of last mouse down + */ THIS[this.hash] = { - mouseover: function ( event ) { onMouseOver( _this, event, false ); }, - mouseout: function ( event ) { onMouseOut( _this, event, false ); }, - mousedown: function ( event ) { onMouseDown( _this, event ); }, - mouseup: function ( event ) { onMouseUp( _this, event, false ); }, - mousemove: function ( event ) { onMouseMove( _this, event ); }, - click: function ( event ) { onMouseClick( _this, event ); }, - DOMMouseScroll: function ( event ) { onMouseWheelSpin( _this, event, false ); }, - mousewheel: function ( event ) { onMouseWheelSpin( _this, event, false ); }, - mouseupie: function ( event ) { onMouseUpIE( _this, event ); }, - mousemoveie: function ( event ) { onMouseMoveIE( _this, event ); }, - mouseupwindow: function ( event ) { onMouseUpWindow( _this, event ); }, - mousemovewindow: function ( event ) { onMouseMoveWindow( _this, event, false ); }, - touchstart: function ( event ) { onTouchStart( _this, event ); }, - touchmove: function ( event ) { onTouchMove( _this, event ); }, - touchend: function ( event ) { onTouchEnd( _this, event ); }, - keypress: function ( event ) { onKeyPress( _this, event ); }, - focus: function ( event ) { onFocus( _this, event ); }, - blur: function ( event ) { onBlur( _this, event ); }, - tracking: false, - capturing: false, - buttonDownElement: false, - insideElement: false, - lastPoint: null, - lastMouseDownTime: null, + mouseover: function ( event ) { onMouseOver( _this, event, false ); }, + mouseout: function ( event ) { onMouseOut( _this, event, false ); }, + mousedown: function ( event ) { onMouseDown( _this, event ); }, + mouseup: function ( event ) { onMouseUp( _this, event, false ); }, + mousemove: function ( event ) { onMouseMove( _this, event ); }, + click: function ( event ) { onMouseClick( _this, event ); }, + DOMMouseScroll: function ( event ) { onMouseWheelSpin( _this, event, false ); }, + mousewheel: function ( event ) { onMouseWheelSpin( _this, event, false ); }, + mouseupie: function ( event ) { onMouseUpIE( _this, event ); }, + mousemoveie: function ( event ) { onMouseMoveIE( _this, event ); }, + mouseupwindow: function ( event ) { onMouseUpWindow( _this, event ); }, + mousemovewindow: function ( event ) { onMouseMoveWindow( _this, event, false ); }, + touchstart: function ( event ) { onTouchStart( _this, event ); }, + touchmove: function ( event ) { onTouchMove( _this, event ); }, + touchend: function ( event ) { onTouchEnd( _this, event ); }, + keypress: function ( event ) { onKeyPress( _this, event ); }, + focus: function ( event ) { onFocus( _this, event ); }, + blur: function ( event ) { onBlur( _this, event ); }, + tracking: false, + capturing: false, + buttonDownElement: false, + insideElement: false, + lastPoint: null, + lastMouseDownTime: null, lastMouseDownPoint: null, - lastPinchDelta: 0 + lastPinchDelta: 0 }; }; @@ -184,30 +184,30 @@ $.MouseTracker.prototype = { /** - * Clean up any events or objects created by the mouse tracker. - * @function - */ + * Clean up any events or objects created by the mouse tracker. + * @function + */ destroy: function () { stopTracking( this ); this.element = null; }, /** - * Are we currently tracking events on this element. - * @deprecated Just use this.tracking - * @function - * @returns {Boolean} Are we currently tracking events on this element. - */ + * Are we currently tracking events on this element. + * @deprecated Just use this.tracking + * @function + * @returns {Boolean} Are we currently tracking events on this element. + */ isTracking: function () { return THIS[this.hash].tracking; }, /** - * Enable or disable whether or not we are tracking events on this element. - * @function - * @param {Boolean} track True to start tracking, false to stop tracking. - * @returns {OpenSeadragon.MouseTracker} Chainable. - */ + * Enable or disable whether or not we are tracking events on this element. + * @function + * @param {Boolean} track True to start tracking, false to stop tracking. + * @returns {OpenSeadragon.MouseTracker} Chainable. + */ setTracking: function ( track ) { if ( track ) { startTracking( this ); @@ -219,198 +219,198 @@ }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * buttonDownElement: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. - * buttonDownAny: Was the button down anywhere in the screen during the event. - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } - */ + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * buttonDownElement: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. + * buttonDownAny: Was the button down anywhere in the screen during the event. + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ enterHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * buttonDownElement: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. - * buttonDownAny: Was the button down anywhere in the screen during the event. - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } - */ + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * buttonDownElement: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. + * buttonDownAny: Was the button down anywhere in the screen during the event. + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ exitHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } - */ + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ pressHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * insideElementPress: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. - * insideElementRelease: Was the mouse still inside the tracked element when the button was released. - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } - */ + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * insideElementPress: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. + * insideElementRelease: Was the mouse still inside the tracked element when the button was released. + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ releaseHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } - */ + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ moveHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * scroll: The scroll delta for the event. - * shift: Was the shift key being pressed during this event? - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } - */ + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * scroll: The scroll delta for the event. + * shift: Was the shift key being pressed during this event? + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ scrollHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * quick: True only if the clickDistThreshold and clickDeltaThreshold are both pased. Useful for ignoring events. - * shift: Was the shift key being pressed during this event? - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } - */ + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * quick: True only if the clickDistThreshold and clickDeltaThreshold are both pased. Useful for ignoring events. + * shift: Was the shift key being pressed during this event? + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ clickHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * delta: The x,y components of the difference between start drag and end drag. Usefule for ignoring or weighting the events. - * shift: Was the shift key being pressed during this event? - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } - */ + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * position: The position of the event relative to the tracked element. + * delta: The x,y components of the difference between start drag and end drag. Usefule for ignoring or weighting the events. + * shift: Was the shift key being pressed during this event? + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ dragHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {Object} eventData - * { - * keyCode: The key code that was pressed. - * shift: Was the shift key being pressed during this event? - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } - */ + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * keyCode: The key code that was pressed. + * shift: Was the shift key being pressed during this event? + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ keyHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {Object} eventData - * { - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } - */ + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ focusHandler: function () { }, /** - * Implement or assign implmentation to these handlers during or after - * calling the constructor. - * @function - * @param {OpenSeadragon.MouseTracker} tracker - * A reference to the tracker instance. - * @param {Object} eventData - * { - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } - */ + * Implement or assign implmentation to these handlers during or after + * calling the constructor. + * @function + * @param {OpenSeadragon.MouseTracker} tracker + * A reference to the tracker instance. + * @param {Object} eventData + * { + * isTouchEvent: True if the original event is a touch event, otherwise false. + * originalEvent: The original event object. + * userData: Arbitrary user-defined object. + * } + */ blurHandler: function () { } }; /** - * Starts tracking mouse events on this element. - * @private - * @inner - */ + * Starts tracking mouse events on this element. + * @private + * @inner + */ function startTracking( tracker ) { var events = [ "mouseover", "mouseout", "mousedown", "mouseup", "mousemove", @@ -440,10 +440,10 @@ } /** - * Stops tracking mouse events on this element. - * @private - * @inner - */ + * Stops tracking mouse events on this element. + * @private + * @inner + */ function stopTracking( tracker ) { var events = [ "mouseover", "mouseout", "mousedown", "mouseup", "mousemove", @@ -475,18 +475,18 @@ } /** - * @private - * @inner - */ + * @private + * @inner + */ function hasMouse( tracker ) { return THIS[tracker.hash].insideElement; } /** - * Begin capturing mouse events on this element. - * @private - * @inner - */ + * Begin capturing mouse events on this element. + * @private + * @inner + */ function captureMouse( tracker ) { var delegate = THIS[tracker.hash]; if ( !delegate.capturing ) { @@ -530,10 +530,10 @@ /** - * Stop capturing mouse events on this element. - * @private - * @inner - */ + * Stop capturing mouse events on this element. + * @private + * @inner + */ function releaseMouse( tracker ) { var delegate = THIS[tracker.hash]; if ( delegate.capturing ) { @@ -577,9 +577,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function triggerOthers( tracker, handler, event, isTouch ) { var otherHash; for ( otherHash in ACTIVE ) { @@ -591,9 +591,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onFocus( tracker, event ) { //console.log( "focus %s", event ); var propagate; @@ -614,9 +614,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onBlur( tracker, event ) { //console.log( "blur %s", event ); var propagate; @@ -637,9 +637,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onKeyPress( tracker, event ) { //console.log( "keypress %s %s %s %s %s", event.keyCode, event.charCode, event.ctrlKey, event.shiftKey, event.altKey ); var propagate; @@ -663,9 +663,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onMouseOver( tracker, event, isTouch ) { var delegate = THIS[tracker.hash], @@ -717,9 +717,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onMouseOut( tracker, event, isTouch ) { var delegate = THIS[tracker.hash], propagate; @@ -772,9 +772,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onMouseDown( tracker, event, noCapture, isTouch ) { var delegate = THIS[tracker.hash], propagate; @@ -829,9 +829,9 @@ } /** - * @private - * @inner - */ + * @private + * @inner + */ function onTouchStart( tracker, event ) { var touchA, touchB; @@ -866,9 +866,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onMouseUp( tracker, event, isTouch ) { var delegate = THIS[tracker.hash], //were we inside the tracked element when we were pressed @@ -911,9 +911,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onTouchEnd( tracker, event ) { if ( event.touches.length === 0 && @@ -937,15 +937,15 @@ /** - * Only triggered once by the deepest element that initially received - * the mouse down event. We want to make sure THIS event doesn't bubble. - * Instead, we want to trigger the elements that initially received the - * mouse down event (including this one) only if the mouse is no longer - * inside them. Then, we want to release capture, and emulate a regular - * mouseup on the event that this event was meant for. - * @private - * @inner - */ + * Only triggered once by the deepest element that initially received + * the mouse down event. We want to make sure THIS event doesn't bubble. + * Instead, we want to trigger the elements that initially received the + * mouse down event (including this one) only if the mouse is no longer + * inside them. Then, we want to release capture, and emulate a regular + * mouseup on the event that this event was meant for. + * @private + * @inner + */ function onMouseUpIE( tracker, event ) { var othertracker, i; @@ -975,14 +975,14 @@ /** - * Only triggered in W3C browsers by elements within which the mouse was - * initially pressed, since they are now listening to the window for - * mouseup during the capture phase. We shouldn't handle the mouseup - * here if the mouse is still inside this element, since the regular - * mouseup handler will still fire. - * @private - * @inner - */ + * Only triggered in W3C browsers by elements within which the mouse was + * initially pressed, since they are now listening to the window for + * mouseup during the capture phase. We shouldn't handle the mouseup + * here if the mouse is still inside this element, since the regular + * mouseup handler will still fire. + * @private + * @inner + */ function onMouseUpWindow( tracker, event, noRelease ) { if ( !THIS[tracker.hash].insideElement ) { onMouseUp( tracker, event, false ); @@ -997,9 +997,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onMouseMove( tracker, event ) { if ( tracker.moveHandler ) { event = $.getEvent( event ); @@ -1021,9 +1021,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onMouseClick( tracker, event ) { if ( tracker.clickHandler ) { $.cancelEvent( event ); @@ -1032,9 +1032,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onMouseWheelSpin( tracker, event, isTouch ) { var nDelta = 0, propagate; @@ -1078,9 +1078,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function handleMouseClick( tracker, event ) { var delegate = THIS[tracker.hash], propagate; @@ -1117,9 +1117,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onMouseMoveWindow( tracker, event, isTouch ) { var delegate = THIS[tracker.hash], delta, @@ -1154,9 +1154,9 @@ /** - * @private - * @inner - */ + * @private + * @inner + */ function onTouchMove( tracker, event ) { var touchA, touchB, @@ -1202,14 +1202,14 @@ } /** - * Only triggered once by the deepest element that initially received - * the mouse down event. Since no other element has captured the mouse, - * we want to trigger the elements that initially received the mouse - * down event (including this one). The the param tracker isn't used - * but for consistency with the other event handlers we include it. - * @private - * @inner - */ + * Only triggered once by the deepest element that initially received + * the mouse down event. Since no other element has captured the mouse, + * we want to trigger the elements that initially received the mouse + * down event (including this one). The the param tracker isn't used + * but for consistency with the other event handlers we include it. + * @private + * @inner + */ function onMouseMoveIE( tracker, event ) { var i; for ( i = 0; i < CAPTURING.length; i++ ) { @@ -1220,17 +1220,17 @@ } /** - * @private - * @inner - */ + * @private + * @inner + */ function getMouseAbsolute( event ) { return $.getMousePosition( event ); } /** - * @private - * @inner - */ + * @private + * @inner + */ function getMouseRelative( event, element ) { var mouse = $.getMousePosition( event ), offset = $.getElementOffset( element ); @@ -1239,10 +1239,10 @@ } /** - * @private - * @inner - * Returns true if elementB is a child node of elementA, or if they're equal. - */ + * @private + * @inner + * Returns true if elementB is a child node of elementA, or if they're equal. + */ function isChild( elementA, elementB ) { var body = document.body; while ( elementB && elementA != elementB && body != elementB ) { @@ -1256,17 +1256,17 @@ } /** - * @private - * @inner - */ + * @private + * @inner + */ function onGlobalMouseDown() { IS_BUTTON_DOWN = true; } /** - * @private - * @inner - */ + * @private + * @inner + */ function onGlobalMouseUp() { IS_BUTTON_DOWN = false; } diff --git a/src/openseadragon.js b/src/openseadragon.js index 6da43be9..b28cc507 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -705,7 +705,6 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ * @name OpenSeadragon.getElementOffset * @param {Element|String} element - the element we want the position for. * @returns {Point} - the position of the upper left corner of the element adjusted for current page and/or element scroll. - * Inspired by jQuery.fn.offset() (jquery 1.10.1) */ getElementOffset: function( element ) { var doc = element && element.ownerDocument, @@ -719,11 +718,6 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ docElement = doc.documentElement; - // Make sure it's not a disconnected DOM node - //if ( !jQuery.contains( docElement, element ) ) { - // return new $.Point(); - //} - if ( typeof element.getBoundingClientRect !== typeof undefined ) { boundingRect = element.getBoundingClientRect(); } diff --git a/src/referencestrip.js b/src/referencestrip.js index f822e98a..d6a2e7b0 100644 --- a/src/referencestrip.js +++ b/src/referencestrip.js @@ -34,508 +34,508 @@ (function ( $ ) { - // dictionary from id to private properties - var THIS = {}; +// dictionary from id to private properties +var THIS = {}; - /** - * The CollectionDrawer is a reimplementation if the Drawer API that - * focuses on allowing a viewport to be redefined as a collection - * of smaller viewports, defined by a clear number of rows and / or - * columns of which each item in the matrix of viewports has its own - * source. - * - * This idea is a reexpression of the idea of dzi collections - * which allows a clearer algorithm to reuse the tile sources already - * supported by OpenSeadragon, in heterogenious or homogenious - * sequences just like mixed groups already supported by the viewer - * for the purpose of image sequnces. - * - * TODO: The difficult part of this feature is figuring out how to express - * this functionality as a combination of the functionality already - * provided by Drawer, Viewport, TileSource, and Navigator. It may - * require better abstraction at those points in order to effeciently - * reuse those paradigms. - */ - $.ReferenceStrip = function ( options ) { +/** + * The CollectionDrawer is a reimplementation if the Drawer API that + * focuses on allowing a viewport to be redefined as a collection + * of smaller viewports, defined by a clear number of rows and / or + * columns of which each item in the matrix of viewports has its own + * source. + * + * This idea is a reexpression of the idea of dzi collections + * which allows a clearer algorithm to reuse the tile sources already + * supported by OpenSeadragon, in heterogenious or homogenious + * sequences just like mixed groups already supported by the viewer + * for the purpose of image sequnces. + * + * TODO: The difficult part of this feature is figuring out how to express + * this functionality as a combination of the functionality already + * provided by Drawer, Viewport, TileSource, and Navigator. It may + * require better abstraction at those points in order to effeciently + * reuse those paradigms. + */ +$.ReferenceStrip = function ( options ) { - var _this = this, - viewer = options.viewer, - viewerSize = $.getElementSize( viewer.element ), - element, - style, - i; + var _this = this, + viewer = options.viewer, + viewerSize = $.getElementSize( viewer.element ), + element, + style, + i; - //We may need to create a new element and id if they did not - //provide the id for the existing element - if ( !options.id ) { - options.id = 'referencestrip-' + $.now(); - this.element = $.makeNeutralElement( "div" ); - this.element.id = options.id; - this.element.className = 'referencestrip'; - } + //We may need to create a new element and id if they did not + //provide the id for the existing element + if ( !options.id ) { + options.id = 'referencestrip-' + $.now(); + this.element = $.makeNeutralElement( "div" ); + this.element.id = options.id; + this.element.className = 'referencestrip'; + } - options = $.extend( true, { - sizeRatio: $.DEFAULT_SETTINGS.referenceStripSizeRatio, - position: $.DEFAULT_SETTINGS.referenceStripPosition, - scroll: $.DEFAULT_SETTINGS.referenceStripScroll, - clickTimeThreshold: $.DEFAULT_SETTINGS.clickTimeThreshold - }, options, { - //required overrides - element: this.element, - //These need to be overridden to prevent recursion since - //the navigator is a viewer and a viewer has a navigator - showNavigator: false, - mouseNavEnabled: false, - showNavigationControl: false, - showSequenceControl: false - } ); + options = $.extend( true, { + sizeRatio: $.DEFAULT_SETTINGS.referenceStripSizeRatio, + position: $.DEFAULT_SETTINGS.referenceStripPosition, + scroll: $.DEFAULT_SETTINGS.referenceStripScroll, + clickTimeThreshold: $.DEFAULT_SETTINGS.clickTimeThreshold + }, options, { + //required overrides + element: this.element, + //These need to be overridden to prevent recursion since + //the navigator is a viewer and a viewer has a navigator + showNavigator: false, + mouseNavEnabled: false, + showNavigationControl: false, + showSequenceControl: false + } ); - $.extend( this, options ); - //Private state properties - THIS[this.id] = { - "animating": false - }; + $.extend( this, options ); + //Private state properties + THIS[this.id] = { + "animating": false + }; - this.minPixelRatio = this.viewer.minPixelRatio; + this.minPixelRatio = this.viewer.minPixelRatio; - style = this.element.style; - style.marginTop = '0px'; - style.marginRight = '0px'; - style.marginBottom = '0px'; - style.marginLeft = '0px'; - style.left = '0px'; - style.bottom = '0px'; - style.border = '0px'; - style.background = '#000'; - style.position = 'relative'; + style = this.element.style; + style.marginTop = '0px'; + style.marginRight = '0px'; + style.marginBottom = '0px'; + style.marginLeft = '0px'; + style.left = '0px'; + style.bottom = '0px'; + style.border = '0px'; + style.background = '#000'; + style.position = 'relative'; - $.setElementOpacity( this.element, 0.8 ); + $.setElementOpacity( this.element, 0.8 ); - this.viewer = viewer; - this.innerTracker = new $.MouseTracker( { - element: this.element, - dragHandler: $.delegate( this, onStripDrag ), - scrollHandler: $.delegate( this, onStripScroll ), - enterHandler: $.delegate( this, onStripEnter ), - exitHandler: $.delegate( this, onStripExit ), - keyHandler: $.delegate( this, onKeyPress ) - } ).setTracking( true ); + this.viewer = viewer; + this.innerTracker = new $.MouseTracker( { + element: this.element, + dragHandler: $.delegate( this, onStripDrag ), + scrollHandler: $.delegate( this, onStripScroll ), + enterHandler: $.delegate( this, onStripEnter ), + exitHandler: $.delegate( this, onStripExit ), + keyHandler: $.delegate( this, onKeyPress ) + } ).setTracking( true ); + + //Controls the position and orientation of the reference strip and sets the + //appropriate width and height + if ( options.width && options.height ) { + this.element.style.width = options.width + 'px'; + this.element.style.height = options.height + 'px'; + viewer.addControl( + this.element, + { anchor: $.ControlAnchor.BOTTOM_LEFT } + ); + } else { + if ( "horizontal" == options.scroll ) { + this.element.style.width = ( + viewerSize.x * + options.sizeRatio * + viewer.tileSources.length + ) + ( 12 * viewer.tileSources.length ) + 'px'; + + this.element.style.height = ( + viewerSize.y * + options.sizeRatio + ) + 'px'; - //Controls the position and orientation of the reference strip and sets the - //appropriate width and height - if ( options.width && options.height ) { - this.element.style.width = options.width + 'px'; - this.element.style.height = options.height + 'px'; viewer.addControl( this.element, { anchor: $.ControlAnchor.BOTTOM_LEFT } ); } else { - if ( "horizontal" == options.scroll ) { - this.element.style.width = ( - viewerSize.x * - options.sizeRatio * - viewer.tileSources.length - ) + ( 12 * viewer.tileSources.length ) + 'px'; + this.element.style.height = ( + viewerSize.y * + options.sizeRatio * + viewer.tileSources.length + ) + ( 12 * viewer.tileSources.length ) + 'px'; - this.element.style.height = ( - viewerSize.y * - options.sizeRatio - ) + 'px'; + this.element.style.width = ( + viewerSize.x * + options.sizeRatio + ) + 'px'; - viewer.addControl( - this.element, - { anchor: $.ControlAnchor.BOTTOM_LEFT } - ); + viewer.addControl( + this.element, + { anchor: $.ControlAnchor.TOP_LEFT } + ); + + } + } + + this.panelWidth = ( viewerSize.x * this.sizeRatio ) + 8; + this.panelHeight = ( viewerSize.y * this.sizeRatio ) + 8; + this.panels = []; + + /*jshint loopfunc:true*/ + for ( i = 0; i < viewer.tileSources.length; i++ ) { + + element = $.makeNeutralElement( 'div' ); + element.id = this.element.id + "-" + i; + + element.style.width = _this.panelWidth + 'px'; + element.style.height = _this.panelHeight + 'px'; + element.style.display = 'inline'; + element.style.float = 'left'; //Webkit + element.style.cssFloat = 'left'; //Firefox + element.style.styleFloat = 'left'; //IE + element.style.padding = '2px'; + + element.innerTracker = new $.MouseTracker( { + element: element, + clickTimeThreshold: this.clickTimeThreshold, + clickDistThreshold: this.clickDistThreshold, + pressHandler: function ( tracker, eventData ) { + tracker.dragging = $.now(); + }, + releaseHandler: function ( tracker, eventData ) { + var id = tracker.element.id, + page = Number( id.split( '-' )[2] ), + now = $.now(); + + if ( eventData.insideElementPress && + eventData.insideElementRelease && + tracker.dragging && + ( now - tracker.dragging ) < tracker.clickTimeThreshold ) { + tracker.dragging = null; + viewer.goToPage( page ); + } + } + } ).setTracking( true ); + + this.element.appendChild( element ); + + element.activePanel = false; + + this.panels.push( element ); + + } + loadPanels( this, this.scroll == 'vertical' ? viewerSize.y : viewerSize.y, 0 ); + this.setFocus( 0 ); + +}; + +$.extend( $.ReferenceStrip.prototype, $.EventHandler.prototype, $.Viewer.prototype, { + + setFocus: function ( page ) { + var element = $.getElement( this.element.id + '-' + page ), + viewerSize = $.getElementSize( this.viewer.canvas ), + scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), + scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), + offsetLeft = -Number( this.element.style.marginLeft.replace( 'px', '' ) ), + offsetTop = -Number( this.element.style.marginTop.replace( 'px', '' ) ), + offset; + + if ( this.currentSelected !== element ) { + if ( this.currentSelected ) { + this.currentSelected.style.background = '#000'; + } + this.currentSelected = element; + this.currentSelected.style.background = '#999'; + + if ( 'horizontal' == this.scroll ) { + //right left + offset = ( Number( page ) ) * ( this.panelWidth + 3 ); + if ( offset > offsetLeft + viewerSize.x - this.panelWidth ) { + offset = Math.min( offset, ( scrollWidth - viewerSize.x ) ); + this.element.style.marginLeft = -offset + 'px'; + loadPanels( this, viewerSize.x, -offset ); + } else if ( offset < offsetLeft ) { + offset = Math.max( 0, offset - viewerSize.x / 2 ); + this.element.style.marginLeft = -offset + 'px'; + loadPanels( this, viewerSize.x, -offset ); + } } else { - this.element.style.height = ( - viewerSize.y * - options.sizeRatio * - viewer.tileSources.length - ) + ( 12 * viewer.tileSources.length ) + 'px'; + offset = ( Number( page ) ) * ( this.panelHeight + 3 ); + if ( offset > offsetTop + viewerSize.y - this.panelHeight ) { + offset = Math.min( offset, ( scrollHeight - viewerSize.y ) ); + this.element.style.marginTop = -offset + 'px'; + loadPanels( this, viewerSize.y, -offset ); + } else if ( offset < offsetTop ) { + offset = Math.max( 0, offset - viewerSize.y / 2 ); + this.element.style.marginTop = -offset + 'px'; + loadPanels( this, viewerSize.y, -offset ); + } + } - this.element.style.width = ( - viewerSize.x * - options.sizeRatio - ) + 'px'; + this.currentPage = page; + $.getElement( element.id + '-displayregion' ).focus(); + onStripEnter.call( this, this.innerTracker, {} ); + } + }, + /** + * @function + * @name OpenSeadragon.ReferenceStrip.prototype.update + */ + update: function () { + if ( THIS[this.id].animating ) { + $.console.log( 'image reference strip update' ); + return true; + } + return false; + } - viewer.addControl( - this.element, - { anchor: $.ControlAnchor.TOP_LEFT } - ); +} ); + + + +/** + * @private + * @inner + * @function + */ +function onStripDrag( tracker, eventData ) { + + var offsetLeft = Number( this.element.style.marginLeft.replace( 'px', '' ) ), + offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ), + scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), + scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), + viewerSize = $.getElementSize( this.viewer.canvas ); + this.dragging = true; + if ( this.element ) { + if ( 'horizontal' == this.scroll ) { + if ( -eventData.delta.x > 0 ) { + //forward + if ( offsetLeft > -( scrollWidth - viewerSize.x ) ) { + this.element.style.marginLeft = ( offsetLeft + ( eventData.delta.x * 2 ) ) + 'px'; + loadPanels( this, viewerSize.x, offsetLeft + ( eventData.delta.x * 2 ) ); + } + } else if ( -eventData.delta.x < 0 ) { + //reverse + if ( offsetLeft < 0 ) { + this.element.style.marginLeft = ( offsetLeft + ( eventData.delta.x * 2 ) ) + 'px'; + loadPanels( this, viewerSize.x, offsetLeft + ( eventData.delta.x * 2 ) ); + } + } + } else { + if ( -eventData.delta.y > 0 ) { + //forward + if ( offsetTop > -( scrollHeight - viewerSize.y ) ) { + this.element.style.marginTop = ( offsetTop + ( eventData.delta.y * 2 ) ) + 'px'; + loadPanels( this, viewerSize.y, offsetTop + ( eventData.delta.y * 2 ) ); + } + } else if ( -eventData.delta.y < 0 ) { + //reverse + if ( offsetTop < 0 ) { + this.element.style.marginTop = ( offsetTop + ( eventData.delta.y * 2 ) ) + 'px'; + loadPanels( this, viewerSize.y, offsetTop + ( eventData.delta.y * 2 ) ); + } } } + } + return false; - this.panelWidth = ( viewerSize.x * this.sizeRatio ) + 8; - this.panelHeight = ( viewerSize.y * this.sizeRatio ) + 8; - this.panels = []; +} - /*jshint loopfunc:true*/ - for ( i = 0; i < viewer.tileSources.length; i++ ) { - element = $.makeNeutralElement( 'div' ); - element.id = this.element.id + "-" + i; - element.style.width = _this.panelWidth + 'px'; - element.style.height = _this.panelHeight + 'px'; - element.style.display = 'inline'; - element.style.float = 'left'; //Webkit - element.style.cssFloat = 'left'; //Firefox - element.style.styleFloat = 'left'; //IE - element.style.padding = '2px'; +/** + * @private + * @inner + * @function + */ +function onStripScroll( tracker, eventData ) { + var offsetLeft = Number( this.element.style.marginLeft.replace( 'px', '' ) ), + offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ), + scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), + scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), + viewerSize = $.getElementSize( this.viewer.canvas ); + if ( this.element ) { + if ( 'horizontal' == this.scroll ) { + if ( eventData.scroll > 0 ) { + //forward + if ( offsetLeft > -( scrollWidth - viewerSize.x ) ) { + this.element.style.marginLeft = ( offsetLeft - ( eventData.scroll * 60 ) ) + 'px'; + loadPanels( this, viewerSize.x, offsetLeft - ( eventData.scroll * 60 ) ); + } + } else if ( eventData.scroll < 0 ) { + //reverse + if ( offsetLeft < 0 ) { + this.element.style.marginLeft = ( offsetLeft - ( eventData.scroll * 60 ) ) + 'px'; + loadPanels( this, viewerSize.x, offsetLeft - ( eventData.scroll * 60 ) ); + } + } + } else { + if ( eventData.scroll < 0 ) { + //scroll up + if ( offsetTop > viewerSize.y - scrollHeight ) { + this.element.style.marginTop = ( offsetTop + ( eventData.scroll * 60 ) ) + 'px'; + loadPanels( this, viewerSize.y, offsetTop + ( eventData.scroll * 60 ) ); + } + } else if ( eventData.scroll > 0 ) { + //scroll dowm + if ( offsetTop < 0 ) { + this.element.style.marginTop = ( offsetTop + ( eventData.scroll * 60 ) ) + 'px'; + loadPanels( this, viewerSize.y, offsetTop + ( eventData.scroll * 60 ) ); + } + } + } + } + //cancels event + return false; +} - element.innerTracker = new $.MouseTracker( { + +function loadPanels( strip, viewerSize, scroll ) { + var panelSize, + activePanelsStart, + activePanelsEnd, + miniViewer, + style, + i, + element; + if ( 'horizontal' == strip.scroll ) { + panelSize = strip.panelWidth; + } else { + panelSize = strip.panelHeight; + } + activePanelsStart = Math.ceil( viewerSize / panelSize ) + 5; + activePanelsEnd = Math.ceil( ( Math.abs( scroll ) + viewerSize ) / panelSize ) + 1; + activePanelsStart = activePanelsEnd - activePanelsStart; + activePanelsStart = activePanelsStart < 0 ? 0 : activePanelsStart; + + for ( i = activePanelsStart; i < activePanelsEnd && i < strip.panels.length; i++ ) { + element = strip.panels[i]; + if ( !element.activePanel ) { + miniViewer = new $.Viewer( { + id: element.id, + tileSources: [strip.viewer.tileSources[i]], element: element, - clickTimeThreshold: this.clickTimeThreshold, - clickDistThreshold: this.clickDistThreshold, - pressHandler: function ( tracker, eventData ) { - tracker.dragging = $.now(); - }, - releaseHandler: function ( tracker, eventData ) { - var id = tracker.element.id, - page = Number( id.split( '-' )[2] ), - now = $.now(); + navigatorSizeRatio: strip.sizeRatio, + showNavigator: false, + mouseNavEnabled: false, + showNavigationControl: false, + showSequenceControl: false, + immediateRender: true, + blendTime: 0, + animationTime: 0 + } ); - if ( eventData.insideElementPress && - eventData.insideElementRelease && - tracker.dragging && - ( now - tracker.dragging ) < tracker.clickTimeThreshold ) { - tracker.dragging = null; - viewer.goToPage( page ); - } - } - } ).setTracking( true ); + miniViewer.displayRegion = $.makeNeutralElement( "textarea" ); + miniViewer.displayRegion.id = element.id + '-displayregion'; + miniViewer.displayRegion.className = 'displayregion'; - this.element.appendChild( element ); + style = miniViewer.displayRegion.style; + style.position = 'relative'; + style.top = '0px'; + style.left = '0px'; + style.fontSize = '0px'; + style.overflow = 'hidden'; + style.float = 'left'; //Webkit + style.cssFloat = 'left'; //Firefox + style.styleFloat = 'left'; //IE + style.zIndex = 999999999; + style.cursor = 'default'; + style.width = ( strip.panelWidth - 4 ) + 'px'; + style.height = ( strip.panelHeight - 4 ) + 'px'; - element.activePanel = false; + miniViewer.displayRegion.innerTracker = new $.MouseTracker( { + element: miniViewer.displayRegion + } ); - this.panels.push( element ); + element.getElementsByTagName( 'form' )[0].appendChild( + miniViewer.displayRegion + ); + element.activePanel = true; } - loadPanels( this, this.scroll == 'vertical' ? viewerSize.y : viewerSize.y, 0 ); - this.setFocus( 0 ); + } +} - }; - $.extend( $.ReferenceStrip.prototype, $.EventHandler.prototype, $.Viewer.prototype, { +/** + * @private + * @inner + * @function + */ +function onStripEnter( tracker, eventData ) { - setFocus: function ( page ) { - var element = $.getElement( this.element.id + '-' + page ), - viewerSize = $.getElementSize( this.viewer.canvas ), - scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), - scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), - offsetLeft = -Number( this.element.style.marginLeft.replace( 'px', '' ) ), - offsetTop = -Number( this.element.style.marginTop.replace( 'px', '' ) ), - offset; + //$.setElementOpacity(tracker.element, 0.8); - if ( this.currentSelected !== element ) { - if ( this.currentSelected ) { - this.currentSelected.style.background = '#000'; - } - this.currentSelected = element; - this.currentSelected.style.background = '#999'; + //tracker.element.style.border = '1px solid #555'; + //tracker.element.style.background = '#000'; - if ( 'horizontal' == this.scroll ) { - //right left - offset = ( Number( page ) ) * ( this.panelWidth + 3 ); - if ( offset > offsetLeft + viewerSize.x - this.panelWidth ) { - offset = Math.min( offset, ( scrollWidth - viewerSize.x ) ); - this.element.style.marginLeft = -offset + 'px'; - loadPanels( this, viewerSize.x, -offset ); - } else if ( offset < offsetLeft ) { - offset = Math.max( 0, offset - viewerSize.x / 2 ); - this.element.style.marginLeft = -offset + 'px'; - loadPanels( this, viewerSize.x, -offset ); - } - } else { - offset = ( Number( page ) ) * ( this.panelHeight + 3 ); - if ( offset > offsetTop + viewerSize.y - this.panelHeight ) { - offset = Math.min( offset, ( scrollHeight - viewerSize.y ) ); - this.element.style.marginTop = -offset + 'px'; - loadPanels( this, viewerSize.y, -offset ); - } else if ( offset < offsetTop ) { - offset = Math.max( 0, offset - viewerSize.y / 2 ); - this.element.style.marginTop = -offset + 'px'; - loadPanels( this, viewerSize.y, -offset ); - } - } + if ( 'horizontal' == this.scroll ) { - this.currentPage = page; - $.getElement( element.id + '-displayregion' ).focus(); - onStripEnter.call( this, this.innerTracker, {} ); - } - }, - /** - * @function - * @name OpenSeadragon.ReferenceStrip.prototype.update - */ - update: function () { - if ( THIS[this.id].animating ) { - $.console.log( 'image reference strip update' ); - return true; - } + //tracker.element.style.paddingTop = "0px"; + tracker.element.style.marginBottom = "0px"; + + } else { + + //tracker.element.style.paddingRight = "0px"; + tracker.element.style.marginLeft = "0px"; + + } + return false; +} + + +/** + * @private + * @inner + * @function + */ +function onStripExit( tracker, eventData ) { + if ( 'horizontal' == this.scroll ) { + + //tracker.element.style.paddingTop = "10px"; + tracker.element.style.marginBottom = "-" + ( $.getElementSize( tracker.element ).y / 2 ) + "px"; + + } else { + + //tracker.element.style.paddingRight = "10px"; + tracker.element.style.marginLeft = "-" + ( $.getElementSize( tracker.element ).x / 2 ) + "px"; + + } + return false; +} + + + +/** + * @private + * @inner + * @function + */ +function onKeyPress( tracker, eventData ) { + //console.log( eventData.keyCode ); + + switch ( eventData.keyCode ) { + case 61: //=|+ + onStripScroll.call( this, this.tracker, { position: null, scroll: 1, shift: null } ); return false; - } - - } ); - - - - - /** - * @private - * @inner - * @function - */ - function onStripDrag( tracker, eventData ) { - - var offsetLeft = Number( this.element.style.marginLeft.replace( 'px', '' ) ), - offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ), - scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), - scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), - viewerSize = $.getElementSize( this.viewer.canvas ); - this.dragging = true; - if ( this.element ) { - if ( 'horizontal' == this.scroll ) { - if ( -eventData.delta.x > 0 ) { - //forward - if ( offsetLeft > -( scrollWidth - viewerSize.x ) ) { - this.element.style.marginLeft = ( offsetLeft + ( eventData.delta.x * 2 ) ) + 'px'; - loadPanels( this, viewerSize.x, offsetLeft + ( eventData.delta.x * 2 ) ); - } - } else if ( -eventData.delta.x < 0 ) { - //reverse - if ( offsetLeft < 0 ) { - this.element.style.marginLeft = ( offsetLeft + ( eventData.delta.x * 2 ) ) + 'px'; - loadPanels( this, viewerSize.x, offsetLeft + ( eventData.delta.x * 2 ) ); - } - } - } else { - if ( -eventData.delta.y > 0 ) { - //forward - if ( offsetTop > -( scrollHeight - viewerSize.y ) ) { - this.element.style.marginTop = ( offsetTop + ( eventData.delta.y * 2 ) ) + 'px'; - loadPanels( this, viewerSize.y, offsetTop + ( eventData.delta.y * 2 ) ); - } - } else if ( -eventData.delta.y < 0 ) { - //reverse - if ( offsetTop < 0 ) { - this.element.style.marginTop = ( offsetTop + ( eventData.delta.y * 2 ) ) + 'px'; - loadPanels( this, viewerSize.y, offsetTop + ( eventData.delta.y * 2 ) ); - } - } - } - } - return false; - - } - - - - /** - * @private - * @inner - * @function - */ - function onStripScroll( tracker, eventData ) { - var offsetLeft = Number( this.element.style.marginLeft.replace( 'px', '' ) ), - offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ), - scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), - scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), - viewerSize = $.getElementSize( this.viewer.canvas ); - if ( this.element ) { - if ( 'horizontal' == this.scroll ) { - if ( eventData.scroll > 0 ) { - //forward - if ( offsetLeft > -( scrollWidth - viewerSize.x ) ) { - this.element.style.marginLeft = ( offsetLeft - ( eventData.scroll * 60 ) ) + 'px'; - loadPanels( this, viewerSize.x, offsetLeft - ( eventData.scroll * 60 ) ); - } - } else if ( eventData.scroll < 0 ) { - //reverse - if ( offsetLeft < 0 ) { - this.element.style.marginLeft = ( offsetLeft - ( eventData.scroll * 60 ) ) + 'px'; - loadPanels( this, viewerSize.x, offsetLeft - ( eventData.scroll * 60 ) ); - } - } - } else { - if ( eventData.scroll < 0 ) { - //scroll up - if ( offsetTop > viewerSize.y - scrollHeight ) { - this.element.style.marginTop = ( offsetTop + ( eventData.scroll * 60 ) ) + 'px'; - loadPanels( this, viewerSize.y, offsetTop + ( eventData.scroll * 60 ) ); - } - } else if ( eventData.scroll > 0 ) { - //scroll dowm - if ( offsetTop < 0 ) { - this.element.style.marginTop = ( offsetTop + ( eventData.scroll * 60 ) ) + 'px'; - loadPanels( this, viewerSize.y, offsetTop + ( eventData.scroll * 60 ) ); - } - } - } - } - //cancels event - return false; - } - - - function loadPanels( strip, viewerSize, scroll ) { - var panelSize, - activePanelsStart, - activePanelsEnd, - miniViewer, - style, - i, - element; - if ( 'horizontal' == strip.scroll ) { - panelSize = strip.panelWidth; - } else { - panelSize = strip.panelHeight; - } - activePanelsStart = Math.ceil( viewerSize / panelSize ) + 5; - activePanelsEnd = Math.ceil( ( Math.abs( scroll ) + viewerSize ) / panelSize ) + 1; - activePanelsStart = activePanelsEnd - activePanelsStart; - activePanelsStart = activePanelsStart < 0 ? 0 : activePanelsStart; - - for ( i = activePanelsStart; i < activePanelsEnd && i < strip.panels.length; i++ ) { - element = strip.panels[i]; - if ( !element.activePanel ) { - miniViewer = new $.Viewer( { - id: element.id, - tileSources: [strip.viewer.tileSources[i]], - element: element, - navigatorSizeRatio: strip.sizeRatio, - showNavigator: false, - mouseNavEnabled: false, - showNavigationControl: false, - showSequenceControl: false, - immediateRender: true, - blendTime: 0, - animationTime: 0 - } ); - - miniViewer.displayRegion = $.makeNeutralElement( "textarea" ); - miniViewer.displayRegion.id = element.id + '-displayregion'; - miniViewer.displayRegion.className = 'displayregion'; - - style = miniViewer.displayRegion.style; - style.position = 'relative'; - style.top = '0px'; - style.left = '0px'; - style.fontSize = '0px'; - style.overflow = 'hidden'; - style.float = 'left'; //Webkit - style.cssFloat = 'left'; //Firefox - style.styleFloat = 'left'; //IE - style.zIndex = 999999999; - style.cursor = 'default'; - style.width = ( strip.panelWidth - 4 ) + 'px'; - style.height = ( strip.panelHeight - 4 ) + 'px'; - - miniViewer.displayRegion.innerTracker = new $.MouseTracker( { - element: miniViewer.displayRegion - } ); - - element.getElementsByTagName( 'form' )[0].appendChild( - miniViewer.displayRegion - ); - - element.activePanel = true; - } - } - } - - - /** - * @private - * @inner - * @function - */ - function onStripEnter( tracker, eventData ) { - - //$.setElementOpacity(tracker.element, 0.8); - - //tracker.element.style.border = '1px solid #555'; - //tracker.element.style.background = '#000'; - - if ( 'horizontal' == this.scroll ) { - - //tracker.element.style.paddingTop = "0px"; - tracker.element.style.marginBottom = "0px"; - - } else { - - //tracker.element.style.paddingRight = "0px"; - tracker.element.style.marginLeft = "0px"; - - } - return false; - } - - - /** - * @private - * @inner - * @function - */ - function onStripExit( tracker, eventData ) { - if ( 'horizontal' == this.scroll ) { - - //tracker.element.style.paddingTop = "10px"; - tracker.element.style.marginBottom = "-" + ( $.getElementSize( tracker.element ).y / 2 ) + "px"; - - } else { - - //tracker.element.style.paddingRight = "10px"; - tracker.element.style.marginLeft = "-" + ( $.getElementSize( tracker.element ).x / 2 ) + "px"; - - } - return false; - } - - - - /** - * @private - * @inner - * @function - */ - function onKeyPress( tracker, eventData ) { - //console.log( eventData.keyCode ); - - switch ( eventData.keyCode ) { - case 61: //=|+ - onStripScroll.call( this, this.tracker, { position: null, scroll: 1, shift: null } ); - return false; - case 45: //-|_ - onStripScroll.call( this, this.tracker, { position: null, scroll: -1, shift: null } ); - return false; - case 48: //0|) - case 119: //w - case 87: //W - case 38: //up arrow - onStripScroll.call( this, this.tracker, { position: null, scroll: 1, shift: null } ); - return false; - case 115: //s - case 83: //S - case 40: //down arrow - onStripScroll.call( this, this.tracker, { position: null, scroll: -1, shift: null } ); - return false; - case 97: //a - case 37: //left arrow - onStripScroll.call( this, this.tracker, { position: null, scroll: -1, shift: null } ); - return false; - case 100: //d - case 39: //right arrow - onStripScroll.call( this, this.tracker, { position: null, scroll: 1, shift: null } ); - return false; - default: - //console.log( 'navigator keycode %s', eventData.keyCode ); - return true; - } + case 45: //-|_ + onStripScroll.call( this, this.tracker, { position: null, scroll: -1, shift: null } ); + return false; + case 48: //0|) + case 119: //w + case 87: //W + case 38: //up arrow + onStripScroll.call( this, this.tracker, { position: null, scroll: 1, shift: null } ); + return false; + case 115: //s + case 83: //S + case 40: //down arrow + onStripScroll.call( this, this.tracker, { position: null, scroll: -1, shift: null } ); + return false; + case 97: //a + case 37: //left arrow + onStripScroll.call( this, this.tracker, { position: null, scroll: -1, shift: null } ); + return false; + case 100: //d + case 39: //right arrow + onStripScroll.call( this, this.tracker, { position: null, scroll: 1, shift: null } ); + return false; + default: + //console.log( 'navigator keycode %s', eventData.keyCode ); + return true; } +} From 5f6b89b8b51e2881851ad9f0a65fa7a98507734c Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 6 Sep 2013 11:10:05 -0700 Subject: [PATCH 03/15] MouseTracker Original Events in Handlers More formatting fixes --- src/referencestrip.js | 244 +++++++++++++++++++++--------------------- 1 file changed, 122 insertions(+), 122 deletions(-) diff --git a/src/referencestrip.js b/src/referencestrip.js index d6a2e7b0..49e5bdbd 100644 --- a/src/referencestrip.js +++ b/src/referencestrip.js @@ -58,111 +58,111 @@ var THIS = {}; */ $.ReferenceStrip = function ( options ) { - var _this = this, - viewer = options.viewer, - viewerSize = $.getElementSize( viewer.element ), - element, - style, - i; + var _this = this, + viewer = options.viewer, + viewerSize = $.getElementSize( viewer.element ), + element, + style, + i; //We may need to create a new element and id if they did not //provide the id for the existing element if ( !options.id ) { - options.id = 'referencestrip-' + $.now(); - this.element = $.makeNeutralElement( "div" ); - this.element.id = options.id; - this.element.className = 'referencestrip'; + options.id = 'referencestrip-' + $.now(); + this.element = $.makeNeutralElement( "div" ); + this.element.id = options.id; + this.element.className = 'referencestrip'; } options = $.extend( true, { - sizeRatio: $.DEFAULT_SETTINGS.referenceStripSizeRatio, - position: $.DEFAULT_SETTINGS.referenceStripPosition, - scroll: $.DEFAULT_SETTINGS.referenceStripScroll, - clickTimeThreshold: $.DEFAULT_SETTINGS.clickTimeThreshold + sizeRatio: $.DEFAULT_SETTINGS.referenceStripSizeRatio, + position: $.DEFAULT_SETTINGS.referenceStripPosition, + scroll: $.DEFAULT_SETTINGS.referenceStripScroll, + clickTimeThreshold: $.DEFAULT_SETTINGS.clickTimeThreshold }, options, { //required overrides - element: this.element, + element: this.element, //These need to be overridden to prevent recursion since //the navigator is a viewer and a viewer has a navigator - showNavigator: false, - mouseNavEnabled: false, - showNavigationControl: false, - showSequenceControl: false + showNavigator: false, + mouseNavEnabled: false, + showNavigationControl: false, + showSequenceControl: false } ); $.extend( this, options ); //Private state properties THIS[this.id] = { - "animating": false + "animating": false }; this.minPixelRatio = this.viewer.minPixelRatio; style = this.element.style; - style.marginTop = '0px'; - style.marginRight = '0px'; - style.marginBottom = '0px'; - style.marginLeft = '0px'; - style.left = '0px'; - style.bottom = '0px'; - style.border = '0px'; - style.background = '#000'; - style.position = 'relative'; + style.marginTop = '0px'; + style.marginRight = '0px'; + style.marginBottom = '0px'; + style.marginLeft = '0px'; + style.left = '0px'; + style.bottom = '0px'; + style.border = '0px'; + style.background = '#000'; + style.position = 'relative'; $.setElementOpacity( this.element, 0.8 ); this.viewer = viewer; this.innerTracker = new $.MouseTracker( { - element: this.element, - dragHandler: $.delegate( this, onStripDrag ), - scrollHandler: $.delegate( this, onStripScroll ), - enterHandler: $.delegate( this, onStripEnter ), - exitHandler: $.delegate( this, onStripExit ), - keyHandler: $.delegate( this, onKeyPress ) + element: this.element, + dragHandler: $.delegate( this, onStripDrag ), + scrollHandler: $.delegate( this, onStripScroll ), + enterHandler: $.delegate( this, onStripEnter ), + exitHandler: $.delegate( this, onStripExit ), + keyHandler: $.delegate( this, onKeyPress ) } ).setTracking( true ); //Controls the position and orientation of the reference strip and sets the //appropriate width and height if ( options.width && options.height ) { - this.element.style.width = options.width + 'px'; + this.element.style.width = options.width + 'px'; this.element.style.height = options.height + 'px'; viewer.addControl( - this.element, - { anchor: $.ControlAnchor.BOTTOM_LEFT } - ); - } else { - if ( "horizontal" == options.scroll ) { - this.element.style.width = ( - viewerSize.x * - options.sizeRatio * - viewer.tileSources.length - ) + ( 12 * viewer.tileSources.length ) + 'px'; - - this.element.style.height = ( - viewerSize.y * - options.sizeRatio - ) + 'px'; - - viewer.addControl( this.element, { anchor: $.ControlAnchor.BOTTOM_LEFT } ); - } else { - this.element.style.height = ( - viewerSize.y * - options.sizeRatio * - viewer.tileSources.length - ) + ( 12 * viewer.tileSources.length ) + 'px'; - + } else { + if ( "horizontal" == options.scroll ) { this.element.style.width = ( - viewerSize.x * - options.sizeRatio - ) + 'px'; + viewerSize.x * + options.sizeRatio * + viewer.tileSources.length + ) + ( 12 * viewer.tileSources.length ) + 'px'; + + this.element.style.height = ( + viewerSize.y * + options.sizeRatio + ) + 'px'; viewer.addControl( - this.element, - { anchor: $.ControlAnchor.TOP_LEFT } - ); + this.element, + { anchor: $.ControlAnchor.BOTTOM_LEFT } + ); + } else { + this.element.style.height = ( + viewerSize.y * + options.sizeRatio * + viewer.tileSources.length + ) + ( 12 * viewer.tileSources.length ) + 'px'; + + this.element.style.width = ( + viewerSize.x * + options.sizeRatio + ) + 'px'; + + viewer.addControl( + this.element, + { anchor: $.ControlAnchor.TOP_LEFT } + ); } } @@ -177,16 +177,16 @@ $.ReferenceStrip = function ( options ) { element = $.makeNeutralElement( 'div' ); element.id = this.element.id + "-" + i; - element.style.width = _this.panelWidth + 'px'; - element.style.height = _this.panelHeight + 'px'; - element.style.display = 'inline'; - element.style.float = 'left'; //Webkit - element.style.cssFloat = 'left'; //Firefox - element.style.styleFloat = 'left'; //IE - element.style.padding = '2px'; + element.style.width = _this.panelWidth + 'px'; + element.style.height = _this.panelHeight + 'px'; + element.style.display = 'inline'; + element.style.float = 'left'; //Webkit + element.style.cssFloat = 'left'; //Firefox + element.style.styleFloat = 'left'; //IE + element.style.padding = '2px'; element.innerTracker = new $.MouseTracker( { - element: element, + element: element, clickTimeThreshold: this.clickTimeThreshold, clickDistThreshold: this.clickDistThreshold, pressHandler: function ( tracker, eventData ) { @@ -223,12 +223,12 @@ $.extend( $.ReferenceStrip.prototype, $.EventHandler.prototype, $.Viewer.prototy setFocus: function ( page ) { var element = $.getElement( this.element.id + '-' + page ), - viewerSize = $.getElementSize( this.viewer.canvas ), - scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), - scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), - offsetLeft = -Number( this.element.style.marginLeft.replace( 'px', '' ) ), - offsetTop = -Number( this.element.style.marginTop.replace( 'px', '' ) ), - offset; + viewerSize = $.getElementSize( this.viewer.canvas ), + scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), + scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), + offsetLeft = -Number( this.element.style.marginLeft.replace( 'px', '' ) ), + offsetTop = -Number( this.element.style.marginTop.replace( 'px', '' ) ), + offset; if ( this.currentSelected !== element ) { if ( this.currentSelected ) { @@ -292,10 +292,10 @@ $.extend( $.ReferenceStrip.prototype, $.EventHandler.prototype, $.Viewer.prototy function onStripDrag( tracker, eventData ) { var offsetLeft = Number( this.element.style.marginLeft.replace( 'px', '' ) ), - offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ), - scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), - scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), - viewerSize = $.getElementSize( this.viewer.canvas ); + offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ), + scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), + scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), + viewerSize = $.getElementSize( this.viewer.canvas ); this.dragging = true; if ( this.element ) { if ( 'horizontal' == this.scroll ) { @@ -341,10 +341,10 @@ function onStripDrag( tracker, eventData ) { */ function onStripScroll( tracker, eventData ) { var offsetLeft = Number( this.element.style.marginLeft.replace( 'px', '' ) ), - offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ), - scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), - scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), - viewerSize = $.getElementSize( this.viewer.canvas ); + offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ), + scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), + scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), + viewerSize = $.getElementSize( this.viewer.canvas ); if ( this.element ) { if ( 'horizontal' == this.scroll ) { if ( eventData.scroll > 0 ) { @@ -383,12 +383,12 @@ function onStripScroll( tracker, eventData ) { function loadPanels( strip, viewerSize, scroll ) { var panelSize, - activePanelsStart, - activePanelsEnd, - miniViewer, - style, - i, - element; + activePanelsStart, + activePanelsEnd, + miniViewer, + style, + i, + element; if ( 'horizontal' == strip.scroll ) { panelSize = strip.panelWidth; } else { @@ -403,44 +403,44 @@ function loadPanels( strip, viewerSize, scroll ) { element = strip.panels[i]; if ( !element.activePanel ) { miniViewer = new $.Viewer( { - id: element.id, - tileSources: [strip.viewer.tileSources[i]], - element: element, - navigatorSizeRatio: strip.sizeRatio, - showNavigator: false, - mouseNavEnabled: false, - showNavigationControl: false, - showSequenceControl: false, - immediateRender: true, - blendTime: 0, - animationTime: 0 + id: element.id, + tileSources: [strip.viewer.tileSources[i]], + element: element, + navigatorSizeRatio: strip.sizeRatio, + showNavigator: false, + mouseNavEnabled: false, + showNavigationControl: false, + showSequenceControl: false, + immediateRender: true, + blendTime: 0, + animationTime: 0 } ); - miniViewer.displayRegion = $.makeNeutralElement( "textarea" ); - miniViewer.displayRegion.id = element.id + '-displayregion'; + miniViewer.displayRegion = $.makeNeutralElement( "textarea" ); + miniViewer.displayRegion.id = element.id + '-displayregion'; miniViewer.displayRegion.className = 'displayregion'; - style = miniViewer.displayRegion.style; - style.position = 'relative'; - style.top = '0px'; - style.left = '0px'; - style.fontSize = '0px'; - style.overflow = 'hidden'; - style.float = 'left'; //Webkit - style.cssFloat = 'left'; //Firefox - style.styleFloat = 'left'; //IE - style.zIndex = 999999999; - style.cursor = 'default'; - style.width = ( strip.panelWidth - 4 ) + 'px'; - style.height = ( strip.panelHeight - 4 ) + 'px'; + style = miniViewer.displayRegion.style; + style.position = 'relative'; + style.top = '0px'; + style.left = '0px'; + style.fontSize = '0px'; + style.overflow = 'hidden'; + style.float = 'left'; //Webkit + style.cssFloat = 'left'; //Firefox + style.styleFloat = 'left'; //IE + style.zIndex = 999999999; + style.cursor = 'default'; + style.width = ( strip.panelWidth - 4 ) + 'px'; + style.height = ( strip.panelHeight - 4 ) + 'px'; miniViewer.displayRegion.innerTracker = new $.MouseTracker( { element: miniViewer.displayRegion } ); element.getElementsByTagName( 'form' )[0].appendChild( - miniViewer.displayRegion - ); + miniViewer.displayRegion + ); element.activePanel = true; } From 8229a9aba568cd5c946dbad72995c3965fb38bfa Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 6 Sep 2013 11:20:14 -0700 Subject: [PATCH 04/15] MouseTracker Original Events in Handlers More formatting fixes --- src/referencestrip.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/referencestrip.js b/src/referencestrip.js index 49e5bdbd..4f8f2bf0 100644 --- a/src/referencestrip.js +++ b/src/referencestrip.js @@ -198,9 +198,9 @@ $.ReferenceStrip = function ( options ) { now = $.now(); if ( eventData.insideElementPress && - eventData.insideElementRelease && - tracker.dragging && - ( now - tracker.dragging ) < tracker.clickTimeThreshold ) { + eventData.insideElementRelease && + tracker.dragging && + ( now - tracker.dragging ) < tracker.clickTimeThreshold ) { tracker.dragging = null; viewer.goToPage( page ); } From 2e1f71a82435bf92efc54165041148898a2205ff Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 6 Sep 2013 12:24:19 -0700 Subject: [PATCH 05/15] MouseTracker Original Events in Handlers Bug fixes. Event handler methods shouldn't be called directly in theory... --- src/buttongroup.js | 4 ++-- src/viewer.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/buttongroup.js b/src/buttongroup.js index 550a2ac1..da0f658a 100644 --- a/src/buttongroup.js +++ b/src/buttongroup.js @@ -119,7 +119,7 @@ $.ButtonGroup.prototype = { * @name OpenSeadragon.ButtonGroup.prototype.emulateEnter */ emulateEnter: function() { - this.tracker.enterHandler(); + this.tracker.enterHandler( this.tracker, {} ); }, /** @@ -129,7 +129,7 @@ $.ButtonGroup.prototype = { * @name OpenSeadragon.ButtonGroup.prototype.emulateExit */ emulateExit: function() { - this.tracker.exitHandler(); + this.tracker.exitHandler( this.tracker, {} ); } }; diff --git a/src/viewer.js b/src/viewer.js index 7c374daa..88df1d81 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -730,7 +730,7 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype, THIS[ this.hash ].fullPage = true; // mouse will be inside container now - $.delegate( this, onContainerEnter )(); + $.delegate( this, onContainerEnter )( null, {} ); } else { @@ -789,7 +789,7 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype, THIS[ this.hash ].fullPage = false; // mouse will likely be outside now - $.delegate( this, onContainerExit )(); + $.delegate( this, onContainerExit )( null, {} ); } From d60224b615ffea9a212cdc9511842684ac8302e8 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 6 Sep 2013 13:12:11 -0700 Subject: [PATCH 06/15] MouseTracker Original Events in Handlers Pass original touch events to handlers. --- src/mousetracker.js | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/mousetracker.js b/src/mousetracker.js index c765b3d1..7c063521 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -841,10 +841,10 @@ event.changedTouches.length == 1 ) { THIS[tracker.hash].lastTouch = event.touches[0]; - onMouseOver( tracker, event.changedTouches[0], true ); + onMouseOver( tracker, event, true ); // call with no capture as the onMouseMoveWindow will // be triggered by onTouchMove - onMouseDown( tracker, event.touches[0], true, true ); + onMouseDown( tracker, event, true, true ); } if ( event.touches.length == 2 ) { @@ -924,8 +924,8 @@ // call with no release, as the mouse events are // not registered in onTouchStart - onMouseUpWindow( tracker, event.changedTouches[0], true ); - onMouseOut( tracker, event.changedTouches[0], true ); + onMouseUpWindow( tracker, event, true, true ); + onMouseOut( tracker, event, true ); } if ( event.touches.length + event.changedTouches.length == 2 ) { THIS[tracker.hash].lastPinchDelta = null; @@ -983,9 +983,11 @@ * @private * @inner */ - function onMouseUpWindow( tracker, event, noRelease ) { + function onMouseUpWindow( tracker, event, noRelease, isTouch ) { + isTouch = ( isTouch !== undefined ) ? isTouch : false; + if ( !THIS[tracker.hash].insideElement ) { - onMouseUp( tracker, event, false ); + onMouseUp( tracker, event, isTouch ); } if ( noRelease ) { @@ -1171,7 +1173,7 @@ event.changedTouches.length === 1 && THIS[tracker.hash].lastTouch.identifier === event.touches[0].identifier ) { - onMouseMoveWindow( tracker, event.touches[0], true ); + onMouseMoveWindow( tracker, event, true ); } else if ( event.touches.length === 2 ) { @@ -1185,15 +1187,14 @@ if ( Math.abs( THIS[tracker.hash].lastPinchDelta - pinchDelta ) > 75 ) { //$.console.debug( "pinch delta : " + pinchDelta + " | previous : " + THIS[ tracker.hash ].lastPinchDelta); - onMouseWheelSpin( tracker, { - shift: false, - shiftKey: false, - pageX: THIS[tracker.hash].pinchMidpoint.x, - pageY: THIS[tracker.hash].pinchMidpoint.y, - detail: ( - THIS[tracker.hash].lastPinchDelta > pinchDelta - ) ? 1 : -1 - }, true ); + // Adjust the original event enough to simulate a mouse wheel scroll + event.shift = false; + event.shiftKey = false; + event.pageX = THIS[tracker.hash].pinchMidpoint.x; + event.pageY = THIS[tracker.hash].pinchMidpoint.y; + event.detail = ( THIS[tracker.hash].lastPinchDelta > pinchDelta ) ? 1 : -1; + + onMouseWheelSpin( tracker, event, true ); THIS[tracker.hash].lastPinchDelta = pinchDelta; } From 13415b36f356638b31386b0f80edbcc798e0aca9 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Mon, 9 Sep 2013 14:27:58 -0700 Subject: [PATCH 07/15] MouseTracker Original Events in Handlers Misc name changes, indentation/whitespace fixes. Still TODO: Fix documentation, evaluate presence of key handler in a mouse tracker, evaluate whether isTouchEvent flag should be in all eventData objects or not. --- src/button.js | 8 +-- src/buttongroup.js | 2 +- src/mousetracker.js | 123 +++++++++++++++++++++--------------------- src/navigator.js | 4 +- src/openseadragon.js | 2 + src/referencestrip.js | 34 ++++++------ src/viewer.js | 12 ++--- 7 files changed, 93 insertions(+), 92 deletions(-) diff --git a/src/button.js b/src/button.js index c1f711bd..22db888b 100644 --- a/src/button.js +++ b/src/button.js @@ -176,7 +176,7 @@ $.Button = function( options ) { clickDistThreshold: this.clickDistThreshold, enterHandler: function( tracker, eventData ) { - if ( eventData.buttonDownElement ) { + if ( eventData.insideElementPressed ) { inTo( _this, $.ButtonState.DOWN ); _this.raiseEvent( "onEnter", _this ); } else if ( !eventData.buttonDownAny ) { @@ -191,7 +191,7 @@ $.Button = function( options ) { exitHandler: function( tracker, eventData ) { outTo( _this, $.ButtonState.GROUP ); - if ( eventData.buttonDownElement ) { + if ( eventData.insideElementPressed ) { _this.raiseEvent( "onExit", _this ); } }, @@ -207,10 +207,10 @@ $.Button = function( options ) { }, releaseHandler: function( tracker, eventData ) { - if ( eventData.insideElementPress && eventData.insideElementRelease ) { + if ( eventData.insideElementPressed && eventData.insideElementRelease ) { outTo( _this, $.ButtonState.HOVER ); _this.raiseEvent( "onRelease", _this ); - } else if ( eventData.insideElementPress ) { + } else if ( eventData.insideElementPressed ) { outTo( _this, $.ButtonState.GROUP ); } else { inTo( _this, $.ButtonState.HOVER ); diff --git a/src/buttongroup.js b/src/buttongroup.js index da0f658a..db133352 100644 --- a/src/buttongroup.js +++ b/src/buttongroup.js @@ -93,7 +93,7 @@ $.ButtonGroup = function( options ) { }, exitHandler: function ( tracker, eventData ) { var i; - if ( !eventData.buttonDownElement ) { + if ( !eventData.insideElementPressed ) { for ( i = 0; i < _this.buttons.length; i++ ) { _this.buttons[ i ].notifyGroupExit(); } diff --git a/src/mousetracker.js b/src/mousetracker.js index 7c063521..015ee8b8 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -138,7 +138,7 @@ * Are we currently tracking mouse events. * @property {Boolean} capturing * Are we curruently capturing mouse events. - * @property {Boolean} buttonDownElement + * @property {Boolean} insideElementPressed * True if the left mouse button is currently being pressed and was * initiated inside the tracked element, otherwise false. * @property {Boolean} insideElement @@ -151,32 +151,32 @@ * Position of last mouse down */ THIS[this.hash] = { - mouseover: function ( event ) { onMouseOver( _this, event, false ); }, - mouseout: function ( event ) { onMouseOut( _this, event, false ); }, - mousedown: function ( event ) { onMouseDown( _this, event ); }, - mouseup: function ( event ) { onMouseUp( _this, event, false ); }, - mousemove: function ( event ) { onMouseMove( _this, event ); }, - click: function ( event ) { onMouseClick( _this, event ); }, - DOMMouseScroll: function ( event ) { onMouseWheelSpin( _this, event, false ); }, - mousewheel: function ( event ) { onMouseWheelSpin( _this, event, false ); }, - mouseupie: function ( event ) { onMouseUpIE( _this, event ); }, - mousemoveie: function ( event ) { onMouseMoveIE( _this, event ); }, - mouseupwindow: function ( event ) { onMouseUpWindow( _this, event ); }, - mousemovewindow: function ( event ) { onMouseMoveWindow( _this, event, false ); }, - touchstart: function ( event ) { onTouchStart( _this, event ); }, - touchmove: function ( event ) { onTouchMove( _this, event ); }, - touchend: function ( event ) { onTouchEnd( _this, event ); }, - keypress: function ( event ) { onKeyPress( _this, event ); }, - focus: function ( event ) { onFocus( _this, event ); }, - blur: function ( event ) { onBlur( _this, event ); }, - tracking: false, - capturing: false, - buttonDownElement: false, - insideElement: false, - lastPoint: null, - lastMouseDownTime: null, - lastMouseDownPoint: null, - lastPinchDelta: 0 + mouseover: function ( event ) { onMouseOver( _this, event, false ); }, + mouseout: function ( event ) { onMouseOut( _this, event, false ); }, + mousedown: function ( event ) { onMouseDown( _this, event ); }, + mouseup: function ( event ) { onMouseUp( _this, event, false ); }, + mousemove: function ( event ) { onMouseMove( _this, event ); }, + click: function ( event ) { onMouseClick( _this, event ); }, + DOMMouseScroll: function ( event ) { onMouseWheelSpin( _this, event, false ); }, + mousewheel: function ( event ) { onMouseWheelSpin( _this, event, false ); }, + mouseupie: function ( event ) { onMouseUpIE( _this, event ); }, + mousemovecapturedie: function ( event ) { onMouseMoveCapturedIE( _this, event ); }, + mouseupcaptured: function ( event ) { onMouseUpCaptured( _this, event ); }, + mousemovecaptured: function ( event ) { onMouseMoveCaptured( _this, event, false ); }, + touchstart: function ( event ) { onTouchStart( _this, event ); }, + touchmove: function ( event ) { onTouchMove( _this, event ); }, + touchend: function ( event ) { onTouchEnd( _this, event ); }, + keypress: function ( event ) { onKeyPress( _this, event ); }, + focus: function ( event ) { onFocus( _this, event ); }, + blur: function ( event ) { onBlur( _this, event ); }, + tracking: false, + capturing: false, + insideElementPressed: false, + insideElement: false, + lastPoint: null, + lastMouseDownTime: null, + lastMouseDownPoint: null, + lastPinchDelta: 0 }; }; @@ -227,7 +227,7 @@ * @param {Object} eventData * { * position: The position of the event relative to the tracked element. - * buttonDownElement: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. + * insideElementPressed: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. * buttonDownAny: Was the button down anywhere in the screen during the event. * isTouchEvent: True if the original event is a touch event, otherwise false. * originalEvent: The original event object. @@ -245,7 +245,7 @@ * @param {Object} eventData * { * position: The position of the event relative to the tracked element. - * buttonDownElement: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. + * insideElementPressed: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. * buttonDownAny: Was the button down anywhere in the screen during the event. * isTouchEvent: True if the original event is a touch event, otherwise false. * originalEvent: The original event object. @@ -279,7 +279,7 @@ * @param {Object} eventData * { * position: The position of the event relative to the tracked element. - * insideElementPress: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. + * insideElementPressed: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. * insideElementRelease: Was the mouse still inside the tracked element when the button was released. * isTouchEvent: True if the original event is a touch event, otherwise false. * originalEvent: The original event object. @@ -507,20 +507,20 @@ $.addEvent( tracker.element, "mousemove", - delegate.mousemoveie, + delegate.mousemovecapturedie, true ); } else { $.addEvent( window, "mouseup", - delegate.mouseupwindow, + delegate.mouseupcaptured, true ); $.addEvent( window, "mousemove", - delegate.mousemovewindow, + delegate.mousemovecaptured, true ); } @@ -542,7 +542,7 @@ $.removeEvent( tracker.element, "mousemove", - delegate.mousemoveie, + delegate.mousemovecapturedie, true ); $.removeEvent( @@ -561,13 +561,13 @@ $.removeEvent( window, "mousemove", - delegate.mousemovewindow, + delegate.mousemovecaptured, true ); $.removeEvent( window, "mouseup", - delegate.mouseupwindow, + delegate.mouseupcaptured, true ); } @@ -671,7 +671,7 @@ var delegate = THIS[tracker.hash], propagate; - isTouch = ( isTouch !== undefined ) ? isTouch : false; + isTouch = isTouch || false; event = $.getEvent( event ); @@ -702,7 +702,7 @@ tracker, { position: getMouseRelative( event, tracker.element ), - buttonDownElement: delegate.buttonDownElement, + insideElementPressed: delegate.insideElementPressed, buttonDownAny: IS_BUTTON_DOWN, isTouchEvent: isTouch, originalEvent: event, @@ -724,7 +724,7 @@ var delegate = THIS[tracker.hash], propagate; - isTouch = ( isTouch !== undefined ) ? isTouch : false; + isTouch = isTouch || false; event = $.getEvent( event ); @@ -756,7 +756,7 @@ tracker, { position: getMouseRelative( event, tracker.element ), - buttonDownElement: delegate.buttonDownElement, + insideElementPressed: delegate.insideElementPressed, buttonDownAny: IS_BUTTON_DOWN, isTouchEvent: isTouch, originalEvent: event, @@ -779,7 +779,7 @@ var delegate = THIS[tracker.hash], propagate; - isTouch = ( isTouch !== undefined ) ? isTouch : false; + isTouch = isTouch || false; event = $.getEvent( event ); @@ -787,7 +787,7 @@ return; } - delegate.buttonDownElement = true; + delegate.insideElementPressed = true; delegate.lastPoint = getMouseAbsolute( event ); delegate.lastMouseDownPoint = delegate.lastPoint; @@ -842,7 +842,7 @@ THIS[tracker.hash].lastTouch = event.touches[0]; onMouseOver( tracker, event, true ); - // call with no capture as the onMouseMoveWindow will + // call with no capture as the onMouseMoveCaptured will // be triggered by onTouchMove onMouseDown( tracker, event, true, true ); } @@ -871,13 +871,13 @@ */ function onMouseUp( tracker, event, isTouch ) { var delegate = THIS[tracker.hash], - //were we inside the tracked element when we were pressed - insideElementPress = delegate.buttonDownElement, - //are we still inside the tracked element when we released + //were we inside the tracked element when we were pressed + insideElementPressed = delegate.insideElementPressed, + //are we still inside the tracked element when we released insideElementRelease = delegate.insideElement, propagate; - isTouch = ( isTouch !== undefined ) ? isTouch : false; + isTouch = isTouch || false; event = $.getEvent( event ); @@ -885,14 +885,14 @@ return; } - delegate.buttonDownElement = false; + delegate.insideElementPressed = false; if ( tracker.releaseHandler ) { propagate = tracker.releaseHandler( tracker, { position: getMouseRelative( event, tracker.element ), - insideElementPress: insideElementPress, + insideElementPressed: insideElementPressed, insideElementRelease: insideElementRelease, isTouchEvent: isTouch, originalEvent: event, @@ -904,7 +904,7 @@ } } - if ( insideElementPress && insideElementRelease ) { + if ( insideElementPressed && insideElementRelease ) { handleMouseClick( tracker, event ); } } @@ -924,7 +924,7 @@ // call with no release, as the mouse events are // not registered in onTouchStart - onMouseUpWindow( tracker, event, true, true ); + onMouseUpCaptured( tracker, event, true, true ); onMouseOut( tracker, event, true ); } if ( event.touches.length + event.changedTouches.length == 2 ) { @@ -983,8 +983,8 @@ * @private * @inner */ - function onMouseUpWindow( tracker, event, noRelease, isTouch ) { - isTouch = ( isTouch !== undefined ) ? isTouch : false; + function onMouseUpCaptured( tracker, event, noRelease, isTouch ) { + isTouch = isTouch || false; if ( !THIS[tracker.hash].insideElement ) { onMouseUp( tracker, event, isTouch ); @@ -1041,7 +1041,7 @@ var nDelta = 0, propagate; - isTouch = ( isTouch !== undefined ) ? isTouch : false; + isTouch = isTouch || false; if ( !event ) { // For IE, access the global (window) event object event = window.event; @@ -1122,13 +1122,13 @@ * @private * @inner */ - function onMouseMoveWindow( tracker, event, isTouch ) { + function onMouseMoveCaptured( tracker, event, isTouch ) { var delegate = THIS[tracker.hash], delta, propagate, point; - isTouch = ( isTouch !== undefined ) ? isTouch : false; + isTouch = isTouch || false; event = $.getEvent( event ); point = getMouseAbsolute( event ); @@ -1173,7 +1173,7 @@ event.changedTouches.length === 1 && THIS[tracker.hash].lastTouch.identifier === event.touches[0].identifier ) { - onMouseMoveWindow( tracker, event, true ); + onMouseMoveCaptured( tracker, event, true ); } else if ( event.touches.length === 2 ) { @@ -1188,8 +1188,7 @@ //$.console.debug( "pinch delta : " + pinchDelta + " | previous : " + THIS[ tracker.hash ].lastPinchDelta); // Adjust the original event enough to simulate a mouse wheel scroll - event.shift = false; - event.shiftKey = false; + event.shiftKey = event.shiftKey || false; event.pageX = THIS[tracker.hash].pinchMidpoint.x; event.pageY = THIS[tracker.hash].pinchMidpoint.y; event.detail = ( THIS[tracker.hash].lastPinchDelta > pinchDelta ) ? 1 : -1; @@ -1211,10 +1210,10 @@ * @private * @inner */ - function onMouseMoveIE( tracker, event ) { + function onMouseMoveCapturedIE( tracker, event ) { var i; for ( i = 0; i < CAPTURING.length; i++ ) { - onMouseMoveWindow( CAPTURING[i], event, false ); + onMouseMoveCaptured( CAPTURING[i], event, false ); } $.stopEvent( event ); @@ -1233,7 +1232,7 @@ * @inner */ function getMouseRelative( event, element ) { - var mouse = $.getMousePosition( event ), + var mouse = $.getMousePosition( event ), offset = $.getElementOffset( element ); return mouse.minus( offset ); diff --git a/src/navigator.js b/src/navigator.js index f1999831..7197776a 100644 --- a/src/navigator.js +++ b/src/navigator.js @@ -308,8 +308,8 @@ function onCanvasDrag( tracker, eventData ) { * @inner * @function */ -function onCanvasRelease( tracker, eventData ) {//position, insideElementPress, insideElementRelease - if ( eventData.insideElementPress && this.viewer.viewport ) { +function onCanvasRelease( tracker, eventData ) { + if ( eventData.insideElementPressed && this.viewer.viewport ) { this.viewer.viewport.applyConstraints(); } } diff --git a/src/openseadragon.js b/src/openseadragon.js index b28cc507..79e683c6 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -707,6 +707,8 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ * @returns {Point} - the position of the upper left corner of the element adjusted for current page and/or element scroll. */ getElementOffset: function( element ) { + element = $.getElement( element ); + var doc = element && element.ownerDocument, docElement, win, diff --git a/src/referencestrip.js b/src/referencestrip.js index 4f8f2bf0..94662764 100644 --- a/src/referencestrip.js +++ b/src/referencestrip.js @@ -193,11 +193,11 @@ $.ReferenceStrip = function ( options ) { tracker.dragging = $.now(); }, releaseHandler: function ( tracker, eventData ) { - var id = tracker.element.id, - page = Number( id.split( '-' )[2] ), - now = $.now(); + var id = tracker.element.id, + page = Number( id.split( '-' )[2] ), + now = $.now(); - if ( eventData.insideElementPress && + if ( eventData.insideElementPressed && eventData.insideElementRelease && tracker.dragging && ( now - tracker.dragging ) < tracker.clickTimeThreshold ) { @@ -222,12 +222,12 @@ $.ReferenceStrip = function ( options ) { $.extend( $.ReferenceStrip.prototype, $.EventHandler.prototype, $.Viewer.prototype, { setFocus: function ( page ) { - var element = $.getElement( this.element.id + '-' + page ), - viewerSize = $.getElementSize( this.viewer.canvas ), - scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), + var element = $.getElement( this.element.id + '-' + page ), + viewerSize = $.getElementSize( this.viewer.canvas ), + scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), - offsetLeft = -Number( this.element.style.marginLeft.replace( 'px', '' ) ), - offsetTop = -Number( this.element.style.marginTop.replace( 'px', '' ) ), + offsetLeft = -Number( this.element.style.marginLeft.replace( 'px', '' ) ), + offsetTop = -Number( this.element.style.marginTop.replace( 'px', '' ) ), offset; if ( this.currentSelected !== element ) { @@ -291,11 +291,11 @@ $.extend( $.ReferenceStrip.prototype, $.EventHandler.prototype, $.Viewer.prototy */ function onStripDrag( tracker, eventData ) { - var offsetLeft = Number( this.element.style.marginLeft.replace( 'px', '' ) ), - offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ), - scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), + var offsetLeft = Number( this.element.style.marginLeft.replace( 'px', '' ) ), + offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ), + scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), - viewerSize = $.getElementSize( this.viewer.canvas ); + viewerSize = $.getElementSize( this.viewer.canvas ); this.dragging = true; if ( this.element ) { if ( 'horizontal' == this.scroll ) { @@ -340,11 +340,11 @@ function onStripDrag( tracker, eventData ) { * @function */ function onStripScroll( tracker, eventData ) { - var offsetLeft = Number( this.element.style.marginLeft.replace( 'px', '' ) ), - offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ), - scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), + var offsetLeft = Number( this.element.style.marginLeft.replace( 'px', '' ) ), + offsetTop = Number( this.element.style.marginTop.replace( 'px', '' ) ), + scrollWidth = Number( this.element.style.width.replace( 'px', '' ) ), scrollHeight = Number( this.element.style.height.replace( 'px', '' ) ), - viewerSize = $.getElementSize( this.viewer.canvas ); + viewerSize = $.getElementSize( this.viewer.canvas ); if ( this.element ) { if ( 'horizontal' == this.scroll ) { if ( eventData.scroll > 0 ) { diff --git a/src/viewer.js b/src/viewer.js index 88df1d81..c7995d9b 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -1472,13 +1472,13 @@ function onCanvasDrag( tracker, eventData ) { } function onCanvasRelease( tracker, eventData ) { - if ( eventData.insideElementPress && this.viewport ) { + if ( eventData.insideElementPressed && this.viewport ) { this.viewport.applyConstraints(); } this.raiseEvent( 'canvas-release', { tracker: tracker, position: eventData.position, - insideElementPress: eventData.insideElementPress, + insideElementPressed: eventData.insideElementPressed, insideElementRelease: eventData.insideElementRelease }); } @@ -1504,7 +1504,7 @@ function onCanvasScroll( tracker, eventData ) { } function onContainerExit( tracker, eventData ) { - if ( !eventData.buttonDownElement ) { + if ( !eventData.insideElementPressed ) { THIS[ this.hash ].mouseInside = false; if ( !THIS[ this.hash ].animating ) { beginControlsAutoHide( this ); @@ -1513,7 +1513,7 @@ function onContainerExit( tracker, eventData ) { this.raiseEvent( 'container-exit', { tracker: tracker, position: eventData.position, - buttonDownElement: eventData.buttonDownElement, + insideElementPressed: eventData.insideElementPressed, buttonDownAny: eventData.buttonDownAny }); } @@ -1528,7 +1528,7 @@ function onContainerRelease( tracker, eventData ) { this.raiseEvent( 'container-release', { tracker: tracker, position: eventData.position, - insideElementPress: eventData.insideElementPress, + insideElementPressed: eventData.insideElementPressed, insideElementRelease: eventData.insideElementRelease }); } @@ -1539,7 +1539,7 @@ function onContainerEnter( tracker, eventData ) { this.raiseEvent( 'container-enter', { tracker: tracker, position: eventData.position, - buttonDownElement: eventData.buttonDownElement, + insideElementPressed: eventData.insideElementPressed, buttonDownAny: eventData.buttonDownAny }); } From 1dc2d7e01188fb1ffa2f1ca8949a02dd3fdeda86 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Tue, 10 Sep 2013 17:23:19 -0700 Subject: [PATCH 08/15] MouseTracker Original Events in Handlers Touch events bug fix. Now uses touch object(s) properly when calculating positions. --- src/mousetracker.js | 119 +++++++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 51 deletions(-) diff --git a/src/mousetracker.js b/src/mousetracker.js index 015ee8b8..ace89018 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -675,24 +675,26 @@ event = $.getEvent( event ); - if ( $.Browser.vendor == $.BROWSERS.IE && - $.Browser.version < 9 && - delegate.capturing && - !isChild( event.srcElement, tracker.element ) ) { + if ( !isTouch ) { + if ( $.Browser.vendor == $.BROWSERS.IE && + $.Browser.version < 9 && + delegate.capturing && + !isChild( event.srcElement, tracker.element ) ) { - triggerOthers( tracker, onMouseOver, event, isTouch ); - } + triggerOthers( tracker, onMouseOver, event, isTouch ); + } - var to = event.target ? - event.target : - event.srcElement, - from = event.relatedTarget ? - event.relatedTarget : - event.fromElement; + var to = event.target ? + event.target : + event.srcElement, + from = event.relatedTarget ? + event.relatedTarget : + event.fromElement; - if ( !isChild( tracker.element, to ) || - isChild( tracker.element, from ) ) { - return; + if ( !isChild( tracker.element, to ) || + isChild( tracker.element, from ) ) { + return; + } } delegate.insideElement = true; @@ -701,7 +703,7 @@ propagate = tracker.enterHandler( tracker, { - position: getMouseRelative( event, tracker.element ), + position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), insideElementPressed: delegate.insideElementPressed, buttonDownAny: IS_BUTTON_DOWN, isTouchEvent: isTouch, @@ -728,25 +730,27 @@ event = $.getEvent( event ); - if ( $.Browser.vendor == $.BROWSERS.IE && - $.Browser.version < 9 && - delegate.capturing && - !isChild( event.srcElement, tracker.element ) ) { + if ( !isTouch ) { + if ( $.Browser.vendor == $.BROWSERS.IE && + $.Browser.version < 9 && + delegate.capturing && + !isChild( event.srcElement, tracker.element ) ) { - triggerOthers( tracker, onMouseOut, event, isTouch ); + triggerOthers( tracker, onMouseOut, event, isTouch ); - } + } - var from = event.target ? - event.target : - event.srcElement, - to = event.relatedTarget ? - event.relatedTarget : - event.toElement; + var from = event.target ? + event.target : + event.srcElement, + to = event.relatedTarget ? + event.relatedTarget : + event.toElement; - if ( !isChild( tracker.element, from ) || - isChild( tracker.element, to ) ) { - return; + if ( !isChild( tracker.element, from ) || + isChild( tracker.element, to ) ) { + return; + } } delegate.insideElement = false; @@ -755,7 +759,7 @@ propagate = tracker.exitHandler( tracker, { - position: getMouseRelative( event, tracker.element ), + position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), insideElementPressed: delegate.insideElementPressed, buttonDownAny: IS_BUTTON_DOWN, isTouchEvent: isTouch, @@ -781,7 +785,9 @@ isTouch = isTouch || false; - event = $.getEvent( event ); + var originalEvent = $.getEvent(event); + + event = isTouch ? event.touches[ 0 ] : event; if ( event.button == 2 ) { return; @@ -799,24 +805,25 @@ { position: getMouseRelative( event, tracker.element ), isTouchEvent: isTouch, - originalEvent: event, + originalEvent: originalEvent, userData: tracker.userData } ); if ( propagate === false ) { - $.cancelEvent( event ); + $.cancelEvent( originalEvent ); } } if ( tracker.pressHandler || tracker.dragHandler ) { - $.cancelEvent( event ); + $.cancelEvent( originalEvent ); } if ( noCapture ) { return; } - if ( !( $.Browser.vendor == $.BROWSERS.IE && $.Browser.version < 9 ) || + if ( isTouch || + !( $.Browser.vendor == $.BROWSERS.IE && $.Browser.version < 9 ) || !IS_CAPTURING ) { captureMouse( tracker ); IS_CAPTURING = true; @@ -879,7 +886,9 @@ isTouch = isTouch || false; - event = $.getEvent( event ); + var originalEvent = $.getEvent(event); + + event = isTouch ? event.changedTouches[ 0 ] : event; if ( event.button == 2 ) { return; @@ -895,17 +904,17 @@ insideElementPressed: insideElementPressed, insideElementRelease: insideElementRelease, isTouchEvent: isTouch, - originalEvent: event, + originalEvent: originalEvent, userData: tracker.userData } ); if ( propagate === false ) { - $.cancelEvent( event ); + $.cancelEvent( originalEvent ); } } if ( insideElementPressed && insideElementRelease ) { - handleMouseClick( tracker, event ); + handleMouseClick( tracker, originalEvent, isTouch ); } } @@ -1064,6 +1073,9 @@ propagate = tracker.scrollHandler( tracker, { + // Note: Ok to call getMouseRelative on passed event for isTouch==true since + // event.pageX/event.pageY are added to the original touchmove event in + // onTouchMove(). position: getMouseRelative( event, tracker.element ), scroll: nDelta, shift: event.shiftKey, @@ -1083,11 +1095,15 @@ * @private * @inner */ - function handleMouseClick( tracker, event ) { + function handleMouseClick( tracker, event, isTouch ) { var delegate = THIS[tracker.hash], propagate; - event = $.getEvent( event ); + isTouch = isTouch || false; + + var originalEvent = $.getEvent( event ); + + event = isTouch ? event.changedTouches[0] : event; if ( event.button == 2 ) { return; @@ -1105,14 +1121,14 @@ { position: getMouseRelative( event, tracker.element ), quick: quick, - shift: event.shiftKey, - isTouchEvent: false, - originalEvent: event, + shift: originalEvent.shiftKey, + isTouchEvent: isTouch, + originalEvent: originalEvent, userData: tracker.userData } ); if ( propagate === false ) { - $.cancelEvent( event ); + $.cancelEvent( originalEvent ); } } } @@ -1130,7 +1146,8 @@ isTouch = isTouch || false; - event = $.getEvent( event ); + var originalEvent = $.getEvent(event); + event = isTouch ? event.touches[0] : event; point = getMouseAbsolute( event ); delta = point.minus( delegate.lastPoint ); @@ -1142,14 +1159,14 @@ { position: getMouseRelative( event, tracker.element ), delta: delta, - shift: event.shiftKey, + shift: originalEvent.shiftKey, isTouchEvent: isTouch, - originalEvent: event, + originalEvent: originalEvent, userData: tracker.userData } ); if ( propagate === false ) { - $.cancelEvent( event ); + $.cancelEvent( originalEvent ); } } } From af078f8f1921179903c02aa1703467a7e8127fa6 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Tue, 10 Sep 2013 17:31:51 -0700 Subject: [PATCH 09/15] MouseTracker Original Events in Handlers Renamed insideElementRelease to insideElementReleased. --- src/button.js | 2 +- src/buttongroup.js | 2 +- src/mousetracker.js | 8 ++++---- src/referencestrip.js | 2 +- src/viewer.js | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/button.js b/src/button.js index 22db888b..f6aca329 100644 --- a/src/button.js +++ b/src/button.js @@ -207,7 +207,7 @@ $.Button = function( options ) { }, releaseHandler: function( tracker, eventData ) { - if ( eventData.insideElementPressed && eventData.insideElementRelease ) { + if ( eventData.insideElementPressed && eventData.insideElementReleased ) { outTo( _this, $.ButtonState.HOVER ); _this.raiseEvent( "onRelease", _this ); } else if ( eventData.insideElementPressed ) { diff --git a/src/buttongroup.js b/src/buttongroup.js index db133352..5adaf09e 100644 --- a/src/buttongroup.js +++ b/src/buttongroup.js @@ -101,7 +101,7 @@ $.ButtonGroup = function( options ) { }, releaseHandler: function ( tracker, eventData ) { var i; - if ( !eventData.insideElementRelease ) { + if ( !eventData.insideElementReleased ) { for ( i = 0; i < _this.buttons.length; i++ ) { _this.buttons[ i ].notifyGroupExit(); } diff --git a/src/mousetracker.js b/src/mousetracker.js index ace89018..6d46b002 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -280,7 +280,7 @@ * { * position: The position of the event relative to the tracked element. * insideElementPressed: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. - * insideElementRelease: Was the mouse still inside the tracked element when the button was released. + * insideElementReleased: Was the mouse still inside the tracked element when the button was released. * isTouchEvent: True if the original event is a touch event, otherwise false. * originalEvent: The original event object. * userData: Arbitrary user-defined object. @@ -881,7 +881,7 @@ //were we inside the tracked element when we were pressed insideElementPressed = delegate.insideElementPressed, //are we still inside the tracked element when we released - insideElementRelease = delegate.insideElement, + insideElementReleased = delegate.insideElement, propagate; isTouch = isTouch || false; @@ -902,7 +902,7 @@ { position: getMouseRelative( event, tracker.element ), insideElementPressed: insideElementPressed, - insideElementRelease: insideElementRelease, + insideElementReleased: insideElementReleased, isTouchEvent: isTouch, originalEvent: originalEvent, userData: tracker.userData @@ -913,7 +913,7 @@ } } - if ( insideElementPressed && insideElementRelease ) { + if ( insideElementPressed && insideElementReleased ) { handleMouseClick( tracker, originalEvent, isTouch ); } } diff --git a/src/referencestrip.js b/src/referencestrip.js index 94662764..47e7cf46 100644 --- a/src/referencestrip.js +++ b/src/referencestrip.js @@ -198,7 +198,7 @@ $.ReferenceStrip = function ( options ) { now = $.now(); if ( eventData.insideElementPressed && - eventData.insideElementRelease && + eventData.insideElementReleased && tracker.dragging && ( now - tracker.dragging ) < tracker.clickTimeThreshold ) { tracker.dragging = null; diff --git a/src/viewer.js b/src/viewer.js index c7995d9b..524e82f3 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -1479,7 +1479,7 @@ function onCanvasRelease( tracker, eventData ) { tracker: tracker, position: eventData.position, insideElementPressed: eventData.insideElementPressed, - insideElementRelease: eventData.insideElementRelease + insideElementReleased: eventData.insideElementReleased }); } @@ -1519,7 +1519,7 @@ function onContainerExit( tracker, eventData ) { } function onContainerRelease( tracker, eventData ) { - if ( !eventData.insideElementRelease ) { + if ( !eventData.insideElementReleased ) { THIS[ this.hash ].mouseInside = false; if ( !THIS[ this.hash ].animating ) { beginControlsAutoHide( this ); @@ -1529,7 +1529,7 @@ function onContainerRelease( tracker, eventData ) { tracker: tracker, position: eventData.position, insideElementPressed: eventData.insideElementPressed, - insideElementRelease: eventData.insideElementRelease + insideElementReleased: eventData.insideElementReleased }); } From 56ef12e850b77fbddd829c755a5c27c321438f82 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Thu, 12 Sep 2013 10:05:50 -0700 Subject: [PATCH 10/15] Original Events in Handlers Documentation fixes isTouchEvent property removed from eventData where not used 'eventOrTouchPoint' var name used and 'originalEvent' var name restored to 'event' --- src/eventhandler.js | 2 +- src/mousetracker.js | 247 ++++++++++++++++++++++++-------------------- 2 files changed, 137 insertions(+), 112 deletions(-) diff --git a/src/eventhandler.js b/src/eventhandler.js index 1595bd54..51fa54a1 100644 --- a/src/eventhandler.js +++ b/src/eventhandler.js @@ -55,7 +55,7 @@ $.EventHandler.prototype = { * @function * @param {String} eventName - Name of event to register. * @param {Function} handler - Function to call when event is triggered. - * @param {Object} optional userData - Arbitrary object to be passed unchanged to the handler. + * @param {Object} [userData=null] - Arbitrary object to be passed unchanged to the handler. */ addHandler: function ( eventName, handler, userData ) { var events = this.events[ eventName ]; diff --git a/src/mousetracker.js b/src/mousetracker.js index 6d46b002..886a800a 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -86,6 +86,8 @@ * An optional handler for focus. * @param {Function} options.blurHandler * An optional handler for blur. + * @param {Object} [options.userData=null] + * Arbitrary object to be passed unchanged to any attached handler methods. * @property {Number} hash * An unique hash for this tracker. * @property {Element} element @@ -96,8 +98,6 @@ * @property {Number} clickDistThreshold * The distance between mouse click within multiple mouse clicks * will be treated as a single event. - * @property {Object} optional userData - * Arbitrary object to be passed unchanged to any attached handler methods. */ $.MouseTracker = function ( options ) { @@ -225,14 +225,19 @@ * @param {OpenSeadragon.MouseTracker} tracker * A reference to the tracker instance. * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * insideElementPressed: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. - * buttonDownAny: Was the button down anywhere in the screen during the event. - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } + * @param {OpenSeadragon.Point} eventData.position + * The position of the event relative to the tracked element. + * @param {Boolean} eventData.insideElementPressed + * True if the left mouse button is currently being pressed and was + * initiated inside the tracked element, otherwise false. + * @param {Boolean} eventData.buttonDownAny + * Was the button down anywhere in the screen during the event. + * @param {Boolean} eventData.isTouchEvent + * True if the original event is a touch event, otherwise false. + * @param {Object} eventData.originalEvent + * The original event object. + * @param {Object} eventData.userData + * Arbitrary user-defined object. */ enterHandler: function () { }, @@ -243,14 +248,19 @@ * @param {OpenSeadragon.MouseTracker} tracker * A reference to the tracker instance. * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * insideElementPressed: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. - * buttonDownAny: Was the button down anywhere in the screen during the event. - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } + * @param {OpenSeadragon.Point} eventData.position + * The position of the event relative to the tracked element. + * @param {Boolean} eventData.insideElementPressed + * True if the left mouse button is currently being pressed and was + * initiated inside the tracked element, otherwise false. + * @param {Boolean} eventData.buttonDownAny + * Was the button down anywhere in the screen during the event. + * @param {Boolean} eventData.isTouchEvent + * True if the original event is a touch event, otherwise false. + * @param {Object} eventData.originalEvent + * The original event object. + * @param {Object} eventData.userData + * Arbitrary user-defined object. */ exitHandler: function () { }, @@ -261,12 +271,14 @@ * @param {OpenSeadragon.MouseTracker} tracker * A reference to the tracker instance. * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } + * @param {OpenSeadragon.Point} eventData.position + * The position of the event relative to the tracked element. + * @param {Boolean} eventData.isTouchEvent + * True if the original event is a touch event, otherwise false. + * @param {Object} eventData.originalEvent + * The original event object. + * @param {Object} eventData.userData + * Arbitrary user-defined object. */ pressHandler: function () { }, @@ -277,14 +289,19 @@ * @param {OpenSeadragon.MouseTracker} tracker * A reference to the tracker instance. * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * insideElementPressed: True if the left mouse button is currently being pressed and was initiated inside the tracked element, otherwise false. - * insideElementReleased: Was the mouse still inside the tracked element when the button was released. - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } + * @param {OpenSeadragon.Point} eventData.position + * The position of the event relative to the tracked element. + * @param {Boolean} eventData.insideElementPressed + * True if the left mouse button is currently being pressed and was + * initiated inside the tracked element, otherwise false. + * @param {Boolean} eventData.insideElementReleased + * True if the cursor still inside the tracked element when the button was released. + * @param {Boolean} eventData.isTouchEvent + * True if the original event is a touch event, otherwise false. + * @param {Object} eventData.originalEvent + * The original event object. + * @param {Object} eventData.userData + * Arbitrary user-defined object. */ releaseHandler: function () { }, @@ -295,12 +312,14 @@ * @param {OpenSeadragon.MouseTracker} tracker * A reference to the tracker instance. * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } + * @param {OpenSeadragon.Point} eventData.position + * The position of the event relative to the tracked element. + * @param {Boolean} eventData.isTouchEvent + * True if the original event is a touch event, otherwise false. + * @param {Object} eventData.originalEvent + * The original event object. + * @param {Object} eventData.userData + * Arbitrary user-defined object. */ moveHandler: function () { }, @@ -311,14 +330,18 @@ * @param {OpenSeadragon.MouseTracker} tracker * A reference to the tracker instance. * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * scroll: The scroll delta for the event. - * shift: Was the shift key being pressed during this event? - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } + * @param {OpenSeadragon.Point} eventData.position + * The position of the event relative to the tracked element. + * @param {Number} eventData.scroll + * The scroll delta for the event. + * @param {Boolean} eventData.shift + * True if the shift key was pressed during this event. + * @param {Boolean} eventData.isTouchEvent + * True if the original event is a touch event, otherwise false. + * @param {Object} eventData.originalEvent + * The original event object. + * @param {Object} eventData.userData + * Arbitrary user-defined object. */ scrollHandler: function () { }, @@ -329,14 +352,18 @@ * @param {OpenSeadragon.MouseTracker} tracker * A reference to the tracker instance. * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * quick: True only if the clickDistThreshold and clickDeltaThreshold are both pased. Useful for ignoring events. - * shift: Was the shift key being pressed during this event? - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } + * @param {OpenSeadragon.Point} eventData.position + * The position of the event relative to the tracked element. + * @param {Number} eventData.quick + * True only if the clickDistThreshold and clickDeltaThreshold are both pased. Useful for ignoring events. + * @param {Boolean} eventData.shift + * True if the shift key was pressed during this event. + * @param {Boolean} eventData.isTouchEvent + * True if the original event is a touch event, otherwise false. + * @param {Object} eventData.originalEvent + * The original event object. + * @param {Object} eventData.userData + * Arbitrary user-defined object. */ clickHandler: function () { }, @@ -347,14 +374,18 @@ * @param {OpenSeadragon.MouseTracker} tracker * A reference to the tracker instance. * @param {Object} eventData - * { - * position: The position of the event relative to the tracked element. - * delta: The x,y components of the difference between start drag and end drag. Usefule for ignoring or weighting the events. - * shift: Was the shift key being pressed during this event? - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } + * @param {OpenSeadragon.Point} eventData.position + * The position of the event relative to the tracked element. + * @param {OpenSeadragon.Point} eventData.delta + * The x,y components of the difference between start drag and end drag. Usefule for ignoring or weighting the events. + * @param {Boolean} eventData.shift + * True if the shift key was pressed during this event. + * @param {Boolean} eventData.isTouchEvent + * True if the original event is a touch event, otherwise false. + * @param {Object} eventData.originalEvent + * The original event object. + * @param {Object} eventData.userData + * Arbitrary user-defined object. */ dragHandler: function () { }, @@ -365,13 +396,14 @@ * @param {OpenSeadragon.MouseTracker} tracker * A reference to the tracker instance. * @param {Object} eventData - * { - * keyCode: The key code that was pressed. - * shift: Was the shift key being pressed during this event? - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } + * @param {Number} eventData.keyCode + * The key code that was pressed. + * @param {Boolean} eventData.shift + * True if the shift key was pressed during this event. + * @param {Object} eventData.originalEvent + * The original event object. + * @param {Object} eventData.userData + * Arbitrary user-defined object. */ keyHandler: function () { }, @@ -382,11 +414,10 @@ * @param {OpenSeadragon.MouseTracker} tracker * A reference to the tracker instance. * @param {Object} eventData - * { - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } + * @param {Object} eventData.originalEvent + * The original event object. + * @param {Object} eventData.userData + * Arbitrary user-defined object. */ focusHandler: function () { }, @@ -397,11 +428,10 @@ * @param {OpenSeadragon.MouseTracker} tracker * A reference to the tracker instance. * @param {Object} eventData - * { - * isTouchEvent: True if the original event is a touch event, otherwise false. - * originalEvent: The original event object. - * userData: Arbitrary user-defined object. - * } + * @param {Object} eventData.originalEvent + * The original event object. + * @param {Object} eventData.userData + * Arbitrary user-defined object. */ blurHandler: function () { } }; @@ -601,7 +631,6 @@ propagate = tracker.focusHandler( tracker, { - isTouchEvent: false, originalEvent: event, userData: tracker.userData } @@ -624,7 +653,6 @@ propagate = tracker.blurHandler( tracker, { - isTouchEvent: false, originalEvent: event, userData: tracker.userData } @@ -650,7 +678,6 @@ position: getMouseRelative( event, tracker.element ), keyCode: event.keyCode ? event.keyCode : event.charCode, shift: event.shiftKey, - isTouchEvent: false, originalEvent: event, userData: tracker.userData } @@ -785,9 +812,9 @@ isTouch = isTouch || false; - var originalEvent = $.getEvent(event); - - event = isTouch ? event.touches[ 0 ] : event; + event = $.getEvent(event); + + var eventOrTouchPoint = isTouch ? event.touches[ 0 ] : event; if ( event.button == 2 ) { return; @@ -795,7 +822,7 @@ delegate.insideElementPressed = true; - delegate.lastPoint = getMouseAbsolute( event ); + delegate.lastPoint = getMouseAbsolute( eventOrTouchPoint ); delegate.lastMouseDownPoint = delegate.lastPoint; delegate.lastMouseDownTime = $.now(); @@ -803,19 +830,19 @@ propagate = tracker.pressHandler( tracker, { - position: getMouseRelative( event, tracker.element ), + position: getMouseRelative( eventOrTouchPoint, tracker.element ), isTouchEvent: isTouch, - originalEvent: originalEvent, + originalEvent: event, userData: tracker.userData } ); if ( propagate === false ) { - $.cancelEvent( originalEvent ); + $.cancelEvent( event ); } } if ( tracker.pressHandler || tracker.dragHandler ) { - $.cancelEvent( originalEvent ); + $.cancelEvent( event ); } if ( noCapture ) { @@ -886,9 +913,7 @@ isTouch = isTouch || false; - var originalEvent = $.getEvent(event); - - event = isTouch ? event.changedTouches[ 0 ] : event; + event = $.getEvent(event); if ( event.button == 2 ) { return; @@ -900,21 +925,21 @@ propagate = tracker.releaseHandler( tracker, { - position: getMouseRelative( event, tracker.element ), + position: getMouseRelative( isTouch ? event.changedTouches[ 0 ] : event, tracker.element ), insideElementPressed: insideElementPressed, insideElementReleased: insideElementReleased, isTouchEvent: isTouch, - originalEvent: originalEvent, + originalEvent: event, userData: tracker.userData } ); if ( propagate === false ) { - $.cancelEvent( originalEvent ); + $.cancelEvent( event ); } } if ( insideElementPressed && insideElementReleased ) { - handleMouseClick( tracker, originalEvent, isTouch ); + handleMouseClick( tracker, event, isTouch ); } } @@ -1101,16 +1126,16 @@ isTouch = isTouch || false; - var originalEvent = $.getEvent( event ); + event = $.getEvent( event ); - event = isTouch ? event.changedTouches[0] : event; + var eventOrTouchPoint = isTouch ? event.changedTouches[0] : event; if ( event.button == 2 ) { return; } var time = $.now() - delegate.lastMouseDownTime, - point = getMouseAbsolute( event ), + point = getMouseAbsolute( eventOrTouchPoint ), distance = delegate.lastMouseDownPoint.distanceTo( point ), quick = time <= tracker.clickTimeThreshold && distance <= tracker.clickDistThreshold; @@ -1119,16 +1144,16 @@ propagate = tracker.clickHandler( tracker, { - position: getMouseRelative( event, tracker.element ), + position: getMouseRelative( eventOrTouchPoint, tracker.element ), quick: quick, - shift: originalEvent.shiftKey, + shift: event.shiftKey, isTouchEvent: isTouch, - originalEvent: originalEvent, + originalEvent: event, userData: tracker.userData } ); if ( propagate === false ) { - $.cancelEvent( originalEvent ); + $.cancelEvent( event ); } } } @@ -1146,9 +1171,9 @@ isTouch = isTouch || false; - var originalEvent = $.getEvent(event); - event = isTouch ? event.touches[0] : event; - point = getMouseAbsolute( event ); + event = $.getEvent(event); + var eventOrTouchPoint = isTouch ? event.touches[0] : event; + point = getMouseAbsolute( eventOrTouchPoint ); delta = point.minus( delegate.lastPoint ); delegate.lastPoint = point; @@ -1157,16 +1182,16 @@ propagate = tracker.dragHandler( tracker, { - position: getMouseRelative( event, tracker.element ), + position: getMouseRelative( eventOrTouchPoint, tracker.element ), delta: delta, - shift: originalEvent.shiftKey, + shift: event.shiftKey, isTouchEvent: isTouch, - originalEvent: originalEvent, + originalEvent: event, userData: tracker.userData } ); if ( propagate === false ) { - $.cancelEvent( originalEvent ); + $.cancelEvent( event ); } } } From 4adeacdc5e19bf18a0368f82f58aaa7ebff474cd Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 20 Sep 2013 09:17:48 -0700 Subject: [PATCH 11/15] MouseTracker Original Events in Handlers MouseTracker Unit Tests --- test/events.js | 125 ++++++++++++++++++++++++++++++++++++++++--------- test/test.js | 3 +- 2 files changed, 106 insertions(+), 22 deletions(-) diff --git a/test/events.js b/test/events.js index b2e71eb6..c7608711 100644 --- a/test/events.js +++ b/test/events.js @@ -61,19 +61,49 @@ } ); // ---------- - asyncTest( 'canvas-drag canvas-release canvas-click', function () { - var dragCount = 10, - dragMovesHandled = 0, - releasesHandled = 0, - releasesExpected = 1; + asyncTest( 'MouseTracker, EventHandler canvas-drag canvas-release canvas-click', function () { + var $canvas = $( viewer.element ).find( '.openseadragon-canvas' ).not( '.navigator .openseadragon-canvas' ), + mouseTracker = null, + userData = { item1: 'Test user data', item2: Math.random() }, + originalUserData = { item1: userData.item1, item2: userData.item2 }, + dragCount = 10, + dragsHandledEventHandler = 0, + releasesHandledEventHandler = 0, + clicksHandledEventHandler = 0, + eventsHandledMouseTracker = 0, + originalEventsPassedMouseTracker = 0, + releasesExpected = 1, + clicksExpected = 1; - var openHandler = function ( eventSender, eventData ) { - viewer.removeHandler( 'open', openHandler ); + var onOpen = function ( eventSender, eventData ) { + viewer.removeHandler( 'open', onOpen ); - viewer.addHandler( 'canvas-drag', canvasDragHandler ); - viewer.addHandler( 'canvas-release', canvasReleaseHandler ); - viewer.addHandler( 'canvas-click', canvasClickHandler ); + viewer.addHandler( 'canvas-drag', onEventHandlerDrag ); + viewer.addHandler( 'canvas-release', onEventHandlerRelease ); + viewer.addHandler( 'canvas-click', onEventHandlerClick ); + mouseTracker = new OpenSeadragon.MouseTracker( { + element: $canvas[0], + userData: userData, + clickTimeThreshold: OpenSeadragon.DEFAULT_SETTINGS.clickTimeThreshold, + clickDistThreshold: OpenSeadragon.DEFAULT_SETTINGS.clickDistThreshold, + focusHandler: onMouseTrackerFocus, + blurHandler: onMouseTrackerBlur, + enterHandler: onMouseTrackerEnter, + pressHandler: onMouseTrackerPress, + moveHandler: onMouseTrackerMove, + dragHandler: onMouseTrackerDrag, + releaseHandler: onMouseTrackerRelease, + clickHandler: onMouseTrackerClick, + exitHandler: onMouseTrackerExit + } ).setTracking( true ); + + var event = { + clientX:1, + clientY:1 + }; + + $canvas.simulate( 'focus', event ); Util.simulateViewerClickWithDrag( { viewer: viewer, widthFactor: 0.25, @@ -82,27 +112,80 @@ dragDx: 1, dragDy: 1 } ); + $canvas.simulate( 'blur', event ); }; - var canvasDragHandler = function ( eventSender, eventData ) { - dragMovesHandled++; + var onEventHandlerDrag = function ( eventSender, eventData ) { + dragsHandledEventHandler++; }; - var canvasReleaseHandler = function ( eventSender, eventData ) { - releasesHandled++; + var onEventHandlerRelease = function ( eventSender, eventData ) { + releasesHandledEventHandler++; }; - var canvasClickHandler = function ( eventSender, eventData ) { - viewer.removeHandler( 'canvas-drag', canvasDragHandler ); - viewer.removeHandler( 'canvas-release', canvasReleaseHandler ); - viewer.removeHandler( 'canvas-click', canvasClickHandler ); - equal( dragMovesHandled, dragCount, "'canvas-drag' event count matches 'mousemove' event count (" + dragCount + ")" ); - equal( releasesHandled, releasesExpected, "'canvas-release' event count matches expected (" + releasesExpected + ")" ); + var onEventHandlerClick = function ( eventSender, eventData ) { + clicksHandledEventHandler++; + }; + + var checkOriginalEventReceived = function ( eventData ) { + eventsHandledMouseTracker++; + if ( eventData && eventData.originalEvent ) { + originalEventsPassedMouseTracker++; + } + }; + + var onMouseTrackerFocus = function ( tracker, eventData ) { + checkOriginalEventReceived( eventData ); + }; + + var onMouseTrackerBlur = function ( tracker, eventData ) { + checkOriginalEventReceived( eventData ); + }; + + var onMouseTrackerEnter = function ( tracker, eventData ) { + checkOriginalEventReceived( eventData ); + }; + + var onMouseTrackerPress = function ( tracker, eventData ) { + checkOriginalEventReceived( eventData ); + }; + + var onMouseTrackerMove = function ( tracker, eventData ) { + checkOriginalEventReceived( eventData ); + }; + + var onMouseTrackerDrag = function ( tracker, eventData ) { + checkOriginalEventReceived( eventData ); + }; + + var onMouseTrackerRelease = function ( tracker, eventData ) { + checkOriginalEventReceived( eventData ); + }; + + var onMouseTrackerClick = function ( tracker, eventData ) { + checkOriginalEventReceived( eventData ); + }; + + var onMouseTrackerExit = function ( tracker, eventData ) { + checkOriginalEventReceived( eventData ); + + mouseTracker.destroy(); + viewer.removeHandler( 'canvas-drag', onEventHandlerDrag ); + viewer.removeHandler( 'canvas-release', onEventHandlerRelease ); + viewer.removeHandler( 'canvas-click', onEventHandlerClick ); + + equal( dragsHandledEventHandler, dragCount, "'canvas-drag' event count matches 'mousemove' event count (" + dragCount + ")" ); + equal( releasesHandledEventHandler, releasesExpected, "'canvas-release' event count matches expected (" + releasesExpected + ")" ); + equal( clicksHandledEventHandler, releasesExpected, "'canvas-click' event count matches expected (" + releasesExpected + ")" ); + + equal( originalEventsPassedMouseTracker, eventsHandledMouseTracker, "Original event received count matches expected (" + eventsHandledMouseTracker + ")" ); + deepEqual( eventData.userData, originalUserData, 'MouseTracker userData was untouched' ); + viewer.close(); start(); }; - viewer.addHandler( 'open', openHandler ); + viewer.addHandler( 'open', onOpen ); viewer.open( '/test/data/testpattern.dzi' ); } ); diff --git a/test/test.js b/test/test.js index def55713..2272ea9d 100644 --- a/test/test.js +++ b/test/test.js @@ -46,7 +46,8 @@ .simulate( "mousemove", event ); } $canvas - .simulate( 'mouseup', event ); + .simulate( 'mouseup', event ) + .simulate( 'mouseout', event ); }, initializeTestDOM: function () { From 47a911bb4ac1d03c6f28ab000507f85b49452daf Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 20 Sep 2013 09:38:01 -0700 Subject: [PATCH 12/15] MouseTracker Original Events in Handlers changelog.txt update --- changelog.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 42be4060..5a47088a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,13 @@ OPENSEADRAGON CHANGELOG ======================= -0.9.130: (In progress) +1.0.000: (In progress) + +* MouseTracker now passes the original event objects to its handler methods (#215) +* MouseTracker now supports a 'moveHandler' method for tracking mousemove events (#215) +* Breaking change: MouseTracker event handler method signatures changed to 'handlerMethod( tracker, eventData)' (#215) + +0.9.130: * Fixed: navigatorPosition option corrected. (#163) * OpenSeadragon.now() returned undefined the first time; fixed From c27481546aec35b36df0b54cefe3e131ec8b3571 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 20 Sep 2013 09:58:18 -0700 Subject: [PATCH 13/15] MouseTracker Original Events in Handlers Whitespace fixes on un-empty [] brackets --- src/mousetracker.js | 92 ++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/mousetracker.js b/src/mousetracker.js index 886a800a..5161c879 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -105,9 +105,9 @@ if ( !$.isPlainObject( options ) ) { options = { - element: args[0], - clickTimeThreshold: args[1], - clickDistThreshold: args[2] + element: args[ 0 ], + clickTimeThreshold: args[ 1 ], + clickDistThreshold: args[ 2 ] }; } @@ -150,7 +150,7 @@ * @property {OpenSeadragon.Point} lastMouseDownPoint * Position of last mouse down */ - THIS[this.hash] = { + THIS[ this.hash ] = { mouseover: function ( event ) { onMouseOver( _this, event, false ); }, mouseout: function ( event ) { onMouseOut( _this, event, false ); }, mousedown: function ( event ) { onMouseDown( _this, event ); }, @@ -199,7 +199,7 @@ * @returns {Boolean} Are we currently tracking events on this element. */ isTracking: function () { - return THIS[this.hash].tracking; + return THIS[ this.hash ].tracking; }, /** @@ -450,22 +450,22 @@ "keypress", "focus", "blur" ], - delegate = THIS[tracker.hash], + delegate = THIS[ tracker.hash ], event, i; if ( !delegate.tracking ) { for ( i = 0; i < events.length; i++ ) { - event = events[i]; + event = events[ i ]; $.addEvent( tracker.element, event, - delegate[event], + delegate[ event ], false ); } delegate.tracking = true; - ACTIVE[tracker.hash] = tracker; + ACTIVE[ tracker.hash ] = tracker; } } @@ -483,24 +483,24 @@ "keypress", "focus", "blur" ], - delegate = THIS[tracker.hash], + delegate = THIS[ tracker.hash ], event, i; if ( delegate.tracking ) { for ( i = 0; i < events.length; i++ ) { - event = events[i]; + event = events[ i ]; $.removeEvent( tracker.element, event, - delegate[event], + delegate[ event ], false ); } releaseMouse( tracker ); delegate.tracking = false; - delete ACTIVE[tracker.hash]; + delete ACTIVE[ tracker.hash ]; } } @@ -509,7 +509,7 @@ * @inner */ function hasMouse( tracker ) { - return THIS[tracker.hash].insideElement; + return THIS[ tracker.hash ].insideElement; } /** @@ -518,7 +518,7 @@ * @inner */ function captureMouse( tracker ) { - var delegate = THIS[tracker.hash]; + var delegate = THIS[ tracker.hash ]; if ( !delegate.capturing ) { if ( $.Browser.vendor == $.BROWSERS.IE && $.Browser.version < 9 ) { @@ -565,7 +565,7 @@ * @inner */ function releaseMouse( tracker ) { - var delegate = THIS[tracker.hash]; + var delegate = THIS[ tracker.hash ]; if ( delegate.capturing ) { if ( $.Browser.vendor == $.BROWSERS.IE && $.Browser.version < 9 ) { @@ -614,7 +614,7 @@ var otherHash; for ( otherHash in ACTIVE ) { if ( ACTIVE.hasOwnProperty( otherHash ) && tracker.hash != otherHash ) { - handler( ACTIVE[otherHash], event, isTouch ); + handler( ACTIVE[ otherHash ], event, isTouch ); } } } @@ -695,7 +695,7 @@ */ function onMouseOver( tracker, event, isTouch ) { - var delegate = THIS[tracker.hash], + var delegate = THIS[ tracker.hash ], propagate; isTouch = isTouch || false; @@ -750,7 +750,7 @@ * @inner */ function onMouseOut( tracker, event, isTouch ) { - var delegate = THIS[tracker.hash], + var delegate = THIS[ tracker.hash ], propagate; isTouch = isTouch || false; @@ -807,7 +807,7 @@ * @inner */ function onMouseDown( tracker, event, noCapture, isTouch ) { - var delegate = THIS[tracker.hash], + var delegate = THIS[ tracker.hash ], propagate; isTouch = isTouch || false; @@ -855,7 +855,7 @@ captureMouse( tracker ); IS_CAPTURING = true; // reset to empty & add us - CAPTURING = [tracker]; + CAPTURING = [ tracker ]; } else if ( $.Browser.vendor == $.BROWSERS.IE && $.Browser.version < 9 ) { // add us to the list CAPTURING.push( tracker ); @@ -874,7 +874,7 @@ event.targetTouches.length == 1 && event.changedTouches.length == 1 ) { - THIS[tracker.hash].lastTouch = event.touches[0]; + THIS[ tracker.hash ].lastTouch = event.touches[ 0 ]; onMouseOver( tracker, event, true ); // call with no capture as the onMouseMoveCaptured will // be triggered by onTouchMove @@ -883,12 +883,12 @@ if ( event.touches.length == 2 ) { - touchA = getMouseAbsolute( event.touches[0] ); - touchB = getMouseAbsolute( event.touches[1] ); - THIS[tracker.hash].lastPinchDelta = + touchA = getMouseAbsolute( event.touches[ 0 ] ); + touchB = getMouseAbsolute( event.touches[ 1 ] ); + THIS[ tracker.hash ].lastPinchDelta = Math.abs( touchA.x - touchB.x ) + Math.abs( touchA.y - touchB.y ); - THIS[tracker.hash].pinchMidpoint = new $.Point( + THIS[ tracker.hash ].pinchMidpoint = new $.Point( ( touchA.x + touchB.x ) / 2, ( touchA.y + touchB.y ) / 2 ); @@ -904,7 +904,7 @@ * @inner */ function onMouseUp( tracker, event, isTouch ) { - var delegate = THIS[tracker.hash], + var delegate = THIS[ tracker.hash ], //were we inside the tracked element when we were pressed insideElementPressed = delegate.insideElementPressed, //are we still inside the tracked element when we released @@ -954,7 +954,7 @@ event.targetTouches.length === 0 && event.changedTouches.length == 1 ) { - THIS[tracker.hash].lastTouch = null; + THIS[ tracker.hash ].lastTouch = null; // call with no release, as the mouse events are // not registered in onTouchStart @@ -962,8 +962,8 @@ onMouseOut( tracker, event, true ); } if ( event.touches.length + event.changedTouches.length == 2 ) { - THIS[tracker.hash].lastPinchDelta = null; - THIS[tracker.hash].pinchMidpoint = null; + THIS[ tracker.hash ].lastPinchDelta = null; + THIS[ tracker.hash ].pinchMidpoint = null; //$.console.debug("pinch end"); } event.preventDefault(); @@ -991,7 +991,7 @@ } for ( i = 0; i < CAPTURING.length; i++ ) { - othertracker = CAPTURING[i]; + othertracker = CAPTURING[ i ]; if ( !hasMouse( othertracker ) ) { onMouseUp( othertracker, event, false ); } @@ -1020,7 +1020,7 @@ function onMouseUpCaptured( tracker, event, noRelease, isTouch ) { isTouch = isTouch || false; - if ( !THIS[tracker.hash].insideElement ) { + if ( !THIS[ tracker.hash ].insideElement ) { onMouseUp( tracker, event, isTouch ); } @@ -1121,14 +1121,14 @@ * @inner */ function handleMouseClick( tracker, event, isTouch ) { - var delegate = THIS[tracker.hash], + var delegate = THIS[ tracker.hash ], propagate; isTouch = isTouch || false; event = $.getEvent( event ); - var eventOrTouchPoint = isTouch ? event.changedTouches[0] : event; + var eventOrTouchPoint = isTouch ? event.changedTouches[ 0 ] : event; if ( event.button == 2 ) { return; @@ -1164,7 +1164,7 @@ * @inner */ function onMouseMoveCaptured( tracker, event, isTouch ) { - var delegate = THIS[tracker.hash], + var delegate = THIS[ tracker.hash ], delta, propagate, point; @@ -1172,7 +1172,7 @@ isTouch = isTouch || false; event = $.getEvent(event); - var eventOrTouchPoint = isTouch ? event.touches[0] : event; + var eventOrTouchPoint = isTouch ? event.touches[ 0 ] : event; point = getMouseAbsolute( eventOrTouchPoint ); delta = point.minus( delegate.lastPoint ); @@ -1206,38 +1206,38 @@ touchB, pinchDelta; - if ( !THIS[tracker.hash].lastTouch ) { + if ( !THIS[ tracker.hash ].lastTouch ) { return; } if ( event.touches.length === 1 && event.targetTouches.length === 1 && event.changedTouches.length === 1 && - THIS[tracker.hash].lastTouch.identifier === event.touches[0].identifier ) { + THIS[ tracker.hash ].lastTouch.identifier === event.touches[ 0 ].identifier ) { onMouseMoveCaptured( tracker, event, true ); } else if ( event.touches.length === 2 ) { - touchA = getMouseAbsolute( event.touches[0] ); - touchB = getMouseAbsolute( event.touches[1] ); + touchA = getMouseAbsolute( event.touches[ 0 ] ); + touchB = getMouseAbsolute( event.touches[ 1 ] ); pinchDelta = Math.abs( touchA.x - touchB.x ) + Math.abs( touchA.y - touchB.y ); //TODO: make the 75px pinch threshold configurable - if ( Math.abs( THIS[tracker.hash].lastPinchDelta - pinchDelta ) > 75 ) { + if ( Math.abs( THIS[ tracker.hash ].lastPinchDelta - pinchDelta ) > 75 ) { //$.console.debug( "pinch delta : " + pinchDelta + " | previous : " + THIS[ tracker.hash ].lastPinchDelta); // Adjust the original event enough to simulate a mouse wheel scroll event.shiftKey = event.shiftKey || false; - event.pageX = THIS[tracker.hash].pinchMidpoint.x; - event.pageY = THIS[tracker.hash].pinchMidpoint.y; - event.detail = ( THIS[tracker.hash].lastPinchDelta > pinchDelta ) ? 1 : -1; + event.pageX = THIS[ tracker.hash ].pinchMidpoint.x; + event.pageY = THIS[ tracker.hash ].pinchMidpoint.y; + event.detail = ( THIS[ tracker.hash ].lastPinchDelta > pinchDelta ) ? 1 : -1; onMouseWheelSpin( tracker, event, true ); - THIS[tracker.hash].lastPinchDelta = pinchDelta; + THIS[ tracker.hash ].lastPinchDelta = pinchDelta; } } event.preventDefault(); @@ -1255,7 +1255,7 @@ function onMouseMoveCapturedIE( tracker, event ) { var i; for ( i = 0; i < CAPTURING.length; i++ ) { - onMouseMoveCaptured( CAPTURING[i], event, false ); + onMouseMoveCaptured( CAPTURING[ i ], event, false ); } $.stopEvent( event ); From 93159aaf5184bcc8b8043631afda5579b7bca6a9 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 20 Sep 2013 10:05:01 -0700 Subject: [PATCH 14/15] MouseTracker Original EVents in Handlers changelog.txt fixed issue reference numbers (#23) (#215) --- changelog.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 5a47088a..8e567ff6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,9 +3,9 @@ OPENSEADRAGON CHANGELOG 1.0.000: (In progress) -* MouseTracker now passes the original event objects to its handler methods (#215) +* MouseTracker now passes the original event objects to its handler methods (#23) +* Breaking change: MouseTracker event handler method signatures changed to 'handlerMethod( tracker, eventData)' (#23) * MouseTracker now supports a 'moveHandler' method for tracking mousemove events (#215) -* Breaking change: MouseTracker event handler method signatures changed to 'handlerMethod( tracker, eventData)' (#215) 0.9.130: From 5335048c64dd2e13d575a149f662aea418b4af55 Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Fri, 20 Sep 2013 10:23:22 -0700 Subject: [PATCH 15/15] changelog.txt update for fixed issue #131 --- changelog.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 8e567ff6..b84279a6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -5,7 +5,8 @@ OPENSEADRAGON CHANGELOG * MouseTracker now passes the original event objects to its handler methods (#23) * Breaking change: MouseTracker event handler method signatures changed to 'handlerMethod( tracker, eventData)' (#23) -* MouseTracker now supports a 'moveHandler' method for tracking mousemove events (#215) +* MouseTracker now supports an optional 'moveHandler' method for tracking mousemove events (#215) +* Fixed: Element-relative mouse coordinates now correct if the element and/or page is scrolled (using new OpenSeadragon.getElementOffset() method) (#131) 0.9.130: