├── screenshot.png ├── jcrop ├── css │ ├── Jcrop.gif │ ├── jquery.Jcrop.min.css │ └── jquery.Jcrop.css ├── demos │ ├── demo_files │ │ ├── pool.jpg │ │ ├── sago.jpg │ │ ├── sagomod.jpg │ │ ├── sagomod.png │ │ └── demos.css │ ├── tutorial1.html │ ├── non-image.html │ ├── tutorial2.html │ ├── tutorial3.html │ ├── crop.php │ ├── styling.html │ ├── jquery-ui.html │ ├── tutorial4.html │ └── tutorial5.html ├── MIT-LICENSE.txt ├── index.html ├── README.md └── js │ ├── jquery.color.js │ ├── jquery.Jcrop.min.js │ └── jquery.Jcrop.js ├── lib ├── Process.php └── Boot.php ├── config.php ├── README.md ├── LICENSE ├── plugin.js ├── plugin.php └── dialog.php /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephwoodward/CKFinderJcrop/master/screenshot.png -------------------------------------------------------------------------------- /jcrop/css/Jcrop.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephwoodward/CKFinderJcrop/master/jcrop/css/Jcrop.gif -------------------------------------------------------------------------------- /jcrop/demos/demo_files/pool.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephwoodward/CKFinderJcrop/master/jcrop/demos/demo_files/pool.jpg -------------------------------------------------------------------------------- /jcrop/demos/demo_files/sago.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephwoodward/CKFinderJcrop/master/jcrop/demos/demo_files/sago.jpg -------------------------------------------------------------------------------- /jcrop/demos/demo_files/sagomod.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephwoodward/CKFinderJcrop/master/jcrop/demos/demo_files/sagomod.jpg -------------------------------------------------------------------------------- /jcrop/demos/demo_files/sagomod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephwoodward/CKFinderJcrop/master/jcrop/demos/demo_files/sagomod.png -------------------------------------------------------------------------------- /lib/Process.php: -------------------------------------------------------------------------------- 1 | isPosted() ) { 8 | $new_file = $image->resize(); 9 | echo 'Image successfully cropped and is located within the same folder with name: \''.$new_file.'\''; 10 | } 11 | -------------------------------------------------------------------------------- /config.php: -------------------------------------------------------------------------------- 1 | 'Default' 5 | ), 6 | array( 7 | 'title'=>'Example', 8 | 'over_write'=>'true', 9 | 'aspectRatio'=>array( 10 | 'width'=>10, 11 | 'height'=>5 12 | ), 13 | 'resize'=> array( 14 | 'width'=>1000, 15 | 'height'=>500 16 | ) 17 | ) 18 | ); 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CKFinderJcrop 2 | ============= 3 | CKFinder plugin of a much needed image cropping feature using the JQuery based JCrop (http://deepliquid.com/content/Jcrop.html). 4 | 5 | ![](http://oi58.tinypic.com/10p6grm.jpg) 6 | 7 | Features : 8 | 9 | Presets - You can define your own rules in config.php file, and easly crop-resize your images. 10 | Aspect Ratio - You can cut your images with aspect ratio 11 | Resize - If you want, you can resize your images after cutting them. 12 | Overwrite - If you don't want to create a new file, you may overwirte it. 13 | 14 | 15 | To install the plugin 16 | 1. Create folder "cropresize" inside CKfinder/plugins 17 | 2. Export the code inside this folder 18 | 3. Edit CKfinder/config.php and at the end of the file add line 19 | 20 | > include_once "plugins/cropresize/plugin.php"; 21 | 22 | Edit config.php and define your own presets. An example plesed is allready defined. 23 | Note: Do not delete default preset in config.php 24 | 25 | License 26 | ------- 27 | All files are under the [The MIT License (MIT) license][license]. 28 | 29 | [license]:http://en.wikipedia.org/wiki/MIT_License 30 | 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /jcrop/MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Tapmodo Interactive LLC, 2 | http://github.com/tapmodo/Jcrop 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /jcrop/demos/tutorial1.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Jcrop » Tutorials » Hello World 7 | 8 | 9 | 10 | 11 | 21 | 22 | 23 | 24 |
25 |
26 |
27 | 28 |

Jcrop - Hello World

29 | Flowers 30 | 31 |

32 | This example demonstrates the default behavior of Jcrop. 33 | Since no event handlers have been attached it only performs 34 | the cropping behavior. 35 |

36 | 37 | 41 | 42 |
43 |
44 |
45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /jcrop/css/jquery.Jcrop.min.css: -------------------------------------------------------------------------------- 1 | /* jquery.Jcrop.min.css v0.9.10 (build:20120429) */ 2 | .jcrop-holder{direction:ltr;text-align:left;} 3 | .jcrop-vline,.jcrop-hline{background:#FFF url(Jcrop.gif) top left repeat;font-size:0;position:absolute;} 4 | .jcrop-vline{height:100%;width:1px!important;} 5 | .jcrop-hline{height:1px!important;width:100%;} 6 | .jcrop-vline.right{right:0;} 7 | .jcrop-hline.bottom{bottom:0;} 8 | .jcrop-handle{background-color:#333;border:1px #eee solid;font-size:1px;} 9 | .jcrop-tracker{-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;-webkit-user-select:none;height:100%;width:100%;} 10 | .jcrop-handle.ord-n{left:50%;margin-left:-4px;margin-top:-4px;top:0;} 11 | .jcrop-handle.ord-s{bottom:0;left:50%;margin-bottom:-4px;margin-left:-4px;} 12 | .jcrop-handle.ord-e{margin-right:-4px;margin-top:-4px;right:0;top:50%;} 13 | .jcrop-handle.ord-w{left:0;margin-left:-4px;margin-top:-4px;top:50%;} 14 | .jcrop-handle.ord-nw{left:0;margin-left:-4px;margin-top:-4px;top:0;} 15 | .jcrop-handle.ord-ne{margin-right:-4px;margin-top:-4px;right:0;top:0;} 16 | .jcrop-handle.ord-se{bottom:0;margin-bottom:-4px;margin-right:-4px;right:0;} 17 | .jcrop-handle.ord-sw{bottom:0;left:0;margin-bottom:-4px;margin-left:-4px;} 18 | .jcrop-dragbar.ord-n,.jcrop-dragbar.ord-s{height:7px;width:100%;} 19 | .jcrop-dragbar.ord-e,.jcrop-dragbar.ord-w{height:100%;width:7px;} 20 | .jcrop-dragbar.ord-n{margin-top:-4px;} 21 | .jcrop-dragbar.ord-s{bottom:0;margin-bottom:-4px;} 22 | .jcrop-dragbar.ord-e{margin-right:-4px;right:0;} 23 | .jcrop-dragbar.ord-w{margin-left:-4px;} 24 | .jcrop-light .jcrop-vline,.jcrop-light .jcrop-hline{background:#FFF;filter:Alpha(opacity=70)!important;opacity:.70!important;} 25 | .jcrop-light .jcrop-handle{-moz-border-radius:3px;-webkit-border-radius:3px;background-color:#000;border-color:#FFF;border-radius:3px;} 26 | .jcrop-dark .jcrop-vline,.jcrop-dark .jcrop-hline{background:#000;filter:Alpha(opacity=70)!important;opacity:.7!important;} 27 | .jcrop-dark .jcrop-handle{-moz-border-radius:3px;-webkit-border-radius:3px;background-color:#FFF;border-color:#000;border-radius:3px;} 28 | .jcrop-holder img,img.jcrop-preview{max-width:none;} 29 | -------------------------------------------------------------------------------- /jcrop/demos/non-image.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Jcrop » Tutorials » Non-Image 7 | 8 | 9 | 10 | 11 | 26 | 35 | 36 | 37 | 38 |
39 |
40 |
41 | 42 |

Jcrop - Non-Image

43 |

44 | 45 | This is an example of attaching Jcrop to a target that is not an image. You are now cropping a paragraph tag. 46 | 47 |

48 | 49 |

50 | Attaching Jcrop to a non-image element. 51 | This is mostly useful to implement other interfaces, such as canvas or over an arbitrary div. 52 |

53 | 54 | 58 | 59 |
60 |
61 |
62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /jcrop/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Jcrop: the jQuery Image Cropping Plugin 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |

Jcrop Image Cropping Plugin

15 | 16 | 17 | Jcrop 18 | is the image cropping plugin for 19 | jQuery.
20 | You've successfully unpacked Jcrop. 21 |
22 | 23 |

Static Demos

24 | 25 | 49 | 50 |

Live Demo

51 | 52 | 56 | 57 |

Jcrop Links

58 | 59 | 63 | 64 |
65 | 66 | © 2008-2012 Tapmodo Interactive LLC
67 | Free software released under MIT License 68 |
69 |
70 |
71 |
72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /jcrop/README.md: -------------------------------------------------------------------------------- 1 | Jcrop Image Cropping Plugin 2 | =========================== 3 | 4 | Jcrop is the quick and easy way to add image cropping functionality to 5 | your web application. It combines the ease-of-use of a typical jQuery 6 | plugin with a powerful cross-platform DHTML cropping engine that is 7 | faithful to familiar desktop graphics applications. 8 | 9 | Cross-platform Compatibility 10 | ---------------------------- 11 | 12 | * Firefox 2+ 13 | * Safari 3+ 14 | * Opera 9.5+ 15 | * Google Chrome 0.2+ 16 | * Internet Explorer 6+ 17 | 18 | Feature Overview 19 | ---------------- 20 | 21 | * Attaches unobtrusively to any image 22 | * Supports aspect ratio locking 23 | * Supports minSize/maxSize setting 24 | * Callbacks for selection done, or while moving 25 | * Keyboard support for nudging selection 26 | * API features to create interactivity, including animation 27 | * Support for CSS styling 28 | * Experimental touch-screen support (iOS, Android, etc) 29 | 30 | Contributors 31 | ============ 32 | 33 | **Special thanks to the following contributors:** 34 | 35 | * [Bruno Agutoli](mailto:brunotla1@gmail.com) 36 | * dhorrigan 37 | * Phil-B 38 | * jaymecd 39 | * all others who have committed their time and effort to help improve Jcrop 40 | 41 | MIT License 42 | =========== 43 | 44 | **Jcrop is free software under MIT License.** 45 | 46 | #### Copyright (c) 2008-2012 Tapmodo Interactive LLC,
http://github.com/tapmodo/Jcrop 47 | 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of this software and associated documentation files (the 50 | "Software"), to deal in the Software without restriction, including 51 | without limitation the rights to use, copy, modify, merge, publish, 52 | distribute, sublicense, and/or sell copies of the Software, and to 53 | permit persons to whom the Software is furnished to do so, subject to 54 | the following conditions: 55 | 56 | The above copyright notice and this permission notice shall be 57 | included in all copies or substantial portions of the Software. 58 | 59 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 60 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 61 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 62 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 63 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 64 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 65 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 66 | 67 | -------------------------------------------------------------------------------- /jcrop/demos/demo_files/demos.css: -------------------------------------------------------------------------------- 1 | /* Jcrop Demo CSS 2 | * Not required to run Jcrop 3 | * Just makes the demo pages look less ugly 4 | */ 5 | 6 | body 7 | { 8 | margin: 0; 9 | padding: 0; 10 | background: #eee; 11 | font-family: Calibri, sans-serif; 12 | } 13 | 14 | .article h1 15 | { 16 | color: #333; 17 | font-size: 2.2em; 18 | margin-top: .2em; 19 | } 20 | 21 | .jcropper-holder { border: 1px black solid; } 22 | 23 | #outer { text-align: center; } 24 | 25 | .jcExample 26 | { 27 | text-align: left; 28 | background: white; 29 | width: 700px; 30 | font-size: 80%; 31 | margin: 1.5em auto 2em auto; 32 | border: 1px #999 solid; 33 | padding: 1em 2em 2em; 34 | } 35 | 36 | .jcExample .article { width: 565px; } 37 | 38 | form { margin: 1.5em 0; } 39 | form.coords label { margin-right: 1em; font-weight: bold; color: #900; } 40 | form.coords input { width: 3em; } 41 | 42 | .ui-button { font-size: 10pt; } 43 | .ui-dialog { font-size: 9pt; } 44 | .ui-state-default { font-size: 9pt; } 45 | .ui-widget-overlay { opacity: 0.80; filter: Alpha(opacity=70); } 46 | .jc-dialog { padding-top: 1em; } 47 | .ui-dialog p tt { color: yellow; } 48 | 49 | li small { font-style: normal; color: #CF4429; font-size: 11px; } 50 | 51 | .jcrop-light .jcrop-selection { 52 | -moz-box-shadow: 0px 0px 15px #999; /* Firefox */ 53 | -webkit-box-shadow: 0px 0px 15px #999; /* Safari, Chrome */ 54 | box-shadow: 0px 0px 15px #999; /* CSS3 */ 55 | } 56 | .jcrop-dark .jcrop-selection { 57 | -moz-box-shadow: 0px 0px 15px #000; /* Firefox */ 58 | -webkit-box-shadow: 0px 0px 15px #000; /* Safari, Chrome */ 59 | box-shadow: 0px 0px 15px #000; /* CSS3 */ 60 | } 61 | 62 | .jcrop-fancy .jcrop-handle.ord-e { 63 | -webkit-border-top-left-radius: 0px; 64 | -webkit-border-bottom-left-radius: 0px; 65 | } 66 | .jcrop-fancy .jcrop-handle.ord-w { 67 | -webkit-border-top-right-radius: 0px; 68 | -webkit-border-bottom-right-radius: 0px; 69 | } 70 | .jcrop-fancy .jcrop-handle.ord-nw { 71 | -webkit-border-bottom-right-radius: 0px; 72 | } 73 | .jcrop-fancy .jcrop-handle.ord-ne { 74 | -webkit-border-bottom-left-radius: 0px; 75 | } 76 | .jcrop-fancy .jcrop-handle.ord-sw { 77 | -webkit-border-top-right-radius: 0px; 78 | } 79 | .jcrop-fancy .jcrop-handle.ord-se { 80 | -webkit-border-top-left-radius: 0px; 81 | } 82 | .jcrop-fancy .jcrop-handle.ord-s { 83 | -webkit-border-top-left-radius: 0px; 84 | -webkit-border-top-right-radius: 0px; 85 | } 86 | .jcrop-fancy .jcrop-handle.ord-n { 87 | -webkit-border-bottom-left-radius: 0px; 88 | -webkit-border-bottom-right-radius: 0px; 89 | } 90 | -------------------------------------------------------------------------------- /jcrop/demos/tutorial2.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Jcrop » Tutorials » Event Handler 7 | 8 | 9 | 10 | 11 | 41 | 42 | 43 |
44 |
45 |
46 | 47 |

Jcrop - Event Handlers

48 | 49 | 50 | Flowers 51 | 52 | 53 |
57 | 58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 |
66 |
67 | 68 |

69 | An example with a basic event handler. Here we've tied 70 | several form values together with a simple event handler invocation. 71 | The result is that the form values are updated in real-time as 72 | the selection is changed using Jcrop's onChange handler. 73 |

74 | 75 |

76 | That's how easily Jcrop can be integrated into a traditional web form! 77 |

78 | 79 | 83 | 84 | 85 |
86 |
87 |
88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /jcrop/demos/tutorial3.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Jcrop » Tutorials » aspectRatio w/ Preview 7 | 8 | 9 | 10 | 11 | 50 | 51 | 52 | 53 | 54 | 55 |
56 |
57 |
58 | 59 |

Jcrop - Aspect ratio w/ preview pane

60 | 61 | 62 | 63 | 66 | 71 | 72 |
64 | Flowers 65 | 67 |
68 | Preview 69 |
70 |
73 | 74 |

75 | An example implementing a preview pane. 76 | Obviously the most visual demo, the preview pane is accomplished 77 | entirely outside of Jcrop with a simple jQuery-flavored callback. 78 | This type of interface could be useful for creating a thumbnail 79 | or avatar. The onChange event handler is used to update the 80 | view in the preview pane. 81 |

82 | 83 | 87 | 88 | 89 |
90 |
91 |
92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /jcrop/demos/crop.php: -------------------------------------------------------------------------------- 1 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 67 | 68 | 69 | 70 | 71 | 72 |
73 |
74 |
75 | 76 |

Jcrop - Crop Behavior

77 | 78 | 79 | 80 | 81 | 82 |
83 | 84 | 85 | 86 | 87 | 88 |
89 | 90 |

91 | An example server-side crop script. Hidden form values 92 | are set when a selection is made. If you press the Crop Image 93 | button, the form will be submitted and a 150x150 thumbnail will be 94 | dumped to the browser. Try it! 95 |

96 | 97 | 101 | 102 | 103 |
104 |
105 |
106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /jcrop/css/jquery.Jcrop.css: -------------------------------------------------------------------------------- 1 | /* jquery.Jcrop.css v0.9.10 - MIT License */ 2 | 3 | /* 4 | The outer-most container in a typical Jcrop instance 5 | If you are having difficulty with formatting related to styles 6 | on a parent element, place any fixes here or in a like selector 7 | 8 | You can also style this element if you want to add a border, etc 9 | A better method for styling can be seen below with .jcrop-light 10 | (Add a class to the holder and style elements for that extended class) 11 | */ 12 | .jcrop-holder { 13 | direction: ltr; 14 | text-align: left; 15 | } 16 | 17 | /* These styles define the border lines */ 18 | .jcrop-vline,.jcrop-hline{background:#FFF url(Jcrop.gif) top left repeat;font-size:0;position:absolute;} 19 | .jcrop-vline{height:100%;width:1px!important;} 20 | .jcrop-hline{height:1px!important;width:100%;} 21 | .jcrop-vline.right{right:0;} 22 | .jcrop-hline.bottom{bottom:0;} 23 | 24 | /* Handle style - size is set by Jcrop handleSize option (currently) */ 25 | .jcrop-handle{background-color:#333;border:1px #eee solid;font-size:1px;} 26 | 27 | /* This style is used for invisible click targets */ 28 | .jcrop-tracker 29 | { 30 | height: 100%; 31 | width: 100%; 32 | -webkit-tap-highlight-color: transparent; /* "turn off" link highlight */ 33 | -webkit-touch-callout: none; /* disable callout, image save panel */ 34 | -webkit-user-select: none; /* disable cut copy paste */ 35 | } 36 | 37 | /* Positioning of handles and drag bars */ 38 | .jcrop-handle.ord-n{left:50%;margin-left:-4px;margin-top:-4px;top:0;} 39 | .jcrop-handle.ord-s{bottom:0;left:50%;margin-bottom:-4px;margin-left:-4px;} 40 | .jcrop-handle.ord-e{margin-right:-4px;margin-top:-4px;right:0;top:50%;} 41 | .jcrop-handle.ord-w{left:0;margin-left:-4px;margin-top:-4px;top:50%;} 42 | .jcrop-handle.ord-nw{left:0;margin-left:-4px;margin-top:-4px;top:0;} 43 | .jcrop-handle.ord-ne{margin-right:-4px;margin-top:-4px;right:0;top:0;} 44 | .jcrop-handle.ord-se{bottom:0;margin-bottom:-4px;margin-right:-4px;right:0;} 45 | .jcrop-handle.ord-sw{bottom:0;left:0;margin-bottom:-4px;margin-left:-4px;} 46 | .jcrop-dragbar.ord-n,.jcrop-dragbar.ord-s{height:7px;width:100%;} 47 | .jcrop-dragbar.ord-e,.jcrop-dragbar.ord-w{height:100%;width:7px;} 48 | .jcrop-dragbar.ord-n{margin-top:-4px;} 49 | .jcrop-dragbar.ord-s{bottom:0;margin-bottom:-4px;} 50 | .jcrop-dragbar.ord-e{margin-right:-4px;right:0;} 51 | .jcrop-dragbar.ord-w{margin-left:-4px;} 52 | 53 | /* The "jcrop-light" class/extension */ 54 | .jcrop-light .jcrop-vline,.jcrop-light .jcrop-hline 55 | { 56 | background:#FFF; 57 | filter:Alpha(opacity=70)!important; 58 | opacity:.70!important; 59 | } 60 | .jcrop-light .jcrop-handle 61 | { 62 | -moz-border-radius:3px; 63 | -webkit-border-radius:3px; 64 | background-color:#000; 65 | border-color:#FFF; 66 | border-radius:3px; 67 | } 68 | 69 | /* The "jcrop-dark" class/extension */ 70 | .jcrop-dark .jcrop-vline,.jcrop-dark .jcrop-hline 71 | { 72 | background:#000; 73 | filter:Alpha(opacity=70)!important; 74 | opacity:.7!important; 75 | } 76 | .jcrop-dark .jcrop-handle 77 | { 78 | -moz-border-radius:3px; 79 | -webkit-border-radius:3px; 80 | background-color:#FFF; 81 | border-color:#000; 82 | border-radius:3px; 83 | } 84 | 85 | /* Fix for twitter bootstrap et al. */ 86 | .jcrop-holder img,img.jcrop-preview{ max-width: none; } 87 | -------------------------------------------------------------------------------- /plugin.js: -------------------------------------------------------------------------------- 1 | CKFinder.addPlugin( 'cropresize', function( api ) { 2 | 3 | CKFinder.dialog.add( 'cropresize', function( api ) { 4 | 5 | var file = api.getSelectedFile(); 6 | 7 | var fileUrl = file.getUrl(); 8 | var fileName = file.name; 9 | var folderName = file.folder; 10 | 11 | /*alert( api.getSelectedFile().name );*/ 12 | 13 | var dialogDefinition = 14 | { 15 | title : "Crop " + file.name, 16 | minWidth : 800, 17 | minHeight : 500, 18 | onCancel : function() { 19 | api.refreshOpenedFolder(); 20 | return true; 21 | }, 22 | onOk : function() { 23 | 24 | api.refreshOpenedFolder(); 25 | return true; 26 | 27 | // "this" is now a CKFinder.dialog object. 28 | 29 | /* 30 | var value = this.getValueOf( 'tab1', 'textareaId' ); 31 | if ( !value ) { 32 | api.openMsgDialog( '', api.lang.dummy.typeText ); 33 | return false; 34 | } else { 35 | alert( "You have entered: " + value ); 36 | return true; 37 | }*/ 38 | }, 39 | contents : [ 40 | { 41 | id : 'tab1', 42 | label : '', 43 | title : 'Crop ' + fileName, 44 | expand : true, 45 | elements : 46 | [ 47 | { 48 | type : 'html', 49 | html: '' 50 | } 51 | ] 52 | } 53 | ], 54 | buttons : [ CKFinder.dialog.okButton, CKFinder.dialog.cancelButton ] 55 | }; 56 | 57 | return dialogDefinition; 58 | }); 59 | 60 | api.addFileContextMenuOption( { label : 'Crop Image', command : "myCommand" } , function( api, file ) 61 | { 62 | 63 | if ( !file.isImage() ) { 64 | api.openMsgDialog("Image cropping", "This feature is only available for editing images."); 65 | return; 66 | } 67 | 68 | api.openDialog('cropresize'); 69 | 70 | }, 71 | function(file ) 72 | { 73 | 74 | // Disable for files other than images. 75 | if ( !file.isImage() || !api.getSelectedFolder().type ) 76 | return false; 77 | if ( file.folder.acl.fileDelete && file.folder.acl.fileUpload ) 78 | return true; 79 | else 80 | return -1; 81 | 82 | /* api.connector.sendCommand( 'FileSize', { fileName : api.getSelectedFile().name }, function( xml ) { 83 | if ( xml.checkError() ) 84 | return; 85 | 86 | var size = xml.selectSingleNode( 'Connector/FileSize/@size' ); 87 | var msg = xml.selectSingleNode( 'Connector/MyMessage/@message' ); 88 | api.openMsgDialog( "", "The exact size of a file is: " + size.value + " bytes"); 89 | //api.openMsgDialog( "", "my message is : " + msg.value + "!"); 90 | });*/ 91 | 92 | }); 93 | 94 | }); -------------------------------------------------------------------------------- /jcrop/demos/styling.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Jcrop » Tutorials » Styling Example 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 57 | 58 | 59 | 60 |
61 |
62 |
63 | 64 |

Jcrop - Styling Example

65 | Flowers 66 | 67 |
68 |
69 | Manipulate classes 70 |
71 | 72 | 73 | 74 |
75 |
76 |
77 | 78 |

79 | Example styling tricks. Click the buttons above to change the appearance of Jcrop in real-time. 80 |

81 | 82 | 86 | 87 |
88 |
89 |
90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /jcrop/js/jquery.color.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery Color Animations 3 | * Copyright 2007 John Resig 4 | * Released under the MIT and GPL licenses. 5 | */ 6 | 7 | (function(jQuery){ 8 | 9 | // We override the animation for all of these color styles 10 | jQuery.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i,attr){ 11 | jQuery.fx.step[attr] = function(fx){ 12 | if ( fx.state == 0 ) { 13 | fx.start = getColor( fx.elem, attr ); 14 | fx.end = getRGB( fx.end ); 15 | } 16 | 17 | fx.elem.style[attr] = "rgb(" + [ 18 | Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0]), 255), 0), 19 | Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1]), 255), 0), 20 | Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2]), 255), 0) 21 | ].join(",") + ")"; 22 | } 23 | }); 24 | 25 | // Color Conversion functions from highlightFade 26 | // By Blair Mitchelmore 27 | // http://jquery.offput.ca/highlightFade/ 28 | 29 | // Parse strings looking for color tuples [255,255,255] 30 | function getRGB(color) { 31 | var result; 32 | 33 | // Check if we're already dealing with an array of colors 34 | if ( color && color.constructor == Array && color.length == 3 ) 35 | return color; 36 | 37 | // Look for rgb(num,num,num) 38 | if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) 39 | return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])]; 40 | 41 | // Look for rgb(num%,num%,num%) 42 | if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) 43 | return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55]; 44 | 45 | // Look for #a0b1c2 46 | if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) 47 | return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)]; 48 | 49 | // Look for #fff 50 | if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) 51 | return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)]; 52 | 53 | // Otherwise, we're most likely dealing with a named color 54 | return colors[jQuery.trim(color).toLowerCase()]; 55 | } 56 | 57 | function getColor(elem, attr) { 58 | var color; 59 | 60 | do { 61 | color = jQuery.curCSS(elem, attr); 62 | 63 | // Keep going until we find an element that has color, or we hit the body 64 | if ( color != '' && color != 'transparent' || jQuery.nodeName(elem, "body") ) 65 | break; 66 | 67 | attr = "backgroundColor"; 68 | } while ( elem = elem.parentNode ); 69 | 70 | return getRGB(color); 71 | }; 72 | 73 | // Some named colors to work with 74 | // From Interface by Stefan Petre 75 | // http://interface.eyecon.ro/ 76 | 77 | var colors = { 78 | aqua:[0,255,255], 79 | azure:[240,255,255], 80 | beige:[245,245,220], 81 | black:[0,0,0], 82 | blue:[0,0,255], 83 | brown:[165,42,42], 84 | cyan:[0,255,255], 85 | darkblue:[0,0,139], 86 | darkcyan:[0,139,139], 87 | darkgrey:[169,169,169], 88 | darkgreen:[0,100,0], 89 | darkkhaki:[189,183,107], 90 | darkmagenta:[139,0,139], 91 | darkolivegreen:[85,107,47], 92 | darkorange:[255,140,0], 93 | darkorchid:[153,50,204], 94 | darkred:[139,0,0], 95 | darksalmon:[233,150,122], 96 | darkviolet:[148,0,211], 97 | fuchsia:[255,0,255], 98 | gold:[255,215,0], 99 | green:[0,128,0], 100 | indigo:[75,0,130], 101 | khaki:[240,230,140], 102 | lightblue:[173,216,230], 103 | lightcyan:[224,255,255], 104 | lightgreen:[144,238,144], 105 | lightgrey:[211,211,211], 106 | lightpink:[255,182,193], 107 | lightyellow:[255,255,224], 108 | lime:[0,255,0], 109 | magenta:[255,0,255], 110 | maroon:[128,0,0], 111 | navy:[0,0,128], 112 | olive:[128,128,0], 113 | orange:[255,165,0], 114 | pink:[255,192,203], 115 | purple:[128,0,128], 116 | violet:[128,0,128], 117 | red:[255,0,0], 118 | silver:[192,192,192], 119 | white:[255,255,255], 120 | yellow:[255,255,0] 121 | }; 122 | 123 | })(jQuery); 124 | -------------------------------------------------------------------------------- /plugin.php: -------------------------------------------------------------------------------- 1 | checkConnector(); 17 | $this->checkRequest(); 18 | 19 | // Checking ACL permissions, we're just getting an information about a file, so FILE_VIEW permission seems to be ok. 20 | if (!$this->_currentFolder->checkAcl(CKFINDER_CONNECTOR_ACL_FILE_VIEW)) { 21 | $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); 22 | } 23 | 24 | // Make sure we actually received a file name 25 | if (!isset($_GET["fileName"])) { 26 | $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_NAME); 27 | } 28 | 29 | $fileName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($_GET["fileName"]); 30 | $resourceTypeInfo = $this->_currentFolder->getResourceTypeConfig(); 31 | 32 | // Use the resource type configuration object to check whether the extension of a file to check is really allowed. 33 | if (!$resourceTypeInfo->checkExtension($fileName)) { 34 | $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_EXTENSION); 35 | } 36 | 37 | // Make sure that the file name is really ok and has not been sent by a hacker 38 | if (!CKFinder_Connector_Utils_FileSystem::checkFileName($fileName) || $resourceTypeInfo->checkIsHiddenFile($fileName)) { 39 | $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); 40 | } 41 | 42 | $filePath = CKFinder_Connector_Utils_FileSystem::combinePaths($this->_currentFolder->getServerPath(), $fileName); 43 | 44 | if (!file_exists($filePath) || !is_file($filePath)) { 45 | $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND); 46 | } 47 | 48 | $size = filesize($filePath); 49 | 50 | // *** The main part of this plugin **** 51 | // Adding a element to the XML response. 52 | //$oNode = new Ckfinder_Connector_Utils_XmlNode("FileSize"); 53 | //$oNode->addAttribute("size", $size); 54 | //$this->_connectorNode->addChild($oNode); 55 | 56 | 57 | 58 | $myNode = new Ckfinder_Connector_Utils_XmlNode("MyMessage"); 59 | $myNode->addAttribute("message", "Hello world!"); 60 | $this->_connectorNode->addChild($myNode); 61 | 62 | 63 | } 64 | 65 | // Register the "FileSize" command 66 | function onBeforeExecuteCommand( &$command ) 67 | { 68 | if ( $command == 'FileSize' ) 69 | { 70 | // The sendResponse method is defined in XmlCommandHandlerBase, it creates 71 | // a basic XML response and calls the buildXml()method 72 | $this->sendResponse(); 73 | // false = stop further execution. 74 | return false; 75 | } 76 | 77 | return true ; 78 | } 79 | 80 | public function myCommand ( &$command ) 81 | { 82 | 83 | if ( $command == 'FileSize' ) 84 | { 85 | // The sendResponse method is defined in XmlCommandHandlerBase, it creates 86 | // a basic XML response and calls the buildXml()method 87 | $this->sendResponse(); 88 | // false = stop further execution. 89 | return false; 90 | } 91 | 92 | return true ; 93 | 94 | } 95 | } 96 | 97 | $CommandHandler_FileSize = new CKFinder_Connector_CommandHandler_FileSize(); 98 | 99 | // Register the onBeforeExecuteCommand method to be called by the BeforeExecuteCommand hook. 100 | $config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_FileSize, "myCommand"); 101 | 102 | // (Optional) Register a javascript plugin named "myplugin" 103 | $config['Plugins'][] = 'cropresize'; -------------------------------------------------------------------------------- /jcrop/demos/jquery-ui.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Jcrop » Tutorials » Hello World 7 | 8 | 9 | 10 | 11 | 12 | 13 | 58 | 59 | 60 | 61 |
62 |
63 |
64 | 65 |

Jcrop - jQuery UI Example

66 | 67 | 68 | 69 | 76 | 77 | 78 |

79 | This example demonstrates more complex invocations of Jcrop. 80 | These techniques can be integrated with other libraries or more 81 | complex user interfaces. 82 |

83 | 84 |
85 |
86 | 90 |
91 |

92 | Prior to v0.9.10 release, it was difficult to instantiate Jcrop 93 | on an image unless it was visible on the page. This meant that 94 | opening Jcrop in a dialog or a hidden tab was problematic, and 95 | involved specific timing (e.g. attaching the Jcrop method 96 | call to an "open" handler for the UI element). 97 |

98 |

99 | This demo shows simple invocations of Jcrop using jQuery UI. If 100 | you are using a different library to produce dialog boxes or tabs, 101 | the theory of operation should be similar. 102 |

103 | 104 | 105 |
106 |
107 | 108 |
109 |
110 |
111 | 112 | 116 | 117 |
118 |
119 |
120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /lib/Boot.php: -------------------------------------------------------------------------------- 1 | baseDir = rtrim($_SERVER['DOCUMENT_ROOT'], '/'); 44 | 45 | //Set up file location url 46 | if (isset($_GET['fileUrl']) && !empty($_GET['fileUrl'])) { 47 | $this->imageUrl = filter_var($_GET['fileUrl'], FILTER_SANITIZE_STRING); 48 | } else if (isset($_POST['fileUrl']) && !empty($_POST['fileUrl'])) { 49 | $this->imageUrl = filter_var($_POST['fileUrl'], FILTER_SANITIZE_STRING); 50 | } 51 | 52 | if ( file_exists($this->baseDir . $this->imageUrl) ) { 53 | $this->imageDimensions = getimagesize($this->baseDir . $this->imageUrl); 54 | } 55 | 56 | //Set up filename 57 | if (isset($_GET['fileName']) && !empty($_GET['fileName'])) { 58 | $this->fileName = filter_var($_GET['fileName'], FILTER_SANITIZE_STRING); 59 | } else if (isset($_POST['fileName']) && !empty($_POST['fileName'])) { 60 | $this->fileName = filter_var($_POST['fileName'], FILTER_SANITIZE_STRING); 61 | } 62 | 63 | //Set up folder name 64 | if (isset($_GET['folderName']) && !empty($_GET['folderName'])) { 65 | $this->folderName = str_replace('/', '', filter_var($_GET['folderName'], FILTER_SANITIZE_STRING) ); 66 | } else if (isset($_POST['folderName']) && !empty($_POST['folderName'])) { 67 | $this->folderName = str_replace('/', '', filter_var($_POST['folderName'], FILTER_SANITIZE_STRING) ); 68 | } 69 | 70 | } 71 | 72 | public function getBaseDir() 73 | { 74 | return $this->baseDir; 75 | } 76 | 77 | public function isPosted() { 78 | if ( $_SERVER['REQUEST_METHOD'] === 'POST' && !empty($this->imageUrl) && !empty($this->fileName) ) { 79 | $this->postError = false; 80 | return true; 81 | } 82 | return false; 83 | } 84 | 85 | public function resize() 86 | { 87 | 88 | if ($this->postError) { 89 | return false; 90 | } 91 | 92 | $targ_w = $_POST['w']; 93 | $targ_h = $_POST['h']; 94 | $jpeg_quality = (int) $_POST['imageQuality']; 95 | 96 | $imageFileName=$this->baseDir . $this->imageUrl; 97 | $pathInfo=pathinfo($imageFileName); 98 | $fileExtension=strtolower($pathInfo['extension']); 99 | 100 | if ($fileExtension=='png') { 101 | $img_r = imagecreatefrompng($this->baseDir . $this->imageUrl); 102 | } else { 103 | $img_r = imagecreatefromjpeg($this->baseDir . $this->imageUrl); 104 | } 105 | 106 | $dst_r = ImageCreateTrueColor( $targ_w, $targ_h ); 107 | 108 | imagecopyresampled( $dst_r, $img_r, 0, 0, $_POST['x'], $_POST['y'], $targ_w, $targ_h, $_POST['w'], $_POST['h'] ); 109 | 110 | if ($_POST['post_resize']==true && is_numeric($_POST['post_resize_width']) && is_numeric($_POST['post_resize_height'])) { 111 | $new_w=$_POST['post_resize_width']; 112 | $new_h=$_POST['post_resize_height']; 113 | $new_img=ImageCreateTrueColor( $new_w, $new_h ); 114 | 115 | imagecopyresized($new_img , $dst_r , 0, 0, 0, 0, $new_w, $new_h, $targ_w, $targ_h); 116 | $dst_r=$new_img; 117 | } 118 | 119 | $saveDir = dirname($this->baseDir . $this->imageUrl); 120 | 121 | if ($_POST['post_over_write']==true) { 122 | $saveFile =$this->fileName; 123 | } else { 124 | $saveFile = $this->createFilename($this->fileName); 125 | } 126 | 127 | $filename = $saveDir. '/' . $saveFile; 128 | imagejpeg($dst_r, $filename, $jpeg_quality); 129 | return $saveFile; 130 | } 131 | 132 | private function createFilename($fileName) 133 | { 134 | $ext = substr($fileName, strrpos($fileName, ".")); 135 | return basename($fileName, $ext) . '_' . (int) $_POST['w'] . 'x' . (int) $_POST['h'] . $ext; 136 | } 137 | 138 | public function getWidth() 139 | { 140 | return $this->imageDimensions[0]; 141 | } 142 | 143 | public function getHeight() 144 | { 145 | return $this->imageDimensions[1]; 146 | } 147 | 148 | public function getUrl() 149 | { 150 | return $this->imageUrl; 151 | } 152 | 153 | public function getName() 154 | { 155 | return $this->fileName; 156 | } 157 | 158 | public function getFolderName() 159 | { 160 | return $this->folderName; 161 | } 162 | 163 | } -------------------------------------------------------------------------------- /jcrop/demos/tutorial4.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Jcrop » Tutorials » Animations / Transitions 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 137 | 138 | 139 | 140 | 141 |
142 |
143 |
144 | 145 |

Jcrop - Animations/Transitions

146 | Flowers 147 | 148 |
149 |
150 |
151 | 152 | 159 | 160 |

161 | Animation/Transitions. 162 | Demonstration of animateTo API method and transitions for bgColor 163 | and bgOpacity options. Color fading requires inclusion of John Resig's 164 | jQuery Color 165 | Animations plugin. If it is not included, colors will not fade. 166 |

167 | 168 | 172 | 173 |
174 |
175 |
176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /jcrop/demos/tutorial5.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Jcrop » Tutorials » API Demo 7 | 8 | 9 | 10 | 11 | 17 | 185 | 186 | 187 | 188 | 189 |
190 |
191 |
192 | 193 |

Jcrop - API Demo

194 | Jcrop Image 195 | 196 |
197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 |
207 | 208 |
209 | Option Toggles 210 |
211 | 212 | 213 |
214 |
215 | 216 | 217 | 218 |
219 |
220 | 221 |
222 | Change Image 223 | 224 | 225 | 226 | 227 | 228 |
229 | 230 | 234 | 235 |
236 |
237 |
238 | 239 | 240 | 241 | -------------------------------------------------------------------------------- /dialog.php: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Jcrop » Tutorials » Hello World 20 | 21 | 22 | 23 | 24 | 103 | 104 | 105 | 106 | 107 | 108 |
109 | <?php echo $image->getName(); ?> 110 | 245 |
246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 |
262 |
263 | 264 |
265 |

Settings

266 | 267 |
268 | 284 |
285 | 286 |
287 | 315 | 316 |

317 | 318 |
319 | 320 | 321 | 322 | 323 | -------------------------------------------------------------------------------- /jcrop/js/jquery.Jcrop.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jquery.Jcrop.min.js v0.9.10 (build:20120429) 3 | * jQuery Image Cropping Plugin - released under MIT License 4 | * Copyright (c) 2008-2012 Tapmodo Interactive LLC 5 | * https://github.com/tapmodo/Jcrop 6 | */ 7 | (function(a){a.Jcrop=function(b,c){function h(a){return a+"px"}function i(a){return d.baseClass+"-"+a}function j(){return a.fx.step.hasOwnProperty("backgroundColor")}function k(b){var c=a(b).offset();return[c.left,c.top]}function l(a){return[a.pageX-e[0],a.pageY-e[1]]}function m(b){typeof b!="object"&&(b={}),d=a.extend(d,b),a.each(["onChange","onSelect","onRelease","onDblClick"],function(a,b){typeof d[b]!="function"&&(d[b]=function(){})})}function n(a,b){e=k(E),bd.setCursor(a==="move"?a:a+"-resize");if(a==="move")return bd.activateHandlers(p(b),u);var c=ba.getFixed(),d=q(a),f=ba.getCorner(q(d));ba.setPressed(ba.getCorner(d)),ba.setCurrent(f),bd.activateHandlers(o(a,c),u)}function o(a,b){return function(c){if(!d.aspectRatio)switch(a){case"e":c[1]=b.y2;break;case"w":c[1]=b.y2;break;case"n":c[0]=b.x2;break;case"s":c[0]=b.x2}else switch(a){case"e":c[1]=b.y+1;break;case"w":c[1]=b.y+1;break;case"n":c[0]=b.x+1;break;case"s":c[0]=b.x+1}ba.setCurrent(c),bc.update()}}function p(a){var b=a;return be.watchKeys(),function( 8 | a){ba.moveOffset([a[0]-b[0],a[1]-b[1]]),b=a,bc.update()}}function q(a){switch(a){case"n":return"sw";case"s":return"nw";case"e":return"nw";case"w":return"ne";case"ne":return"sw";case"nw":return"se";case"se":return"nw";case"sw":return"ne"}}function r(a){return function(b){return d.disabled?!1:a==="move"&&!d.allowMove?!1:(e=k(E),X=!0,n(a,l(b)),b.stopPropagation(),b.preventDefault(),!1)}}function s(a,b,c){var d=a.width(),e=a.height();d>b&&b>0&&(d=b,e=b/a.width()*a.height()),e>c&&c>0&&(e=c,d=c/a.height()*a.width()),U=a.width()/d,V=a.height()/e,a.width(d).height(e)}function t(a){return{x:a.x*U,y:a.y*V,x2:a.x2*U,y2:a.y2*V,w:a.w*U,h:a.h*V}}function u(a){var b=ba.getFixed();b.w>d.minSelect[0]&&b.h>d.minSelect[1]?(bc.enableHandles(),bc.done()):bc.release(),bd.setCursor(d.allowSelect?"crosshair":"default")}function v(a){if(d.disabled)return!1;if(!d.allowSelect)return!1;X=!0,e=k(E),bc.disableHandles(),bd.setCursor("crosshair");var b=l(a);return ba.setPressed(b),bc.update(),bd.activateHandlers(w,u),be.watchKeys(),a.stopPropagation 9 | (),a.preventDefault(),!1}function w(a){ba.setCurrent(a),bc.update()}function z(){var b=a("
").addClass(i("tracker"));return a.browser.msie&&b.css({opacity:0,backgroundColor:"white"}),b}function bf(a){H.removeClass().addClass(i("holder")).addClass(a)}function bg(a,b){function t(){window.setTimeout(u,l)}var c=a[0]/U,e=a[1]/V,f=a[2]/U,g=a[3]/V;if(Y)return;var h=ba.flipCoords(c,e,f,g),i=ba.getFixed(),j=[i.x,i.y,i.x2,i.y2],k=j,l=d.animationDelay,m=h[0]-j[0],n=h[1]-j[1],o=h[2]-j[2],p=h[3]-j[3],q=0,r=d.swingSpeed;x=k[0],y=k[1],f=k[2],g=k[3],bc.animMode(!0);var s,u=function(){return function(){q+=(100-q)/r,k[0]=x+q/100*m,k[1]=y+q/100*n,k[2]=f+q/100*o,k[3]=g+q/100*p,q>=99.8&&(q=100),q<100?(bi(k),t()):(bc.done(),typeof b=="function"&&b.call(bt))}}();t()}function bh(a){bi([a[0]/U,a[1]/V,a[2]/U,a[3]/V]),d.onSelect.call(bt,t(ba.getFixed())),bc.enableHandles()}function bi(a){ba.setPressed([a[0],a[1]]),ba.setCurrent([a[2],a[3]]),bc.update()}function bj(){return t(ba.getFixed())}function bk(){return ba.getFixed()}function bl 10 | (a){m(a),bs()}function bm(){d.disabled=!0,bc.disableHandles(),bc.setCursor("default"),bd.setCursor("default")}function bn(){d.disabled=!1,bs()}function bo(){bc.done(),bd.activateHandlers(null,null)}function bp(){H.remove(),B.show(),a(b).removeData("Jcrop")}function bq(a,b){bc.release(),bm();var c=new Image;c.onload=function(){var e=c.width,f=c.height,g=d.boxWidth,h=d.boxHeight;E.width(e).height(f),E.attr("src",a),I.attr("src",a),s(E,g,h),F=E.width(),G=E.height(),I.width(F).height(G),N.width(F+M*2).height(G+M*2),H.width(F).height(G),bb.resize(F,G),bn(),typeof b=="function"&&b.call(bt)},c.src=a}function br(a,b,c){var e=b||d.bgColor;d.bgFade&&j()&&d.fadeTime&&!c?a.animate({backgroundColor:e},{queue:!1,duration:d.fadeTime}):a.css("backgroundColor",e)}function bs(a){d.allowResize?a?bc.enableOnly():bc.enableHandles():bc.disableHandles(),bd.setCursor(d.allowSelect?"crosshair":"default"),bc.setCursor(d.allowMove?"move":"default"),d.hasOwnProperty("trueSize")&&(U=d.trueSize[0]/F,V=d.trueSize[1]/G),d.hasOwnProperty("setSelect" 11 | )&&(bh(d.setSelect),bc.done(),delete d.setSelect),bb.refresh(),d.bgColor!=O&&(br(d.shade?bb.getShades():H,d.shade?d.shadeColor||d.bgColor:d.bgColor),O=d.bgColor),P!=d.bgOpacity&&(P=d.bgOpacity,d.shade?bb.refresh():bc.setBgOpacity(P)),Q=d.maxSize[0]||0,R=d.maxSize[1]||0,S=d.minSize[0]||0,T=d.minSize[1]||0,d.hasOwnProperty("outerImage")&&(E.attr("src",d.outerImage),delete d.outerImage),bc.refresh()}var d=a.extend({},a.Jcrop.defaults),e,f,g=!1;a.browser.msie&&a.browser.version.split(".")[0]==="6"&&(g=!0),typeof b!="object"&&(b=a(b)[0]),typeof c!="object"&&(c={}),m(c);var A={border:"none",visibility:"visible",margin:0,padding:0,position:"absolute",top:0,left:0},B=a(b),C=!0;if(b.tagName=="IMG"){if(B[0].width!=0&&B[0].height!=0)B.width(B[0].width),B.height(B[0].height);else{var D=new Image;D.src=B[0].src,B.width(D.width),B.height(D.height)}var E=B.clone().removeAttr("id").css(A).show();E.width(B.width()),E.height(B.height()),B.after(E).hide()}else E=B.css(A).show(),C=!1,d.shade===null&&(d.shade=!0);s(E,d.boxWidth,d. 12 | boxHeight);var F=E.width(),G=E.height(),H=a("
").width(F).height(G).addClass(i("holder")).css({position:"relative",backgroundColor:d.bgColor}).insertAfter(B).append(E);d.addClass&&H.addClass(d.addClass);var I=a("
"),J=a("
").width("100%").height("100%").css({zIndex:310,position:"absolute",overflow:"hidden"}),K=a("
").width("100%").height("100%").css("zIndex",320),L=a("
").css({position:"absolute",zIndex:600}).dblclick(function(){var a=ba.getFixed();d.onDblClick.call(bt,a)}).insertBefore(E).append(J,K);C&&(I=a("").attr("src",E.attr("src")).css(A).width(F).height(G),J.append(I)),g&&L.css({overflowY:"hidden"});var M=d.boundary,N=z().width(F+M*2).height(G+M*2).css({position:"absolute",top:h(-M),left:h(-M),zIndex:290}).mousedown(v),O=d.bgColor,P=d.bgOpacity,Q,R,S,T,U,V,W=!0,X,Y,Z;e=k(E);var _=function(){function a(){var a={},b=["touchstart","touchmove","touchend"],c=document.createElement("div"),d;try{for(d=0;da+f&&(f-=f+a),0>b+g&&(g-=g+b),GF&&(r=F,u=Math.abs((r-a)/f),s=k<0?b-u:u+b)):(r=c,u=l/f,s=k<0?b-u:b+u,s<0?(s=0,t=Math.abs((s-b)*f),r=j<0?a-t:t+a):s>G&&(s=G,t=Math.abs(s-b)*f,r=j<0?a-t:t+a)),r>a?(r-ah&&(r=a+h),s>b?s=b+(r-a)/f:s=b-(r-a)/f):rh&&(r=a-h),s>b?s=b+(a-r)/f:s=b-(a-r)/f),r<0?(a-=r,r=0):r>F&&(a-=r-F,r=F),s<0?(b-=s,s=0):s>G&&(b-=s-G,s=G),q(o(a,b,r,s))}function n(a){return a[0]<0&&(a[0]=0),a[1]<0&&(a[1]=0),a[0]>F&&(a[0]=F),a[1]>G&&(a[1]=G),[a[0],a[1]]}function o(a,b,c,d){var e=a,f=c,g=b,h=d;return cQ&&(c=d>0?a+Q:a-Q),R&&Math.abs(f)>R&&(e=f>0?b+R:b-R),T/V&&Math.abs(f)0?b+T/V:b-T/V),S/U&&Math.abs(d)0?a+S/U:a-S/U),a<0&&(c-=a,a-=a),b<0&&(e-=b,b-=b),c<0&& 15 | (a-=c,c-=c),e<0&&(b-=e,e-=e),c>F&&(g=c-F,a-=g,c-=g),e>G&&(g=e-G,b-=g,e-=g),a>F&&(g=a-G,e-=g,b-=g),b>G&&(g=b-G,e-=g,b-=g),q(o(a,b,c,e))}function q(a){return{x:a[0],y:a[1],x2:a[2],y2:a[3],w:a[2]-a[0],h:a[3]-a[1]}}var a=0,b=0,c=0,e=0,f,g;return{flipCoords:o,setPressed:h,setCurrent:i,getOffset:j,moveOffset:k,getCorner:l,getFixed:m}}(),bb=function(){function f(a,b){e.left.css({height:h(b)}),e.right.css({height:h(b)})}function g(){return i(ba.getFixed())}function i(a){e.top.css({left:h(a.x),width:h(a.w),height:h(a.y)}),e.bottom.css({top:h(a.y2),left:h(a.x),width:h(a.w),height:h(G-a.y2)}),e.right.css({left:h(a.x2),width:h(F-a.x2)}),e.left.css({width:h(a.x)})}function j(){return a("
").css({position:"absolute",backgroundColor:d.shadeColor||d.bgColor}).appendTo(c)}function k(){b||(b=!0,c.insertBefore(E),g(),bc.setBgOpacity(1,0,1),I.hide(),l(d.shadeColor||d.bgColor,1),bc.isAwake()?n(d.bgOpacity,1):n(1,1))}function l(a,b){br(p(),a,b)}function m(){b&&(c.remove(),I.show(),b=!1,bc.isAwake()?bc.setBgOpacity(d.bgOpacity 16 | ,1,1):(bc.setBgOpacity(1,1,1),bc.disableHandles()),br(H,0,1))}function n(a,e){b&&(d.bgFade&&!e?c.animate({opacity:1-a},{queue:!1,duration:d.fadeTime}):c.css({opacity:1-a}))}function o(){d.shade?k():m(),bc.isAwake()&&n(d.bgOpacity)}function p(){return c.children()}var b=!1,c=a("
").css({position:"absolute",zIndex:240,opacity:0}),e={top:j(),left:j().height(G),right:j().height(G),bottom:j()};return{update:g,updateRaw:i,getShades:p,setBgColor:l,enable:k,disable:m,resize:f,refresh:o,opacity:n}}(),bc=function(){function k(b){var c=a("
").css({position:"absolute",opacity:d.borderOpacity}).addClass(i(b));return J.append(c),c}function l(b,c){var d=a("
").mousedown(r(b)).css({cursor:b+"-resize",position:"absolute",zIndex:c}).addClass("ord-"+b);return _.support&&d.bind("touchstart.jcrop",_.createDragger(b)),K.append(d),d}function m(a){var b=d.handleSize;return l(a,c++).css({opacity:d.handleOpacity}).width(b).height(b).addClass(i("handle"))}function n(a){return l(a,c++).addClass("jcrop-dragbar")}function o 17 | (a){var b;for(b=0;b').css({position:"fixed",left:"-120px",width:"12px"}),c=a("
").css({position:"absolute",overflow:"hidden"}).append(b);return d.keySupport&&(b.keydown(i).blur(f),g||!d.fixedSupport?(b.css({position:"absolute",left:"-20px"}),c.append(b).insertBefore(E)):b.insertBefore(E)),{watchKeys:e}}();_.support&&N.bind("touchstart.jcrop",_.newSelection),K.hide(),bs(!0);var bt={setImage:bq,animateTo:bg,setSelect:bh,setOptions:bl,tellSelect:bj,tellScaled:bk,setClass:bf,disable:bm,enable:bn,cancel:bo,release:bc.release,destroy:bp,focus:be.watchKeys,getBounds:function(){return[F*U,G*V]},getWidgetSize:function(){return[F,G]},getScaleFactor:function(){return[U,V]},getOptions:function(){return d},ui:{holder:H,selection:L}};return a.browser.msie&&H.bind("selectstart",function(){return!1}),B.data("Jcrop",bt),bt},a.fn.Jcrop=function(b,c){var d;return this.each(function(){if(a(this).data("Jcrop")){if(b==="api")return a 21 | (this).data("Jcrop");a(this).data("Jcrop").setOptions(b)}else this.tagName=="IMG"?a.Jcrop.Loader(this,function(){a(this).css({display:"block",visibility:"hidden"}),d=a.Jcrop(this,b),a.isFunction(c)&&c.call(d)}):(a(this).css({display:"block",visibility:"hidden"}),d=a.Jcrop(this,b),a.isFunction(c)&&c.call(d))}),this},a.Jcrop.Loader=function(b,c,d){function g(){f.complete?(e.unbind(".jcloader"),a.isFunction(c)&&c.call(f)):window.setTimeout(g,50)}var e=a(b),f=e[0];e.bind("load.jcloader",g).bind("error.jcloader",function(b){e.unbind(".jcloader"),a.isFunction(d)&&d.call(f)}),f.complete&&a.isFunction(c)&&(e.unbind(".jcloader"),c.call(f))},a.Jcrop.defaults={allowSelect:!0,allowMove:!0,allowResize:!0,trackDocument:!0,baseClass:"jcrop",addClass:null,bgColor:"black",bgOpacity:.6,bgFade:!1,borderOpacity:.4,handleOpacity:.5,handleSize:7,aspectRatio:0,keySupport:!0,createHandles:["n","s","e","w","nw","ne","se","sw"],createDragbars:["n","s","e","w"],createBorders:["n","s","e","w"],drawBorders:!0,dragEdges:!0,fixedSupport:!0, 22 | touchSupport:null,shade:null,boxWidth:0,boxHeight:0,boundary:2,fadeTime:400,animationDelay:20,swingSpeed:3,minSelect:[0,0],maxSize:[0,0],minSize:[0,0],onChange:function(){},onSelect:function(){},onDblClick:function(){},onRelease:function(){}}})(jQuery); -------------------------------------------------------------------------------- /jcrop/js/jquery.Jcrop.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jquery.Jcrop.js v0.9.10 3 | * jQuery Image Cropping Plugin - released under MIT License 4 | * Author: Kelly Hallman 5 | * http://github.com/tapmodo/Jcrop 6 | * Copyright (c) 2008-2012 Tapmodo Interactive LLC {{{ 7 | * 8 | * Permission is hereby granted, free of charge, to any person 9 | * obtaining a copy of this software and associated documentation 10 | * files (the "Software"), to deal in the Software without 11 | * restriction, including without limitation the rights to use, 12 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the 14 | * Software is furnished to do so, subject to the following 15 | * conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | * OTHER DEALINGS IN THE SOFTWARE. 28 | * 29 | * }}} 30 | */ 31 | 32 | (function ($) { 33 | 34 | $.Jcrop = function (obj, opt) { 35 | var options = $.extend({}, $.Jcrop.defaults), 36 | docOffset, lastcurs, ie6mode = false; 37 | 38 | // Internal Methods {{{ 39 | function px(n) { 40 | return n + 'px'; 41 | } 42 | function cssClass(cl) { 43 | return options.baseClass + '-' + cl; 44 | } 45 | function supportsColorFade() { 46 | return $.fx.step.hasOwnProperty('backgroundColor'); 47 | } 48 | function getPos(obj) //{{{ 49 | { 50 | var pos = $(obj).offset(); 51 | return [pos.left, pos.top]; 52 | } 53 | //}}} 54 | function mouseAbs(e) //{{{ 55 | { 56 | return [(e.pageX - docOffset[0]), (e.pageY - docOffset[1])]; 57 | } 58 | //}}} 59 | function setOptions(opt) //{{{ 60 | { 61 | if (typeof(opt) !== 'object') opt = {}; 62 | options = $.extend(options, opt); 63 | 64 | $.each(['onChange','onSelect','onRelease','onDblClick'],function(i,e) { 65 | if (typeof(options[e]) !== 'function') options[e] = function () {}; 66 | }); 67 | } 68 | //}}} 69 | function startDragMode(mode, pos) //{{{ 70 | { 71 | docOffset = getPos($img); 72 | Tracker.setCursor(mode === 'move' ? mode : mode + '-resize'); 73 | 74 | if (mode === 'move') { 75 | return Tracker.activateHandlers(createMover(pos), doneSelect); 76 | } 77 | 78 | var fc = Coords.getFixed(); 79 | var opp = oppLockCorner(mode); 80 | var opc = Coords.getCorner(oppLockCorner(opp)); 81 | 82 | Coords.setPressed(Coords.getCorner(opp)); 83 | Coords.setCurrent(opc); 84 | 85 | Tracker.activateHandlers(dragmodeHandler(mode, fc), doneSelect); 86 | } 87 | //}}} 88 | function dragmodeHandler(mode, f) //{{{ 89 | { 90 | return function (pos) { 91 | if (!options.aspectRatio) { 92 | switch (mode) { 93 | case 'e': 94 | pos[1] = f.y2; 95 | break; 96 | case 'w': 97 | pos[1] = f.y2; 98 | break; 99 | case 'n': 100 | pos[0] = f.x2; 101 | break; 102 | case 's': 103 | pos[0] = f.x2; 104 | break; 105 | } 106 | } else { 107 | switch (mode) { 108 | case 'e': 109 | pos[1] = f.y + 1; 110 | break; 111 | case 'w': 112 | pos[1] = f.y + 1; 113 | break; 114 | case 'n': 115 | pos[0] = f.x + 1; 116 | break; 117 | case 's': 118 | pos[0] = f.x + 1; 119 | break; 120 | } 121 | } 122 | Coords.setCurrent(pos); 123 | Selection.update(); 124 | }; 125 | } 126 | //}}} 127 | function createMover(pos) //{{{ 128 | { 129 | var lloc = pos; 130 | KeyManager.watchKeys(); 131 | 132 | return function (pos) { 133 | Coords.moveOffset([pos[0] - lloc[0], pos[1] - lloc[1]]); 134 | lloc = pos; 135 | 136 | Selection.update(); 137 | }; 138 | } 139 | //}}} 140 | function oppLockCorner(ord) //{{{ 141 | { 142 | switch (ord) { 143 | case 'n': 144 | return 'sw'; 145 | case 's': 146 | return 'nw'; 147 | case 'e': 148 | return 'nw'; 149 | case 'w': 150 | return 'ne'; 151 | case 'ne': 152 | return 'sw'; 153 | case 'nw': 154 | return 'se'; 155 | case 'se': 156 | return 'nw'; 157 | case 'sw': 158 | return 'ne'; 159 | } 160 | } 161 | //}}} 162 | function createDragger(ord) //{{{ 163 | { 164 | return function (e) { 165 | if (options.disabled) { 166 | return false; 167 | } 168 | if ((ord === 'move') && !options.allowMove) { 169 | return false; 170 | } 171 | 172 | // Fix position of crop area when dragged the very first time. 173 | // Necessary when crop image is in a hidden element when page is loaded. 174 | docOffset = getPos($img); 175 | 176 | btndown = true; 177 | startDragMode(ord, mouseAbs(e)); 178 | e.stopPropagation(); 179 | e.preventDefault(); 180 | return false; 181 | }; 182 | } 183 | //}}} 184 | function presize($obj, w, h) //{{{ 185 | { 186 | var nw = $obj.width(), 187 | nh = $obj.height(); 188 | if ((nw > w) && w > 0) { 189 | nw = w; 190 | nh = (w / $obj.width()) * $obj.height(); 191 | } 192 | if ((nh > h) && h > 0) { 193 | nh = h; 194 | nw = (h / $obj.height()) * $obj.width(); 195 | } 196 | xscale = $obj.width() / nw; 197 | yscale = $obj.height() / nh; 198 | $obj.width(nw).height(nh); 199 | } 200 | //}}} 201 | function unscale(c) //{{{ 202 | { 203 | return { 204 | x: c.x * xscale, 205 | y: c.y * yscale, 206 | x2: c.x2 * xscale, 207 | y2: c.y2 * yscale, 208 | w: c.w * xscale, 209 | h: c.h * yscale 210 | }; 211 | } 212 | //}}} 213 | function doneSelect(pos) //{{{ 214 | { 215 | var c = Coords.getFixed(); 216 | if ((c.w > options.minSelect[0]) && (c.h > options.minSelect[1])) { 217 | Selection.enableHandles(); 218 | Selection.done(); 219 | } else { 220 | Selection.release(); 221 | } 222 | Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default'); 223 | } 224 | //}}} 225 | function newSelection(e) //{{{ 226 | { 227 | if (options.disabled) { 228 | return false; 229 | } 230 | if (!options.allowSelect) { 231 | return false; 232 | } 233 | btndown = true; 234 | docOffset = getPos($img); 235 | Selection.disableHandles(); 236 | Tracker.setCursor('crosshair'); 237 | var pos = mouseAbs(e); 238 | Coords.setPressed(pos); 239 | Selection.update(); 240 | Tracker.activateHandlers(selectDrag, doneSelect); 241 | KeyManager.watchKeys(); 242 | 243 | e.stopPropagation(); 244 | e.preventDefault(); 245 | return false; 246 | } 247 | //}}} 248 | function selectDrag(pos) //{{{ 249 | { 250 | Coords.setCurrent(pos); 251 | Selection.update(); 252 | } 253 | //}}} 254 | function newTracker() //{{{ 255 | { 256 | var trk = $('
').addClass(cssClass('tracker')); 257 | if ($.browser.msie) { 258 | trk.css({ 259 | opacity: 0, 260 | backgroundColor: 'white' 261 | }); 262 | } 263 | return trk; 264 | } 265 | //}}} 266 | 267 | // }}} 268 | // Initialization {{{ 269 | // Sanitize some options {{{ 270 | if ($.browser.msie && ($.browser.version.split('.')[0] === '6')) { 271 | ie6mode = true; 272 | } 273 | if (typeof(obj) !== 'object') { 274 | obj = $(obj)[0]; 275 | } 276 | if (typeof(opt) !== 'object') { 277 | opt = {}; 278 | } 279 | // }}} 280 | setOptions(opt); 281 | // Initialize some jQuery objects {{{ 282 | // The values are SET on the image(s) for the interface 283 | // If the original image has any of these set, they will be reset 284 | // However, if you destroy() the Jcrop instance the original image's 285 | // character in the DOM will be as you left it. 286 | var img_css = { 287 | border: 'none', 288 | visibility: 'visible', 289 | margin: 0, 290 | padding: 0, 291 | position: 'absolute', 292 | top: 0, 293 | left: 0 294 | }; 295 | 296 | var $origimg = $(obj), 297 | img_mode = true; 298 | 299 | if (obj.tagName == 'IMG') { 300 | // Fix size of crop image. 301 | // Necessary when crop image is within a hidden element when page is loaded. 302 | if ($origimg[0].width != 0 && $origimg[0].height != 0) { 303 | // Obtain dimensions from contained img element. 304 | $origimg.width($origimg[0].width); 305 | $origimg.height($origimg[0].height); 306 | } else { 307 | // Obtain dimensions from temporary image in case the original is not loaded yet (e.g. IE 7.0). 308 | var tempImage = new Image(); 309 | tempImage.src = $origimg[0].src; 310 | $origimg.width(tempImage.width); 311 | $origimg.height(tempImage.height); 312 | } 313 | 314 | var $img = $origimg.clone().removeAttr('id').css(img_css).show(); 315 | 316 | $img.width($origimg.width()); 317 | $img.height($origimg.height()); 318 | $origimg.after($img).hide(); 319 | 320 | } else { 321 | $img = $origimg.css(img_css).show(); 322 | img_mode = false; 323 | if (options.shade === null) { options.shade = true; } 324 | } 325 | 326 | presize($img, options.boxWidth, options.boxHeight); 327 | 328 | var boundx = $img.width(), 329 | boundy = $img.height(), 330 | 331 | 332 | $div = $('
').width(boundx).height(boundy).addClass(cssClass('holder')).css({ 333 | position: 'relative', 334 | backgroundColor: options.bgColor 335 | }).insertAfter($origimg).append($img); 336 | 337 | if (options.addClass) { 338 | $div.addClass(options.addClass); 339 | } 340 | 341 | var $img2 = $('
'), 342 | 343 | $img_holder = $('
') 344 | .width('100%').height('100%').css({ 345 | zIndex: 310, 346 | position: 'absolute', 347 | overflow: 'hidden' 348 | }), 349 | 350 | $hdl_holder = $('
') 351 | .width('100%').height('100%').css('zIndex', 320), 352 | 353 | $sel = $('
') 354 | .css({ 355 | position: 'absolute', 356 | zIndex: 600 357 | }).dblclick(function(){ 358 | var c = Coords.getFixed(); 359 | options.onDblClick.call(api,c); 360 | }).insertBefore($img).append($img_holder, $hdl_holder); 361 | 362 | if (img_mode) { 363 | 364 | $img2 = $('') 365 | .attr('src', $img.attr('src')).css(img_css).width(boundx).height(boundy), 366 | 367 | $img_holder.append($img2); 368 | 369 | } 370 | 371 | if (ie6mode) { 372 | $sel.css({ 373 | overflowY: 'hidden' 374 | }); 375 | } 376 | 377 | var bound = options.boundary; 378 | var $trk = newTracker().width(boundx + (bound * 2)).height(boundy + (bound * 2)).css({ 379 | position: 'absolute', 380 | top: px(-bound), 381 | left: px(-bound), 382 | zIndex: 290 383 | }).mousedown(newSelection); 384 | 385 | /* }}} */ 386 | // Set more variables {{{ 387 | var bgcolor = options.bgColor, 388 | bgopacity = options.bgOpacity, 389 | xlimit, ylimit, xmin, ymin, xscale, yscale, enabled = true, 390 | btndown, animating, shift_down; 391 | 392 | docOffset = getPos($img); 393 | // }}} 394 | // }}} 395 | // Internal Modules {{{ 396 | // Touch Module {{{ 397 | var Touch = (function () { 398 | // Touch support detection function adapted (under MIT License) 399 | // from code by Jeffrey Sambells - http://github.com/iamamused/ 400 | function hasTouchSupport() { 401 | var support = {}, 402 | events = ['touchstart', 'touchmove', 'touchend'], 403 | el = document.createElement('div'), i; 404 | 405 | try { 406 | for(i=0; i x1 + ox) { 490 | ox -= ox + x1; 491 | } 492 | if (0 > y1 + oy) { 493 | oy -= oy + y1; 494 | } 495 | 496 | if (boundy < y2 + oy) { 497 | oy += boundy - (y2 + oy); 498 | } 499 | if (boundx < x2 + ox) { 500 | ox += boundx - (x2 + ox); 501 | } 502 | 503 | x1 += ox; 504 | x2 += ox; 505 | y1 += oy; 506 | y2 += oy; 507 | } 508 | //}}} 509 | function getCorner(ord) //{{{ 510 | { 511 | var c = getFixed(); 512 | switch (ord) { 513 | case 'ne': 514 | return [c.x2, c.y]; 515 | case 'nw': 516 | return [c.x, c.y]; 517 | case 'se': 518 | return [c.x2, c.y2]; 519 | case 'sw': 520 | return [c.x, c.y2]; 521 | } 522 | } 523 | //}}} 524 | function getFixed() //{{{ 525 | { 526 | if (!options.aspectRatio) { 527 | return getRect(); 528 | } 529 | // This function could use some optimization I think... 530 | var aspect = options.aspectRatio, 531 | min_x = options.minSize[0] / xscale, 532 | 533 | 534 | //min_y = options.minSize[1]/yscale, 535 | max_x = options.maxSize[0] / xscale, 536 | max_y = options.maxSize[1] / yscale, 537 | rw = x2 - x1, 538 | rh = y2 - y1, 539 | rwa = Math.abs(rw), 540 | rha = Math.abs(rh), 541 | real_ratio = rwa / rha, 542 | xx, yy, w, h; 543 | 544 | if (max_x === 0) { 545 | max_x = boundx * 10; 546 | } 547 | if (max_y === 0) { 548 | max_y = boundy * 10; 549 | } 550 | if (real_ratio < aspect) { 551 | yy = y2; 552 | w = rha * aspect; 553 | xx = rw < 0 ? x1 - w : w + x1; 554 | 555 | if (xx < 0) { 556 | xx = 0; 557 | h = Math.abs((xx - x1) / aspect); 558 | yy = rh < 0 ? y1 - h : h + y1; 559 | } else if (xx > boundx) { 560 | xx = boundx; 561 | h = Math.abs((xx - x1) / aspect); 562 | yy = rh < 0 ? y1 - h : h + y1; 563 | } 564 | } else { 565 | xx = x2; 566 | h = rwa / aspect; 567 | yy = rh < 0 ? y1 - h : y1 + h; 568 | if (yy < 0) { 569 | yy = 0; 570 | w = Math.abs((yy - y1) * aspect); 571 | xx = rw < 0 ? x1 - w : w + x1; 572 | } else if (yy > boundy) { 573 | yy = boundy; 574 | w = Math.abs(yy - y1) * aspect; 575 | xx = rw < 0 ? x1 - w : w + x1; 576 | } 577 | } 578 | 579 | // Magic %-) 580 | if (xx > x1) { // right side 581 | if (xx - x1 < min_x) { 582 | xx = x1 + min_x; 583 | } else if (xx - x1 > max_x) { 584 | xx = x1 + max_x; 585 | } 586 | if (yy > y1) { 587 | yy = y1 + (xx - x1) / aspect; 588 | } else { 589 | yy = y1 - (xx - x1) / aspect; 590 | } 591 | } else if (xx < x1) { // left side 592 | if (x1 - xx < min_x) { 593 | xx = x1 - min_x; 594 | } else if (x1 - xx > max_x) { 595 | xx = x1 - max_x; 596 | } 597 | if (yy > y1) { 598 | yy = y1 + (x1 - xx) / aspect; 599 | } else { 600 | yy = y1 - (x1 - xx) / aspect; 601 | } 602 | } 603 | 604 | if (xx < 0) { 605 | x1 -= xx; 606 | xx = 0; 607 | } else if (xx > boundx) { 608 | x1 -= xx - boundx; 609 | xx = boundx; 610 | } 611 | 612 | if (yy < 0) { 613 | y1 -= yy; 614 | yy = 0; 615 | } else if (yy > boundy) { 616 | y1 -= yy - boundy; 617 | yy = boundy; 618 | } 619 | 620 | return makeObj(flipCoords(x1, y1, xx, yy)); 621 | } 622 | //}}} 623 | function rebound(p) //{{{ 624 | { 625 | if (p[0] < 0) { 626 | p[0] = 0; 627 | } 628 | if (p[1] < 0) { 629 | p[1] = 0; 630 | } 631 | 632 | if (p[0] > boundx) { 633 | p[0] = boundx; 634 | } 635 | if (p[1] > boundy) { 636 | p[1] = boundy; 637 | } 638 | 639 | return [p[0], p[1]]; 640 | } 641 | //}}} 642 | function flipCoords(x1, y1, x2, y2) //{{{ 643 | { 644 | var xa = x1, 645 | xb = x2, 646 | ya = y1, 647 | yb = y2; 648 | if (x2 < x1) { 649 | xa = x2; 650 | xb = x1; 651 | } 652 | if (y2 < y1) { 653 | ya = y2; 654 | yb = y1; 655 | } 656 | return [xa, ya, xb, yb]; 657 | } 658 | //}}} 659 | function getRect() //{{{ 660 | { 661 | var xsize = x2 - x1, 662 | ysize = y2 - y1, 663 | delta; 664 | 665 | if (xlimit && (Math.abs(xsize) > xlimit)) { 666 | x2 = (xsize > 0) ? (x1 + xlimit) : (x1 - xlimit); 667 | } 668 | if (ylimit && (Math.abs(ysize) > ylimit)) { 669 | y2 = (ysize > 0) ? (y1 + ylimit) : (y1 - ylimit); 670 | } 671 | 672 | if (ymin / yscale && (Math.abs(ysize) < ymin / yscale)) { 673 | y2 = (ysize > 0) ? (y1 + ymin / yscale) : (y1 - ymin / yscale); 674 | } 675 | if (xmin / xscale && (Math.abs(xsize) < xmin / xscale)) { 676 | x2 = (xsize > 0) ? (x1 + xmin / xscale) : (x1 - xmin / xscale); 677 | } 678 | 679 | if (x1 < 0) { 680 | x2 -= x1; 681 | x1 -= x1; 682 | } 683 | if (y1 < 0) { 684 | y2 -= y1; 685 | y1 -= y1; 686 | } 687 | if (x2 < 0) { 688 | x1 -= x2; 689 | x2 -= x2; 690 | } 691 | if (y2 < 0) { 692 | y1 -= y2; 693 | y2 -= y2; 694 | } 695 | if (x2 > boundx) { 696 | delta = x2 - boundx; 697 | x1 -= delta; 698 | x2 -= delta; 699 | } 700 | if (y2 > boundy) { 701 | delta = y2 - boundy; 702 | y1 -= delta; 703 | y2 -= delta; 704 | } 705 | if (x1 > boundx) { 706 | delta = x1 - boundy; 707 | y2 -= delta; 708 | y1 -= delta; 709 | } 710 | if (y1 > boundy) { 711 | delta = y1 - boundy; 712 | y2 -= delta; 713 | y1 -= delta; 714 | } 715 | 716 | return makeObj(flipCoords(x1, y1, x2, y2)); 717 | } 718 | //}}} 719 | function makeObj(a) //{{{ 720 | { 721 | return { 722 | x: a[0], 723 | y: a[1], 724 | x2: a[2], 725 | y2: a[3], 726 | w: a[2] - a[0], 727 | h: a[3] - a[1] 728 | }; 729 | } 730 | //}}} 731 | 732 | return { 733 | flipCoords: flipCoords, 734 | setPressed: setPressed, 735 | setCurrent: setCurrent, 736 | getOffset: getOffset, 737 | moveOffset: moveOffset, 738 | getCorner: getCorner, 739 | getFixed: getFixed 740 | }; 741 | }()); 742 | 743 | //}}} 744 | // Shade Module {{{ 745 | var Shade = (function() { 746 | var enabled = false, 747 | holder = $('
').css({ 748 | position: 'absolute', 749 | zIndex: 240, 750 | opacity: 0 751 | }), 752 | shades = { 753 | top: createShade(), 754 | left: createShade().height(boundy), 755 | right: createShade().height(boundy), 756 | bottom: createShade() 757 | }; 758 | 759 | function resizeShades(w,h) { 760 | shades.left.css({ height: px(h) }); 761 | shades.right.css({ height: px(h) }); 762 | } 763 | function updateAuto() 764 | { 765 | return updateShade(Coords.getFixed()); 766 | } 767 | function updateShade(c) 768 | { 769 | shades.top.css({ 770 | left: px(c.x), 771 | width: px(c.w), 772 | height: px(c.y) 773 | }); 774 | shades.bottom.css({ 775 | top: px(c.y2), 776 | left: px(c.x), 777 | width: px(c.w), 778 | height: px(boundy-c.y2) 779 | }); 780 | shades.right.css({ 781 | left: px(c.x2), 782 | width: px(boundx-c.x2) 783 | }); 784 | shades.left.css({ 785 | width: px(c.x) 786 | }); 787 | } 788 | function createShade() { 789 | return $('
').css({ 790 | position: 'absolute', 791 | backgroundColor: options.shadeColor||options.bgColor 792 | }).appendTo(holder); 793 | } 794 | function enableShade() { 795 | if (!enabled) { 796 | enabled = true; 797 | holder.insertBefore($img); 798 | updateAuto(); 799 | Selection.setBgOpacity(1,0,1); 800 | $img2.hide(); 801 | 802 | setBgColor(options.shadeColor||options.bgColor,1); 803 | if (Selection.isAwake()) 804 | { 805 | setOpacity(options.bgOpacity,1); 806 | } 807 | else setOpacity(1,1); 808 | } 809 | } 810 | function setBgColor(color,now) { 811 | colorChangeMacro(getShades(),color,now); 812 | } 813 | function disableShade() { 814 | if (enabled) { 815 | holder.remove(); 816 | $img2.show(); 817 | enabled = false; 818 | if (Selection.isAwake()) { 819 | Selection.setBgOpacity(options.bgOpacity,1,1); 820 | } else { 821 | Selection.setBgOpacity(1,1,1); 822 | Selection.disableHandles(); 823 | } 824 | colorChangeMacro($div,0,1); 825 | } 826 | } 827 | function setOpacity(opacity,now) { 828 | if (enabled) { 829 | if (options.bgFade && !now) { 830 | holder.animate({ 831 | opacity: 1-opacity 832 | },{ 833 | queue: false, 834 | duration: options.fadeTime 835 | }); 836 | } 837 | else holder.css({opacity:1-opacity}); 838 | } 839 | } 840 | function refreshAll() { 841 | options.shade ? enableShade() : disableShade(); 842 | if (Selection.isAwake()) setOpacity(options.bgOpacity); 843 | } 844 | function getShades() { 845 | return holder.children(); 846 | } 847 | 848 | return { 849 | update: updateAuto, 850 | updateRaw: updateShade, 851 | getShades: getShades, 852 | setBgColor: setBgColor, 853 | enable: enableShade, 854 | disable: disableShade, 855 | resize: resizeShades, 856 | refresh: refreshAll, 857 | opacity: setOpacity 858 | }; 859 | }()); 860 | // }}} 861 | // Selection Module {{{ 862 | var Selection = (function () { 863 | var awake, 864 | hdep = 370, 865 | borders = {}, 866 | handle = {}, 867 | dragbar = {}, 868 | seehandles = false; 869 | 870 | // Private Methods 871 | function insertBorder(type) //{{{ 872 | { 873 | var jq = $('
').css({ 874 | position: 'absolute', 875 | opacity: options.borderOpacity 876 | }).addClass(cssClass(type)); 877 | $img_holder.append(jq); 878 | return jq; 879 | } 880 | //}}} 881 | function dragDiv(ord, zi) //{{{ 882 | { 883 | var jq = $('
').mousedown(createDragger(ord)).css({ 884 | cursor: ord + '-resize', 885 | position: 'absolute', 886 | zIndex: zi 887 | }).addClass('ord-'+ord); 888 | 889 | if (Touch.support) { 890 | jq.bind('touchstart.jcrop', Touch.createDragger(ord)); 891 | } 892 | 893 | $hdl_holder.append(jq); 894 | return jq; 895 | } 896 | //}}} 897 | function insertHandle(ord) //{{{ 898 | { 899 | var hs = options.handleSize; 900 | return dragDiv(ord, hdep++).css({ 901 | opacity: options.handleOpacity 902 | }).width(hs).height(hs).addClass(cssClass('handle')); 903 | } 904 | //}}} 905 | function insertDragbar(ord) //{{{ 906 | { 907 | return dragDiv(ord, hdep++).addClass('jcrop-dragbar'); 908 | } 909 | //}}} 910 | function createDragbars(li) //{{{ 911 | { 912 | var i; 913 | for (i = 0; i < li.length; i++) { 914 | dragbar[li[i]] = insertDragbar(li[i]); 915 | } 916 | } 917 | //}}} 918 | function createBorders(li) //{{{ 919 | { 920 | var cl,i; 921 | for (i = 0; i < li.length; i++) { 922 | switch(li[i]){ 923 | case'n': cl='hline'; break; 924 | case's': cl='hline bottom'; break; 925 | case'e': cl='vline right'; break; 926 | case'w': cl='vline'; break; 927 | } 928 | borders[li[i]] = insertBorder(cl); 929 | } 930 | } 931 | //}}} 932 | function createHandles(li) //{{{ 933 | { 934 | var i; 935 | for (i = 0; i < li.length; i++) { 936 | handle[li[i]] = insertHandle(li[i]); 937 | } 938 | } 939 | //}}} 940 | function moveto(x, y) //{{{ 941 | { 942 | if (!options.shade) { 943 | $img2.css({ 944 | top: px(-y), 945 | left: px(-x) 946 | }); 947 | } 948 | $sel.css({ 949 | top: px(y), 950 | left: px(x) 951 | }); 952 | } 953 | //}}} 954 | function resize(w, h) //{{{ 955 | { 956 | $sel.width(w).height(h); 957 | } 958 | //}}} 959 | function refresh() //{{{ 960 | { 961 | var c = Coords.getFixed(); 962 | 963 | Coords.setPressed([c.x, c.y]); 964 | Coords.setCurrent([c.x2, c.y2]); 965 | 966 | updateVisible(); 967 | } 968 | //}}} 969 | 970 | // Internal Methods 971 | function updateVisible(select) //{{{ 972 | { 973 | if (awake) { 974 | return update(select); 975 | } 976 | } 977 | //}}} 978 | function update(select) //{{{ 979 | { 980 | var c = Coords.getFixed(); 981 | 982 | resize(c.w, c.h); 983 | moveto(c.x, c.y); 984 | if (options.shade) Shade.updateRaw(c); 985 | 986 | awake || show(); 987 | 988 | if (select) { 989 | options.onSelect.call(api, unscale(c)); 990 | } else { 991 | options.onChange.call(api, unscale(c)); 992 | } 993 | } 994 | //}}} 995 | function setBgOpacity(opacity,force,now) //{{{ 996 | { 997 | if (!awake && !force) return; 998 | if (options.bgFade && !now) { 999 | $img.animate({ 1000 | opacity: opacity 1001 | },{ 1002 | queue: false, 1003 | duration: options.fadeTime 1004 | }); 1005 | } else { 1006 | $img.css('opacity', opacity); 1007 | } 1008 | } 1009 | //}}} 1010 | function show() //{{{ 1011 | { 1012 | $sel.show(); 1013 | 1014 | if (options.shade) Shade.opacity(bgopacity); 1015 | else setBgOpacity(bgopacity,true); 1016 | 1017 | awake = true; 1018 | } 1019 | //}}} 1020 | function release() //{{{ 1021 | { 1022 | disableHandles(); 1023 | $sel.hide(); 1024 | 1025 | if (options.shade) Shade.opacity(1); 1026 | else setBgOpacity(1); 1027 | 1028 | awake = false; 1029 | options.onRelease.call(api); 1030 | } 1031 | //}}} 1032 | function showHandles() //{{{ 1033 | { 1034 | if (seehandles) { 1035 | $hdl_holder.show(); 1036 | } 1037 | } 1038 | //}}} 1039 | function enableHandles() //{{{ 1040 | { 1041 | seehandles = true; 1042 | if (options.allowResize) { 1043 | $hdl_holder.show(); 1044 | return true; 1045 | } 1046 | } 1047 | //}}} 1048 | function disableHandles() //{{{ 1049 | { 1050 | seehandles = false; 1051 | $hdl_holder.hide(); 1052 | } 1053 | //}}} 1054 | function animMode(v) //{{{ 1055 | { 1056 | if (animating === v) { 1057 | disableHandles(); 1058 | } else { 1059 | enableHandles(); 1060 | } 1061 | } 1062 | //}}} 1063 | function done() //{{{ 1064 | { 1065 | animMode(false); 1066 | refresh(); 1067 | } 1068 | //}}} 1069 | // Insert draggable elements {{{ 1070 | // Insert border divs for outline 1071 | 1072 | if (options.dragEdges && $.isArray(options.createDragbars)) 1073 | createDragbars(options.createDragbars); 1074 | 1075 | if ($.isArray(options.createHandles)) 1076 | createHandles(options.createHandles); 1077 | 1078 | if (options.drawBorders && $.isArray(options.createBorders)) 1079 | createBorders(options.createBorders); 1080 | 1081 | //}}} 1082 | 1083 | // This is a hack for iOS5 to support drag/move touch functionality 1084 | $(document).bind('touchstart.jcrop-ios',function(e) { 1085 | if ($(e.currentTarget).hasClass('jcrop-tracker')) e.stopPropagation(); 1086 | }); 1087 | 1088 | var $track = newTracker().mousedown(createDragger('move')).css({ 1089 | cursor: 'move', 1090 | position: 'absolute', 1091 | zIndex: 360 1092 | }); 1093 | 1094 | if (Touch.support) { 1095 | $track.bind('touchstart.jcrop', Touch.createDragger('move')); 1096 | } 1097 | 1098 | $img_holder.append($track); 1099 | disableHandles(); 1100 | 1101 | return { 1102 | updateVisible: updateVisible, 1103 | update: update, 1104 | release: release, 1105 | refresh: refresh, 1106 | isAwake: function () { 1107 | return awake; 1108 | }, 1109 | setCursor: function (cursor) { 1110 | $track.css('cursor', cursor); 1111 | }, 1112 | enableHandles: enableHandles, 1113 | enableOnly: function () { 1114 | seehandles = true; 1115 | }, 1116 | showHandles: showHandles, 1117 | disableHandles: disableHandles, 1118 | animMode: animMode, 1119 | setBgOpacity: setBgOpacity, 1120 | done: done 1121 | }; 1122 | }()); 1123 | 1124 | //}}} 1125 | // Tracker Module {{{ 1126 | var Tracker = (function () { 1127 | var onMove = function () {}, 1128 | onDone = function () {}, 1129 | trackDoc = options.trackDocument; 1130 | 1131 | function toFront() //{{{ 1132 | { 1133 | $trk.css({ 1134 | zIndex: 450 1135 | }); 1136 | if (Touch.support) { 1137 | $(document) 1138 | .bind('touchmove.jcrop', trackTouchMove) 1139 | .bind('touchend.jcrop', trackTouchEnd); 1140 | } 1141 | if (trackDoc) { 1142 | $(document) 1143 | .bind('mousemove.jcrop',trackMove) 1144 | .bind('mouseup.jcrop',trackUp); 1145 | } 1146 | } 1147 | //}}} 1148 | function toBack() //{{{ 1149 | { 1150 | $trk.css({ 1151 | zIndex: 290 1152 | }); 1153 | $(document).unbind('.jcrop'); 1154 | } 1155 | //}}} 1156 | function trackMove(e) //{{{ 1157 | { 1158 | onMove(mouseAbs(e)); 1159 | return false; 1160 | } 1161 | //}}} 1162 | function trackUp(e) //{{{ 1163 | { 1164 | e.preventDefault(); 1165 | e.stopPropagation(); 1166 | 1167 | if (btndown) { 1168 | btndown = false; 1169 | 1170 | onDone(mouseAbs(e)); 1171 | 1172 | if (Selection.isAwake()) { 1173 | options.onSelect.call(api, unscale(Coords.getFixed())); 1174 | } 1175 | 1176 | toBack(); 1177 | onMove = function () {}; 1178 | onDone = function () {}; 1179 | } 1180 | 1181 | return false; 1182 | } 1183 | //}}} 1184 | function activateHandlers(move, done) //{{{ 1185 | { 1186 | btndown = true; 1187 | onMove = move; 1188 | onDone = done; 1189 | toFront(); 1190 | return false; 1191 | } 1192 | //}}} 1193 | function trackTouchMove(e) //{{{ 1194 | { 1195 | e.pageX = e.originalEvent.changedTouches[0].pageX; 1196 | e.pageY = e.originalEvent.changedTouches[0].pageY; 1197 | return trackMove(e); 1198 | } 1199 | //}}} 1200 | function trackTouchEnd(e) //{{{ 1201 | { 1202 | e.pageX = e.originalEvent.changedTouches[0].pageX; 1203 | e.pageY = e.originalEvent.changedTouches[0].pageY; 1204 | return trackUp(e); 1205 | } 1206 | //}}} 1207 | function setCursor(t) //{{{ 1208 | { 1209 | $trk.css('cursor', t); 1210 | } 1211 | //}}} 1212 | 1213 | if (!trackDoc) { 1214 | $trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp); 1215 | } 1216 | 1217 | $img.before($trk); 1218 | return { 1219 | activateHandlers: activateHandlers, 1220 | setCursor: setCursor 1221 | }; 1222 | }()); 1223 | //}}} 1224 | // KeyManager Module {{{ 1225 | var KeyManager = (function () { 1226 | var $keymgr = $('').css({ 1227 | position: 'fixed', 1228 | left: '-120px', 1229 | width: '12px' 1230 | }), 1231 | $keywrap = $('
').css({ 1232 | position: 'absolute', 1233 | overflow: 'hidden' 1234 | }).append($keymgr); 1235 | 1236 | function watchKeys() //{{{ 1237 | { 1238 | if (options.keySupport) { 1239 | $keymgr.show(); 1240 | $keymgr.focus(); 1241 | } 1242 | } 1243 | //}}} 1244 | function onBlur(e) //{{{ 1245 | { 1246 | $keymgr.hide(); 1247 | } 1248 | //}}} 1249 | function doNudge(e, x, y) //{{{ 1250 | { 1251 | if (options.allowMove) { 1252 | Coords.moveOffset([x, y]); 1253 | Selection.updateVisible(true); 1254 | } 1255 | e.preventDefault(); 1256 | e.stopPropagation(); 1257 | } 1258 | //}}} 1259 | function parseKey(e) //{{{ 1260 | { 1261 | if (e.ctrlKey || e.metaKey) { 1262 | return true; 1263 | } 1264 | shift_down = e.shiftKey ? true : false; 1265 | var nudge = shift_down ? 10 : 1; 1266 | 1267 | switch (e.keyCode) { 1268 | case 37: 1269 | doNudge(e, -nudge, 0); 1270 | break; 1271 | case 39: 1272 | doNudge(e, nudge, 0); 1273 | break; 1274 | case 38: 1275 | doNudge(e, 0, -nudge); 1276 | break; 1277 | case 40: 1278 | doNudge(e, 0, nudge); 1279 | break; 1280 | case 27: 1281 | if (options.allowSelect) Selection.release(); 1282 | break; 1283 | case 9: 1284 | return true; 1285 | } 1286 | 1287 | return false; 1288 | } 1289 | //}}} 1290 | 1291 | if (options.keySupport) { 1292 | $keymgr.keydown(parseKey).blur(onBlur); 1293 | if (ie6mode || !options.fixedSupport) { 1294 | $keymgr.css({ 1295 | position: 'absolute', 1296 | left: '-20px' 1297 | }); 1298 | $keywrap.append($keymgr).insertBefore($img); 1299 | } else { 1300 | $keymgr.insertBefore($img); 1301 | } 1302 | } 1303 | 1304 | 1305 | return { 1306 | watchKeys: watchKeys 1307 | }; 1308 | }()); 1309 | //}}} 1310 | // }}} 1311 | // API methods {{{ 1312 | function setClass(cname) //{{{ 1313 | { 1314 | $div.removeClass().addClass(cssClass('holder')).addClass(cname); 1315 | } 1316 | //}}} 1317 | function animateTo(a, callback) //{{{ 1318 | { 1319 | var x1 = a[0] / xscale, 1320 | y1 = a[1] / yscale, 1321 | x2 = a[2] / xscale, 1322 | y2 = a[3] / yscale; 1323 | 1324 | if (animating) { 1325 | return; 1326 | } 1327 | 1328 | var animto = Coords.flipCoords(x1, y1, x2, y2), 1329 | c = Coords.getFixed(), 1330 | initcr = [c.x, c.y, c.x2, c.y2], 1331 | animat = initcr, 1332 | interv = options.animationDelay, 1333 | ix1 = animto[0] - initcr[0], 1334 | iy1 = animto[1] - initcr[1], 1335 | ix2 = animto[2] - initcr[2], 1336 | iy2 = animto[3] - initcr[3], 1337 | pcent = 0, 1338 | velocity = options.swingSpeed; 1339 | 1340 | x = animat[0]; 1341 | y = animat[1]; 1342 | x2 = animat[2]; 1343 | y2 = animat[3]; 1344 | 1345 | Selection.animMode(true); 1346 | var anim_timer; 1347 | 1348 | function queueAnimator() { 1349 | window.setTimeout(animator, interv); 1350 | } 1351 | var animator = (function () { 1352 | return function () { 1353 | pcent += (100 - pcent) / velocity; 1354 | 1355 | animat[0] = x + ((pcent / 100) * ix1); 1356 | animat[1] = y + ((pcent / 100) * iy1); 1357 | animat[2] = x2 + ((pcent / 100) * ix2); 1358 | animat[3] = y2 + ((pcent / 100) * iy2); 1359 | 1360 | if (pcent >= 99.8) { 1361 | pcent = 100; 1362 | } 1363 | if (pcent < 100) { 1364 | setSelectRaw(animat); 1365 | queueAnimator(); 1366 | } else { 1367 | Selection.done(); 1368 | if (typeof(callback) === 'function') { 1369 | callback.call(api); 1370 | } 1371 | } 1372 | }; 1373 | }()); 1374 | queueAnimator(); 1375 | } 1376 | //}}} 1377 | function setSelect(rect) //{{{ 1378 | { 1379 | setSelectRaw([rect[0] / xscale, rect[1] / yscale, rect[2] / xscale, rect[3] / yscale]); 1380 | options.onSelect.call(api, unscale(Coords.getFixed())); 1381 | Selection.enableHandles(); 1382 | } 1383 | //}}} 1384 | function setSelectRaw(l) //{{{ 1385 | { 1386 | Coords.setPressed([l[0], l[1]]); 1387 | Coords.setCurrent([l[2], l[3]]); 1388 | Selection.update(); 1389 | } 1390 | //}}} 1391 | function tellSelect() //{{{ 1392 | { 1393 | return unscale(Coords.getFixed()); 1394 | } 1395 | //}}} 1396 | function tellScaled() //{{{ 1397 | { 1398 | return Coords.getFixed(); 1399 | } 1400 | //}}} 1401 | function setOptionsNew(opt) //{{{ 1402 | { 1403 | setOptions(opt); 1404 | interfaceUpdate(); 1405 | } 1406 | //}}} 1407 | function disableCrop() //{{{ 1408 | { 1409 | options.disabled = true; 1410 | Selection.disableHandles(); 1411 | Selection.setCursor('default'); 1412 | Tracker.setCursor('default'); 1413 | } 1414 | //}}} 1415 | function enableCrop() //{{{ 1416 | { 1417 | options.disabled = false; 1418 | interfaceUpdate(); 1419 | } 1420 | //}}} 1421 | function cancelCrop() //{{{ 1422 | { 1423 | Selection.done(); 1424 | Tracker.activateHandlers(null, null); 1425 | } 1426 | //}}} 1427 | function destroy() //{{{ 1428 | { 1429 | $div.remove(); 1430 | $origimg.show(); 1431 | $(obj).removeData('Jcrop'); 1432 | } 1433 | //}}} 1434 | function setImage(src, callback) //{{{ 1435 | { 1436 | Selection.release(); 1437 | disableCrop(); 1438 | var img = new Image(); 1439 | img.onload = function () { 1440 | var iw = img.width; 1441 | var ih = img.height; 1442 | var bw = options.boxWidth; 1443 | var bh = options.boxHeight; 1444 | $img.width(iw).height(ih); 1445 | $img.attr('src', src); 1446 | $img2.attr('src', src); 1447 | presize($img, bw, bh); 1448 | boundx = $img.width(); 1449 | boundy = $img.height(); 1450 | $img2.width(boundx).height(boundy); 1451 | $trk.width(boundx + (bound * 2)).height(boundy + (bound * 2)); 1452 | $div.width(boundx).height(boundy); 1453 | Shade.resize(boundx,boundy); 1454 | enableCrop(); 1455 | 1456 | if (typeof(callback) === 'function') { 1457 | callback.call(api); 1458 | } 1459 | }; 1460 | img.src = src; 1461 | } 1462 | //}}} 1463 | function colorChangeMacro($obj,color,now) { 1464 | var mycolor = color || options.bgColor; 1465 | if (options.bgFade && supportsColorFade() && options.fadeTime && !now) { 1466 | $obj.animate({ 1467 | backgroundColor: mycolor 1468 | }, { 1469 | queue: false, 1470 | duration: options.fadeTime 1471 | }); 1472 | } else { 1473 | $obj.css('backgroundColor', mycolor); 1474 | } 1475 | } 1476 | function interfaceUpdate(alt) //{{{ 1477 | // This method tweaks the interface based on options object. 1478 | // Called when options are changed and at end of initialization. 1479 | { 1480 | if (options.allowResize) { 1481 | if (alt) { 1482 | Selection.enableOnly(); 1483 | } else { 1484 | Selection.enableHandles(); 1485 | } 1486 | } else { 1487 | Selection.disableHandles(); 1488 | } 1489 | 1490 | Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default'); 1491 | Selection.setCursor(options.allowMove ? 'move' : 'default'); 1492 | 1493 | if (options.hasOwnProperty('trueSize')) { 1494 | xscale = options.trueSize[0] / boundx; 1495 | yscale = options.trueSize[1] / boundy; 1496 | } 1497 | 1498 | if (options.hasOwnProperty('setSelect')) { 1499 | setSelect(options.setSelect); 1500 | Selection.done(); 1501 | delete(options.setSelect); 1502 | } 1503 | 1504 | Shade.refresh(); 1505 | 1506 | if (options.bgColor != bgcolor) { 1507 | colorChangeMacro( 1508 | options.shade? Shade.getShades(): $div, 1509 | options.shade? 1510 | (options.shadeColor || options.bgColor): 1511 | options.bgColor 1512 | ); 1513 | bgcolor = options.bgColor; 1514 | } 1515 | 1516 | if (bgopacity != options.bgOpacity) { 1517 | bgopacity = options.bgOpacity; 1518 | if (options.shade) Shade.refresh(); 1519 | else Selection.setBgOpacity(bgopacity); 1520 | } 1521 | 1522 | xlimit = options.maxSize[0] || 0; 1523 | ylimit = options.maxSize[1] || 0; 1524 | xmin = options.minSize[0] || 0; 1525 | ymin = options.minSize[1] || 0; 1526 | 1527 | if (options.hasOwnProperty('outerImage')) { 1528 | $img.attr('src', options.outerImage); 1529 | delete(options.outerImage); 1530 | } 1531 | 1532 | Selection.refresh(); 1533 | } 1534 | //}}} 1535 | //}}} 1536 | 1537 | if (Touch.support) $trk.bind('touchstart.jcrop', Touch.newSelection); 1538 | 1539 | $hdl_holder.hide(); 1540 | interfaceUpdate(true); 1541 | 1542 | var api = { 1543 | setImage: setImage, 1544 | animateTo: animateTo, 1545 | setSelect: setSelect, 1546 | setOptions: setOptionsNew, 1547 | tellSelect: tellSelect, 1548 | tellScaled: tellScaled, 1549 | setClass: setClass, 1550 | 1551 | disable: disableCrop, 1552 | enable: enableCrop, 1553 | cancel: cancelCrop, 1554 | release: Selection.release, 1555 | destroy: destroy, 1556 | 1557 | focus: KeyManager.watchKeys, 1558 | 1559 | getBounds: function () { 1560 | return [boundx * xscale, boundy * yscale]; 1561 | }, 1562 | getWidgetSize: function () { 1563 | return [boundx, boundy]; 1564 | }, 1565 | getScaleFactor: function () { 1566 | return [xscale, yscale]; 1567 | }, 1568 | getOptions: function() { 1569 | // careful: internal values are returned 1570 | return options; 1571 | }, 1572 | 1573 | ui: { 1574 | holder: $div, 1575 | selection: $sel 1576 | } 1577 | }; 1578 | 1579 | if ($.browser.msie) 1580 | $div.bind('selectstart', function () { return false; }); 1581 | 1582 | $origimg.data('Jcrop', api); 1583 | return api; 1584 | }; 1585 | $.fn.Jcrop = function (options, callback) //{{{ 1586 | { 1587 | var api; 1588 | // Iterate over each object, attach Jcrop 1589 | this.each(function () { 1590 | // If we've already attached to this object 1591 | if ($(this).data('Jcrop')) { 1592 | // The API can be requested this way (undocumented) 1593 | if (options === 'api') return $(this).data('Jcrop'); 1594 | // Otherwise, we just reset the options... 1595 | else $(this).data('Jcrop').setOptions(options); 1596 | } 1597 | // If we haven't been attached, preload and attach 1598 | else { 1599 | if (this.tagName == 'IMG') 1600 | $.Jcrop.Loader(this,function(){ 1601 | $(this).css({display:'block',visibility:'hidden'}); 1602 | api = $.Jcrop(this, options); 1603 | if ($.isFunction(callback)) callback.call(api); 1604 | }); 1605 | else { 1606 | $(this).css({display:'block',visibility:'hidden'}); 1607 | api = $.Jcrop(this, options); 1608 | if ($.isFunction(callback)) callback.call(api); 1609 | } 1610 | } 1611 | }); 1612 | 1613 | // Return "this" so the object is chainable (jQuery-style) 1614 | return this; 1615 | }; 1616 | //}}} 1617 | // $.Jcrop.Loader - basic image loader {{{ 1618 | 1619 | $.Jcrop.Loader = function(imgobj,success,error){ 1620 | var $img = $(imgobj), img = $img[0]; 1621 | 1622 | function completeCheck(){ 1623 | if (img.complete) { 1624 | $img.unbind('.jcloader'); 1625 | if ($.isFunction(success)) success.call(img); 1626 | } 1627 | else window.setTimeout(completeCheck,50); 1628 | } 1629 | 1630 | $img 1631 | .bind('load.jcloader',completeCheck) 1632 | .bind('error.jcloader',function(e){ 1633 | $img.unbind('.jcloader'); 1634 | if ($.isFunction(error)) error.call(img); 1635 | }); 1636 | 1637 | if (img.complete && $.isFunction(success)){ 1638 | $img.unbind('.jcloader'); 1639 | success.call(img); 1640 | } 1641 | }; 1642 | 1643 | //}}} 1644 | // Global Defaults {{{ 1645 | $.Jcrop.defaults = { 1646 | 1647 | // Basic Settings 1648 | allowSelect: true, 1649 | allowMove: true, 1650 | allowResize: true, 1651 | 1652 | trackDocument: true, 1653 | 1654 | // Styling Options 1655 | baseClass: 'jcrop', 1656 | addClass: null, 1657 | bgColor: 'black', 1658 | bgOpacity: 0.6, 1659 | bgFade: false, 1660 | borderOpacity: 0.4, 1661 | handleOpacity: 0.5, 1662 | handleSize: 7, 1663 | 1664 | aspectRatio: 0, 1665 | keySupport: true, 1666 | createHandles: ['n','s','e','w','nw','ne','se','sw'], 1667 | createDragbars: ['n','s','e','w'], 1668 | createBorders: ['n','s','e','w'], 1669 | drawBorders: true, 1670 | dragEdges: true, 1671 | fixedSupport: true, 1672 | touchSupport: null, 1673 | 1674 | shade: null, 1675 | 1676 | boxWidth: 0, 1677 | boxHeight: 0, 1678 | boundary: 2, 1679 | fadeTime: 400, 1680 | animationDelay: 20, 1681 | swingSpeed: 3, 1682 | 1683 | minSelect: [0, 0], 1684 | maxSize: [0, 0], 1685 | minSize: [0, 0], 1686 | 1687 | // Callbacks / Event Handlers 1688 | onChange: function () {}, 1689 | onSelect: function () {}, 1690 | onDblClick: function () {}, 1691 | onRelease: function () {} 1692 | }; 1693 | 1694 | // }}} 1695 | }(jQuery)); 1696 | --------------------------------------------------------------------------------