Skip to content

Instantly share code, notes, and snippets.

@sullenfish
Created January 20, 2009 07:05
Show Gist options
  • Save sullenfish/49373 to your computer and use it in GitHub Desktop.
Save sullenfish/49373 to your computer and use it in GitHub Desktop.
/**
* 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