From ad6c29890dc6c3c62fa499c4198b01a06398668c Mon Sep 17 00:00:00 2001 From: Mark-Hetherington Date: Tue, 23 Apr 2013 12:20:09 +1000 Subject: [PATCH 1/2] Add titles for hover to zoom buttons --- jquery.jWindowCrop.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jquery.jWindowCrop.js b/jquery.jWindowCrop.js index a2f85d4..d3083a8 100644 --- a/jquery.jWindowCrop.js +++ b/jquery.jWindowCrop.js @@ -31,7 +31,7 @@ base.$image.addClass('jwc_image').wrap('
'); // wrap image in frame base.$frame = base.$image.parent(); base.$frame.append('
' + base.options.loadingText + '
'); - base.$frame.append('
click to drag
'); + base.$frame.append('
click to drag
'); base.$frame.css({'overflow': 'hidden', 'position': 'relative', 'width': base.options.targetWidth, 'height': base.options.targetHeight}); base.$image.css({'position': 'absolute', 'top': '0px', 'left': '0px'}); initializeDimensions(); From aa00788c29cbdefa2ada2709c183e334a1f23ba8 Mon Sep 17 00:00:00 2001 From: Mark Hetherington Date: Wed, 24 Apr 2013 09:56:09 +1000 Subject: [PATCH 2/2] Add custom buttons option Allows adding custom buttons to trigger internal functions or external handlers. --- README.markdown | 152 ++++++++--------- jquery.jWindowCrop.js | 370 ++++++++++++++++++++++-------------------- 2 files changed, 269 insertions(+), 253 deletions(-) diff --git a/README.markdown b/README.markdown index 4698f85..def0249 100644 --- a/README.markdown +++ b/README.markdown @@ -1,74 +1,78 @@ -Description -=========== -Easy to use jQuery plugin for zoom & pan image cropping. - -Demo -==== -Visit: http://www.tmatthew.net/jwindowcrop - -Usage -===== - // minimum - $('img.crop_me').jWindowCrop(); - - // typical - $('img.crop_me').jWindowCrop({ - targetWidth:300, - targetHeight:300, - onChange: function(result) { - console.log($(this).attr('id')); - console.log('x: '+result.cropX); - } - }); - -Options -======= - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OptionTypeDefaultRequiredDescription
targetWidthinteger320noWidth in pixels of the cropping window
targetHeightinteger180noHeight in pixels of the cropping window
onChangefunctionfunction(){}noCallback function that gets called whenever the values change. cropX, cropY, cropW, cropH, mustStretch (boolean) values are passed to this function in a hash. Use the this keyword in the function for a reference to the element that was updated.
zoomStepsinteger10noNumber of incremental zoom steps. With the default of 10, you have to click the zoom-in button 9 times to reach 100%.
loadingTextstring"Loading..."noText (can be HTML) to display within frame until image is loaded.
smartControlsbooleantruenoIf true, controls will hide on mouseleave and appear on mouseenter.
showControlsOnStartbooleantruenoIf true, controls will be hidden on start. Note: Do not set both this and smartControls to false.
- -Advanced -======== -The structure for this plugin comes from http://starter.pixelgraphics.us/. An object is created for each dom element jWindowCrop is initialized on. A reverse reference to that object can be accessed like so: - - var jwc = $('img#beach').getjWindowCrop(); - -You then have access to all the properties and methods used for that specific element. - -Questions -========= -Email tyler at tmatthew dot net +Description +=========== +Easy to use jQuery plugin for zoom & pan image cropping. + +Demo +==== +Visit: http://www.tmatthew.net/jwindowcrop + +Usage +===== + // minimum + $('img.crop_me').jWindowCrop(); + + // typical + $('img.crop_me').jWindowCrop({ + targetWidth:300, + targetHeight:300, + onChange: function(result) { + console.log($(this).attr('id')); + console.log('x: '+result.cropX); + } + }); + +Options +======= + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultRequiredDescription
targetWidthinteger320noWidth in pixels of the cropping window
targetHeightinteger180noHeight in pixels of the cropping window
onChangefunctionfunction(){}noCallback function that gets called whenever the values change. cropX, cropY, cropW, cropH, mustStretch (boolean) values are passed to this function in a hash. Use the this keyword in the function for a reference to the element that was updated.
zoomStepsinteger10noNumber of incremental zoom steps. With the default of 10, you have to click the zoom-in button 9 times to reach 100%.
loadingTextstring"Loading..."noText (can be HTML) to display within frame until image is loaded.
smartControlsbooleantruenoIf true, controls will hide on mouseleave and appear on mouseenter.
showControlsOnStartbooleantruenoIf true, controls will be hidden on start. Note: Do not set both this and smartControls to false.
customButtonsarray[]noButtons can be added to the toolbar here. e.g: [{class:'jwc_replace',name:'Replace Image', handler:triggerUpload, content:'Replace Image'}]
+ +Advanced +======== +The structure for this plugin comes from http://starter.pixelgraphics.us/. An object is created for each dom element jWindowCrop is initialized on. A reverse reference to that object can be accessed like so: + + var jwc = $('img#beach').getjWindowCrop(); + +You then have access to all the properties and methods used for that specific element. + +Questions +========= +Email tyler at tmatthew dot net diff --git a/jquery.jWindowCrop.js b/jquery.jWindowCrop.js index d3083a8..2cea2f6 100644 --- a/jquery.jWindowCrop.js +++ b/jquery.jWindowCrop.js @@ -1,179 +1,191 @@ -/* - * jWindowCrop v1.0.0 - * - * Copyright (c) 2012 Tyler Brown - * Licensed under the MIT license. - * - */ - -(function($){ - function fillContainer(val, targetLength, containerLength) { // ensure that no gaps are between target's edges and container's edges - if(val + targetLength < containerLength) val = containerLength-targetLength; - if(val > 0) val = 0; - return val; - } - - $.jWindowCrop = function(image, options){ - var base = this; - base.$image = $(image); // target image jquery element - base.image = image; // target image dom element - base.$image.data("jWindowCrop", base); // target frame jquery element - - base.namespace = 'jWindowCrop'; - base.originalWidth = 0; - base.isDragging = false; - - base.init = function(){ - base.$image.css({display:'none'}); // hide image until loaded - base.options = $.extend({},$.jWindowCrop.defaultOptions, options); - if(base.options.zoomSteps < 2) base.options.zoomSteps = 2; - - base.$image.addClass('jwc_image').wrap('
'); // wrap image in frame - base.$frame = base.$image.parent(); - base.$frame.append('
' + base.options.loadingText + '
'); - base.$frame.append('
click to drag
'); - base.$frame.css({'overflow': 'hidden', 'position': 'relative', 'width': base.options.targetWidth, 'height': base.options.targetHeight}); - base.$image.css({'position': 'absolute', 'top': '0px', 'left': '0px'}); - initializeDimensions(); - - base.$frame.find('.jwc_zoom_in').on('click.'+base.namespace, base.zoomIn); - base.$frame.find('.jwc_zoom_out').on('click.'+base.namespace, base.zoomOut); - base.$frame.on('mouseenter.'+base.namespace, handleMouseEnter); - base.$frame.on('mouseleave.'+base.namespace, handleMouseLeave); - base.$image.on('load.'+base.namespace, handeImageLoad); - base.$image.on('mousedown.'+base.namespace, handleMouseDown); - $(document).on('mousemove.'+base.namespace, handleMouseMove); - $(document).on('mouseup.'+base.namespace, handleMouseUp); - }; - - base.destroy = function() { - base.$image.removeData("jWindowCrop"); // remove data - $(document).unbind(); // remove body binds - base.$image.unbind(); // remove image binds - base.$frame.unbind(); // remove frame binds - base.$frame.find('.jwc_zoom_out').unbind(); // remove zoom triggers - base.$frame.find('.jwc_zoom_in').unbind(); // remove zoom triggers - $('.jwc_loader').remove(); // remove the added text - $('.jwc_controls').remove(); // remove the added controls - base.$image.removeAttr( 'style' ); // undo the style - base.$image.unwrap(); // undo the wrap - }; - - base.setZoom = function(percent) { - if(base.minPercent >= 1) { - percent = base.minPercent; - } else if(percent > 1.0) { - percent = 1; - } else if(percent < base.minPercent) { - percent = base.minPercent; - } - base.$image.width(Math.ceil(base.originalWidth*percent)); - base.workingPercent = percent; - focusOnCenter(); - updateResult(); - }; - base.zoomIn = function() { - var zoomIncrement = (1.0 - base.minPercent) / (base.options.zoomSteps-1); - base.setZoom(base.workingPercent+zoomIncrement); - return false; - }; - base.zoomOut = function() { - var zoomIncrement = (1.0 - base.minPercent) / (base.options.zoomSteps-1); - base.setZoom(base.workingPercent-zoomIncrement); - return false; - }; - - function initializeDimensions() { - if(base.originalWidth == 0) { - base.originalWidth = base.$image.width(); - base.originalHeight = base.$image.height(); - } - if(base.originalWidth > 0) { - var widthRatio = base.options.targetWidth / base.originalWidth; - var heightRatio = base.options.targetHeight / base.originalHeight; - //base.minPercent = (widthRatio >= heightRatio) ? widthRatio : heightRatio; - if(widthRatio >= heightRatio) { - base.minPercent = (base.originalWidth < base.options.targetWidth) ? (base.options.targetWidth / base.originalWidth) : widthRatio; - } else { - base.minPercent = (base.originalHeight < base.options.targetHeight) ? (base.options.targetHeight / base.originalHeight) : heightRatio; - } - base.focalPoint = {'x': Math.round(base.originalWidth/2), 'y': Math.round(base.originalHeight/2)}; - base.setZoom(base.minPercent); - base.$image.fadeIn('fast'); //display image now that it has loaded - } - } - function storeFocalPoint() { - var x = (parseInt(base.$image.css('left'))*-1 + base.options.targetWidth/2) / base.workingPercent; - var y = (parseInt(base.$image.css('top'))*-1 + base.options.targetHeight/2) / base.workingPercent; - base.focalPoint = {'x': Math.round(x), 'y': Math.round(y)}; - } - function focusOnCenter() { - var left = fillContainer((Math.round((base.focalPoint.x*base.workingPercent) - base.options.targetWidth/2)*-1), base.$image.width(), base.options.targetWidth); - var top = fillContainer((Math.round((base.focalPoint.y*base.workingPercent) - base.options.targetHeight/2)*-1), base.$image.height(), base.options.targetHeight); - base.$image.css({'left': (left.toString()+'px'), 'top': (top.toString()+'px')}) - storeFocalPoint(); - } - function updateResult() { - base.result = { - cropX: Math.floor(parseInt(base.$image.css('left'))/base.workingPercent*-1), - cropY: Math.floor(parseInt(base.$image.css('top'))/base.workingPercent*-1), - cropW: Math.round(base.options.targetWidth/base.workingPercent), - cropH: Math.round(base.options.targetHeight/base.workingPercent), - mustStretch: (base.minPercent > 1) - }; - base.options.onChange.call(base.image, base.result); - } - function handeImageLoad() { - initializeDimensions(); - } - function handleMouseDown(event) { - event.preventDefault(); //some browsers do image dragging themselves - base.isDragging = true; - base.dragMouseCoords = {x: event.pageX, y: event.pageY}; - base.dragImageCoords = {x: parseInt(base.$image.css('left')), y: parseInt(base.$image.css('top'))} - } - function handleMouseUp() { - base.isDragging = false; - } - function handleMouseMove(event) { - if(base.isDragging) { - var xDif = event.pageX - base.dragMouseCoords.x; - var yDif = event.pageY - base.dragMouseCoords.y; - var newLeft = fillContainer((base.dragImageCoords.x + xDif), base.$image.width(), base.options.targetWidth); - var newTop = fillContainer((base.dragImageCoords.y + yDif), base.$image.height(), base.options.targetHeight); - base.$image.css({'left' : (newLeft.toString()+'px'), 'top' : (newTop.toString()+'px')}); - storeFocalPoint(); - updateResult(); - } - } - function handleMouseEnter() { - if(base.options.smartControls) base.$frame.find('.jwc_controls').fadeIn('fast'); - } - function handleMouseLeave() { - if(base.options.smartControls) base.$frame.find('.jwc_controls').fadeOut('fast'); - } - - base.init(); - }; - - $.jWindowCrop.defaultOptions = { - targetWidth: 320, - targetHeight: 180, - zoomSteps: 10, - loadingText: 'Loading...', - smartControls: true, - showControlsOnStart: true, - onChange: function() {} - }; - - $.fn.jWindowCrop = function(options){ - return this.each(function(){ - (new $.jWindowCrop(this, options)); - }); - }; - - $.fn.getjWindowCrop = function(){ - return this.data("jWindowCrop"); - }; -})(jQuery); - +/* + * jWindowCrop v1.0.0 + * + * Copyright (c) 2012 Tyler Brown + * Licensed under the MIT license. + * + */ + +(function($){ + function fillContainer(val, targetLength, containerLength) { // ensure that no gaps are between target's edges and container's edges + if(val + targetLength < containerLength) val = containerLength-targetLength; + if(val > 0) val = 0; + return val; + } + + $.jWindowCrop = function(image, options){ + var base = this; + base.$image = $(image); // target image jquery element + base.image = image; // target image dom element + base.$image.data("jWindowCrop", base); // target frame jquery element + + base.namespace = 'jWindowCrop'; + base.originalWidth = 0; + base.isDragging = false; + + base.init = function(){ + base.$image.css({display:'none'}); // hide image until loaded + base.options = $.extend(true,{},$.jWindowCrop.defaultOptions, options); + if(base.options.zoomSteps < 2) base.options.zoomSteps = 2; + + base.$image.addClass('jwc_image').wrap('
'); // wrap image in frame + base.$frame = base.$image.parent(); + base.$frame.append('
' + base.options.loadingText + '
'); + base.$frame.append('
click to drag
'); + base.$frame.css({'overflow': 'hidden', 'position': 'relative', 'width': base.options.targetWidth, 'height': base.options.targetHeight}); + base.$image.css({'position': 'absolute', 'top': '0px', 'left': '0px'}); + initializeDimensions(); + + //Add custom buttons to default buttons array. + $.merge(base.options.buttons,base.options.customButtons); + $.each(base.options.buttons,function (i,button){ + base.$frame.find('.jwc_controls').append('' + ((button.content) ? button.content : '')+ ''); + if (button.function && base[button.function]) { //Bind function to button. + base.$frame.find('.'+button.class).on('click.'+base.namespace, base[button.function]); + } else if (button.handler){ + base.$frame.find('.'+button.class).on('click.'+base.namespace,button.handler); + } + }); + base.$frame.on('mouseenter.'+base.namespace, handleMouseEnter); + base.$frame.on('mouseleave.'+base.namespace, handleMouseLeave); + base.$image.on('load.'+base.namespace, handeImageLoad); + base.$image.on('mousedown.'+base.namespace, handleMouseDown); + $(document).on('mousemove.'+base.namespace, handleMouseMove); + $(document).on('mouseup.'+base.namespace, handleMouseUp); + }; + + base.destroy = function() { + base.$image.removeData("jWindowCrop"); // remove data + $(document).unbind(); // remove body binds + base.$image.unbind(); // remove image binds + base.$frame.unbind(); // remove frame binds + $.each(base.options.buttons,function (i,button){ + base.$frame.find('.jwc_controls').unbind();// remove button triggers + }); + $('.jwc_loader').remove(); // remove the added text + $('.jwc_controls').remove(); // remove the added controls + base.$image.removeAttr( 'style' ); // undo the style + base.$image.unwrap(); // undo the wrap + base.options = null; + }; + + base.setZoom = function(percent) { + if(base.minPercent >= 1) { + percent = base.minPercent; + } else if(percent > 1.0) { + percent = 1; + } else if(percent < base.minPercent) { + percent = base.minPercent; + } + base.$image.width(Math.ceil(base.originalWidth*percent)); + base.workingPercent = percent; + focusOnCenter(); + updateResult(); + }; + base.zoomIn = function() { + var zoomIncrement = (1.0 - base.minPercent) / (base.options.zoomSteps-1); + base.setZoom(base.workingPercent+zoomIncrement); + return false; + }; + base.zoomOut = function() { + var zoomIncrement = (1.0 - base.minPercent) / (base.options.zoomSteps-1); + base.setZoom(base.workingPercent-zoomIncrement); + return false; + }; + + function initializeDimensions() { + if(base.originalWidth == 0) { + base.originalWidth = base.$image.width(); + base.originalHeight = base.$image.height(); + } + if(base.originalWidth > 0) { + var widthRatio = base.options.targetWidth / base.originalWidth; + var heightRatio = base.options.targetHeight / base.originalHeight; + //base.minPercent = (widthRatio >= heightRatio) ? widthRatio : heightRatio; + if(widthRatio >= heightRatio) { + base.minPercent = (base.originalWidth < base.options.targetWidth) ? (base.options.targetWidth / base.originalWidth) : widthRatio; + } else { + base.minPercent = (base.originalHeight < base.options.targetHeight) ? (base.options.targetHeight / base.originalHeight) : heightRatio; + } + base.focalPoint = {'x': Math.round(base.originalWidth/2), 'y': Math.round(base.originalHeight/2)}; + base.setZoom(base.minPercent); + base.$image.fadeIn('fast'); //display image now that it has loaded + } + } + function storeFocalPoint() { + var x = (parseInt(base.$image.css('left'))*-1 + base.options.targetWidth/2) / base.workingPercent; + var y = (parseInt(base.$image.css('top'))*-1 + base.options.targetHeight/2) / base.workingPercent; + base.focalPoint = {'x': Math.round(x), 'y': Math.round(y)}; + } + function focusOnCenter() { + var left = fillContainer((Math.round((base.focalPoint.x*base.workingPercent) - base.options.targetWidth/2)*-1), base.$image.width(), base.options.targetWidth); + var top = fillContainer((Math.round((base.focalPoint.y*base.workingPercent) - base.options.targetHeight/2)*-1), base.$image.height(), base.options.targetHeight); + base.$image.css({'left': (left.toString()+'px'), 'top': (top.toString()+'px')}) + storeFocalPoint(); + } + function updateResult() { + base.result = { + cropX: Math.floor(parseInt(base.$image.css('left'))/base.workingPercent*-1), + cropY: Math.floor(parseInt(base.$image.css('top'))/base.workingPercent*-1), + cropW: Math.round(base.options.targetWidth/base.workingPercent), + cropH: Math.round(base.options.targetHeight/base.workingPercent), + mustStretch: (base.minPercent > 1) + }; + base.options.onChange.call(base.image, base.result); + } + function handeImageLoad() { + initializeDimensions(); + } + function handleMouseDown(event) { + event.preventDefault(); //some browsers do image dragging themselves + base.isDragging = true; + base.dragMouseCoords = {x: event.pageX, y: event.pageY}; + base.dragImageCoords = {x: parseInt(base.$image.css('left')), y: parseInt(base.$image.css('top'))} + } + function handleMouseUp() { + base.isDragging = false; + } + function handleMouseMove(event) { + if(base.isDragging) { + var xDif = event.pageX - base.dragMouseCoords.x; + var yDif = event.pageY - base.dragMouseCoords.y; + var newLeft = fillContainer((base.dragImageCoords.x + xDif), base.$image.width(), base.options.targetWidth); + var newTop = fillContainer((base.dragImageCoords.y + yDif), base.$image.height(), base.options.targetHeight); + base.$image.css({'left' : (newLeft.toString()+'px'), 'top' : (newTop.toString()+'px')}); + storeFocalPoint(); + updateResult(); + } + } + function handleMouseEnter() { + if(base.options.smartControls) base.$frame.find('.jwc_controls').fadeIn('fast'); + } + function handleMouseLeave() { + if(base.options.smartControls) base.$frame.find('.jwc_controls').fadeOut('fast'); + } + + base.init(); + }; + + $.jWindowCrop.defaultOptions = { + targetWidth: 320, + targetHeight: 180, + zoomSteps: 10, + loadingText: 'Loading...', + smartControls: true, + showControlsOnStart: true, + onChange: function() {}, + buttons: [{class:'jwc_zoom_in',name:'Zoom In', function:'zoomIn'},{class:'jwc_zoom_out',name:'Zoom Out', function:'zoomOut'}], + customButtons:[] + }; + + $.fn.jWindowCrop = function(options){ + return this.each(function(){ + (new $.jWindowCrop(this, options)); + }); + }; + + $.fn.getjWindowCrop = function(){ + return this.data("jWindowCrop"); + }; +})(jQuery); +