-
-
Save triptych/946055 to your computer and use it in GitHub Desktop.
draggable-background.js YUI widget
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Draggable Background Widget | |
* | |
* A widget that will use a specified image and dimensions to | |
* produce a draggable, window-like view of an image. | |
* | |
* Example usage: | |
* | |
* YUI.use('widget-draggable-background', function(Y) { | |
* var widget = new Y.WD.Widget.DraggableBackground({ | |
* boundingBox: '#foo' | |
* imageUrl: 'http://someimagepath.com/image.png', | |
* viewWidth: 400, | |
* viewHeight: 400 | |
* }); | |
* | |
* widget.render(); | |
* }); | |
* | |
*/ | |
YUI.add('widget-draggable-background', function(Y) { | |
// Keep these around for convenience. | |
var L = Y.Lang; | |
/** | |
* DraggableBackground constructor | |
* | |
* @extends Widget | |
* @constructor | |
* @param {object} config | |
*/ | |
function DraggableBackground(config) { | |
DraggableBackground.superclass.constructor.apply(this, arguments); | |
} | |
/** | |
* YUI Widget Meta (see http://yhoo.it/4raYhI) | |
*/ | |
DraggableBackground.NAME = 'draggable-background'; | |
/** | |
* Magic ATTRS! | |
*/ | |
DraggableBackground.ATTRS = { | |
/** | |
* @attribute imageUrl | |
* @description URL of the background image. | |
*/ | |
imageUrl: { | |
value: '', | |
validator: L.isValue | |
}, | |
/** | |
* @attribute view width | |
* @description The width of `node` element that the background image is | |
* applied to. | |
*/ | |
viewWidth: { | |
value: 400, | |
validator: L.isNumber | |
}, | |
/** | |
* @attribute viewHeight | |
* @description The height of `node` element that the background image is | |
* applied to. | |
*/ | |
viewHeight: { | |
value: 400, | |
validator: L.isNumber | |
}, | |
/** | |
* @attribute lastPosition | |
* @description The last x and y position offsets for the background image. | |
*/ | |
lastPosition: { | |
value: [0,0], | |
validator: L.isArray | |
}, | |
/** | |
* @attribute isDragging | |
* @description Denotes that a drag is in progress. | |
*/ | |
isDragging: { | |
value: false, | |
validator: L.isBoolean | |
}, | |
/** | |
* @attribute image | |
* @description An `Image` object reference of the background image. | |
* Use this to obtain image width and height and then to | |
* prevent the user from positioning the image outside of | |
* its bounds. | |
*/ | |
image: { | |
value: null | |
} | |
}; | |
var isDragging = false; | |
/** | |
* DraggableBackground extends Widget | |
*/ | |
Y.extend(DraggableBackground, Y.Widget, { | |
initializer: function(config) { | |
Y.log(this.get('contentBox')); | |
Y.log(this.get('imageUrl')); | |
Y.log(this.get('viewWidth')); | |
Y.log(this.get('viewHeight')); | |
// setup our internal image | |
var image = new Image(); | |
image.src = this.get('imageUrl'); | |
this.set('image', image); | |
}, | |
destructor: function() { | |
// detach all events here | |
Y.detach('mousedown', this._onMouseDown); | |
Y.detach('mousemove', this._onMouseMove); | |
Y.detach('mouseup', this._onMouseUp); | |
Y.detach('mouseout', this._onMouseOut); | |
}, | |
renderUI: function() { | |
var node = Y.one(this.get('contentBox')); | |
// set the background of the `node` to `imageUrl` and make sure other repeat/position | |
// styles are correctly initialized. | |
node.setStyle('backgroundImage', ['url(', this.get('imageUrl'), ')'].join('')); | |
node.setStyle('backgroundRepeat', 'no-repeat'); | |
node.setStyle('backgroundPositionX', '0'); | |
node.setStyle('backgroundPositionY', '0'); | |
// set the cursor to move to indicate dragging | |
node.setStyle('cursor', 'move'); | |
// set the dimensions of the element | |
node.setStyle('width', this.get('viewWidth')); | |
node.setStyle('height', this.get('viewHeight')); | |
}, | |
bindUI: function() { | |
// ATTR Change events | |
this.after('viewWidthChange', this._afterViewWidthChange); | |
this.after('viewHeightChange', this._afterViewHeightChange); | |
// delegate mouse events over `node` | |
var node = Y.one(this.get('contentBox')); | |
node.on('mousedown', this._onMouseDown, null, this); | |
node.on('mousemove', this._onMouseMove, null, this); | |
node.on('mouseup', this._onMouseUp, null, this); | |
node.on('mouseout', this._onMouseOut, null, this); | |
}, | |
syncUI: function() { | |
}, | |
/** | |
* Turns dragging on and set current position so that the image doesn't jump | |
* around when a new drag is instantiated. | |
* | |
* @method _onMouseDown | |
* @param e {Event} Event for the mouse down. | |
* @param scope {DraggableBackground} Scope on which to apply this event. | |
* @private | |
*/ | |
_onMouseDown: function(e, scope) { | |
e.preventDefault(); | |
// reset last position to where the user just clicked | |
var currentPosition = [e.pageX, e.pageY]; | |
scope.set('lastPosition', currentPosition); | |
// start the dragging | |
scope.set('isDragging', true); | |
}, | |
/** | |
* Performs a calculation to determine how much to adjust the backround image position | |
* then calls the adjustment method with those deltas. | |
* | |
* @method _onMouseMove | |
* @param e {Event} Event for the mouse down. | |
* @param scope {DraggableBackground} Scope on which to apply this event. | |
* @private | |
*/ | |
_onMouseMove: function(e, scope) { | |
e.preventDefault(); | |
if(scope.get('isDragging')) { | |
var lastPosition = scope.get('lastPosition'); | |
var currentPosition = [e.pageX, e.pageY]; | |
var diffx = lastPosition[0] - currentPosition[0]; | |
var diffy = lastPosition[1] - currentPosition[1]; | |
scope._adjustImagePosition(diffx, diffy); | |
scope.set('lastPosition', currentPosition); | |
} | |
}, | |
/** | |
* Turns dragging off. | |
* | |
* @method _onMouseUp | |
* @param e {Event} Event for the mouse down. | |
* @param scope {DraggableBackground} Scope on which to apply this event. | |
* @private | |
*/ | |
_onMouseUp: function(e, scope) { | |
e.preventDefault(); | |
scope.set('isDragging', false); | |
}, | |
/** | |
* Also turns dragging off. | |
* | |
* @method _onMouseOut | |
* @param e {Event} Event for the mouse down. | |
* @param scope {DraggableBackground} Scope on which to apply this event. | |
* @private | |
*/ | |
_onMouseOut: function(e, scope) { | |
e.preventDefault(); | |
scope.set('isDragging', false); | |
}, | |
/** | |
* Called after the `viewWidth` ATTR has changed to update the UI. | |
* | |
* @method _afterViewWidthChange | |
* @param e {Event} Event for the mouse down. | |
* @private | |
*/ | |
_afterViewWidthChange: function(e) { | |
this._uiSetViewWidth(this.get('viewWidth')); | |
}, | |
/** | |
* Called after the `viewHeight` ATTR has changed to update the UI. | |
* | |
* @method _afterViewHeightChange | |
* @param e {Event} Event for the mouse down. | |
* @private | |
*/ | |
_afterViewHeightChange: function(e) { | |
this._uiSetViewHeight(this.get('viewHeight')); | |
}, | |
/** | |
* Propagates the `viewWidth` ATTR to the UI. | |
* | |
* @method _uiSetViewWidth | |
* @param e {int} new width in pixels. | |
* @private | |
*/ | |
_uiSetViewWidth: function(val) { | |
Y.one(this.get('contentBox')).setStyle('width', val); | |
}, | |
/** | |
* Propagates the `viewHeight` ATTR to the UI. | |
* | |
* @method _uiSetViewHeight | |
* @param e {int} new height in pixels. | |
* @private | |
*/ | |
_uiSetViewHeight: function(val) { | |
Y.one(this.get('contentBox')).setStyle('height', val); | |
}, | |
/** | |
* Applies the background image position adjustment. | |
* | |
* @method _adjustImagePosition | |
* @param diffx {int} background-position-x delta. | |
* @param diffy {int} background-position-y delta. | |
* @private | |
*/ | |
_adjustImagePosition: function(diffX, diffY) { | |
var node = Y.one(this.get('contentBox')); | |
var image = this.get('image'); | |
// parse out current position elements | |
var xy = node.getStyle('backgroundPosition').replace(/%/g, '').replace('px', '').split(' '); | |
// individual position components | |
var currX = parseInt(xy[0]); | |
var currY = parseInt(xy[1]); | |
// calculate new position | |
var newX = currX - diffX; | |
var newY = currY - diffY; | |
Y.log('new position: ' + newX + 'px ' + newY + 'px'); | |
// make sure not to scale past image boundaries before adjusting | |
if(!(newX <= 0 && newX >= -(image.width - this.get('viewWidth')))) { | |
newX = currX; | |
} | |
if(!(newY <= 0 && newY >= -(image.height - this.get('viewHeight')))) { | |
newY = currY; | |
} | |
node.setStyle('backgroundPosition', newX + 'px ' + newY + 'px'); | |
} | |
}); | |
// Hang it off of Y.WD.Widget | |
Y.namespace('WD.Widget').DraggableBackground = DraggableBackground; | |
}, '0.0.1', { | |
requires: [ | |
'node', | |
'widget', | |
'console' | |
] | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment