Created
January 20, 2009 07:05
-
-
Save sullenfish/49373 to your computer and use it in GitHub Desktop.
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
/** | |
* MooWrangler - simple MooTools-powered image scaling and cropping. | |
* @classDescription creates a new MooWrangler object | |
* @return {Class} returns a MooTools Class Object | |
* @author Frederick J. Ostrander | |
* @version 0.3 | |
*/ | |
var MooWrangler = new Class({ | |
version: '0.3', | |
Implements: [Options], | |
//Binds: ['finalize'], // Binds not working properly in MooTools 1.2.1 | |
options: { | |
width: { | |
min: 0, | |
max: Infinity, | |
position: 'center' | |
}, | |
height: { | |
min: 0, | |
max: Infinity, | |
position: 'middle' | |
}, | |
debug: false, | |
createWrapper: false, | |
wrapper: null | |
}, | |
initialize: function(element, options){ | |
this.element = $(element); | |
this.setOptions(options); | |
this.isDetached = !$defined(this.element.getParent('body')); | |
if (this.options.width.max == Infinity || this.options.height.max == Infinity) { | |
var parentElement = this.isDetached ? window : this.element.getParent(); | |
var parentSize = { | |
x: parentElement.clientWidth, | |
y: parentElement.clientHeight | |
}; | |
this.setOptions($merge({ | |
height: { | |
max: parentSize.y | |
}, | |
width: { | |
max: parentSize.x | |
} | |
}, options)); | |
} | |
this.debug = this.options.debug; | |
this.originalStyles = this.element.getStyles('position','visibility','display'); | |
// if this.element is not visible, prepare to expose it in the dom | |
if (this.isDetached || this.originalStyle.display == 'none') { | |
this.element.setStyles({ | |
'visibility': 'hidden', | |
'position': 'absolute', | |
'display': 'block' | |
}); | |
} | |
// if this.element is not in the body of the DOM, drop it in to measure it | |
if (this.isDetached){ | |
this.element.inject(document.body); | |
} | |
// wait for image to load | |
if (this.element.get('tag') == 'img' && !this.element.complete) | |
this.element.addEvent('load', (function(){ | |
this.finalize(); | |
}).bind(this)); | |
else | |
this.finalize(); | |
}, | |
finalize: function(){ | |
// set up scale ratios | |
var size = this.element.getSize(); | |
var length = size.y; | |
var width = size.x; | |
var minLength = this.options.height.min; | |
var minWidth = this.options.width.min; | |
var maxLength = this.options.height.max; | |
var maxWidth = this.options.width.max; | |
var minScaleRatio = ((length/width)<(minLength/minWidth)) ? minLength/length : minWidth/width; | |
var maxScaleRatio = ((length/width)<(maxLength/maxWidth)) ? maxWidth/width : maxLength/length; | |
var scaleRatio = (minScaleRatio <= maxScaleRatio) ? maxScaleRatio : minScaleRatio; | |
if (this.debug) alert('minsr: ' + minScaleRatio + '\nmaxsr: ' + maxScaleRatio + '\nsr: ' + scaleRatio); | |
// scale the element and set styles and properties accordingly | |
this.length = ((length * scaleRatio).round()); //.limit(this.options.height.min, this.options.height.max); | |
this.width = ((width * scaleRatio).round()); //.limit(this.options.width.min, this.options.width.max); | |
var yOffset = ((this.length - this.options.height.max)/2).round().limit(-Infinity, Infinity); | |
var xOffset = ((this.width - this.options.width.max)/2).round().limit(-Infinity, Infinity); | |
function calculateClip(position, offset) { | |
switch (position) { | |
case 'top': | |
case 'left': | |
return 0; | |
break; | |
case 'bottom': | |
case 'right': | |
return 2 * offset; | |
break; | |
case 'middle': | |
case 'center': | |
default: | |
return offset; | |
break; | |
} | |
} | |
var clipTop = calculateClip.run([this.options.height.position, yOffset], this); | |
var clipLeft = calculateClip.run([this.options.width.position, xOffset], this); | |
var clipBottom = clipTop + this.options.height.max; | |
var clipRight = clipLeft + this.options.width.max; | |
this.clip = 'rect(' + clipTop + 'px ' + clipRight + 'px ' + clipBottom + 'px ' + clipLeft + 'px)'; | |
if (this.debug) alert('length: ' + this.length + '\nwidth: ' + this.width + '\nyOffset: ' + yOffset + '\nxOffset: ' + xOffset + '\nclip: ' + this.clip); | |
this.element.set({ | |
height: this.length.limit(this.options.height.min, this.options.height.max), | |
width: this.width.limit(this.options.width.min, this.options.width.max), | |
styles: { | |
// position: 'absolute', | |
height: this.length + 'px', | |
width: this.width + 'px', | |
top: -clipTop + 'px', | |
left: -clipLeft + 'px', | |
clip: this.clip, | |
overflow: 'hidden' | |
} | |
}); | |
if (this.debug) alert('style: ' + this.element.getStyle('clip')); | |
// clean up | |
if (this.isDetached) this.element.dispose(); | |
this.element.setStyles(this.originalStyles); | |
}, | |
toElement: function(){ | |
return this.element; | |
} | |
}); | |
Element.implement({ | |
mooWrangle: function(options){ | |
return new MooWrangler(this, options); | |
} | |
}); | |
Element.implement({ | |
wrangle: function(options){ | |
return this.mooWrangle(options); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment