?? cropper.uncompressed.js
字號:
* Whether we've attached sucessfully
*/
this.attached = false;
/**
* @var boolean
* Whether we've got a fixed width (if minWidth EQ or GT maxWidth then we have a fixed width
* in the case of minWidth > maxWidth maxWidth wins as the fixed width)
*/
this.fixedWidth = ( this.options.maxWidth > 0 && ( this.options.minWidth >= this.options.maxWidth ) );
/**
* @var boolean
* Whether we've got a fixed height (if minHeight EQ or GT maxHeight then we have a fixed height
* in the case of minHeight > maxHeight maxHeight wins as the fixed height)
*/
this.fixedHeight = ( this.options.maxHeight > 0 && ( this.options.minHeight >= this.options.maxHeight ) );
// quit if the image element doesn't exist
if( typeof this.img == 'undefined' ) return;
// include the stylesheet
$A( document.getElementsByTagName( 'script' ) ).each(
function(s) {
if( s.src.match( /cropper\.js/ ) ) {
var path = s.src.replace( /cropper\.js(.*)?/, '' );
// '<link rel="stylesheet" type="text/css" href="' + path + 'cropper.css" media="screen" />';
var style = document.createElement( 'link' );
style.rel = 'stylesheet';
style.type = 'text/css';
style.href = path + 'cropper.css';
style.media = 'screen';
document.getElementsByTagName( 'head' )[0].appendChild( style );
}
}
);
// calculate the ratio when neccessary
if( this.options.ratioDim.x > 0 && this.options.ratioDim.y > 0 ) {
var gcd = this.getGCD( this.options.ratioDim.x, this.options.ratioDim.y );
this.ratioX = this.options.ratioDim.x / gcd;
this.ratioY = this.options.ratioDim.y / gcd;
// dump( 'RATIO : ' + this.ratioX + ':' + this.ratioY + '\n' );
}
// initialise sub classes
this.subInitialize();
// only load the event observers etc. once the image is loaded
// this is done after the subInitialize() call just in case the sub class does anything
// that will affect the result of the call to onLoad()
if( this.img.complete || this.isWebKit ) this.onLoad(); // for some reason Safari seems to support img.complete but returns 'undefined' on the this.img object
else Event.observe( this.img, 'load', this.onLoad.bindAsEventListener( this) );
},
/**
* The Euclidean algorithm used to find the greatest common divisor
*
* @acces private
* @param int Value 1
* @param int Value 2
* @return int
*/
getGCD : function( a , b ) {
if( b == 0 ) return a;
return this.getGCD(b, a % b );
},
/**
* Attaches the cropper to the image once it has loaded
*
* @access private
* @return void
*/
onLoad: function( ) {
/*
* Build the container and all related elements, will result in the following
*
* <div class="imgCrop_wrap">
* <img ... this.img ... />
* <div class="imgCrop_dragArea">
* <!-- the inner spans are only required for IE to stop it making the divs 1px high/wide -->
* <div class="imgCrop_overlay imageCrop_north"><span></span></div>
* <div class="imgCrop_overlay imageCrop_east"><span></span></div>
* <div class="imgCrop_overlay imageCrop_south"><span></span></div>
* <div class="imgCrop_overlay imageCrop_west"><span></span></div>
* <div class="imgCrop_selArea">
* <!-- marquees -->
* <!-- the inner spans are only required for IE to stop it making the divs 1px high/wide -->
* <div class="imgCrop_marqueeHoriz imgCrop_marqueeNorth"><span></span></div>
* <div class="imgCrop_marqueeVert imgCrop_marqueeEast"><span></span></div>
* <div class="imgCrop_marqueeHoriz imgCrop_marqueeSouth"><span></span></div>
* <div class="imgCrop_marqueeVert imgCrop_marqueeWest"><span></span></div>
* <!-- handles -->
* <div class="imgCrop_handle imgCrop_handleN"></div>
* <div class="imgCrop_handle imgCrop_handleNE"></div>
* <div class="imgCrop_handle imgCrop_handleE"></div>
* <div class="imgCrop_handle imgCrop_handleSE"></div>
* <div class="imgCrop_handle imgCrop_handleS"></div>
* <div class="imgCrop_handle imgCrop_handleSW"></div>
* <div class="imgCrop_handle imgCrop_handleW"></div>
* <div class="imgCrop_handle imgCrop_handleNW"></div>
* <div class="imgCrop_clickArea"></div>
* </div>
* <div class="imgCrop_clickArea"></div>
* </div>
* </div>
*/
var cNamePrefix = 'imgCrop_';
// get the point to insert the container
var insertPoint = this.img.parentNode;
// apply an extra class to the wrapper to fix Opera below version 9
var fixOperaClass = '';
if( this.isOpera8 ) fixOperaClass = ' opera8';
this.imgWrap = Builder.node( 'div', { 'class': cNamePrefix + 'wrap' + fixOperaClass } );
this.north = Builder.node( 'div', { 'class': cNamePrefix + 'overlay ' + cNamePrefix + 'north' }, [Builder.node( 'span' )] );
this.east = Builder.node( 'div', { 'class': cNamePrefix + 'overlay ' + cNamePrefix + 'east' } , [Builder.node( 'span' )] );
this.south = Builder.node( 'div', { 'class': cNamePrefix + 'overlay ' + cNamePrefix + 'south' }, [Builder.node( 'span' )] );
this.west = Builder.node( 'div', { 'class': cNamePrefix + 'overlay ' + cNamePrefix + 'west' } , [Builder.node( 'span' )] );
var overlays = [ this.north, this.east, this.south, this.west ];
this.dragArea = Builder.node( 'div', { 'class': cNamePrefix + 'dragArea' }, overlays );
this.handleN = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleN' } );
this.handleNE = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleNE' } );
this.handleE = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleE' } );
this.handleSE = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleSE' } );
this.handleS = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleS' } );
this.handleSW = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleSW' } );
this.handleW = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleW' } );
this.handleNW = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleNW' } );
this.selArea = Builder.node( 'div', { 'class': cNamePrefix + 'selArea' },
[
Builder.node( 'div', { 'class': cNamePrefix + 'marqueeHoriz ' + cNamePrefix + 'marqueeNorth' }, [Builder.node( 'span' )] ),
Builder.node( 'div', { 'class': cNamePrefix + 'marqueeVert ' + cNamePrefix + 'marqueeEast' } , [Builder.node( 'span' )] ),
Builder.node( 'div', { 'class': cNamePrefix + 'marqueeHoriz ' + cNamePrefix + 'marqueeSouth' }, [Builder.node( 'span' )] ),
Builder.node( 'div', { 'class': cNamePrefix + 'marqueeVert ' + cNamePrefix + 'marqueeWest' } , [Builder.node( 'span' )] ),
this.handleN,
this.handleNE,
this.handleE,
this.handleSE,
this.handleS,
this.handleSW,
this.handleW,
this.handleNW,
Builder.node( 'div', { 'class': cNamePrefix + 'clickArea' } )
]
);
this.imgWrap.appendChild( this.img );
this.imgWrap.appendChild( this.dragArea );
this.dragArea.appendChild( this.selArea );
this.dragArea.appendChild( Builder.node( 'div', { 'class': cNamePrefix + 'clickArea' } ) );
insertPoint.appendChild( this.imgWrap );
// add event observers
this.startDragBind = this.startDrag.bindAsEventListener( this );
Event.observe( this.dragArea, 'mousedown', this.startDragBind );
this.onDragBind = this.onDrag.bindAsEventListener( this );
Event.observe( document, 'mousemove', this.onDragBind );
this.endCropBind = this.endCrop.bindAsEventListener( this );
Event.observe( document, 'mouseup', this.endCropBind );
this.resizeBind = this.startResize.bindAsEventListener( this );
this.handles = [ this.handleN, this.handleNE, this.handleE, this.handleSE, this.handleS, this.handleSW, this.handleW, this.handleNW ];
this.registerHandles( true );
if( this.options.captureKeys ) {
this.keysBind = this.handleKeys.bindAsEventListener( this );
Event.observe( document, 'keypress', this.keysBind );
}
// attach the dragable to the select area
new CropDraggable( this.selArea, { drawMethod: this.moveArea.bindAsEventListener( this ) } );
this.setParams();
},
/**
* Manages adding or removing the handle event handler and hiding or displaying them as appropriate
*
* @access private
* @param boolean registration true = add, false = remove
* @return void
*/
registerHandles: function( registration ) {
for( var i = 0; i < this.handles.length; i++ ) {
var handle = $( this.handles[i] );
if( registration ) {
var hideHandle = false; // whether to hide the handle
// disable handles asappropriate if we've got fixed dimensions
// if both dimensions are fixed we don't need to do much
if( this.fixedWidth && this.fixedHeight ) hideHandle = true;
else if( this.fixedWidth || this.fixedHeight ) {
// if one of the dimensions is fixed then just hide those handles
var isCornerHandle = handle.className.match( /([S|N][E|W])$/ )
var isWidthHandle = handle.className.match( /(E|W)$/ );
var isHeightHandle = handle.className.match( /(N|S)$/ );
if( isCornerHandle ) hideHandle = true;
else if( this.fixedWidth && isWidthHandle ) hideHandle = true;
else if( this.fixedHeight && isHeightHandle ) hideHandle = true;
}
if( hideHandle ) handle.hide();
else Event.observe( handle, 'mousedown', this.resizeBind );
} else {
handle.show();
Event.stopObserving( handle, 'mousedown', this.resizeBind );
}
}
},
/**
* Sets up all the cropper parameters, this can be used to reset the cropper when dynamically
* changing the images
*
* @access private
* @return void
*/
setParams: function() {
/**
* @var int
* The image width
*/
this.imgW = this.img.width;
/**
* @var int
* The image height
*/
this.imgH = this.img.height;
$( this.north ).setStyle( { height: 0 } );
$( this.east ).setStyle( { width: 0, height: 0 } );
$( this.south ).setStyle( { height: 0 } );
$( this.west ).setStyle( { width: 0, height: 0 } );
// resize the container to fit the image
$( this.imgWrap ).setStyle( { 'width': this.imgW + 'px', 'height': this.imgH + 'px' } );
// hide the select area
$( this.selArea ).hide();
// setup the starting position of the select area
var startCoords = { x1: 0, y1: 0, x2: 0, y2: 0 };
var validCoordsSet = false;
// display the select area
if( this.options.onloadCoords != null ) {
// if we've being given some coordinates to
startCoords = this.cloneCoords( this.options.onloadCoords );
validCoordsSet = true;
} else if( this.options.ratioDim.x > 0 && this.options.ratioDim.y > 0 ) {
// if there is a ratio limit applied and the then set it to initial ratio
startCoords.x1 = Math.ceil( ( this.imgW - this.options.ratioDim.x ) / 2 );
startCoords.y1 = Math.ceil( ( this.imgH - this.options.ratioDim.y ) / 2 );
startCoords.x2 = startCoords.x1 + this.options.ratioDim.x;
startCoords.y2 = startCoords.y1 + this.options.ratioDim.y;
validCoordsSet = true;
}
this.setAreaCoords( startCoords, false, false, 1 );
if( this.options.displayOnInit && validCoordsSet ) {
this.selArea.show();
this.drawArea();
this.endCrop();
}
this.attached = true;
},
/**
* Removes the cropper
*
* @access public
* @return void
*/
remove: function() {
if( this.attached ) {
this.attached = false;
// remove the elements we inserted
this.imgWrap.parentNode.insertBefore( this.img, this.imgWrap );
this.imgWrap.parentNode.removeChild( this.imgWrap );
// remove the event observers
Event.stopObserving( this.dragArea, 'mousedown', this.startDragBind );
Event.stopObserving( document, 'mousemove', this.onDragBind );
Event.stopObserving( document, 'mouseup', this.endCropBind );
this.registerHandles( false );
if( this.options.captureKeys ) Event.stopObserving( document, 'keypress', this.keysBind );
}
},
/**
* Resets the cropper, can be used either after being removed or any time you wish
*
* @access public
* @return void
*/
reset: function() {
if( !this.attached ) this.onLoad();
else this.setParams();
this.endCrop();
},
/**
* Handles the key functionality, currently just using arrow keys to move, if the user
* presses shift then the area will move by 10 pixels
*/
handleKeys: function( e ) {
var dir = { x: 0, y: 0 }; // direction to move it in & the amount in pixels
if( !this.dragging ) {
// catch the arrow keys
switch( e.keyCode ) {
case( 37 ) : // left
dir.x = -1;
break;
case( 38 ) : // up
dir.y = -1;
break;
case( 39 ) : // right
dir.x = 1;
break
case( 40 ) : // down
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -