├── .gitignore ├── README.md ├── cors ├── postmessage.html └── result.html ├── css ├── Jcrop.gif ├── bootstrap-ie6.min.css ├── bootstrap-image-gallery.css ├── bootstrap-image-gallery.min.css ├── bootstrap-responsive.css ├── bootstrap-responsive.min.css ├── bootstrap.css ├── bootstrap.min.css ├── jquery.Jcrop.css ├── jquery.Jcrop.min.css ├── jquery.fileupload-ui.css ├── jquery.furac.ui.css └── style.css ├── gitpull.php ├── img ├── glyphicons-halflings-white.png ├── glyphicons-halflings.png ├── loading.gif └── progressbar.gif ├── index.html ├── js ├── ZeroClipboard.swf ├── bootstrap-image-gallery.min.js ├── bootstrap.min.js ├── canvas-to-blob.min.js ├── cors │ ├── jquery.postmessage-transport.js │ └── jquery.xdr-transport.js ├── jquery.Jcrop.js ├── jquery.Jcrop.min.js ├── jquery.fileupload-fp.js ├── jquery.fileupload-ui.js ├── jquery.fileupload.js ├── jquery.iframe-transport.js ├── jquery.zclip.js ├── load-image.min.js ├── locale.js ├── main.js ├── tmpl.min.js └── vendor │ └── jquery.ui.widget.js ├── package.json ├── server ├── gae-go │ ├── app.yaml │ ├── app │ │ └── main.go │ ├── resize │ │ └── resize.go │ └── static │ │ ├── favicon.ico │ │ └── robots.txt ├── gae-python │ ├── app.yaml │ ├── main.py │ └── static │ │ ├── favicon.ico │ │ └── robots.txt ├── node │ ├── .gitignore │ ├── package.json │ ├── public │ │ └── files │ │ │ └── thumbnail │ │ │ └── .gitignore │ ├── server.js │ └── tmp │ │ └── .gitignore └── php │ ├── LiquenImg.php │ ├── config_liquen.ini │ ├── files │ ├── .htaccess │ ├── DSC02004 - agaricus arvensis.JPG │ ├── DSC_9066 -rl.jpg │ ├── DSC_9066 -rl.jpg_w900_cx475_cy254_cw869_ch483.jpg │ ├── DSC_9073 - COLLIGUAY. Colliguaya odorifera.JPG │ ├── DSC_9095.JPG │ └── DSC_9114.JPG │ ├── image_crop_and_size.php │ ├── index.php │ ├── thumbnails │ ├── .htaccess │ ├── DSC02004 - agaricus arvensis.JPG │ ├── DSC02004 - agaricus arvensis.JPG_w932_cx48_cy612_cw2696_ch923.jpg_w80.jpg │ ├── DSC_9066 -rl.jpg │ ├── DSC_9066 -rl.jpg_w900_cx475_cy254_cw869_ch483.jpg │ ├── DSC_9073 - COLLIGUAY. Colliguaya odorifera.JPG │ ├── DSC_9095.JPG │ └── DSC_9114.JPG │ └── upload.class.php └── test ├── index.html └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | assets/ 4 | server/php/files/ 5 | server/php/thumbnails/ 6 | x3.php 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jQuery File Upload, Resize and Crop Plugin 2 | Modified by Agustín Amenabar 3 | 4 | ## Setup instructions 5 | * [How to setup the plugin on your website](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup) 6 | * [How to use only the basic plugin (minimal setup guide).](https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin) 7 | 8 | ## Features 9 | * **Multiple file upload:** 10 | Allows to select multiple files at once and upload them simultaneously. 11 | * **Drag & Drop support:** 12 | Allows to upload files by dragging them from your desktop or filemanager and dropping them on your browser window. 13 | * **Upload progress bar:** 14 | Shows a progress bar indicating the upload progress for individual files and for all uploads combined. 15 | * **Cancelable uploads:** 16 | Individual file uploads can be canceled to stop the upload progress. 17 | * **Resumable uploads:** 18 | Aborted uploads can be resumed with browsers supporting the Blob API. 19 | * **Chunked uploads:** 20 | Large files can be uploaded in smaller chunks with browsers supporting the Blob API. 21 | * **Client-side image resizing:** 22 | Images can be automatically resized on client-side with browsers supporting the required JS APIs. 23 | * **Preview images:** 24 | A preview of image files can be displayed before uploading with browsers supporting the required JS APIs. 25 | * **No browser plugins (e.g. Adobe Flash) required:** 26 | The implementation is based on open standards like HTML5 and JavaScript and requires no additional browser plugins. 27 | * **Graceful fallback for legacy browsers:** 28 | Uploads files via XMLHttpRequests if supported and uses iframes as fallback for legacy browsers. 29 | * **HTML file upload form fallback:** 30 | Shows a standard HTML file upload form if JavaScript is disabled. 31 | * **Cross-site file uploads:** 32 | Supports uploading files to a different domain with Cross-site XMLHttpRequests. 33 | * **Multiple plugin instances:** 34 | Allows to use multiple plugin instances on the same webpage. 35 | * **Customizable and extensible:** 36 | Provides an API to set individual options and define callBack methods for various upload events. 37 | * **Multipart and file contents stream uploads:** 38 | Files can be uploaded as standard "multipart/form-data" or file contents stream (HTTP PUT file upload). 39 | * **Compatible with any server-side application platform:** 40 | Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads. 41 | 42 | ## Requirements 43 | * [jQuery](http://jquery.com/) v. 1.6+ 44 | * [jQuery UI widget factory](http://wiki.jqueryui.com/w/page/12138135/Widget%20factory) v. 1.8+ 45 | * [jQuery Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/jquery.iframe-transport.js) (included) 46 | * [JavaScript Templates engine](https://github.com/blueimp/JavaScript-Templates) v. 2.1.0+ (optional) 47 | * [JavaScript Load Image function](https://github.com/blueimp/JavaScript-Load-Image) v. 1.1.6+ (optional) 48 | * [JavaScript Canvas to Blob function](https://github.com/blueimp/JavaScript-Canvas-to-Blob) v. 2.0.0+ (optional) 49 | * [Bootstrap CSS Toolkit](https://github.com/twitter/bootstrap/) v. 2.0+ (optional) 50 | 51 | The jQuery UI widget factory is a requirement for the basic File Upload plugin, but very lightweight without any other dependencies. 52 | The jQuery Iframe Transport is required for [browsers without XHR file upload support](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support). 53 | The UI version of the File Upload plugin also requires the JavaScript Templates engine as well as the JavaScript Load Image and JavaScript Canvas to Blob functions (for the image previews and resizing functionality). These dependencies are marked as optional, as the basic File Upload plugin can be used without them and the UI version of the plugin can be extended to override these dependencies with alternative solutions. 54 | 55 | The User Interface is built with Twitter's [Bootstrap](https://github.com/twitter/bootstrap/) Toolkit. This enables a CSS based, responsive layout and fancy transition effects on modern browsers. The demo also includes the [Bootstrap Image Gallery Plugin](https://github.com/blueimp/Bootstrap-Image-Gallery). Both of these components are optional and not required. 56 | 57 | The repository also includes the [jQuery XDomainRequest Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/cors/jquery.xdr-transport.js), which enables Cross-domain AJAX requests (GET and POST only) in Microsoft Internet Explorer >= 8. However, the XDomainRequest object doesn't support file uploads and the plugin is only used by the [Demo](http://blueimp.github.com/jQuery-File-Upload/) for Cross-domain requests to delete uploaded files from the demo file upload service. 58 | 59 | [Cross-domain File Uploads](https://github.com/blueimp/jQuery-File-Upload/wiki/Cross-domain-uploads) using the [Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js) require a redirect back to the origin server to retrieve the upload results. The [example implementation](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/main.js) makes use of [result.html](https://github.com/blueimp/jQuery-File-Upload/blob/master/cors/result.html) as a static redirect page for the origin server. 60 | 61 | ## Browser Support (tested versions) 62 | * Google Chrome - 7.0+ 63 | * Apple Safari - 4.0+ 64 | * Mozilla Firefox - 3.0+ 65 | * Opera - 10.0+ 66 | * Microsoft Internet Explorer 6.0+ 67 | 68 | Drag & Drop is only supported on Google Chrome, Firefox 4.0+, Safari 5.0+ and Opera 12.0+. 69 | Microsoft Internet Explorer has no support for multiple file selection or upload progress. 70 | [Extended browser support information](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support). 71 | 72 | ## License 73 | Released under the [MIT license](http://www.opensource.org/licenses/MIT). 74 | -------------------------------------------------------------------------------- /cors/postmessage.html: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | jQuery File Upload Plugin postMessage API 18 | 19 | 20 | 21 | 74 | 75 | -------------------------------------------------------------------------------- /cors/result.html: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | jQuery Iframe Transport Plugin Redirect Page 18 | 19 | 20 | -------------------------------------------------------------------------------- /css/Jcrop.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/css/Jcrop.gif -------------------------------------------------------------------------------- /css/bootstrap-ie6.min.css: -------------------------------------------------------------------------------- 1 | @charset 'UTF-8'; 2 | .span1,.span2,.span3,.span4,.span5,.span6,.span7,.span8,.span9,.span10,.span11,.span12{display:inline;float:left;margin-left:20px;} 3 | input{width:auto;} 4 | .modal{position:absolute;top:50%;filter:none;} 5 | .navbar-fixed-top{position:absolute;} 6 | .nav li{display:block;float:left;} 7 | .nav li a{display:block;padding:10px 10px 11px;line-height:19px;} 8 | .navbar .nav li a{color:#999999;} 9 | .navbar .nav li a:hover{color:#ffffff;text-decoration:none;} 10 | .nav-pills .active a{color:#ffffff;background-color:#0088cc;} 11 | .nav-pills a:hover{text-decoration:none;} 12 | -------------------------------------------------------------------------------- /css/bootstrap-image-gallery.css: -------------------------------------------------------------------------------- 1 | @charset 'UTF-8'; 2 | /* 3 | * Bootstrap Image Gallery CSS 2.5 4 | * https://github.com/blueimp/Bootstrap-Image-Gallery 5 | * 6 | * Copyright 2011, Sebastian Tschan 7 | * https://blueimp.net 8 | * 9 | * Licensed under the MIT license: 10 | * http://www.opensource.org/licenses/MIT 11 | */ 12 | 13 | .modal-gallery { 14 | width: auto; 15 | max-height: none; 16 | } 17 | .modal-gallery .modal-body { 18 | max-height: none; 19 | } 20 | .modal-gallery .modal-title { 21 | display: inline-block; 22 | max-height: 54px; 23 | overflow: hidden; 24 | } 25 | .modal-gallery .modal-image { 26 | position: relative; 27 | margin: auto; 28 | min-width: 128px; 29 | min-height: 128px; 30 | overflow: hidden; 31 | cursor: pointer; 32 | } 33 | .modal-gallery .modal-image:hover:before, 34 | .modal-gallery .modal-image:hover:after { 35 | content: '\2039'; 36 | position: absolute; 37 | top: 50%; 38 | left: 15px; 39 | width: 40px; 40 | height: 40px; 41 | margin-top: -20px; 42 | font-size: 60px; 43 | font-weight: 100; 44 | line-height: 30px; 45 | color: #ffffff; 46 | text-align: center; 47 | background: #222222; 48 | border: 3px solid #ffffff; 49 | -webkit-border-radius: 23px; 50 | -moz-border-radius: 23px; 51 | border-radius: 23px; 52 | opacity: 0.5; 53 | filter: alpha(opacity=50); 54 | z-index: 1; 55 | } 56 | .modal-gallery .modal-image:hover:after { 57 | content: '\203A'; 58 | left: auto; 59 | right: 15px; 60 | } 61 | .modal-single .modal-image:hover:before, 62 | .modal-single .modal-image:hover:after { 63 | display: none; 64 | } 65 | .modal-loading .modal-image { 66 | background: url(../img/loading.gif) center no-repeat; 67 | } 68 | .modal-gallery.fade .modal-image { 69 | -webkit-transition: width 0.15s ease, height 0.15s ease; 70 | -moz-transition: width 0.15s ease, height 0.15s ease; 71 | -ms-transition: width 0.15s ease, height 0.15s ease; 72 | -o-transition: width 0.15s ease, height 0.15s ease; 73 | transition: width 0.15s ease, height 0.15s ease; 74 | } 75 | .modal-gallery .modal-image * { 76 | position: absolute; 77 | top: 0; 78 | opacity: 0; 79 | filter: alpha(opacity=0); 80 | } 81 | .modal-gallery.fade .modal-image * { 82 | -webkit-transition: opacity 0.5s linear; 83 | -moz-transition: opacity 0.5s linear; 84 | -ms-transition: opacity 0.5s linear; 85 | -o-transition: opacity 0.5s linear; 86 | transition: opacity 0.5s linear; 87 | } 88 | .modal-gallery .modal-image *.in { 89 | opacity: 1; 90 | filter: alpha(opacity=100); 91 | } 92 | .modal-fullscreen { 93 | border: none; 94 | -webkit-border-radius: 0; 95 | -moz-border-radius: 0; 96 | border-radius: 0; 97 | background: transparent; 98 | overflow: hidden; 99 | } 100 | .modal-fullscreen.modal-loading { 101 | border: 0; 102 | -webkit-box-shadow: none; 103 | -moz-box-shadow: none; 104 | box-shadow: none; 105 | } 106 | .modal-fullscreen .modal-body { 107 | padding: 0; 108 | } 109 | .modal-fullscreen .modal-header, 110 | .modal-fullscreen .modal-footer { 111 | position: absolute; 112 | top: 0; 113 | right: 0; 114 | left: 0; 115 | background: transparent; 116 | border: 0; 117 | -webkit-box-shadow: none; 118 | -moz-box-shadow: none; 119 | box-shadow: none; 120 | opacity: 0; 121 | z-index: 2000; 122 | } 123 | .modal-fullscreen .modal-footer { 124 | top: auto; 125 | bottom: 0; 126 | } 127 | .modal-fullscreen .close, 128 | .modal-fullscreen .modal-title { 129 | color: #fff; 130 | text-shadow: 0 0 2px rgba(33, 33, 33, 0.8); 131 | } 132 | .modal-fullscreen .modal-header:hover, 133 | .modal-fullscreen .modal-footer:hover { 134 | opacity: 1; 135 | } 136 | 137 | @media (max-width: 480px) { 138 | .modal-gallery .btn span { 139 | display: none; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /css/bootstrap-image-gallery.min.css: -------------------------------------------------------------------------------- 1 | @charset 'UTF-8'; 2 | .modal-gallery{width:auto;max-height:none;} 3 | .modal-gallery .modal-body{max-height:none;} 4 | .modal-gallery .modal-title{display:inline-block;max-height:54px;overflow:hidden;} 5 | .modal-gallery .modal-image{position:relative;margin:auto;min-width:128px;min-height:128px;overflow:hidden;cursor:pointer;} 6 | .modal-gallery .modal-image:hover:before,.modal-gallery .modal-image:hover:after{content:'\2039';position:absolute;top:50%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#ffffff;text-align:center;background:#222222;border:3px solid #ffffff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:0.5;filter:alpha(opacity=50);z-index:1;} 7 | .modal-gallery .modal-image:hover:after{content:'\203A';left:auto;right:15px;} 8 | .modal-single .modal-image:hover:before,.modal-single .modal-image:hover:after{display:none;} 9 | .modal-loading .modal-image{background:url(../img/loading.gif) center no-repeat;} 10 | .modal-gallery.fade .modal-image{-webkit-transition:width 0.15s ease, height 0.15s ease;-moz-transition:width 0.15s ease, height 0.15s ease;-ms-transition:width 0.15s ease, height 0.15s ease;-o-transition:width 0.15s ease, height 0.15s ease;transition:width 0.15s ease, height 0.15s ease;} 11 | .modal-gallery .modal-image *{position:absolute;top:0;opacity:0;filter:alpha(opacity=0);} 12 | .modal-gallery.fade .modal-image *{-webkit-transition:opacity 0.5s linear;-moz-transition:opacity 0.5s linear;-ms-transition:opacity 0.5s linear;-o-transition:opacity 0.5s linear;transition:opacity 0.5s linear;} 13 | .modal-gallery .modal-image *.in{opacity:1;filter:alpha(opacity=100);} 14 | .modal-fullscreen{border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;background:transparent;overflow:hidden;} 15 | .modal-fullscreen.modal-loading{border:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} 16 | .modal-fullscreen .modal-body{padding:0;} 17 | .modal-fullscreen .modal-header,.modal-fullscreen .modal-footer{position:absolute;top:0;right:0;left:0;background:transparent;border:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:0;z-index:2000;} 18 | .modal-fullscreen .modal-footer{top:auto;bottom:0;} 19 | .modal-fullscreen .close,.modal-fullscreen .modal-title{color:#fff;text-shadow:0 0 2px rgba(33, 33, 33, 0.8);} 20 | .modal-fullscreen .modal-header:hover,.modal-fullscreen .modal-footer:hover{opacity:1;} 21 | @media (max-width:480px){.modal-gallery .btn span{display:none;}} 22 | -------------------------------------------------------------------------------- /css/bootstrap-responsive.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Responsive v2.0.4 3 | * 4 | * Copyright 2012 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | */ 10 | 11 | .clearfix { 12 | *zoom: 1; 13 | } 14 | 15 | .clearfix:before, 16 | .clearfix:after { 17 | display: table; 18 | content: ""; 19 | } 20 | 21 | .clearfix:after { 22 | clear: both; 23 | } 24 | 25 | .hide-text { 26 | font: 0/0 a; 27 | color: transparent; 28 | text-shadow: none; 29 | background-color: transparent; 30 | border: 0; 31 | } 32 | 33 | .input-block-level { 34 | display: block; 35 | width: 100%; 36 | min-height: 28px; 37 | -webkit-box-sizing: border-box; 38 | -moz-box-sizing: border-box; 39 | -ms-box-sizing: border-box; 40 | box-sizing: border-box; 41 | } 42 | 43 | .hidden { 44 | display: none; 45 | visibility: hidden; 46 | } 47 | 48 | .visible-phone { 49 | display: none !important; 50 | } 51 | 52 | .visible-tablet { 53 | display: none !important; 54 | } 55 | 56 | .hidden-desktop { 57 | display: none !important; 58 | } 59 | 60 | @media (max-width: 767px) { 61 | .visible-phone { 62 | display: inherit !important; 63 | } 64 | .hidden-phone { 65 | display: none !important; 66 | } 67 | .hidden-desktop { 68 | display: inherit !important; 69 | } 70 | .visible-desktop { 71 | display: none !important; 72 | } 73 | } 74 | 75 | @media (min-width: 768px) and (max-width: 979px) { 76 | .visible-tablet { 77 | display: inherit !important; 78 | } 79 | .hidden-tablet { 80 | display: none !important; 81 | } 82 | .hidden-desktop { 83 | display: inherit !important; 84 | } 85 | .visible-desktop { 86 | display: none !important ; 87 | } 88 | } 89 | 90 | @media (max-width: 480px) { 91 | .nav-collapse { 92 | -webkit-transform: translate3d(0, 0, 0); 93 | } 94 | .page-header h1 small { 95 | display: block; 96 | line-height: 18px; 97 | } 98 | input[type="checkbox"], 99 | input[type="radio"] { 100 | border: 1px solid #ccc; 101 | } 102 | .form-horizontal .control-group > label { 103 | float: none; 104 | width: auto; 105 | padding-top: 0; 106 | text-align: left; 107 | } 108 | .form-horizontal .controls { 109 | margin-left: 0; 110 | } 111 | .form-horizontal .control-list { 112 | padding-top: 0; 113 | } 114 | .form-horizontal .form-actions { 115 | padding-right: 10px; 116 | padding-left: 10px; 117 | } 118 | .modal { 119 | position: absolute; 120 | top: 10px; 121 | right: 10px; 122 | left: 10px; 123 | width: auto; 124 | margin: 0; 125 | } 126 | .modal.fade.in { 127 | top: auto; 128 | } 129 | .modal-header .close { 130 | padding: 10px; 131 | margin: -10px; 132 | } 133 | .carousel-caption { 134 | position: static; 135 | } 136 | } 137 | 138 | @media (max-width: 767px) { 139 | body { 140 | padding-right: 20px; 141 | padding-left: 20px; 142 | } 143 | .navbar-fixed-top, 144 | .navbar-fixed-bottom { 145 | margin-right: -20px; 146 | margin-left: -20px; 147 | } 148 | .container-fluid { 149 | padding: 0; 150 | } 151 | .dl-horizontal dt { 152 | float: none; 153 | width: auto; 154 | clear: none; 155 | text-align: left; 156 | } 157 | .dl-horizontal dd { 158 | margin-left: 0; 159 | } 160 | .container { 161 | width: auto; 162 | } 163 | .row-fluid { 164 | width: 100%; 165 | } 166 | .row, 167 | .thumbnails { 168 | margin-left: 0; 169 | } 170 | [class*="span"], 171 | .row-fluid [class*="span"] { 172 | display: block; 173 | float: none; 174 | width: auto; 175 | margin-left: 0; 176 | } 177 | .input-large, 178 | .input-xlarge, 179 | .input-xxlarge, 180 | input[class*="span"], 181 | select[class*="span"], 182 | textarea[class*="span"], 183 | .uneditable-input { 184 | display: block; 185 | width: 100%; 186 | min-height: 28px; 187 | -webkit-box-sizing: border-box; 188 | -moz-box-sizing: border-box; 189 | -ms-box-sizing: border-box; 190 | box-sizing: border-box; 191 | } 192 | .input-prepend input, 193 | .input-append input, 194 | .input-prepend input[class*="span"], 195 | .input-append input[class*="span"] { 196 | display: inline-block; 197 | width: auto; 198 | } 199 | } 200 | 201 | @media (min-width: 768px) and (max-width: 979px) { 202 | .row { 203 | margin-left: -20px; 204 | *zoom: 1; 205 | } 206 | .row:before, 207 | .row:after { 208 | display: table; 209 | content: ""; 210 | } 211 | .row:after { 212 | clear: both; 213 | } 214 | [class*="span"] { 215 | float: left; 216 | margin-left: 20px; 217 | } 218 | .container, 219 | .navbar-fixed-top .container, 220 | .navbar-fixed-bottom .container { 221 | width: 724px; 222 | } 223 | .span12 { 224 | width: 724px; 225 | } 226 | .span11 { 227 | width: 662px; 228 | } 229 | .span10 { 230 | width: 600px; 231 | } 232 | .span9 { 233 | width: 538px; 234 | } 235 | .span8 { 236 | width: 476px; 237 | } 238 | .span7 { 239 | width: 414px; 240 | } 241 | .span6 { 242 | width: 352px; 243 | } 244 | .span5 { 245 | width: 290px; 246 | } 247 | .span4 { 248 | width: 228px; 249 | } 250 | .span3 { 251 | width: 166px; 252 | } 253 | .span2 { 254 | width: 104px; 255 | } 256 | .span1 { 257 | width: 42px; 258 | } 259 | .offset12 { 260 | margin-left: 764px; 261 | } 262 | .offset11 { 263 | margin-left: 702px; 264 | } 265 | .offset10 { 266 | margin-left: 640px; 267 | } 268 | .offset9 { 269 | margin-left: 578px; 270 | } 271 | .offset8 { 272 | margin-left: 516px; 273 | } 274 | .offset7 { 275 | margin-left: 454px; 276 | } 277 | .offset6 { 278 | margin-left: 392px; 279 | } 280 | .offset5 { 281 | margin-left: 330px; 282 | } 283 | .offset4 { 284 | margin-left: 268px; 285 | } 286 | .offset3 { 287 | margin-left: 206px; 288 | } 289 | .offset2 { 290 | margin-left: 144px; 291 | } 292 | .offset1 { 293 | margin-left: 82px; 294 | } 295 | .row-fluid { 296 | width: 100%; 297 | *zoom: 1; 298 | } 299 | .row-fluid:before, 300 | .row-fluid:after { 301 | display: table; 302 | content: ""; 303 | } 304 | .row-fluid:after { 305 | clear: both; 306 | } 307 | .row-fluid [class*="span"] { 308 | display: block; 309 | float: left; 310 | width: 100%; 311 | min-height: 28px; 312 | margin-left: 2.762430939%; 313 | *margin-left: 2.709239449638298%; 314 | -webkit-box-sizing: border-box; 315 | -moz-box-sizing: border-box; 316 | -ms-box-sizing: border-box; 317 | box-sizing: border-box; 318 | } 319 | .row-fluid [class*="span"]:first-child { 320 | margin-left: 0; 321 | } 322 | .row-fluid .span12 { 323 | width: 99.999999993%; 324 | *width: 99.9468085036383%; 325 | } 326 | .row-fluid .span11 { 327 | width: 91.436464082%; 328 | *width: 91.38327259263829%; 329 | } 330 | .row-fluid .span10 { 331 | width: 82.87292817100001%; 332 | *width: 82.8197366816383%; 333 | } 334 | .row-fluid .span9 { 335 | width: 74.30939226%; 336 | *width: 74.25620077063829%; 337 | } 338 | .row-fluid .span8 { 339 | width: 65.74585634900001%; 340 | *width: 65.6926648596383%; 341 | } 342 | .row-fluid .span7 { 343 | width: 57.182320438000005%; 344 | *width: 57.129128948638304%; 345 | } 346 | .row-fluid .span6 { 347 | width: 48.618784527%; 348 | *width: 48.5655930376383%; 349 | } 350 | .row-fluid .span5 { 351 | width: 40.055248616%; 352 | *width: 40.0020571266383%; 353 | } 354 | .row-fluid .span4 { 355 | width: 31.491712705%; 356 | *width: 31.4385212156383%; 357 | } 358 | .row-fluid .span3 { 359 | width: 22.928176794%; 360 | *width: 22.874985304638297%; 361 | } 362 | .row-fluid .span2 { 363 | width: 14.364640883%; 364 | *width: 14.311449393638298%; 365 | } 366 | .row-fluid .span1 { 367 | width: 5.801104972%; 368 | *width: 5.747913482638298%; 369 | } 370 | input, 371 | textarea, 372 | .uneditable-input { 373 | margin-left: 0; 374 | } 375 | input.span12, 376 | textarea.span12, 377 | .uneditable-input.span12 { 378 | width: 714px; 379 | } 380 | input.span11, 381 | textarea.span11, 382 | .uneditable-input.span11 { 383 | width: 652px; 384 | } 385 | input.span10, 386 | textarea.span10, 387 | .uneditable-input.span10 { 388 | width: 590px; 389 | } 390 | input.span9, 391 | textarea.span9, 392 | .uneditable-input.span9 { 393 | width: 528px; 394 | } 395 | input.span8, 396 | textarea.span8, 397 | .uneditable-input.span8 { 398 | width: 466px; 399 | } 400 | input.span7, 401 | textarea.span7, 402 | .uneditable-input.span7 { 403 | width: 404px; 404 | } 405 | input.span6, 406 | textarea.span6, 407 | .uneditable-input.span6 { 408 | width: 342px; 409 | } 410 | input.span5, 411 | textarea.span5, 412 | .uneditable-input.span5 { 413 | width: 280px; 414 | } 415 | input.span4, 416 | textarea.span4, 417 | .uneditable-input.span4 { 418 | width: 218px; 419 | } 420 | input.span3, 421 | textarea.span3, 422 | .uneditable-input.span3 { 423 | width: 156px; 424 | } 425 | input.span2, 426 | textarea.span2, 427 | .uneditable-input.span2 { 428 | width: 94px; 429 | } 430 | input.span1, 431 | textarea.span1, 432 | .uneditable-input.span1 { 433 | width: 32px; 434 | } 435 | } 436 | 437 | @media (min-width: 1200px) { 438 | .row { 439 | margin-left: -30px; 440 | *zoom: 1; 441 | } 442 | .row:before, 443 | .row:after { 444 | display: table; 445 | content: ""; 446 | } 447 | .row:after { 448 | clear: both; 449 | } 450 | [class*="span"] { 451 | float: left; 452 | margin-left: 30px; 453 | } 454 | .container, 455 | .navbar-fixed-top .container, 456 | .navbar-fixed-bottom .container { 457 | width: 1170px; 458 | } 459 | .span12 { 460 | width: 1170px; 461 | } 462 | .span11 { 463 | width: 1070px; 464 | } 465 | .span10 { 466 | width: 970px; 467 | } 468 | .span9 { 469 | width: 870px; 470 | } 471 | .span8 { 472 | width: 770px; 473 | } 474 | .span7 { 475 | width: 670px; 476 | } 477 | .span6 { 478 | width: 570px; 479 | } 480 | .span5 { 481 | width: 470px; 482 | } 483 | .span4 { 484 | width: 370px; 485 | } 486 | .span3 { 487 | width: 270px; 488 | } 489 | .span2 { 490 | width: 170px; 491 | } 492 | .span1 { 493 | width: 70px; 494 | } 495 | .offset12 { 496 | margin-left: 1230px; 497 | } 498 | .offset11 { 499 | margin-left: 1130px; 500 | } 501 | .offset10 { 502 | margin-left: 1030px; 503 | } 504 | .offset9 { 505 | margin-left: 930px; 506 | } 507 | .offset8 { 508 | margin-left: 830px; 509 | } 510 | .offset7 { 511 | margin-left: 730px; 512 | } 513 | .offset6 { 514 | margin-left: 630px; 515 | } 516 | .offset5 { 517 | margin-left: 530px; 518 | } 519 | .offset4 { 520 | margin-left: 430px; 521 | } 522 | .offset3 { 523 | margin-left: 330px; 524 | } 525 | .offset2 { 526 | margin-left: 230px; 527 | } 528 | .offset1 { 529 | margin-left: 130px; 530 | } 531 | .row-fluid { 532 | width: 100%; 533 | *zoom: 1; 534 | } 535 | .row-fluid:before, 536 | .row-fluid:after { 537 | display: table; 538 | content: ""; 539 | } 540 | .row-fluid:after { 541 | clear: both; 542 | } 543 | .row-fluid [class*="span"] { 544 | display: block; 545 | float: left; 546 | width: 100%; 547 | min-height: 28px; 548 | margin-left: 2.564102564%; 549 | *margin-left: 2.510911074638298%; 550 | -webkit-box-sizing: border-box; 551 | -moz-box-sizing: border-box; 552 | -ms-box-sizing: border-box; 553 | box-sizing: border-box; 554 | } 555 | .row-fluid [class*="span"]:first-child { 556 | margin-left: 0; 557 | } 558 | .row-fluid .span12 { 559 | width: 100%; 560 | *width: 99.94680851063829%; 561 | } 562 | .row-fluid .span11 { 563 | width: 91.45299145300001%; 564 | *width: 91.3997999636383%; 565 | } 566 | .row-fluid .span10 { 567 | width: 82.905982906%; 568 | *width: 82.8527914166383%; 569 | } 570 | .row-fluid .span9 { 571 | width: 74.358974359%; 572 | *width: 74.30578286963829%; 573 | } 574 | .row-fluid .span8 { 575 | width: 65.81196581200001%; 576 | *width: 65.7587743226383%; 577 | } 578 | .row-fluid .span7 { 579 | width: 57.264957265%; 580 | *width: 57.2117657756383%; 581 | } 582 | .row-fluid .span6 { 583 | width: 48.717948718%; 584 | *width: 48.6647572286383%; 585 | } 586 | .row-fluid .span5 { 587 | width: 40.170940171000005%; 588 | *width: 40.117748681638304%; 589 | } 590 | .row-fluid .span4 { 591 | width: 31.623931624%; 592 | *width: 31.5707401346383%; 593 | } 594 | .row-fluid .span3 { 595 | width: 23.076923077%; 596 | *width: 23.0237315876383%; 597 | } 598 | .row-fluid .span2 { 599 | width: 14.529914530000001%; 600 | *width: 14.4767230406383%; 601 | } 602 | .row-fluid .span1 { 603 | width: 5.982905983%; 604 | *width: 5.929714493638298%; 605 | } 606 | input, 607 | textarea, 608 | .uneditable-input { 609 | margin-left: 0; 610 | } 611 | input.span12, 612 | textarea.span12, 613 | .uneditable-input.span12 { 614 | width: 1160px; 615 | } 616 | input.span11, 617 | textarea.span11, 618 | .uneditable-input.span11 { 619 | width: 1060px; 620 | } 621 | input.span10, 622 | textarea.span10, 623 | .uneditable-input.span10 { 624 | width: 960px; 625 | } 626 | input.span9, 627 | textarea.span9, 628 | .uneditable-input.span9 { 629 | width: 860px; 630 | } 631 | input.span8, 632 | textarea.span8, 633 | .uneditable-input.span8 { 634 | width: 760px; 635 | } 636 | input.span7, 637 | textarea.span7, 638 | .uneditable-input.span7 { 639 | width: 660px; 640 | } 641 | input.span6, 642 | textarea.span6, 643 | .uneditable-input.span6 { 644 | width: 560px; 645 | } 646 | input.span5, 647 | textarea.span5, 648 | .uneditable-input.span5 { 649 | width: 460px; 650 | } 651 | input.span4, 652 | textarea.span4, 653 | .uneditable-input.span4 { 654 | width: 360px; 655 | } 656 | input.span3, 657 | textarea.span3, 658 | .uneditable-input.span3 { 659 | width: 260px; 660 | } 661 | input.span2, 662 | textarea.span2, 663 | .uneditable-input.span2 { 664 | width: 160px; 665 | } 666 | input.span1, 667 | textarea.span1, 668 | .uneditable-input.span1 { 669 | width: 60px; 670 | } 671 | .thumbnails { 672 | margin-left: -30px; 673 | } 674 | .thumbnails > li { 675 | margin-left: 30px; 676 | } 677 | .row-fluid .thumbnails { 678 | margin-left: 0; 679 | } 680 | } 681 | 682 | @media (max-width: 979px) { 683 | body { 684 | padding-top: 0; 685 | } 686 | .navbar-fixed-top, 687 | .navbar-fixed-bottom { 688 | position: static; 689 | } 690 | .navbar-fixed-top { 691 | margin-bottom: 18px; 692 | } 693 | .navbar-fixed-bottom { 694 | margin-top: 18px; 695 | } 696 | .navbar-fixed-top .navbar-inner, 697 | .navbar-fixed-bottom .navbar-inner { 698 | padding: 5px; 699 | } 700 | .navbar .container { 701 | width: auto; 702 | padding: 0; 703 | } 704 | .navbar .brand { 705 | padding-right: 10px; 706 | padding-left: 10px; 707 | margin: 0 0 0 -5px; 708 | } 709 | .nav-collapse { 710 | clear: both; 711 | } 712 | .nav-collapse .nav { 713 | float: none; 714 | margin: 0 0 9px; 715 | } 716 | .nav-collapse .nav > li { 717 | float: none; 718 | } 719 | .nav-collapse .nav > li > a { 720 | margin-bottom: 2px; 721 | } 722 | .nav-collapse .nav > .divider-vertical { 723 | display: none; 724 | } 725 | .nav-collapse .nav .nav-header { 726 | color: #999999; 727 | text-shadow: none; 728 | } 729 | .nav-collapse .nav > li > a, 730 | .nav-collapse .dropdown-menu a { 731 | padding: 6px 15px; 732 | font-weight: bold; 733 | color: #999999; 734 | -webkit-border-radius: 3px; 735 | -moz-border-radius: 3px; 736 | border-radius: 3px; 737 | } 738 | .nav-collapse .btn { 739 | padding: 4px 10px 4px; 740 | font-weight: normal; 741 | -webkit-border-radius: 4px; 742 | -moz-border-radius: 4px; 743 | border-radius: 4px; 744 | } 745 | .nav-collapse .dropdown-menu li + li a { 746 | margin-bottom: 2px; 747 | } 748 | .nav-collapse .nav > li > a:hover, 749 | .nav-collapse .dropdown-menu a:hover { 750 | background-color: #222222; 751 | } 752 | .nav-collapse.in .btn-group { 753 | padding: 0; 754 | margin-top: 5px; 755 | } 756 | .nav-collapse .dropdown-menu { 757 | position: static; 758 | top: auto; 759 | left: auto; 760 | display: block; 761 | float: none; 762 | max-width: none; 763 | padding: 0; 764 | margin: 0 15px; 765 | background-color: transparent; 766 | border: none; 767 | -webkit-border-radius: 0; 768 | -moz-border-radius: 0; 769 | border-radius: 0; 770 | -webkit-box-shadow: none; 771 | -moz-box-shadow: none; 772 | box-shadow: none; 773 | } 774 | .nav-collapse .dropdown-menu:before, 775 | .nav-collapse .dropdown-menu:after { 776 | display: none; 777 | } 778 | .nav-collapse .dropdown-menu .divider { 779 | display: none; 780 | } 781 | .nav-collapse .navbar-form, 782 | .nav-collapse .navbar-search { 783 | float: none; 784 | padding: 9px 15px; 785 | margin: 9px 0; 786 | border-top: 1px solid #222222; 787 | border-bottom: 1px solid #222222; 788 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); 789 | -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); 790 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); 791 | } 792 | .navbar .nav-collapse .nav.pull-right { 793 | float: none; 794 | margin-left: 0; 795 | } 796 | .nav-collapse, 797 | .nav-collapse.collapse { 798 | height: 0; 799 | overflow: hidden; 800 | } 801 | .navbar .btn-navbar { 802 | display: block; 803 | } 804 | .navbar-static .navbar-inner { 805 | padding-right: 10px; 806 | padding-left: 10px; 807 | } 808 | } 809 | 810 | @media (min-width: 980px) { 811 | .nav-collapse.collapse { 812 | height: auto !important; 813 | overflow: visible !important; 814 | } 815 | } 816 | -------------------------------------------------------------------------------- /css/bootstrap-responsive.min.css: -------------------------------------------------------------------------------- 1 | .clearfix{*zoom:1;} 2 | .clearfix:before,.clearfix:after{display:table;content:"";} 3 | .clearfix:after{clear:both;} 4 | .hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;} 5 | .input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;} 6 | .hidden{display:none;visibility:hidden;} 7 | .visible-phone{display:none !important;} 8 | .visible-tablet{display:none !important;} 9 | .hidden-desktop{display:none !important;} 10 | @media (max-width:767px){.visible-phone{display:inherit !important;} .hidden-phone{display:none !important;} .hidden-desktop{display:inherit !important;} .visible-desktop{display:none !important;}}@media (min-width:768px) and (max-width:979px){.visible-tablet{display:inherit !important;} .hidden-tablet{display:none !important;} .hidden-desktop{display:inherit !important;} .visible-desktop{display:none !important ;}}@media (max-width:480px){.nav-collapse{-webkit-transform:translate3d(0, 0, 0);} .page-header h1 small{display:block;line-height:18px;} input[type="checkbox"],input[type="radio"]{border:1px solid #ccc;} .form-horizontal .control-group>label{float:none;width:auto;padding-top:0;text-align:left;} .form-horizontal .controls{margin-left:0;} .form-horizontal .control-list{padding-top:0;} .form-horizontal .form-actions{padding-right:10px;padding-left:10px;} .modal{position:absolute;top:10px;right:10px;left:10px;width:auto;margin:0;} .modal.fade.in{top:auto;} .modal-header .close{padding:10px;margin:-10px;} .carousel-caption{position:static;}}@media (max-width:767px){body{padding-right:20px;padding-left:20px;} .navbar-fixed-top,.navbar-fixed-bottom{margin-right:-20px;margin-left:-20px;} .container-fluid{padding:0;} .dl-horizontal dt{float:none;width:auto;clear:none;text-align:left;} .dl-horizontal dd{margin-left:0;} .container{width:auto;} .row-fluid{width:100%;} .row,.thumbnails{margin-left:0;} [class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:auto;margin-left:0;} .input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;} .input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto;}}@media (min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1;} .row:before,.row:after{display:table;content:"";} .row:after{clear:both;} [class*="span"]{float:left;margin-left:20px;} .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px;} .span12{width:724px;} .span11{width:662px;} .span10{width:600px;} .span9{width:538px;} .span8{width:476px;} .span7{width:414px;} .span6{width:352px;} .span5{width:290px;} .span4{width:228px;} .span3{width:166px;} .span2{width:104px;} .span1{width:42px;} .offset12{margin-left:764px;} .offset11{margin-left:702px;} .offset10{margin-left:640px;} .offset9{margin-left:578px;} .offset8{margin-left:516px;} .offset7{margin-left:454px;} .offset6{margin-left:392px;} .offset5{margin-left:330px;} .offset4{margin-left:268px;} .offset3{margin-left:206px;} .offset2{margin-left:144px;} .offset1{margin-left:82px;} .row-fluid{width:100%;*zoom:1;} .row-fluid:before,.row-fluid:after{display:table;content:"";} .row-fluid:after{clear:both;} .row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:28px;margin-left:2.762430939%;*margin-left:2.709239449638298%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;} .row-fluid [class*="span"]:first-child{margin-left:0;} .row-fluid .span12{width:99.999999993%;*width:99.9468085036383%;} .row-fluid .span11{width:91.436464082%;*width:91.38327259263829%;} .row-fluid .span10{width:82.87292817100001%;*width:82.8197366816383%;} .row-fluid .span9{width:74.30939226%;*width:74.25620077063829%;} .row-fluid .span8{width:65.74585634900001%;*width:65.6926648596383%;} .row-fluid .span7{width:57.182320438000005%;*width:57.129128948638304%;} .row-fluid .span6{width:48.618784527%;*width:48.5655930376383%;} .row-fluid .span5{width:40.055248616%;*width:40.0020571266383%;} .row-fluid .span4{width:31.491712705%;*width:31.4385212156383%;} .row-fluid .span3{width:22.928176794%;*width:22.874985304638297%;} .row-fluid .span2{width:14.364640883%;*width:14.311449393638298%;} .row-fluid .span1{width:5.801104972%;*width:5.747913482638298%;} input,textarea,.uneditable-input{margin-left:0;} input.span12,textarea.span12,.uneditable-input.span12{width:714px;} input.span11,textarea.span11,.uneditable-input.span11{width:652px;} input.span10,textarea.span10,.uneditable-input.span10{width:590px;} input.span9,textarea.span9,.uneditable-input.span9{width:528px;} input.span8,textarea.span8,.uneditable-input.span8{width:466px;} input.span7,textarea.span7,.uneditable-input.span7{width:404px;} input.span6,textarea.span6,.uneditable-input.span6{width:342px;} input.span5,textarea.span5,.uneditable-input.span5{width:280px;} input.span4,textarea.span4,.uneditable-input.span4{width:218px;} input.span3,textarea.span3,.uneditable-input.span3{width:156px;} input.span2,textarea.span2,.uneditable-input.span2{width:94px;} input.span1,textarea.span1,.uneditable-input.span1{width:32px;}}@media (min-width:1200px){.row{margin-left:-30px;*zoom:1;} .row:before,.row:after{display:table;content:"";} .row:after{clear:both;} [class*="span"]{float:left;margin-left:30px;} .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px;} .span12{width:1170px;} .span11{width:1070px;} .span10{width:970px;} .span9{width:870px;} .span8{width:770px;} .span7{width:670px;} .span6{width:570px;} .span5{width:470px;} .span4{width:370px;} .span3{width:270px;} .span2{width:170px;} .span1{width:70px;} .offset12{margin-left:1230px;} .offset11{margin-left:1130px;} .offset10{margin-left:1030px;} .offset9{margin-left:930px;} .offset8{margin-left:830px;} .offset7{margin-left:730px;} .offset6{margin-left:630px;} .offset5{margin-left:530px;} .offset4{margin-left:430px;} .offset3{margin-left:330px;} .offset2{margin-left:230px;} .offset1{margin-left:130px;} .row-fluid{width:100%;*zoom:1;} .row-fluid:before,.row-fluid:after{display:table;content:"";} .row-fluid:after{clear:both;} .row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:28px;margin-left:2.564102564%;*margin-left:2.510911074638298%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;} .row-fluid [class*="span"]:first-child{margin-left:0;} .row-fluid .span12{width:100%;*width:99.94680851063829%;} .row-fluid .span11{width:91.45299145300001%;*width:91.3997999636383%;} .row-fluid .span10{width:82.905982906%;*width:82.8527914166383%;} .row-fluid .span9{width:74.358974359%;*width:74.30578286963829%;} .row-fluid .span8{width:65.81196581200001%;*width:65.7587743226383%;} .row-fluid .span7{width:57.264957265%;*width:57.2117657756383%;} .row-fluid .span6{width:48.717948718%;*width:48.6647572286383%;} .row-fluid .span5{width:40.170940171000005%;*width:40.117748681638304%;} .row-fluid .span4{width:31.623931624%;*width:31.5707401346383%;} .row-fluid .span3{width:23.076923077%;*width:23.0237315876383%;} .row-fluid .span2{width:14.529914530000001%;*width:14.4767230406383%;} .row-fluid .span1{width:5.982905983%;*width:5.929714493638298%;} input,textarea,.uneditable-input{margin-left:0;} input.span12,textarea.span12,.uneditable-input.span12{width:1160px;} input.span11,textarea.span11,.uneditable-input.span11{width:1060px;} input.span10,textarea.span10,.uneditable-input.span10{width:960px;} input.span9,textarea.span9,.uneditable-input.span9{width:860px;} input.span8,textarea.span8,.uneditable-input.span8{width:760px;} input.span7,textarea.span7,.uneditable-input.span7{width:660px;} input.span6,textarea.span6,.uneditable-input.span6{width:560px;} input.span5,textarea.span5,.uneditable-input.span5{width:460px;} input.span4,textarea.span4,.uneditable-input.span4{width:360px;} input.span3,textarea.span3,.uneditable-input.span3{width:260px;} input.span2,textarea.span2,.uneditable-input.span2{width:160px;} input.span1,textarea.span1,.uneditable-input.span1{width:60px;} .thumbnails{margin-left:-30px;} .thumbnails>li{margin-left:30px;} .row-fluid .thumbnails{margin-left:0;}}@media (max-width:979px){body{padding-top:0;} .navbar-fixed-top,.navbar-fixed-bottom{position:static;} .navbar-fixed-top{margin-bottom:18px;} .navbar-fixed-bottom{margin-top:18px;} .navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px;} .navbar .container{width:auto;padding:0;} .navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px;} .nav-collapse{clear:both;} .nav-collapse .nav{float:none;margin:0 0 9px;} .nav-collapse .nav>li{float:none;} .nav-collapse .nav>li>a{margin-bottom:2px;} .nav-collapse .nav>.divider-vertical{display:none;} .nav-collapse .nav .nav-header{color:#999999;text-shadow:none;} .nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:6px 15px;font-weight:bold;color:#999999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} .nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .nav-collapse .dropdown-menu li+li a{margin-bottom:2px;} .nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#222222;} .nav-collapse.in .btn-group{padding:0;margin-top:5px;} .nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:block;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} .nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none;} .nav-collapse .dropdown-menu .divider{display:none;} .nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:9px 15px;margin:9px 0;border-top:1px solid #222222;border-bottom:1px solid #222222;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);} .navbar .nav-collapse .nav.pull-right{float:none;margin-left:0;} .nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden;} .navbar .btn-navbar{display:block;} .navbar-static .navbar-inner{padding-right:10px;padding-left:10px;}}@media (min-width:980px){.nav-collapse.collapse{height:auto !important;overflow:visible !important;}} 11 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /css/jquery.fileupload-ui.css: -------------------------------------------------------------------------------- 1 | @charset 'UTF-8'; 2 | /* 3 | * jQuery File Upload UI Plugin CSS 6.3 4 | * https://github.com/blueimp/jQuery-File-Upload 5 | * 6 | * Copyright 2010, Sebastian Tschan 7 | * https://blueimp.net 8 | * 9 | * Licensed under the MIT license: 10 | * http://www.opensource.org/licenses/MIT 11 | */ 12 | 13 | .fileinput-button { 14 | position: relative; 15 | overflow: hidden; 16 | float: left; 17 | margin-right: 4px; 18 | } 19 | .fileinput-button input { 20 | position: absolute; 21 | top: 0; 22 | right: 0; 23 | margin: 0; 24 | border: solid transparent; 25 | border-width: 0 0 100px 200px; 26 | opacity: 0; 27 | filter: alpha(opacity=0); 28 | -moz-transform: translate(-300px, 0) scale(4); 29 | direction: ltr; 30 | cursor: pointer; 31 | } 32 | .fileupload-buttonbar .btn, 33 | .fileupload-buttonbar .toggle { 34 | margin-bottom: 5px; 35 | } 36 | .files .progress { 37 | width: 200px; 38 | } 39 | .progress-animated .bar { 40 | background: url(../img/progressbar.gif) !important; 41 | filter: none; 42 | } 43 | .fileupload-loading { 44 | position: absolute; 45 | left: 50%; 46 | width: 128px; 47 | height: 128px; 48 | background: url(../img/loading.gif) center no-repeat; 49 | display: none; 50 | } 51 | .fileupload-processing .fileupload-loading { 52 | display: block; 53 | } 54 | 55 | /* Fix for IE 6: */ 56 | *html .fileinput-button { 57 | line-height: 22px; 58 | margin: 1px -3px 0 0; 59 | } 60 | 61 | /* Fix for IE 7: */ 62 | *+html .fileinput-button { 63 | margin: 1px 0 0 0; 64 | } 65 | 66 | @media (max-width: 480px) { 67 | .files .btn span { 68 | display: none; 69 | } 70 | .files .preview * { 71 | width: 40px; 72 | } 73 | .files .name * { 74 | width: 80px; 75 | display: inline-block; 76 | word-wrap: break-word; 77 | } 78 | .files .progress { 79 | width: 20px; 80 | } 81 | .files .delete { 82 | width: 60px; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /css/jquery.furac.ui.css: -------------------------------------------------------------------------------- 1 | /*jquery.furac.ui.css*/ 2 | #opCrop{ 3 | border-bottom: 1px solid #CCC; 4 | margin-bottom: 8px; 5 | } 6 | #opCrop .btn{vertical-align: baseline;} 7 | 8 | #opCrop label{display: inline;vertical-align: baseline;} 9 | #opCrop input[type="number"]{ 10 | min-width: 0; 11 | width:50px; 12 | vertical-align: baseline; 13 | } 14 | .modal-body{ 15 | overflow-y: hidden; 16 | } -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | @charset 'UTF-8'; 2 | /* 3 | * jQuery File Upload Plugin CSS Example 1.0 4 | * https://github.com/blueimp/jQuery-File-Upload 5 | * 6 | * Copyright 2012, Sebastian Tschan 7 | * https://blueimp.net 8 | * 9 | * Licensed under the MIT license: 10 | * http://www.opensource.org/licenses/MIT 11 | */ 12 | 13 | body{ 14 | padding-top: 60px; 15 | } 16 | -------------------------------------------------------------------------------- /gitpull.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/img/loading.gif -------------------------------------------------------------------------------- /img/progressbar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/img/progressbar.gif -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | 29 | 30 | 31 | 32 | jQ FURAC – jQuery File Upload, Resize & Crop Demo 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 78 |
79 | 83 |

Mod by: Agustín Amenabar

84 |
85 |

File Upload widget with multiple file selection, drag&drop support, progress bars and preview images for jQuery.
86 | Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
87 | Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.

88 |
89 |
90 | 91 |
92 | 93 |
94 |
95 | 96 | 97 | 98 | Add files... 99 | 100 | 101 | 105 | 109 | 113 | 114 |
115 | 116 |
117 | 118 |
119 |
120 |
121 | 122 |
 
123 |
124 |
125 | 126 |
127 |
128 | 129 | 130 |
131 |
132 |
133 |

Demo Notes

134 | 142 |
143 |
144 | 145 | 191 | 192 | 205 | 206 | 236 | 237 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | -------------------------------------------------------------------------------- /js/ZeroClipboard.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/js/ZeroClipboard.swf -------------------------------------------------------------------------------- /js/bootstrap-image-gallery.min.js: -------------------------------------------------------------------------------- 1 | (function(a){"use strict",typeof define=="function"&&define.amd?define(["jquery","load-image","bootstrap"],a):a(window.jQuery,window.loadImage)})(function(a,b){"use strict",a.extend(a.fn.modal.defaults,{delegate:document,selector:null,filter:"*",index:0,href:null,preloadRange:2,offsetWidth:100,offsetHeight:250,canvas:!1,slideshow:0,imageClickDivision:.5});var c=a.fn.modal.Constructor.prototype.show,d=a.fn.modal.Constructor.prototype.hide;a.extend(a.fn.modal.Constructor.prototype,{initLinks:function(){var b=this,c=this.options,d=c.selector||"a[data-target="+c.target+"]";this.$links=a(c.delegate).find(d).filter(c.filter).each(function(a){b.getUrl(this)===c.href&&(c.index=a)}),this.$links[c.index]||(c.index=0)},getUrl:function(b){return b.href||a(b).data("href")},startSlideShow:function(){var a=this;this.options.slideshow&&(this._slideShow=window.setTimeout(function(){a.next()},this.options.slideshow))},stopSlideShow:function(){window.clearTimeout(this._slideShow)},toggleSlideShow:function(){var a=this.$element.find(".modal-slideshow");this.options.slideshow?(this.options.slideshow=0,this.stopSlideShow()):(this.options.slideshow=a.data("slideshow")||5e3,this.startSlideShow()),a.find("i").toggleClass("icon-play icon-pause")},preloadImages:function(){var b=this.options,c=b.index+b.preloadRange+1,d,e;for(e=b.index-b.preloadRange;e").prop("src",this.getUrl(d))},loadImage:function(){var a=this,c=this.$element,d=this.options.index,e=this.getUrl(this.$links[d]),f;this.abortLoad(),this.stopSlideShow(),c.trigger("beforeLoad"),this._loadingTimeout=window.setTimeout(function(){c.addClass("modal-loading")},100),f=c.find(".modal-image").children().removeClass("in"),window.setTimeout(function(){f.remove()},3e3),c.find(".modal-title").text(this.$links[d].title),c.find(".modal-download").prop("href",e),this._loadingImage=b(e,function(b){a.img=b,window.clearTimeout(a._loadingTimeout),c.removeClass("modal-loading"),c.trigger("load"),a.showImage(b),a.startSlideShow()},this._loadImageOptions),this.preloadImages()},showImage:function(b){var c=this.$element,d=a.support.transition&&c.hasClass("fade"),e=d?c.animate:c.css,f=c.find(".modal-image"),g,h;f.css({width:b.width,height:b.height}),c.find(".modal-title").css({width:Math.max(b.width,380)}),a(window).width()>480&&(d&&(g=c.clone().hide().appendTo(document.body)),e.call(c.stop(),{"margin-top":-((g||c).outerHeight()/2),"margin-left":-((g||c).outerWidth()/2)}),g&&g.remove()),f.append(b),h=b.offsetWidth,c.trigger("display"),d?c.is(":visible")?a(b).on(a.support.transition.end,function(d){d.target===b&&(a(b).off(a.support.transition.end),c.trigger("displayed"))}).addClass("in"):(a(b).addClass("in"),c.one("shown",function(){c.trigger("displayed")})):(a(b).addClass("in"),c.trigger("displayed"))},abortLoad:function(){this._loadingImage&&(this._loadingImage.onload=this._loadingImage.onerror=null),window.clearTimeout(this._loadingTimeout)},prev:function(){var a=this.options;a.index-=1,a.index<0&&(a.index=this.$links.length-1),this.loadImage()},next:function(){var a=this.options;a.index+=1,a.index>this.$links.length-1&&(a.index=0),this.loadImage()},keyHandler:function(a){switch(a.which){case 37:case 38:a.preventDefault(),this.prev();break;case 39:case 40:a.preventDefault(),this.next()}},wheelHandler:function(a){a.preventDefault(),a=a.originalEvent,this._wheelCounter=this._wheelCounter||0,this._wheelCounter+=a.wheelDelta||a.detail||0;if(a.wheelDelta&&this._wheelCounter>=120||!a.wheelDelta&&this._wheelCounter<0)this.prev(),this._wheelCounter=0;else if(a.wheelDelta&&this._wheelCounter<=-120||!a.wheelDelta&&this._wheelCounter>0)this.next(),this._wheelCounter=0},initGalleryEvents:function(){var b=this,c=this.$element;c.find(".modal-image").on("click.modal-gallery",function(c){var d=a(this);b.$links.length===1?b.hide():(c.pageX-d.offset().left)/d.width()480&&b.css({"margin-top":-(b.outerHeight()/2),"margin-left":-(b.outerWidth()/2)}),this.initGalleryEvents(),this.initLinks(),this.$links.length&&(b.find(".modal-slideshow, .modal-prev, .modal-next").toggle(this.$links.length!==1),b.toggleClass("modal-single",this.$links.length===1),this.loadImage())}c.apply(this,arguments)},hide:function(){this.isShown&&this.$element.hasClass("modal-gallery")&&(this.options.delegate=document,this.options.href=null,this.destroyGalleryEvents()),d.apply(this,arguments)}}),a(function(){a(document.body).on("click.modal-gallery.data-api",'[data-toggle="modal-gallery"]',function(b){var c=a(this),d=c.data(),e=a(d.target),f=e.data("modal"),g;f||(d=a.extend(e.data(),d)),d.selector||(d.selector="a[rel=gallery]"),g=a(b.target).closest(d.selector),g.length&&e.length&&(b.preventDefault(),d.href=g.prop("href")||g.data("href"),d.delegate=g[0]!==this?this:document,f&&a.extend(f.options,d),e.modal(d))})})}); -------------------------------------------------------------------------------- /js/canvas-to-blob.min.js: -------------------------------------------------------------------------------- 1 | (function(a){"use strict";var b=a.HTMLCanvasElement&&a.HTMLCanvasElement.prototype,c=function(){try{return!!(new Blob)}catch(a){return!1}}(),d=a.BlobBuilder||a.WebKitBlobBuilder||a.MozBlobBuilder||a.MSBlobBuilder,e=(c||d)&&a.atob&&a.ArrayBuffer&&a.Uint8Array&&function(a){var b,e,f,g,h,i;a.split(",")[0].indexOf("base64")>=0?b=atob(a.split(",")[1]):b=decodeURIComponent(a.split(",")[1]),e=new ArrayBuffer(b.length),f=new Uint8Array(e);for(g=0;g').prop('href', options.postMessage)[0], 63 | target = loc.protocol + '//' + loc.host, 64 | xhrUpload = options.xhr().upload; 65 | return { 66 | send: function (_, completeCallback) { 67 | var message = { 68 | id: 'postmessage-transport-' + (counter += 1) 69 | }, 70 | eventName = 'message.' + message.id; 71 | iframe = $( 72 | '' 75 | ).bind('load', function () { 76 | $.each(names, function (i, name) { 77 | message[name] = options[name]; 78 | }); 79 | message.dataType = message.dataType.replace('postmessage ', ''); 80 | $(window).bind(eventName, function (e) { 81 | e = e.originalEvent; 82 | var data = e.data, 83 | ev; 84 | if (e.origin === target && data.id === message.id) { 85 | if (data.type === 'progress') { 86 | ev = document.createEvent('Event'); 87 | ev.initEvent(data.type, false, true); 88 | $.extend(ev, data); 89 | xhrUpload.dispatchEvent(ev); 90 | } else { 91 | completeCallback( 92 | data.status, 93 | data.statusText, 94 | {postmessage: data.result}, 95 | data.headers 96 | ); 97 | iframe.remove(); 98 | $(window).unbind(eventName); 99 | } 100 | } 101 | }); 102 | iframe[0].contentWindow.postMessage( 103 | message, 104 | target 105 | ); 106 | }).appendTo(document.body); 107 | }, 108 | abort: function () { 109 | if (iframe) { 110 | iframe.remove(); 111 | } 112 | } 113 | }; 114 | } 115 | }); 116 | 117 | })); 118 | -------------------------------------------------------------------------------- /js/cors/jquery.xdr-transport.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery XDomainRequest Transport Plugin 1.1.2 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2011, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * http://www.opensource.org/licenses/MIT 10 | * 11 | * Based on Julian Aubourg's ajaxHooks xdr.js: 12 | * https://github.com/jaubourg/ajaxHooks/ 13 | */ 14 | 15 | /*jslint unparam: true */ 16 | /*global define, window, XDomainRequest */ 17 | 18 | (function (factory) { 19 | 'use strict'; 20 | if (typeof define === 'function' && define.amd) { 21 | // Register as an anonymous AMD module: 22 | define(['jquery'], factory); 23 | } else { 24 | // Browser globals: 25 | factory(window.jQuery); 26 | } 27 | }(function ($) { 28 | 'use strict'; 29 | if (window.XDomainRequest && !$.support.cors) { 30 | $.ajaxTransport(function (s) { 31 | if (s.crossDomain && s.async) { 32 | if (s.timeout) { 33 | s.xdrTimeout = s.timeout; 34 | delete s.timeout; 35 | } 36 | var xdr; 37 | return { 38 | send: function (headers, completeCallback) { 39 | function callback(status, statusText, responses, responseHeaders) { 40 | xdr.onload = xdr.onerror = xdr.ontimeout = $.noop; 41 | xdr = null; 42 | completeCallback(status, statusText, responses, responseHeaders); 43 | } 44 | xdr = new XDomainRequest(); 45 | // XDomainRequest only supports GET and POST: 46 | if (s.type === 'DELETE') { 47 | s.url = s.url + (/\?/.test(s.url) ? '&' : '?') + 48 | '_method=DELETE'; 49 | s.type = 'POST'; 50 | } else if (s.type === 'PUT') { 51 | s.url = s.url + (/\?/.test(s.url) ? '&' : '?') + 52 | '_method=PUT'; 53 | s.type = 'POST'; 54 | } 55 | xdr.open(s.type, s.url); 56 | xdr.onload = function () { 57 | callback( 58 | 200, 59 | 'OK', 60 | {text: xdr.responseText}, 61 | 'Content-Type: ' + xdr.contentType 62 | ); 63 | }; 64 | xdr.onerror = function () { 65 | callback(404, 'Not Found'); 66 | }; 67 | if (s.xdrTimeout) { 68 | xdr.ontimeout = function () { 69 | callback(0, 'timeout'); 70 | }; 71 | xdr.timeout = s.xdrTimeout; 72 | } 73 | xdr.send((s.hasContent && s.data) || null); 74 | }, 75 | abort: function () { 76 | if (xdr) { 77 | xdr.onerror = $.noop(); 78 | xdr.abort(); 79 | } 80 | } 81 | }; 82 | } 83 | }); 84 | } 85 | })); 86 | -------------------------------------------------------------------------------- /js/jquery.Jcrop.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jquery.Jcrop.min.js v0.9.10 (build:20120626) 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 Math.round(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(C),bb.setCursor(a==="move"?a:a+"-resize");if(a==="move")return bb.activateHandlers(p(b),u);var c=Z.getFixed(),d=q(a),f=Z.getCorner(q(d));Z.setPressed(Z.getCorner(d)),Z.setCurrent(f),bb.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}Z.setCurrent(c),ba.update()}}function p(a){var b=a;return bc.watchKeys(),function( 8 | a){Z.moveOffset([a[0]-b[0],a[1]-b[1]]),b=a,ba.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(C),V=!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()),S=a.width()/d,T=a.height()/e,a.width(d).height(e)}function t(a){return{x:a.x*S,y:a.y*T,x2:a.x2*S,y2:a.y2*T,w:a.w*S,h:a.h*T}}function u(a){var b=Z.getFixed();b.w>d.minSelect[0]&&b.h>d.minSelect[1]?(ba.enableHandles(),ba.done()):ba.release(),bb.setCursor(d.allowSelect?"crosshair":"default")}function v(a){if(d.disabled)return!1;if(!d.allowSelect)return!1;V=!0,e=k(C),ba.disableHandles(),bb.setCursor("crosshair");var b=l(a);return Z.setPressed(b),ba.update(),bb.activateHandlers(w,u),bc.watchKeys(),a.stopPropagation 9 | (),a.preventDefault(),!1}function w(a){Z.setCurrent(a),ba.update()}function x(){var b=a("
").addClass(i("tracker"));return a.browser.msie&&b.css({opacity:0,backgroundColor:"white"}),b}function bd(a){F.removeClass().addClass(i("holder")).addClass(a)}function be(a,b){function t(){window.setTimeout(u,l)}var c=a[0]/S,e=a[1]/T,f=a[2]/S,g=a[3]/T;if(W)return;var h=Z.flipCoords(c,e,f,g),i=Z.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;c=k[0],e=k[1],f=k[2],g=k[3],ba.animMode(!0);var s,u=function(){return function(){q+=(100-q)/r,k[0]=Math.round(c+q/100*m),k[1]=Math.round(e+q/100*n),k[2]=Math.round(f+q/100*o),k[3]=Math.round(g+q/100*p),q>=99.8&&(q=100),q<100?(bg(k),t()):(ba.done(),ba.animMode(!1),typeof b=="function"&&b.call(br))}}();t()}function bf(a){bg([a[0]/S,a[1]/T,a[2]/S,a[3]/T]),d.onSelect.call(br,t(Z.getFixed())),ba.enableHandles()}function bg(a){Z.setPressed([a[0],a[1]]),Z.setCurrent([a[2],a[3]]),ba.update()}function bh(){return t 10 | (Z.getFixed())}function bi(){return Z.getFixed()}function bj(a){m(a),bq()}function bk(){d.disabled=!0,ba.disableHandles(),ba.setCursor("default"),bb.setCursor("default")}function bl(){d.disabled=!1,bq()}function bm(){ba.done(),bb.activateHandlers(null,null)}function bn(){F.remove(),z.show(),a(b).removeData("Jcrop")}function bo(a,b){ba.release(),bk();var c=new Image;c.onload=function(){var e=c.width,f=c.height,g=d.boxWidth,h=d.boxHeight;C.width(e).height(f),C.attr("src",a),G.attr("src",a),s(C,g,h),D=C.width(),E=C.height(),G.width(D).height(E),L.width(D+K*2).height(E+K*2),F.width(D).height(E),_.resize(D,E),bl(),typeof b=="function"&&b.call(br)},c.src=a}function bp(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 bq(a){d.allowResize?a?ba.enableOnly():ba.enableHandles():ba.disableHandles(),bb.setCursor(d.allowSelect?"crosshair":"default"),ba.setCursor(d.allowMove?"move":"default"),d.hasOwnProperty("trueSize")&& 11 | (S=d.trueSize[0]/D,T=d.trueSize[1]/E),d.hasOwnProperty("setSelect")&&(bf(d.setSelect),ba.done(),delete d.setSelect),_.refresh(),d.bgColor!=M&&(bp(d.shade?_.getShades():F,d.shade?d.shadeColor||d.bgColor:d.bgColor),M=d.bgColor),N!=d.bgOpacity&&(N=d.bgOpacity,d.shade?_.refresh():ba.setBgOpacity(N)),O=d.maxSize[0]||0,P=d.maxSize[1]||0,Q=d.minSize[0]||0,R=d.minSize[1]||0,d.hasOwnProperty("outerImage")&&(C.attr("src",d.outerImage),delete d.outerImage),ba.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 y={border:"none",visibility:"visible",margin:0,padding:0,position:"absolute",top:0,left:0},z=a(b),A=!0;if(b.tagName=="IMG"){if(z[0].width!=0&&z[0].height!=0)z.width(z[0].width),z.height(z[0].height);else{var B=new Image;B.src=z[0].src,z.width(B.width),z.height(B.height)}var C=z.clone().removeAttr("id").css(y).show();C.width(z.width()),C.height(z.height()),z.after(C).hide()}else C=z.css 12 | (y).show(),A=!1,d.shade===null&&(d.shade=!0);s(C,d.boxWidth,d.boxHeight);var D=C.width(),E=C.height(),F=a("
").width(D).height(E).addClass(i("holder")).css({position:"relative",backgroundColor:d.bgColor}).insertAfter(z).append(C);d.addClass&&F.addClass(d.addClass);var G=a("
"),H=a("
").width("100%").height("100%").css({zIndex:310,position:"absolute",overflow:"hidden"}),I=a("
").width("100%").height("100%").css("zIndex",320),J=a("
").css({position:"absolute",zIndex:600}).dblclick(function(){var a=Z.getFixed();d.onDblClick.call(br,a)}).insertBefore(C).append(H,I);A&&(G=a("").attr("src",C.attr("src")).css(y).width(D).height(E),H.append(G)),g&&J.css({overflowY:"hidden"});var K=d.boundary,L=x().width(D+K*2).height(E+K*2).css({position:"absolute",top:h(-K),left:h(-K),zIndex:290}).mousedown(v),M=d.bgColor,N=d.bgOpacity,O,P,Q,R,S,T,U=!0,V,W,X;e=k(C);var Y=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),ED&&(r=D,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>E&&(s=E,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>D&&(a-=r-D,r=D),s<0?(b-=s,s=0):s>E&&(b-=s-E,s=E),q(o(a,b,r,s))}function n(a){return a[0]<0&&(a[0]=0),a[1]<0&&(a[1]=0),a[0]>D&&(a[0]=D),a[1]>E&&(a[1]=E),[a[0],a[1]]}function o(a,b,c,d){var e=a,f=c,g=b,h=d;return cO&&(c=d>0?a+O:a-O),P&&Math.abs(f)>P&&(e=f>0?b+P:b-P),R/T&&Math.abs(f)0?b+R/T:b-R/T),Q/S&&Math. 15 | abs(d)0?a+Q/S:a-Q/S),a<0&&(c-=a,a-=a),b<0&&(e-=b,b-=b),c<0&&(a-=c,c-=c),e<0&&(b-=e,e-=e),c>D&&(g=c-D,a-=g,c-=g),e>E&&(g=e-E,b-=g,e-=g),a>D&&(g=a-E,e-=g,b-=g),b>E&&(g=b-E,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}}(),_=function(){function f(a,b){e.left.css({height:h(b)}),e.right.css({height:h(b)})}function g(){return i(Z.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(E-a.y2)}),e.right.css({left:h(a.x2),width:h(D-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(C),g(),ba.setBgOpacity(1,0,1),G.hide(),l(d.shadeColor||d.bgColor,1),ba.isAwake()?n(d.bgOpacity,1):n(1,1))}function l(a,b){bp(p(),a,b)}function m(){ 16 | b&&(c.remove(),G.show(),b=!1,ba.isAwake()?ba.setBgOpacity(d.bgOpacity,1,1):(ba.setBgOpacity(1,1,1),ba.disableHandles()),bp(F,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(),ba.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(E),right:j().height(E),bottom:j()};return{update:g,updateRaw:i,getShades:p,setBgColor:l,enable:k,disable:m,resize:f,refresh:o,opacity:n}}(),ba=function(){function k(b){var c=a("
").css({position:"absolute",opacity:d.borderOpacity}).addClass(i(b));return H.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 Y.support&&d.bind("touchstart.jcrop",Y.createDragger(b)),I.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" 17 | ))}function n(a){return l(a,c++).addClass("jcrop-dragbar")}function o(a){var b;for(b=0;b').css({position:"fixed",left:"-120px",width:"12px"}).addClass("jcrop-keymgr"),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(C)):b.insertBefore(C)),{watchKeys:e}}();Y.support&&L.bind("touchstart.jcrop",Y.newSelection),I.hide(),bq(!0);var br={setImage:bo,animateTo:be,setSelect:bf,setOptions:bj,tellSelect:bh,tellScaled:bi,setClass:bd,disable:bk,enable:bl,cancel:bm,release:ba.release,destroy:bn,focus:bc.watchKeys,getBounds:function(){return[D*S,E*T]},getWidgetSize:function(){return[D,E]},getScaleFactor:function(){return[S,T]},getOptions:function(){return d},ui:{holder:F,selection:J}};return a.browser.msie&&F.bind("selectstart",function(){return!1}),z.data 21 | ("Jcrop",br),br},a.fn.Jcrop=function(b,c){var d;return this.each(function(){if(a(this).data("Jcrop")){if(b==="api")return a(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" 22 | ,"se","sw"],createDragbars:["n","s","e","w"],createBorders:["n","s","e","w"],drawBorders:!0,dragEdges:!0,fixedSupport:!0,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); -------------------------------------------------------------------------------- /js/jquery.fileupload-fp.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery File Upload File Processing Plugin 1.0 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2012, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * http://www.opensource.org/licenses/MIT 10 | */ 11 | 12 | /*jslint nomen: true, unparam: true, regexp: true */ 13 | /*global define, window, document */ 14 | 15 | (function (factory) { 16 | 'use strict'; 17 | if (typeof define === 'function' && define.amd) { 18 | // Register as an anonymous AMD module: 19 | define([ 20 | 'jquery', 21 | 'load-image', 22 | 'canvas-to-blob', 23 | './jquery.fileupload' 24 | ], factory); 25 | } else { 26 | // Browser globals: 27 | factory( 28 | window.jQuery, 29 | window.loadImage 30 | ); 31 | } 32 | }(function ($, loadImage) { 33 | 'use strict'; 34 | 35 | // The File Upload IP version extends the basic fileupload widget 36 | // with file processing functionality: 37 | $.widget('blueimpFP.fileupload', $.blueimp.fileupload, { 38 | 39 | options: { 40 | // The list of file processing actions: 41 | process: [ 42 | /* 43 | { 44 | action: 'load', 45 | fileTypes: /^image\/(gif|jpeg|png)$/, 46 | maxFileSize: 20000000 // 20MB 47 | }, 48 | { 49 | action: 'resize', 50 | maxWidth: 1920, 51 | maxHeight: 1200, 52 | minWidth: 800, 53 | minHeight: 600 54 | }, 55 | { 56 | action: 'save' 57 | } 58 | */ 59 | ], 60 | 61 | // The add callback is invoked as soon as files are added to the 62 | // fileupload widget (via file input selection, drag & drop or add 63 | // API call). See the basic file upload widget for more information: 64 | add: function (e, data) { 65 | $(this).fileupload('process', data).done(function () { 66 | data.submit(); 67 | }); 68 | } 69 | }, 70 | 71 | processActions: { 72 | // Loads the image given via data.files and data.index 73 | // as canvas element. 74 | // Accepts the options fileTypes (regular expression) 75 | // and maxFileSize (integer) to limit the files to load: 76 | load: function (data, options) { 77 | var that = this, 78 | file = data.files[data.index], 79 | dfd = $.Deferred(); 80 | if (window.HTMLCanvasElement && 81 | window.HTMLCanvasElement.prototype.toBlob && 82 | ($.type(options.maxFileSize) !== 'number' || 83 | file.size < options.maxFileSize) && 84 | (!options.fileTypes || 85 | options.fileTypes.test(file.type))) { 86 | loadImage( 87 | file, 88 | function (canvas) { 89 | data.canvas = canvas; 90 | dfd.resolveWith(that, [data]); 91 | }, 92 | {canvas: true} 93 | ); 94 | } else { 95 | dfd.rejectWith(that, [data]); 96 | } 97 | return dfd.promise(); 98 | }, 99 | // Resizes the image given as data.canvas and updates 100 | // data.canvas with the resized image. 101 | // Accepts the options maxWidth, maxHeight, minWidth and 102 | // minHeight to scale the given image: 103 | resize: function (data, options) { 104 | if (data.canvas) { 105 | var canvas = loadImage.scale(data.canvas, options); 106 | if (canvas.width !== data.canvas.width || 107 | canvas.height !== data.canvas.height) { 108 | data.canvas = canvas; 109 | data.processed = true; 110 | } 111 | } 112 | return data; 113 | }, 114 | // Saves the processed image given as data.canvas 115 | // inplace at data.index of data.files: 116 | save: function (data, options) { 117 | // Do nothing if no processing has happened: 118 | if (!data.canvas || !data.processed) { 119 | return data; 120 | } 121 | var that = this, 122 | file = data.files[data.index], 123 | name = file.name, 124 | dfd = $.Deferred(), 125 | callback = function (blob) { 126 | if (!blob.name) { 127 | if (file.type === blob.type) { 128 | blob.name = file.name; 129 | } else if (file.name) { 130 | blob.name = file.name.replace( 131 | /\..+$/, 132 | '.' + blob.type.substr(6) 133 | ); 134 | } 135 | } 136 | // Store the created blob at the position 137 | // of the original file in the files list: 138 | data.files[data.index] = blob; 139 | dfd.resolveWith(that, [data]); 140 | }; 141 | // Use canvas.mozGetAsFile directly, to retain the filename, as 142 | // Gecko doesn't support the filename option for FormData.append: 143 | if (data.canvas.mozGetAsFile) { 144 | callback(data.canvas.mozGetAsFile( 145 | (/^image\/(jpeg|png)$/.test(file.type) && name) || 146 | ((name && name.replace(/\..+$/, '')) || 147 | 'blob') + '.png', 148 | file.type 149 | )); 150 | } else { 151 | data.canvas.toBlob(callback, file.type); 152 | } 153 | return dfd.promise(); 154 | } 155 | }, 156 | 157 | // Resizes the file at the given index and stores the created blob at 158 | // the original position of the files list, returns a Promise object: 159 | _processFile: function (files, index, options) { 160 | var that = this, 161 | dfd = $.Deferred().resolveWith(that, [{ 162 | files: files, 163 | index: index 164 | }]), 165 | chain = dfd.promise(); 166 | that._processing += 1; 167 | $.each(options.process, function (i, settings) { 168 | chain = chain.pipe(function (data) { 169 | return that.processActions[settings.action] 170 | .call(this, data, settings); 171 | }); 172 | }); 173 | chain.always(function () { 174 | that._processing -= 1; 175 | if (that._processing === 0) { 176 | that.element 177 | .removeClass('fileupload-processing'); 178 | } 179 | }); 180 | if (that._processing === 1) { 181 | that.element.addClass('fileupload-processing'); 182 | } 183 | return chain; 184 | }, 185 | 186 | // Processes the files given as files property of the data parameter, 187 | // returns a Promise object that allows to bind a done handler, which 188 | // will be invoked after processing all files (inplace) is done: 189 | process: function (data) { 190 | var that = this, 191 | options = $.extend({}, this.options, data); 192 | if (options.process && options.process.length && 193 | this._isXHRUpload(options)) { 194 | $.each(data.files, function (index, file) { 195 | that._processingQueue = that._processingQueue.pipe( 196 | function () { 197 | var dfd = $.Deferred(); 198 | that._processFile(data.files, index, options) 199 | .always(function () { 200 | dfd.resolveWith(that); 201 | }); 202 | return dfd.promise(); 203 | } 204 | ); 205 | }); 206 | } 207 | return this._processingQueue; 208 | }, 209 | 210 | _create: function () { 211 | $.blueimp.fileupload.prototype._create.call(this); 212 | this._processing = 0; 213 | this._processingQueue = $.Deferred().resolveWith(this) 214 | .promise(); 215 | } 216 | 217 | }); 218 | 219 | })); 220 | -------------------------------------------------------------------------------- /js/jquery.iframe-transport.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery Iframe Transport Plugin 1.4 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2011, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * http://www.opensource.org/licenses/MIT 10 | */ 11 | 12 | /*jslint unparam: true, nomen: true */ 13 | /*global define, window, document */ 14 | 15 | (function (factory) { 16 | 'use strict'; 17 | if (typeof define === 'function' && define.amd) { 18 | // Register as an anonymous AMD module: 19 | define(['jquery'], factory); 20 | } else { 21 | // Browser globals: 22 | factory(window.jQuery); 23 | } 24 | }(function ($) { 25 | 'use strict'; 26 | 27 | // Helper variable to create unique names for the transport iframes: 28 | var counter = 0; 29 | 30 | // The iframe transport accepts three additional options: 31 | // options.fileInput: a jQuery collection of file input fields 32 | // options.paramName: the parameter name for the file form data, 33 | // overrides the name property of the file input field(s), 34 | // can be a string or an array of strings. 35 | // options.formData: an array of objects with name and value properties, 36 | // equivalent to the return data of .serializeArray(), e.g.: 37 | // [{name: 'a', value: 1}, {name: 'b', value: 2}] 38 | $.ajaxTransport('iframe', function (options) { 39 | if (options.async && (options.type === 'POST' || options.type === 'GET')) { 40 | var form, 41 | iframe; 42 | return { 43 | send: function (_, completeCallback) { 44 | form = $('
'); 45 | // javascript:false as initial iframe src 46 | // prevents warning popups on HTTPS in IE6. 47 | // IE versions below IE8 cannot set the name property of 48 | // elements that have already been added to the DOM, 49 | // so we set the name along with the iframe HTML markup: 50 | iframe = $( 51 | '' 53 | ).bind('load', function () { 54 | var fileInputClones, 55 | paramNames = $.isArray(options.paramName) ? 56 | options.paramName : [options.paramName]; 57 | iframe 58 | .unbind('load') 59 | .bind('load', function () { 60 | var response; 61 | // Wrap in a try/catch block to catch exceptions thrown 62 | // when trying to access cross-domain iframe contents: 63 | try { 64 | response = iframe.contents(); 65 | // Google Chrome and Firefox do not throw an 66 | // exception when calling iframe.contents() on 67 | // cross-domain requests, so we unify the response: 68 | if (!response.length || !response[0].firstChild) { 69 | throw new Error(); 70 | } 71 | } catch (e) { 72 | response = undefined; 73 | } 74 | // The complete callback returns the 75 | // iframe content document as response object: 76 | completeCallback( 77 | 200, 78 | 'success', 79 | {'iframe': response} 80 | ); 81 | // Fix for IE endless progress bar activity bug 82 | // (happens on form submits to iframe targets): 83 | $('') 84 | .appendTo(form); 85 | form.remove(); 86 | }); 87 | form 88 | .prop('target', iframe.prop('name')) 89 | .prop('action', options.url) 90 | .prop('method', options.type); 91 | if (options.formData) { 92 | $.each(options.formData, function (index, field) { 93 | $('') 94 | .prop('name', field.name) 95 | .val(field.value) 96 | .appendTo(form); 97 | }); 98 | } 99 | if (options.fileInput && options.fileInput.length && 100 | options.type === 'POST') { 101 | fileInputClones = options.fileInput.clone(); 102 | // Insert a clone for each file input field: 103 | options.fileInput.after(function (index) { 104 | return fileInputClones[index]; 105 | }); 106 | if (options.paramName) { 107 | options.fileInput.each(function (index) { 108 | $(this).prop( 109 | 'name', 110 | paramNames[index] || options.paramName 111 | ); 112 | }); 113 | } 114 | // Appending the file input fields to the hidden form 115 | // removes them from their original location: 116 | form 117 | .append(options.fileInput) 118 | .prop('enctype', 'multipart/form-data') 119 | // enctype must be set as encoding for IE: 120 | .prop('encoding', 'multipart/form-data'); 121 | } 122 | form.submit(); 123 | // Insert the file input fields at their original location 124 | // by replacing the clones with the originals: 125 | if (fileInputClones && fileInputClones.length) { 126 | options.fileInput.each(function (index, input) { 127 | var clone = $(fileInputClones[index]); 128 | $(input).prop('name', clone.prop('name')); 129 | clone.replaceWith(input); 130 | }); 131 | } 132 | }); 133 | form.append(iframe).appendTo(document.body); 134 | }, 135 | abort: function () { 136 | if (iframe) { 137 | // javascript:false as iframe src aborts the request 138 | // and prevents warning popups on HTTPS in IE6. 139 | // concat is used to avoid the "Script URL" JSLint error: 140 | iframe 141 | .unbind('load') 142 | .prop('src', 'javascript'.concat(':false;')); 143 | } 144 | if (form) { 145 | form.remove(); 146 | } 147 | } 148 | }; 149 | } 150 | }); 151 | 152 | // The iframe transport returns the iframe content document as response. 153 | // The following adds converters from iframe to text, json, html, and script: 154 | $.ajaxSetup({ 155 | converters: { 156 | 'iframe text': function (iframe) { 157 | return $(iframe[0].body).text(); 158 | }, 159 | 'iframe json': function (iframe) { 160 | return $.parseJSON($(iframe[0].body).text()); 161 | }, 162 | 'iframe html': function (iframe) { 163 | return $(iframe[0].body).html(); 164 | }, 165 | 'iframe script': function (iframe) { 166 | return $.globalEval($(iframe[0].body).text()); 167 | } 168 | } 169 | }); 170 | 171 | })); 172 | -------------------------------------------------------------------------------- /js/jquery.zclip.js: -------------------------------------------------------------------------------- 1 | /* 2 | * zClip :: jQuery ZeroClipboard v1.1.1 3 | * http://steamdev.com/zclip 4 | * 5 | * Copyright 2011, SteamDev 6 | * Released under the MIT license. 7 | * http://www.opensource.org/licenses/mit-license.php 8 | * 9 | * Date: Wed Jun 01, 2011 10 | */ 11 | 12 | (function(a){a.fn.zclip=function(c){if(typeof c=="object"&&!c.length){var b=a.extend({path:"ZeroClipboard.swf",copy:null,beforeCopy:null,afterCopy:null,clickAfter:true,setHandCursor:true,setCSSEffects:true},c);return this.each(function(){var e=a(this);if(e.is(":visible")&&(typeof b.copy=="string"||a.isFunction(b.copy))){ZeroClipboard.setMoviePath(b.path);var d=new ZeroClipboard.Client();if(a.isFunction(b.copy)){e.bind("zClip_copy",b.copy)}if(a.isFunction(b.beforeCopy)){e.bind("zClip_beforeCopy",b.beforeCopy)}if(a.isFunction(b.afterCopy)){e.bind("zClip_afterCopy",b.afterCopy)}d.setHandCursor(b.setHandCursor);d.setCSSEffects(b.setCSSEffects);d.addEventListener("mouseOver",function(f){e.trigger("mouseenter")});d.addEventListener("mouseOut",function(f){e.trigger("mouseleave")});d.addEventListener("mouseDown",function(f){e.trigger("mousedown");if(!a.isFunction(b.copy)){d.setText(b.copy)}else{d.setText(e.triggerHandler("zClip_copy"))}if(a.isFunction(b.beforeCopy)){e.trigger("zClip_beforeCopy")}});d.addEventListener("complete",function(f,g){if(a.isFunction(b.afterCopy)){e.trigger("zClip_afterCopy")}else{if(g.length>500){g=g.substr(0,500)+"...\n\n("+(g.length-500)+" characters not shown)"}e.removeClass("hover");alert("Copied text to clipboard:\n\n "+g)}if(b.clickAfter){e.trigger("click")}});d.glue(e[0],e.parent()[0]);a(window).bind("load resize",function(){d.reposition()})}})}else{if(typeof c=="string"){return this.each(function(){var f=a(this);c=c.toLowerCase();var e=f.data("zclipId");var d=a("#"+e+".zclip");if(c=="remove"){d.remove();f.removeClass("active hover")}else{if(c=="hide"){d.hide();f.removeClass("active hover")}else{if(c=="show"){d.show()}}}})}}}})(jQuery);var ZeroClipboard={version:"1.0.7",clients:{},moviePath:"ZeroClipboard.swf",nextId:1,$:function(a){if(typeof(a)=="string"){a=document.getElementById(a)}if(!a.addClass){a.hide=function(){this.style.display="none"};a.show=function(){this.style.display=""};a.addClass=function(b){this.removeClass(b);this.className+=" "+b};a.removeClass=function(d){var e=this.className.split(/\s+/);var b=-1;for(var c=0;c-1){e.splice(b,1);this.className=e.join(" ")}return this};a.hasClass=function(b){return !!this.className.match(new RegExp("\\s*"+b+"\\s*"))}}return a},setMoviePath:function(a){this.moviePath=a},dispatch:function(d,b,c){var a=this.clients[d];if(a){a.receiveEvent(b,c)}},register:function(b,a){this.clients[b]=a},getDOMObjectPosition:function(c,a){var b={left:0,top:0,width:c.width?c.width:c.offsetWidth,height:c.height?c.height:c.offsetHeight};if(c&&(c!=a)){b.left+=c.offsetLeft;b.top+=c.offsetTop}return b},Client:function(a){this.handlers={};this.id=ZeroClipboard.nextId++;this.movieId="ZeroClipboardMovie_"+this.id;ZeroClipboard.register(this.id,this);if(a){this.glue(a)}}};ZeroClipboard.Client.prototype={id:0,ready:false,movie:null,clipText:"",handCursorEnabled:true,cssEffects:true,handlers:null,glue:function(d,b,e){this.domElement=ZeroClipboard.$(d);var f=99;if(this.domElement.style.zIndex){f=parseInt(this.domElement.style.zIndex,10)+1}if(typeof(b)=="string"){b=ZeroClipboard.$(b)}else{if(typeof(b)=="undefined"){b=document.getElementsByTagName("body")[0]}}var c=ZeroClipboard.getDOMObjectPosition(this.domElement,b);this.div=document.createElement("div");this.div.className="zclip";this.div.id="zclip-"+this.movieId;$(this.domElement).data("zclipId","zclip-"+this.movieId);var a=this.div.style;a.position="absolute";a.left=""+c.left+"px";a.top=""+c.top+"px";a.width=""+c.width+"px";a.height=""+c.height+"px";a.zIndex=f;if(typeof(e)=="object"){for(addedStyle in e){a[addedStyle]=e[addedStyle]}}b.appendChild(this.div);this.div.innerHTML=this.getHTML(c.width,c.height)},getHTML:function(d,a){var c="";var b="id="+this.id+"&width="+d+"&height="+a;if(navigator.userAgent.match(/MSIE/)){var e=location.href.match(/^https/i)?"https://":"http://";c+=''}else{c+=''}return c},hide:function(){if(this.div){this.div.style.left="-2000px"}},show:function(){this.reposition()},destroy:function(){if(this.domElement&&this.div){this.hide();this.div.innerHTML="";var a=document.getElementsByTagName("body")[0];try{a.removeChild(this.div)}catch(b){}this.domElement=null;this.div=null}},reposition:function(c){if(c){this.domElement=ZeroClipboard.$(c);if(!this.domElement){this.hide()}}if(this.domElement&&this.div){var b=ZeroClipboard.getDOMObjectPosition(this.domElement);var a=this.div.style;a.left=""+b.left+"px";a.top=""+b.top+"px"}},setText:function(a){this.clipText=a;if(this.ready){this.movie.setText(a)}},addEventListener:function(a,b){a=a.toString().toLowerCase().replace(/^on/,"");if(!this.handlers[a]){this.handlers[a]=[]}this.handlers[a].push(b)},setHandCursor:function(a){this.handCursorEnabled=a;if(this.ready){this.movie.setHandCursor(a)}},setCSSEffects:function(a){this.cssEffects=!!a},receiveEvent:function(d,f){d=d.toString().toLowerCase().replace(/^on/,"");switch(d){case"load":this.movie=document.getElementById(this.movieId);if(!this.movie){var c=this;setTimeout(function(){c.receiveEvent("load",null)},1);return}if(!this.ready&&navigator.userAgent.match(/Firefox/)&&navigator.userAgent.match(/Windows/)){var c=this;setTimeout(function(){c.receiveEvent("load",null)},100);this.ready=true;return}this.ready=true;try{this.movie.setText(this.clipText)}catch(h){}try{this.movie.setHandCursor(this.handCursorEnabled)}catch(h){}break;case"mouseover":if(this.domElement&&this.cssEffects){this.domElement.addClass("hover");if(this.recoverActive){this.domElement.addClass("active")}}break;case"mouseout":if(this.domElement&&this.cssEffects){this.recoverActive=false;if(this.domElement.hasClass("active")){this.domElement.removeClass("active");this.recoverActive=true}this.domElement.removeClass("hover")}break;case"mousedown":if(this.domElement&&this.cssEffects){this.domElement.addClass("active")}break;case"mouseup":if(this.domElement&&this.cssEffects){this.domElement.removeClass("active");this.recoverActive=false}break}if(this.handlers[d]){for(var b=0,a=this.handlers[d].length;b1&&(d=parseInt(d*f,10),e=parseInt(e*f,10)),f=Math.min((b.maxWidth||d)/d,(b.maxHeight||e)/e),f<1&&(d=parseInt(d*f,10),e=parseInt(e*f,10)),a.getContext||b.canvas&&c.getContext?(c.width=d,c.height=e,c.getContext("2d").drawImage(a,0,0,d,e),c):(a.width=d,a.height=e,a)},b.createObjectURL=function(a){return c?c.createObjectURL(a):!1},b.revokeObjectURL=function(a){return c?c.revokeObjectURL(a):!1},b.readFile=function(a,b){if(window.FileReader&&FileReader.prototype.readAsDataURL){var c=new FileReader;return c.onload=function(a){b(a.target.result)},c.readAsDataURL(a),c}return!1},typeof define!="undefined"&&define.amd?define(function(){return b}):a.loadImage=b})(this); -------------------------------------------------------------------------------- /js/locale.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery File Upload Plugin Localization Example 6.5.1 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2012, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * http://www.opensource.org/licenses/MIT 10 | */ 11 | 12 | /*global window */ 13 | 14 | window.locale = { 15 | "fileupload": { 16 | "errors": { 17 | "maxFileSize": "File is too big", 18 | "minFileSize": "File is too small", 19 | "acceptFileTypes": "Filetype not allowed", 20 | "maxNumberOfFiles": "Max number of files exceeded", 21 | "uploadedBytes": "Uploaded bytes exceed file size", 22 | "emptyResult": "Empty file upload result" 23 | }, 24 | "error": "Error", 25 | "start": "Start", 26 | "cancel": "Cancel", 27 | "destroy": "Delete" 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery File Upload Plugin JS Example 6.7 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2010, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * http://www.opensource.org/licenses/MIT 10 | */ 11 | 12 | /*jslint nomen: true, unparam: true, regexp: true */ 13 | /*global $, window, document */ 14 | var $activeImage; 15 | var cropCoordinates={}; 16 | $(function () { 17 | 'use strict'; 18 | 19 | // Initialize the jQuery File Upload widget: 20 | $('#fileupload').fileupload(); 21 | 22 | // Enable iframe cross-domain access via redirect option: 23 | $('#fileupload').fileupload( 24 | 'option', 25 | 'redirect', 26 | window.location.href.replace( 27 | /\/[^\/]*$/, 28 | '/cors/result.html?%s' 29 | ) 30 | ); 31 | 32 | /* if (window.location.hostname === 'blueimp.github.com') { 33 | // Demo settings: 34 | $('#fileupload').fileupload('option', { 35 | url: '//jquery-file-upload.appspot.com/', 36 | maxFileSize: 5000000, 37 | acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, 38 | process: [ 39 | { 40 | action: 'load', 41 | fileTypes: /^image\/(gif|jpeg|png)$/, 42 | maxFileSize: 20000000 // 20MB 43 | }, 44 | { 45 | action: 'resize', 46 | maxWidth: 1440, 47 | maxHeight: 900 48 | }, 49 | { 50 | action: 'save' 51 | } 52 | ] 53 | }); 54 | // Upload server status check for browsers with CORS support: 55 | if ($.support.cors) { 56 | $.ajax({ 57 | url: '//jquery-file-upload.appspot.com/', 58 | type: 'HEAD' 59 | }).fail(function () { 60 | $('') 61 | .text('Upload server currently unavailable - ' + 62 | new Date()) 63 | .appendTo('#fileupload'); 64 | }); 65 | } 66 | } else {//*/ 67 | // Load existing files: 68 | loadExistingFiles(); 69 | /*} //*/ 70 | 71 | /***************** added by Agustín Amenabar *******************************/ 72 | $('#modal-gallery').on('displayed', function () { 73 | var modalData = $(this).data('modal'); 74 | // modalData.$links is the list of (filtered) element nodes as jQuery object 75 | // modalData.img is the img (or canvas) element for the loaded image 76 | // modalData.options.index is the index of the current link 77 | initZClip(); 78 | $('#urlImage').css('vertical-align','top'); 79 | $activeImage = $(modalData.img); 80 | $('#urlImage').val($activeImage.attr('src')); 81 | 82 | $('#inWidthCrop').val($('#croppingModal').attr('data-width')); 83 | $('#inHeightCrop').val($('#croppingModal').attr('data-height')); 84 | 85 | $('#startCrop').click(function(eve){ 86 | eve.preventDefault(); 87 | var $cm = $('#croppingModal'); 88 | var cssProperties = Array('margin-left','margin-top','width'); 89 | for (var i = cssProperties.length - 1; i >= 0; i--) { 90 | $cm.css(cssProperties[i],$('#modal-gallery').css(cssProperties[i])); 91 | }; 92 | $cm.find('.modal-body').css('max-height','none'); 93 | $('#croppingModal').modal('show').find('.close, .closeModal').click(function(eve){ 94 | eve.preventDefault(); 95 | $('#croppingModal').modal('hide'); 96 | }); 97 | $('#modal-gallery').modal('hide'); 98 | 99 | var picWidth = $activeImage.width(); 100 | var picHeight = $activeImage.height(); 101 | if (!picWidth) return; 102 | $('#canvasToCrop').attr('width',picWidth); 103 | $('#canvasToCrop').attr('height',picHeight); 104 | 105 | var canContext = $('#canvasToCrop')[0].getContext("2d"); 106 | canContext.drawImage($activeImage[0],0,0,picWidth,picHeight); 107 | 108 | var jcOptions = {}; 109 | if($('#inWidthCrop').val() && $('#inHeightCrop').val()){ 110 | jcOptions.aspectRatio=$('#inWidthCrop').val() / $('#inHeightCrop').val(); 111 | $('#croppingModal').find('h3 .dimentions').text('to '+$('#inWidthCrop').val() + ' x ' + $('#inHeightCrop').val() + ' px'); 112 | } 113 | 114 | cropCoordinates.source = { 115 | width:picWidth, 116 | height:picHeight, 117 | endWidth:$('#inWidthCrop').val(), 118 | endHeight:$('#inHeightCrop').val(), 119 | file:$activeImage.attr('src') 120 | }; 121 | jcOptions.onSelect = function(c){ 122 | cropCoordinates.c=c; 123 | }; 124 | 125 | $('#canvasToCrop').Jcrop(jcOptions); 126 | }); 127 | $('#opCrop').find('button[type=reset]').click(function(){ 128 | enableStartResize(false); 129 | }); 130 | $('#inWidthCrop').change(function(){ 131 | if(!$(this).val() || $(this).val()=='0'){ 132 | enableStartResize(false); 133 | $('#inHeightCrop').val(''); 134 | return; 135 | }else{ 136 | enableStartResize(true); 137 | } 138 | }); 139 | $('#inHeightCrop').change(function(){ 140 | if(!$(this).val() || $(this).val()=='0'){ 141 | enableStartResize(false); 142 | $('#inWidthCrop').val(''); 143 | return; 144 | }else{ 145 | enableStartResize(true); 146 | } 147 | }); 148 | }); 149 | $('#btnDoCrop').click(function(eve){ 150 | eve.preventDefault(); 151 | $.post('server/php/image_crop_and_size.php',cropCoordinates,afterCropping) 152 | }); 153 | $('#startResize').click(function(){ 154 | var noSize=true; 155 | var resizeData={ file:$activeImage.attr('src') }; 156 | if($('#inWidthCrop').val() && $('#inWidthCrop').val() != '0'){ 157 | resizeData.width=$('#inWidthCrop').val(); 158 | noSize=false; 159 | } 160 | if($('#inHeightCrop').val() && $('#inHeightCrop').val() != '0'){ 161 | resizeData.height=$('#inHeightCrop').val(); 162 | noSize=false; 163 | } 164 | if(noSize)return;//there's no width nor height defined to do the resize. 165 | $('#startCrop, #startResize, #inWidthCrop, #inHeightCrop').attr('disabled','disabled'); 166 | $.post('server/php/image_crop_and_size.php',resizeData,afterResize); 167 | 168 | }); 169 | }); 170 | 171 | function afterCropping(data,textStatus,jqXHR){ 172 | $('#croppingModal').modal('hide'); 173 | $('tbody.files').find('tr').remove(); 174 | loadExistingFiles(); 175 | } 176 | 177 | function afterResize(data,textStatus,jqXHR){ 178 | $('#modal-gallery').modal('hide'); 179 | $('#startCrop, #startResize, #inWidthCrop, #inHeightCrop').removeAttr('disabled'); 180 | $('tbody.files').find('tr').remove(); 181 | loadExistingFiles(); 182 | } 183 | 184 | function loadExistingFiles(){ 185 | result=null; 186 | $('#fileupload').each(function () { 187 | var that = this; 188 | $.getJSON(this.action, function (result) { 189 | if (result && result.length) { 190 | $(that).fileupload('option', 'done') 191 | .call(that, null, {result: result}); 192 | } 193 | }); 194 | }); 195 | } 196 | 197 | var zclipInitialized = false; 198 | function initZClip(){ 199 | if(zclipInitialized)return; 200 | $('a.modal-copy').zclip({ 201 | path:'js/ZeroClipboard.swf', 202 | copy:function(){return $('#urlImage').val();} 203 | }); 204 | zclipInitialized=true; 205 | } 206 | 207 | function enableStartResize(activar){ 208 | $targ=$('#startResize'); 209 | if(activar){ 210 | $targ.removeAttr('disabled'); 211 | }else{ 212 | $targ.attr('disabled','disabled'); 213 | } 214 | 215 | } 216 | /* 217 | * Special event for image load events 218 | * Needed because some browsers does not trigger the event on cached images. 219 | 220 | * MIT License 221 | * Paul Irish | @paul_irish | www.paulirish.com 222 | * Andree Hansson | @peolanha | www.andreehansson.se 223 | * 2010. 224 | * 225 | * Usage: 226 | * $(images).bind('load', function (e) { 227 | * // Do stuff on load 228 | * }); 229 | * 230 | * Note that you can bind the 'error' event on data uri images, this will trigger when 231 | * data uri images isn't supported. 232 | * 233 | * Tested in: 234 | * FF 3+ 235 | * IE 6-8 236 | * Chromium 5-6 237 | * Opera 9-10 238 | */ 239 | (function ($) { 240 | $.event.special.load = { 241 | add: function (hollaback) { 242 | if ( this.nodeType === 1 && this.tagName.toLowerCase() === 'img' && this.src !== '' ) { 243 | // Image is already complete, fire the hollaback (fixes browser issues were cached 244 | // images isn't triggering the load event) 245 | if ( this.complete || this.readyState === 4 ) { 246 | hollaback.handler.apply(this); 247 | } 248 | 249 | // Check if data URI images is supported, fire 'error' event if not 250 | else if ( this.readyState === 'uninitialized' && this.src.indexOf('data:') === 0 ) { 251 | $(this).trigger('error'); 252 | } 253 | 254 | else { 255 | $(this).bind('load', hollaback.handler); 256 | } 257 | } 258 | } 259 | }; 260 | }(jQuery)); -------------------------------------------------------------------------------- /js/tmpl.min.js: -------------------------------------------------------------------------------- 1 | (function(a){"use strict";var b=function(a,c){var d=/[^\w\-\.:]/.test(a)?new Function(b.arg+",tmpl","var _e=tmpl.encode"+b.helper+",_s='"+a.replace(b.regexp,b.func)+"';return _s;"):b.cache[a]=b.cache[a]||b(b.load(a));return c?d(c,b):function(a){return d(a,b)}};b.cache={},b.load=function(a){return document.getElementById(a).innerHTML},b.regexp=/([\s'\\])(?![^%]*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g,b.func=function(a,b,c,d,e,f){if(b)return{"\n":"\\n","\r":"\\r","\t":"\\t"," ":" "}[a]||"\\"+a;if(c)return c==="="?"'+_e("+d+")+'":"'+("+d+"||'')+'";if(e)return"';";if(f)return"_s+='"},b.encReg=/[<>&"'\x00]/g,b.encMap={"<":"<",">":">","&":"&",'"':""","'":"'"},b.encode=function(a){return String(a||"").replace(b.encReg,function(a){return b.encMap[a]||""})},b.arg="o",b.helper=",print=function(s,e){_s+=e&&(s||'')||_e(s);},include=function(s,d){_s+=tmpl(s,d);}",typeof define=="function"&&define.amd?define(function(){return b}):a.tmpl=b})(this); -------------------------------------------------------------------------------- /js/vendor/jquery.ui.widget.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI Widget 1.8.22+amd 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) 6 | * Dual licensed under the MIT or GPL Version 2 licenses. 7 | * http://jquery.org/license 8 | * 9 | * http://docs.jquery.com/UI/Widget 10 | */ 11 | 12 | (function (factory) { 13 | if (typeof define === "function" && define.amd) { 14 | // Register as an anonymous AMD module: 15 | define(["jquery"], factory); 16 | } else { 17 | // Browser globals: 18 | factory(jQuery); 19 | } 20 | }(function( $, undefined ) { 21 | 22 | // jQuery 1.4+ 23 | if ( $.cleanData ) { 24 | var _cleanData = $.cleanData; 25 | $.cleanData = function( elems ) { 26 | for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { 27 | try { 28 | $( elem ).triggerHandler( "remove" ); 29 | // http://bugs.jquery.com/ticket/8235 30 | } catch( e ) {} 31 | } 32 | _cleanData( elems ); 33 | }; 34 | } else { 35 | var _remove = $.fn.remove; 36 | $.fn.remove = function( selector, keepData ) { 37 | return this.each(function() { 38 | if ( !keepData ) { 39 | if ( !selector || $.filter( selector, [ this ] ).length ) { 40 | $( "*", this ).add( [ this ] ).each(function() { 41 | try { 42 | $( this ).triggerHandler( "remove" ); 43 | // http://bugs.jquery.com/ticket/8235 44 | } catch( e ) {} 45 | }); 46 | } 47 | } 48 | return _remove.call( $(this), selector, keepData ); 49 | }); 50 | }; 51 | } 52 | 53 | $.widget = function( name, base, prototype ) { 54 | var namespace = name.split( "." )[ 0 ], 55 | fullName; 56 | name = name.split( "." )[ 1 ]; 57 | fullName = namespace + "-" + name; 58 | 59 | if ( !prototype ) { 60 | prototype = base; 61 | base = $.Widget; 62 | } 63 | 64 | // create selector for plugin 65 | $.expr[ ":" ][ fullName ] = function( elem ) { 66 | return !!$.data( elem, name ); 67 | }; 68 | 69 | $[ namespace ] = $[ namespace ] || {}; 70 | $[ namespace ][ name ] = function( options, element ) { 71 | // allow instantiation without initializing for simple inheritance 72 | if ( arguments.length ) { 73 | this._createWidget( options, element ); 74 | } 75 | }; 76 | 77 | var basePrototype = new base(); 78 | // we need to make the options hash a property directly on the new instance 79 | // otherwise we'll modify the options hash on the prototype that we're 80 | // inheriting from 81 | // $.each( basePrototype, function( key, val ) { 82 | // if ( $.isPlainObject(val) ) { 83 | // basePrototype[ key ] = $.extend( {}, val ); 84 | // } 85 | // }); 86 | basePrototype.options = $.extend( true, {}, basePrototype.options ); 87 | $[ namespace ][ name ].prototype = $.extend( true, basePrototype, { 88 | namespace: namespace, 89 | widgetName: name, 90 | widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, 91 | widgetBaseClass: fullName 92 | }, prototype ); 93 | 94 | $.widget.bridge( name, $[ namespace ][ name ] ); 95 | }; 96 | 97 | $.widget.bridge = function( name, object ) { 98 | $.fn[ name ] = function( options ) { 99 | var isMethodCall = typeof options === "string", 100 | args = Array.prototype.slice.call( arguments, 1 ), 101 | returnValue = this; 102 | 103 | // allow multiple hashes to be passed on init 104 | options = !isMethodCall && args.length ? 105 | $.extend.apply( null, [ true, options ].concat(args) ) : 106 | options; 107 | 108 | // prevent calls to internal methods 109 | if ( isMethodCall && options.charAt( 0 ) === "_" ) { 110 | return returnValue; 111 | } 112 | 113 | if ( isMethodCall ) { 114 | this.each(function() { 115 | var instance = $.data( this, name ), 116 | methodValue = instance && $.isFunction( instance[options] ) ? 117 | instance[ options ].apply( instance, args ) : 118 | instance; 119 | // TODO: add this back in 1.9 and use $.error() (see #5972) 120 | // if ( !instance ) { 121 | // throw "cannot call methods on " + name + " prior to initialization; " + 122 | // "attempted to call method '" + options + "'"; 123 | // } 124 | // if ( !$.isFunction( instance[options] ) ) { 125 | // throw "no such method '" + options + "' for " + name + " widget instance"; 126 | // } 127 | // var methodValue = instance[ options ].apply( instance, args ); 128 | if ( methodValue !== instance && methodValue !== undefined ) { 129 | returnValue = methodValue; 130 | return false; 131 | } 132 | }); 133 | } else { 134 | this.each(function() { 135 | var instance = $.data( this, name ); 136 | if ( instance ) { 137 | instance.option( options || {} )._init(); 138 | } else { 139 | $.data( this, name, new object( options, this ) ); 140 | } 141 | }); 142 | } 143 | 144 | return returnValue; 145 | }; 146 | }; 147 | 148 | $.Widget = function( options, element ) { 149 | // allow instantiation without initializing for simple inheritance 150 | if ( arguments.length ) { 151 | this._createWidget( options, element ); 152 | } 153 | }; 154 | 155 | $.Widget.prototype = { 156 | widgetName: "widget", 157 | widgetEventPrefix: "", 158 | options: { 159 | disabled: false 160 | }, 161 | _createWidget: function( options, element ) { 162 | // $.widget.bridge stores the plugin instance, but we do it anyway 163 | // so that it's stored even before the _create function runs 164 | $.data( element, this.widgetName, this ); 165 | this.element = $( element ); 166 | this.options = $.extend( true, {}, 167 | this.options, 168 | this._getCreateOptions(), 169 | options ); 170 | 171 | var self = this; 172 | this.element.bind( "remove." + this.widgetName, function() { 173 | self.destroy(); 174 | }); 175 | 176 | this._create(); 177 | this._trigger( "create" ); 178 | this._init(); 179 | }, 180 | _getCreateOptions: function() { 181 | return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; 182 | }, 183 | _create: function() {}, 184 | _init: function() {}, 185 | 186 | destroy: function() { 187 | this.element 188 | .unbind( "." + this.widgetName ) 189 | .removeData( this.widgetName ); 190 | this.widget() 191 | .unbind( "." + this.widgetName ) 192 | .removeAttr( "aria-disabled" ) 193 | .removeClass( 194 | this.widgetBaseClass + "-disabled " + 195 | "ui-state-disabled" ); 196 | }, 197 | 198 | widget: function() { 199 | return this.element; 200 | }, 201 | 202 | option: function( key, value ) { 203 | var options = key; 204 | 205 | if ( arguments.length === 0 ) { 206 | // don't return a reference to the internal hash 207 | return $.extend( {}, this.options ); 208 | } 209 | 210 | if (typeof key === "string" ) { 211 | if ( value === undefined ) { 212 | return this.options[ key ]; 213 | } 214 | options = {}; 215 | options[ key ] = value; 216 | } 217 | 218 | this._setOptions( options ); 219 | 220 | return this; 221 | }, 222 | _setOptions: function( options ) { 223 | var self = this; 224 | $.each( options, function( key, value ) { 225 | self._setOption( key, value ); 226 | }); 227 | 228 | return this; 229 | }, 230 | _setOption: function( key, value ) { 231 | this.options[ key ] = value; 232 | 233 | if ( key === "disabled" ) { 234 | this.widget() 235 | [ value ? "addClass" : "removeClass"]( 236 | this.widgetBaseClass + "-disabled" + " " + 237 | "ui-state-disabled" ) 238 | .attr( "aria-disabled", value ); 239 | } 240 | 241 | return this; 242 | }, 243 | 244 | enable: function() { 245 | return this._setOption( "disabled", false ); 246 | }, 247 | disable: function() { 248 | return this._setOption( "disabled", true ); 249 | }, 250 | 251 | _trigger: function( type, event, data ) { 252 | var prop, orig, 253 | callback = this.options[ type ]; 254 | 255 | data = data || {}; 256 | event = $.Event( event ); 257 | event.type = ( type === this.widgetEventPrefix ? 258 | type : 259 | this.widgetEventPrefix + type ).toLowerCase(); 260 | // the original event may come from any element 261 | // so we need to reset the target on the new event 262 | event.target = this.element[ 0 ]; 263 | 264 | // copy original event properties over to the new event 265 | orig = event.originalEvent; 266 | if ( orig ) { 267 | for ( prop in orig ) { 268 | if ( !( prop in event ) ) { 269 | event[ prop ] = orig[ prop ]; 270 | } 271 | } 272 | } 273 | 274 | this.element.trigger( event, data ); 275 | 276 | return !( $.isFunction(callback) && 277 | callback.call( this.element[0], event, data ) === false || 278 | event.isDefaultPrevented() ); 279 | } 280 | }; 281 | 282 | })); 283 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blueimp-file-upload", 3 | "version": "6.9.2", 4 | "title": "jQuery File Upload", 5 | "description": "File Upload widget with multiple file selection, drag&drop support, progress bars and preview images for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.", 6 | "keywords": [ 7 | "jquery", 8 | "file", 9 | "upload", 10 | "widget", 11 | "multiple", 12 | "selection", 13 | "drag", 14 | "drop", 15 | "progress", 16 | "preview", 17 | "cross-domain", 18 | "cross-site", 19 | "chunk", 20 | "resume", 21 | "gae", 22 | "go", 23 | "python", 24 | "php", 25 | "bootstrap" 26 | ], 27 | "homepage": "https://github.com/blueimp/jQuery-File-Upload", 28 | "author": { 29 | "name": "Sebastian Tschan", 30 | "url": "https://blueimp.net" 31 | }, 32 | "maintainers": [ 33 | { 34 | "name": "Sebastian Tschan", 35 | "url": "https://blueimp.net" 36 | } 37 | ], 38 | "repository": { 39 | "type": "git", 40 | "url": "git://github.com/blueimp/jQuery-File-Upload.git" 41 | }, 42 | "bugs": "https://github.com/blueimp/jQuery-File-Upload/issues", 43 | "licenses": [ 44 | { 45 | "type": "MIT", 46 | "url": "http://www.opensource.org/licenses/MIT" 47 | } 48 | ], 49 | "dependencies": { 50 | "jquery": ">=1.6", 51 | "jquery.ui.widget": ">=1.8", 52 | "blueimp-tmpl": ">=2.1.0", 53 | "blueimp-load-image": ">=1.1.6", 54 | "blueimp-canvas-to-blob": ">=2.0.0" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /server/gae-go/app.yaml: -------------------------------------------------------------------------------- 1 | application: jquery-file-upload 2 | version: 2 3 | runtime: go 4 | api_version: go1 5 | 6 | handlers: 7 | - url: /(favicon\.ico|robots\.txt) 8 | static_files: static/\1 9 | upload: static/(.*) 10 | expiration: '1d' 11 | - url: /.* 12 | script: _go_app 13 | -------------------------------------------------------------------------------- /server/gae-go/app/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery File Upload Plugin GAE Go Example 2.0 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2011, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * http://www.opensource.org/licenses/MIT 10 | */ 11 | 12 | package app 13 | 14 | import ( 15 | "appengine" 16 | "appengine/blobstore" 17 | "appengine/memcache" 18 | "appengine/taskqueue" 19 | "bytes" 20 | "encoding/base64" 21 | "encoding/json" 22 | "fmt" 23 | "image" 24 | "image/png" 25 | "io" 26 | "log" 27 | "mime/multipart" 28 | "net/http" 29 | "net/url" 30 | "regexp" 31 | "resize" 32 | "strings" 33 | "time" 34 | ) 35 | 36 | import _ "image/gif" 37 | import _ "image/jpeg" 38 | 39 | const ( 40 | WEBSITE = "http://blueimp.github.com/jQuery-File-Upload/" 41 | MIN_FILE_SIZE = 1 // bytes 42 | MAX_FILE_SIZE = 5000000 // bytes 43 | IMAGE_TYPES = "image/(gif|p?jpeg|(x-)?png)" 44 | ACCEPT_FILE_TYPES = IMAGE_TYPES 45 | EXPIRATION_TIME = 300 // seconds 46 | THUMBNAIL_MAX_WIDTH = 80 47 | THUMBNAIL_MAX_HEIGHT = THUMBNAIL_MAX_WIDTH 48 | ) 49 | 50 | var ( 51 | imageTypes = regexp.MustCompile(IMAGE_TYPES) 52 | acceptFileTypes = regexp.MustCompile(ACCEPT_FILE_TYPES) 53 | ) 54 | 55 | type FileInfo struct { 56 | Key appengine.BlobKey `json:"-"` 57 | Url string `json:"url,omitempty"` 58 | ThumbnailUrl string `json:"thumbnail_url,omitempty"` 59 | Name string `json:"name"` 60 | Type string `json:"type"` 61 | Size int64 `json:"size"` 62 | Error string `json:"error,omitempty"` 63 | DeleteUrl string `json:"delete_url,omitempty"` 64 | DeleteType string `json:"delete_type,omitempty"` 65 | } 66 | 67 | func (fi *FileInfo) ValidateType() (valid bool) { 68 | if acceptFileTypes.MatchString(fi.Type) { 69 | return true 70 | } 71 | fi.Error = "acceptFileTypes" 72 | return false 73 | } 74 | 75 | func (fi *FileInfo) ValidateSize() (valid bool) { 76 | if fi.Size < MIN_FILE_SIZE { 77 | fi.Error = "minFileSize" 78 | } else if fi.Size > MAX_FILE_SIZE { 79 | fi.Error = "maxFileSize" 80 | } else { 81 | return true 82 | } 83 | return false 84 | } 85 | 86 | func (fi *FileInfo) CreateUrls(r *http.Request, c appengine.Context) { 87 | u := &url.URL{ 88 | Scheme: r.URL.Scheme, 89 | Host: appengine.DefaultVersionHostname(c), 90 | Path: "/", 91 | } 92 | uString := u.String() 93 | fi.Url = uString + escape(string(fi.Key)) + "/" + 94 | escape(string(fi.Name)) 95 | fi.DeleteUrl = fi.Url 96 | fi.DeleteType = "DELETE" 97 | if fi.ThumbnailUrl != "" && -1 == strings.Index( 98 | r.Header.Get("Accept"), 99 | "application/json", 100 | ) { 101 | fi.ThumbnailUrl = uString + "thumbnails/" + 102 | escape(string(fi.Key)) 103 | } 104 | } 105 | 106 | func (fi *FileInfo) CreateThumbnail(r io.Reader, c appengine.Context) (data []byte, err error) { 107 | defer func() { 108 | if rec := recover(); rec != nil { 109 | log.Println(rec) 110 | // 1x1 pixel transparent GIf, bas64 encoded: 111 | s := "R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" 112 | data, _ = base64.StdEncoding.DecodeString(s) 113 | fi.ThumbnailUrl = "data:image/gif;base64," + s 114 | } 115 | memcache.Add(c, &memcache.Item{ 116 | Key: string(fi.Key), 117 | Value: data, 118 | Expiration: EXPIRATION_TIME, 119 | }) 120 | }() 121 | img, _, err := image.Decode(r) 122 | check(err) 123 | if bounds := img.Bounds(); bounds.Dx() > THUMBNAIL_MAX_WIDTH || 124 | bounds.Dy() > THUMBNAIL_MAX_HEIGHT { 125 | w, h := THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT 126 | if bounds.Dx() > bounds.Dy() { 127 | h = bounds.Dy() * h / bounds.Dx() 128 | } else { 129 | w = bounds.Dx() * w / bounds.Dy() 130 | } 131 | img = resize.Resize(img, img.Bounds(), w, h) 132 | } 133 | var b bytes.Buffer 134 | err = png.Encode(&b, img) 135 | check(err) 136 | data = b.Bytes() 137 | fi.ThumbnailUrl = "data:image/png;base64," + 138 | base64.StdEncoding.EncodeToString(data) 139 | return 140 | } 141 | 142 | func check(err error) { 143 | if err != nil { 144 | panic(err) 145 | } 146 | } 147 | 148 | func escape(s string) string { 149 | return strings.Replace(url.QueryEscape(s), "+", "%20", -1) 150 | } 151 | 152 | func delayedDelete(c appengine.Context, fi *FileInfo) { 153 | if key := string(fi.Key); key != "" { 154 | task := &taskqueue.Task{ 155 | Path: "/" + escape(key) + "/-", 156 | Method: "DELETE", 157 | Delay: time.Duration(EXPIRATION_TIME) * time.Second, 158 | } 159 | taskqueue.Add(c, task, "") 160 | } 161 | } 162 | 163 | func handleUpload(r *http.Request, p *multipart.Part) (fi *FileInfo) { 164 | fi = &FileInfo{ 165 | Name: p.FileName(), 166 | Type: p.Header.Get("Content-Type"), 167 | } 168 | if !fi.ValidateType() { 169 | return 170 | } 171 | defer func() { 172 | if rec := recover(); rec != nil { 173 | log.Println(rec) 174 | fi.Error = rec.(error).Error() 175 | } 176 | }() 177 | var b bytes.Buffer 178 | lr := &io.LimitedReader{R: p, N: MAX_FILE_SIZE + 1} 179 | context := appengine.NewContext(r) 180 | w, err := blobstore.Create(context, fi.Type) 181 | defer func() { 182 | w.Close() 183 | fi.Size = MAX_FILE_SIZE + 1 - lr.N 184 | fi.Key, err = w.Key() 185 | check(err) 186 | if !fi.ValidateSize() { 187 | err := blobstore.Delete(context, fi.Key) 188 | check(err) 189 | return 190 | } 191 | delayedDelete(context, fi) 192 | if b.Len() > 0 { 193 | fi.CreateThumbnail(&b, context) 194 | } 195 | fi.CreateUrls(r, context) 196 | }() 197 | check(err) 198 | var wr io.Writer = w 199 | if imageTypes.MatchString(fi.Type) { 200 | wr = io.MultiWriter(&b, w) 201 | } 202 | _, err = io.Copy(wr, lr) 203 | return 204 | } 205 | 206 | func getFormValue(p *multipart.Part) string { 207 | var b bytes.Buffer 208 | io.CopyN(&b, p, int64(1<<20)) // Copy max: 1 MiB 209 | return b.String() 210 | } 211 | 212 | func handleUploads(r *http.Request) (fileInfos []*FileInfo) { 213 | fileInfos = make([]*FileInfo, 0) 214 | mr, err := r.MultipartReader() 215 | check(err) 216 | r.Form, err = url.ParseQuery(r.URL.RawQuery) 217 | check(err) 218 | part, err := mr.NextPart() 219 | for err == nil { 220 | if name := part.FormName(); name != "" { 221 | if part.FileName() != "" { 222 | fileInfos = append(fileInfos, handleUpload(r, part)) 223 | } else { 224 | r.Form[name] = append(r.Form[name], getFormValue(part)) 225 | } 226 | } 227 | part, err = mr.NextPart() 228 | } 229 | return 230 | } 231 | 232 | func get(w http.ResponseWriter, r *http.Request) { 233 | if r.URL.Path == "/" { 234 | http.Redirect(w, r, WEBSITE, http.StatusFound) 235 | return 236 | } 237 | parts := strings.Split(r.URL.Path, "/") 238 | if len(parts) == 3 { 239 | if key := parts[1]; key != "" { 240 | blobKey := appengine.BlobKey(key) 241 | bi, err := blobstore.Stat(appengine.NewContext(r), blobKey) 242 | if err == nil { 243 | w.Header().Add( 244 | "Cache-Control", 245 | fmt.Sprintf("public,max-age=%d", EXPIRATION_TIME), 246 | ) 247 | if imageTypes.MatchString(bi.ContentType) { 248 | w.Header().Add("X-Content-Type-Options", "nosniff") 249 | } else { 250 | w.Header().Add("Content-Type", "application/octet-stream") 251 | w.Header().Add( 252 | "Content-Disposition:", 253 | fmt.Sprintf("attachment; filename=%s;", parts[2]), 254 | ) 255 | } 256 | blobstore.Send(w, appengine.BlobKey(key)) 257 | return 258 | } 259 | } 260 | } 261 | http.Error(w, "404 Not Found", http.StatusNotFound) 262 | } 263 | 264 | func post(w http.ResponseWriter, r *http.Request) { 265 | b, err := json.Marshal(handleUploads(r)) 266 | check(err) 267 | if redirect := r.FormValue("redirect"); redirect != "" { 268 | http.Redirect(w, r, fmt.Sprintf( 269 | redirect, 270 | escape(string(b)), 271 | ), http.StatusFound) 272 | return 273 | } 274 | jsonType := "application/json" 275 | if strings.Index(r.Header.Get("Accept"), jsonType) != -1 { 276 | w.Header().Set("Content-Type", jsonType) 277 | } 278 | fmt.Fprintln(w, string(b)) 279 | } 280 | 281 | func delete(w http.ResponseWriter, r *http.Request) { 282 | parts := strings.Split(r.URL.Path, "/") 283 | if len(parts) != 3 { 284 | return 285 | } 286 | if key := parts[1]; key != "" { 287 | c := appengine.NewContext(r) 288 | blobstore.Delete(c, appengine.BlobKey(key)) 289 | memcache.Delete(c, key) 290 | } 291 | } 292 | 293 | func serveThumbnail(w http.ResponseWriter, r *http.Request) { 294 | parts := strings.Split(r.URL.Path, "/") 295 | if len(parts) == 3 { 296 | if key := parts[2]; key != "" { 297 | var data []byte 298 | c := appengine.NewContext(r) 299 | item, err := memcache.Get(c, key) 300 | if err == nil { 301 | data = item.Value 302 | } else { 303 | blobKey := appengine.BlobKey(key) 304 | if _, err = blobstore.Stat(c, blobKey); err == nil { 305 | fi := FileInfo{Key: blobKey} 306 | data, _ = fi.CreateThumbnail( 307 | blobstore.NewReader(c, blobKey), 308 | c, 309 | ) 310 | } 311 | } 312 | if err == nil && len(data) > 3 { 313 | w.Header().Add( 314 | "Cache-Control", 315 | fmt.Sprintf("public,max-age=%d", EXPIRATION_TIME), 316 | ) 317 | contentType := "image/png" 318 | if string(data[:3]) == "GIF" { 319 | contentType = "image/gif" 320 | } else if string(data[1:4]) != "PNG" { 321 | contentType = "image/jpeg" 322 | } 323 | w.Header().Set("Content-Type", contentType) 324 | fmt.Fprintln(w, string(data)) 325 | return 326 | } 327 | } 328 | } 329 | http.Error(w, "404 Not Found", http.StatusNotFound) 330 | } 331 | 332 | func handle(w http.ResponseWriter, r *http.Request) { 333 | params, err := url.ParseQuery(r.URL.RawQuery) 334 | check(err) 335 | w.Header().Add("Access-Control-Allow-Origin", "*") 336 | w.Header().Add( 337 | "Access-Control-Allow-Methods", 338 | "OPTIONS, HEAD, GET, POST, PUT, DELETE", 339 | ) 340 | switch r.Method { 341 | case "OPTIONS": 342 | case "HEAD": 343 | case "GET": 344 | get(w, r) 345 | case "POST": 346 | if len(params["_method"]) > 0 && params["_method"][0] == "DELETE" { 347 | delete(w, r) 348 | } else { 349 | post(w, r) 350 | } 351 | case "DELETE": 352 | delete(w, r) 353 | default: 354 | http.Error(w, "501 Not Implemented", http.StatusNotImplemented) 355 | } 356 | } 357 | 358 | func init() { 359 | http.HandleFunc("/", handle) 360 | http.HandleFunc("/thumbnails/", serveThumbnail) 361 | } 362 | -------------------------------------------------------------------------------- /server/gae-go/resize/resize.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package resize 6 | 7 | import ( 8 | "image" 9 | "image/color" 10 | ) 11 | 12 | // Resize returns a scaled copy of the image slice r of m. 13 | // The returned image has width w and height h. 14 | func Resize(m image.Image, r image.Rectangle, w, h int) image.Image { 15 | if w < 0 || h < 0 { 16 | return nil 17 | } 18 | if w == 0 || h == 0 || r.Dx() <= 0 || r.Dy() <= 0 { 19 | return image.NewRGBA64(image.Rect(0, 0, w, h)) 20 | } 21 | switch m := m.(type) { 22 | case *image.RGBA: 23 | return resizeRGBA(m, r, w, h) 24 | case *image.YCbCr: 25 | if m, ok := resizeYCbCr(m, r, w, h); ok { 26 | return m 27 | } 28 | } 29 | ww, hh := uint64(w), uint64(h) 30 | dx, dy := uint64(r.Dx()), uint64(r.Dy()) 31 | // The scaling algorithm is to nearest-neighbor magnify the dx * dy source 32 | // to a (ww*dx) * (hh*dy) intermediate image and then minify the intermediate 33 | // image back down to a ww * hh destination with a simple box filter. 34 | // The intermediate image is implied, we do not physically allocate a slice 35 | // of length ww*dx*hh*dy. 36 | // For example, consider a 4*3 source image. Label its pixels from a-l: 37 | // abcd 38 | // efgh 39 | // ijkl 40 | // To resize this to a 3*2 destination image, the intermediate is 12*6. 41 | // Whitespace has been added to delineate the destination pixels: 42 | // aaab bbcc cddd 43 | // aaab bbcc cddd 44 | // eeef ffgg ghhh 45 | // 46 | // eeef ffgg ghhh 47 | // iiij jjkk klll 48 | // iiij jjkk klll 49 | // Thus, the 'b' source pixel contributes one third of its value to the 50 | // (0, 0) destination pixel and two thirds to (1, 0). 51 | // The implementation is a two-step process. First, the source pixels are 52 | // iterated over and each source pixel's contribution to 1 or more 53 | // destination pixels are summed. Second, the sums are divided by a scaling 54 | // factor to yield the destination pixels. 55 | // TODO: By interleaving the two steps, instead of doing all of 56 | // step 1 first and all of step 2 second, we could allocate a smaller sum 57 | // slice of length 4*w*2 instead of 4*w*h, although the resultant code 58 | // would become more complicated. 59 | n, sum := dx*dy, make([]uint64, 4*w*h) 60 | for y := r.Min.Y; y < r.Max.Y; y++ { 61 | for x := r.Min.X; x < r.Max.X; x++ { 62 | // Get the source pixel. 63 | r32, g32, b32, a32 := m.At(x, y).RGBA() 64 | r64 := uint64(r32) 65 | g64 := uint64(g32) 66 | b64 := uint64(b32) 67 | a64 := uint64(a32) 68 | // Spread the source pixel over 1 or more destination rows. 69 | py := uint64(y) * hh 70 | for remy := hh; remy > 0; { 71 | qy := dy - (py % dy) 72 | if qy > remy { 73 | qy = remy 74 | } 75 | // Spread the source pixel over 1 or more destination columns. 76 | px := uint64(x) * ww 77 | index := 4 * ((py/dy)*ww + (px / dx)) 78 | for remx := ww; remx > 0; { 79 | qx := dx - (px % dx) 80 | if qx > remx { 81 | qx = remx 82 | } 83 | sum[index+0] += r64 * qx * qy 84 | sum[index+1] += g64 * qx * qy 85 | sum[index+2] += b64 * qx * qy 86 | sum[index+3] += a64 * qx * qy 87 | index += 4 88 | px += qx 89 | remx -= qx 90 | } 91 | py += qy 92 | remy -= qy 93 | } 94 | } 95 | } 96 | return average(sum, w, h, n*0x0101) 97 | } 98 | 99 | // average convert the sums to averages and returns the result. 100 | func average(sum []uint64, w, h int, n uint64) image.Image { 101 | ret := image.NewRGBA(image.Rect(0, 0, w, h)) 102 | for y := 0; y < h; y++ { 103 | for x := 0; x < w; x++ { 104 | index := 4 * (y*w + x) 105 | ret.SetRGBA(x, y, color.RGBA{ 106 | uint8(sum[index+0] / n), 107 | uint8(sum[index+1] / n), 108 | uint8(sum[index+2] / n), 109 | uint8(sum[index+3] / n), 110 | }) 111 | } 112 | } 113 | return ret 114 | } 115 | 116 | // resizeYCbCr returns a scaled copy of the YCbCr image slice r of m. 117 | // The returned image has width w and height h. 118 | func resizeYCbCr(m *image.YCbCr, r image.Rectangle, w, h int) (image.Image, bool) { 119 | var verticalRes int 120 | switch m.SubsampleRatio { 121 | case image.YCbCrSubsampleRatio420: 122 | verticalRes = 2 123 | case image.YCbCrSubsampleRatio422: 124 | verticalRes = 1 125 | default: 126 | return nil, false 127 | } 128 | ww, hh := uint64(w), uint64(h) 129 | dx, dy := uint64(r.Dx()), uint64(r.Dy()) 130 | // See comment in Resize. 131 | n, sum := dx*dy, make([]uint64, 4*w*h) 132 | for y := r.Min.Y; y < r.Max.Y; y++ { 133 | Y := m.Y[y*m.YStride:] 134 | Cb := m.Cb[y/verticalRes*m.CStride:] 135 | Cr := m.Cr[y/verticalRes*m.CStride:] 136 | for x := r.Min.X; x < r.Max.X; x++ { 137 | // Get the source pixel. 138 | r8, g8, b8 := color.YCbCrToRGB(Y[x], Cb[x/2], Cr[x/2]) 139 | r64 := uint64(r8) 140 | g64 := uint64(g8) 141 | b64 := uint64(b8) 142 | // Spread the source pixel over 1 or more destination rows. 143 | py := uint64(y) * hh 144 | for remy := hh; remy > 0; { 145 | qy := dy - (py % dy) 146 | if qy > remy { 147 | qy = remy 148 | } 149 | // Spread the source pixel over 1 or more destination columns. 150 | px := uint64(x) * ww 151 | index := 4 * ((py/dy)*ww + (px / dx)) 152 | for remx := ww; remx > 0; { 153 | qx := dx - (px % dx) 154 | if qx > remx { 155 | qx = remx 156 | } 157 | qxy := qx * qy 158 | sum[index+0] += r64 * qxy 159 | sum[index+1] += g64 * qxy 160 | sum[index+2] += b64 * qxy 161 | sum[index+3] += 0xFFFF * qxy 162 | index += 4 163 | px += qx 164 | remx -= qx 165 | } 166 | py += qy 167 | remy -= qy 168 | } 169 | } 170 | } 171 | return average(sum, w, h, n), true 172 | } 173 | 174 | // resizeRGBA returns a scaled copy of the RGBA image slice r of m. 175 | // The returned image has width w and height h. 176 | func resizeRGBA(m *image.RGBA, r image.Rectangle, w, h int) image.Image { 177 | ww, hh := uint64(w), uint64(h) 178 | dx, dy := uint64(r.Dx()), uint64(r.Dy()) 179 | // See comment in Resize. 180 | n, sum := dx*dy, make([]uint64, 4*w*h) 181 | for y := r.Min.Y; y < r.Max.Y; y++ { 182 | pixOffset := m.PixOffset(r.Min.X, y) 183 | for x := r.Min.X; x < r.Max.X; x++ { 184 | // Get the source pixel. 185 | r64 := uint64(m.Pix[pixOffset+0]) 186 | g64 := uint64(m.Pix[pixOffset+1]) 187 | b64 := uint64(m.Pix[pixOffset+2]) 188 | a64 := uint64(m.Pix[pixOffset+3]) 189 | pixOffset += 4 190 | // Spread the source pixel over 1 or more destination rows. 191 | py := uint64(y) * hh 192 | for remy := hh; remy > 0; { 193 | qy := dy - (py % dy) 194 | if qy > remy { 195 | qy = remy 196 | } 197 | // Spread the source pixel over 1 or more destination columns. 198 | px := uint64(x) * ww 199 | index := 4 * ((py/dy)*ww + (px / dx)) 200 | for remx := ww; remx > 0; { 201 | qx := dx - (px % dx) 202 | if qx > remx { 203 | qx = remx 204 | } 205 | qxy := qx * qy 206 | sum[index+0] += r64 * qxy 207 | sum[index+1] += g64 * qxy 208 | sum[index+2] += b64 * qxy 209 | sum[index+3] += a64 * qxy 210 | index += 4 211 | px += qx 212 | remx -= qx 213 | } 214 | py += qy 215 | remy -= qy 216 | } 217 | } 218 | } 219 | return average(sum, w, h, n) 220 | } 221 | 222 | // Resample returns a resampled copy of the image slice r of m. 223 | // The returned image has width w and height h. 224 | func Resample(m image.Image, r image.Rectangle, w, h int) image.Image { 225 | if w < 0 || h < 0 { 226 | return nil 227 | } 228 | if w == 0 || h == 0 || r.Dx() <= 0 || r.Dy() <= 0 { 229 | return image.NewRGBA64(image.Rect(0, 0, w, h)) 230 | } 231 | curw, curh := r.Dx(), r.Dy() 232 | img := image.NewRGBA(image.Rect(0, 0, w, h)) 233 | for y := 0; y < h; y++ { 234 | for x := 0; x < w; x++ { 235 | // Get a source pixel. 236 | subx := x * curw / w 237 | suby := y * curh / h 238 | r32, g32, b32, a32 := m.At(subx, suby).RGBA() 239 | r := uint8(r32 >> 8) 240 | g := uint8(g32 >> 8) 241 | b := uint8(b32 >> 8) 242 | a := uint8(a32 >> 8) 243 | img.SetRGBA(x, y, color.RGBA{r, g, b, a}) 244 | } 245 | } 246 | return img 247 | } 248 | -------------------------------------------------------------------------------- /server/gae-go/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/gae-go/static/favicon.ico -------------------------------------------------------------------------------- /server/gae-go/static/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /server/gae-python/app.yaml: -------------------------------------------------------------------------------- 1 | application: jquery-file-upload 2 | version: 1 3 | runtime: python27 4 | api_version: 1 5 | threadsafe: true 6 | 7 | builtins: 8 | - deferred: on 9 | 10 | handlers: 11 | - url: /(favicon\.ico|robots\.txt) 12 | static_files: static/\1 13 | upload: static/(.*) 14 | expiration: '1d' 15 | - url: /.* 16 | script: main.app 17 | -------------------------------------------------------------------------------- /server/gae-python/main.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # jQuery File Upload Plugin GAE Python Example 1.1.4 4 | # https://github.com/blueimp/jQuery-File-Upload 5 | # 6 | # Copyright 2011, Sebastian Tschan 7 | # https://blueimp.net 8 | # 9 | # Licensed under the MIT license: 10 | # http://www.opensource.org/licenses/MIT 11 | # 12 | 13 | from __future__ import with_statement 14 | from google.appengine.api import files, images 15 | from google.appengine.ext import blobstore, deferred 16 | from google.appengine.ext.webapp import blobstore_handlers 17 | import json, re, urllib, webapp2 18 | 19 | WEBSITE = 'http://blueimp.github.com/jQuery-File-Upload/' 20 | MIN_FILE_SIZE = 1 # bytes 21 | MAX_FILE_SIZE = 5000000 # bytes 22 | IMAGE_TYPES = re.compile('image/(gif|p?jpeg|(x-)?png)') 23 | ACCEPT_FILE_TYPES = IMAGE_TYPES 24 | THUMBNAIL_MODIFICATOR = '=s80' # max width / height 25 | EXPIRATION_TIME = 300 # seconds 26 | 27 | def cleanup(blob_keys): 28 | blobstore.delete(blob_keys) 29 | 30 | class UploadHandler(webapp2.RequestHandler): 31 | 32 | def initialize(self, request, response): 33 | super(UploadHandler, self).initialize(request, response) 34 | self.response.headers['Access-Control-Allow-Origin'] = '*' 35 | self.response.headers[ 36 | 'Access-Control-Allow-Methods' 37 | ] = 'OPTIONS, HEAD, GET, POST, PUT, DELETE' 38 | 39 | def validate(self, file): 40 | if file['size'] < MIN_FILE_SIZE: 41 | file['error'] = 'minFileSize' 42 | elif file['size'] > MAX_FILE_SIZE: 43 | file['error'] = 'maxFileSize' 44 | elif not ACCEPT_FILE_TYPES.match(file['type']): 45 | file['error'] = 'acceptFileTypes' 46 | else: 47 | return True 48 | return False 49 | 50 | def get_file_size(self, file): 51 | file.seek(0, 2) # Seek to the end of the file 52 | size = file.tell() # Get the position of EOF 53 | file.seek(0) # Reset the file position to the beginning 54 | return size 55 | 56 | def write_blob(self, data, info): 57 | blob = files.blobstore.create( 58 | mime_type=info['type'], 59 | _blobinfo_uploaded_filename=info['name'] 60 | ) 61 | with files.open(blob, 'a') as f: 62 | f.write(data) 63 | files.finalize(blob) 64 | return files.blobstore.get_blob_key(blob) 65 | 66 | def handle_upload(self): 67 | results = [] 68 | blob_keys = [] 69 | for name, fieldStorage in self.request.POST.items(): 70 | if type(fieldStorage) is unicode: 71 | continue 72 | result = {} 73 | result['name'] = re.sub(r'^.*\\', '', 74 | fieldStorage.filename) 75 | result['type'] = fieldStorage.type 76 | result['size'] = self.get_file_size(fieldStorage.file) 77 | if self.validate(result): 78 | blob_key = str( 79 | self.write_blob(fieldStorage.value, result) 80 | ) 81 | blob_keys.append(blob_key) 82 | result['delete_type'] = 'DELETE' 83 | result['delete_url'] = self.request.host_url +\ 84 | '/?key=' + urllib.quote(blob_key, '') 85 | if (IMAGE_TYPES.match(result['type'])): 86 | try: 87 | result['url'] = images.get_serving_url( 88 | blob_key, 89 | secure_url=self.request.host_url\ 90 | .startswith('https') 91 | ) 92 | result['thumbnail_url'] = result['url'] +\ 93 | THUMBNAIL_MODIFICATOR 94 | except: # Could not get an image serving url 95 | pass 96 | if not 'url' in result: 97 | result['url'] = self.request.host_url +\ 98 | '/' + blob_key + '/' + urllib.quote( 99 | result['name'].encode('utf-8'), '') 100 | results.append(result) 101 | deferred.defer( 102 | cleanup, 103 | blob_keys, 104 | _countdown=EXPIRATION_TIME 105 | ) 106 | return results 107 | 108 | def options(self): 109 | pass 110 | 111 | def head(self): 112 | pass 113 | 114 | def get(self): 115 | self.redirect(WEBSITE) 116 | 117 | def post(self): 118 | if (self.request.get('_method') == 'DELETE'): 119 | return self.delete() 120 | s = json.dumps(self.handle_upload(), separators=(',',':')) 121 | redirect = self.request.get('redirect') 122 | if redirect: 123 | return self.redirect(str( 124 | redirect.replace('%s', urllib.quote(s, ''), 1) 125 | )) 126 | if 'application/json' in self.request.headers.get('Accept'): 127 | self.response.headers['Content-Type'] = 'application/json' 128 | self.response.write(s) 129 | 130 | def delete(self): 131 | blobstore.delete(self.request.get('key') or '') 132 | 133 | class DownloadHandler(blobstore_handlers.BlobstoreDownloadHandler): 134 | def get(self, key, filename): 135 | if not blobstore.get(key): 136 | self.error(404) 137 | else: 138 | # Cache for the expiration time: 139 | self.response.headers['Cache-Control'] =\ 140 | 'public,max-age=%d' % EXPIRATION_TIME 141 | self.send_blob(key, save_as=filename) 142 | 143 | app = webapp2.WSGIApplication( 144 | [ 145 | ('/', UploadHandler), 146 | ('/([^/]+)/([^/]+)', DownloadHandler) 147 | ], 148 | debug=True 149 | ) -------------------------------------------------------------------------------- /server/gae-python/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/gae-python/static/favicon.ico -------------------------------------------------------------------------------- /server/gae-python/static/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /server/node/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | -------------------------------------------------------------------------------- /server/node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blueimp-file-upload-node", 3 | "version": "1.0.2", 4 | "title": "jQuery File Upload Node.js example", 5 | "description": "Node.js implementation example of a file upload handler for jQuery File Upload.", 6 | "keywords": [ 7 | "file", 8 | "upload", 9 | "cross-domain", 10 | "cross-site", 11 | "node" 12 | ], 13 | "homepage": "https://github.com/blueimp/jQuery-File-Upload", 14 | "author": { 15 | "name": "Sebastian Tschan", 16 | "url": "https://blueimp.net" 17 | }, 18 | "maintainers": [ 19 | { 20 | "name": "Sebastian Tschan", 21 | "url": "https://blueimp.net" 22 | } 23 | ], 24 | "repository": { 25 | "type": "git", 26 | "url": "git://github.com/blueimp/jQuery-File-Upload.git" 27 | }, 28 | "bugs": "https://github.com/blueimp/jQuery-File-Upload/issues", 29 | "licenses": [ 30 | { 31 | "type": "MIT", 32 | "url": "http://www.opensource.org/licenses/MIT" 33 | } 34 | ], 35 | "dependencies": { 36 | "formidable": ">=1.0.8", 37 | "node-static": ">=0.5.9", 38 | "imagemagick": ">=0.1.2" 39 | }, 40 | "main": "server.js" 41 | } 42 | -------------------------------------------------------------------------------- /server/node/public/files/thumbnail/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/node/public/files/thumbnail/.gitignore -------------------------------------------------------------------------------- /server/node/server.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* 3 | * jQuery File Upload Plugin Node.js Example 1.0.2 4 | * https://github.com/blueimp/jQuery-File-Upload 5 | * 6 | * Copyright 2012, Sebastian Tschan 7 | * https://blueimp.net 8 | * 9 | * Licensed under the MIT license: 10 | * http://www.opensource.org/licenses/MIT 11 | */ 12 | 13 | /*jslint nomen: true, regexp: true, unparam: true */ 14 | /*global require, __dirname, unescape */ 15 | 16 | (function (port) { 17 | 'use strict'; 18 | var path = require('path'), 19 | fs = require('fs'), 20 | // Since Node 0.8, .existsSync() moved from path to fs: 21 | _existsSync = fs.existsSync || path.existsSync, 22 | formidable = require('formidable'), 23 | nodeStatic = require('node-static'), 24 | imageMagick = require('imagemagick'), 25 | options = { 26 | tmpDir: __dirname + '/tmp', 27 | publicDir: __dirname + '/public', 28 | uploadDir: __dirname + '/public/files', 29 | uploadUrl: '/files/', 30 | maxPostSize: 500000000, // 500 MB 31 | minFileSize: 1, 32 | maxFileSize: 100000000, // 100 MB 33 | acceptFileTypes: /.+/i, 34 | // Files not matched by this regular expression force a download dialog, 35 | // to prevent executing any scripts in the context of the service domain: 36 | safeFileTypes: /\.(gif|jpe?g|png)$/i, 37 | imageTypes: /\.(gif|jpe?g|png)$/i, 38 | imageVersions: { 39 | 'thumbnail': { 40 | width: 80, 41 | height: 80 42 | } 43 | }, 44 | accessControl: { 45 | allowOrigin: '*', 46 | allowMethods: 'OPTIONS, HEAD, GET, POST, PUT, DELETE' 47 | }, 48 | /* Uncomment and edit this section to provide the service via HTTPS: 49 | ssl: { 50 | key: fs.readFileSync('/Applications/XAMPP/etc/ssl.key/server.key'), 51 | cert: fs.readFileSync('/Applications/XAMPP/etc/ssl.crt/server.crt') 52 | }, 53 | */ 54 | nodeStatic: { 55 | cache: 3600 // seconds to cache served files 56 | } 57 | }, 58 | utf8encode = function (str) { 59 | return unescape(encodeURIComponent(str)); 60 | }, 61 | fileServer = new nodeStatic.Server(options.publicDir, options.nodeStatic), 62 | nameCountRegexp = /(?:(?: \(([\d]+)\))?(\.[^.]+))?$/, 63 | nameCountFunc = function (s, index, ext) { 64 | return ' (' + ((parseInt(index, 10) || 0) + 1) + ')' + (ext || ''); 65 | }, 66 | FileInfo = function (file) { 67 | this.name = file.name; 68 | this.size = file.size; 69 | this.type = file.type; 70 | this.delete_type = 'DELETE'; 71 | }, 72 | UploadHandler = function (req, res, callback) { 73 | this.req = req; 74 | this.res = res; 75 | this.callback = callback; 76 | }, 77 | serve = function (req, res) { 78 | res.setHeader( 79 | 'Access-Control-Allow-Origin', 80 | options.accessControl.allowOrigin 81 | ); 82 | res.setHeader( 83 | 'Access-Control-Allow-Methods', 84 | options.accessControl.allowMethods 85 | ); 86 | var handleResult = function (result, redirect) { 87 | if (redirect) { 88 | res.writeHead(302, { 89 | 'Location': redirect.replace( 90 | /%s/, 91 | encodeURIComponent(JSON.stringify(result)) 92 | ) 93 | }); 94 | res.end(); 95 | } else { 96 | res.writeHead(200, { 97 | 'Content-Type': req.headers.accept 98 | .indexOf('application/json') !== -1 ? 99 | 'application/json' : 'text/plain' 100 | }); 101 | res.end(JSON.stringify(result)); 102 | } 103 | }, 104 | setNoCacheHeaders = function () { 105 | res.setHeader('Pragma', 'no-cache'); 106 | res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate'); 107 | res.setHeader('Content-Disposition', 'inline; filename="files.json"'); 108 | }, 109 | handler = new UploadHandler(req, res, handleResult); 110 | switch (req.method) { 111 | case 'OPTIONS': 112 | res.end(); 113 | break; 114 | case 'HEAD': 115 | case 'GET': 116 | if (req.url === '/') { 117 | setNoCacheHeaders(); 118 | if (req.method === 'GET') { 119 | handler.get(); 120 | } else { 121 | res.end(); 122 | } 123 | } else { 124 | fileServer.serve(req, res); 125 | } 126 | break; 127 | case 'POST': 128 | setNoCacheHeaders(); 129 | handler.post(); 130 | break; 131 | case 'DELETE': 132 | handler.destroy(); 133 | break; 134 | default: 135 | res.statusCode = 405; 136 | res.end(); 137 | } 138 | }; 139 | fileServer.respond = function (pathname, status, _headers, files, stat, req, res, finish) { 140 | if (!options.safeFileTypes.test(files[0])) { 141 | // Force a download dialog for unsafe file extensions: 142 | res.setHeader( 143 | 'Content-Disposition', 144 | 'attachment; filename="' + utf8encode(path.basename(files[0])) + '"' 145 | ); 146 | } else { 147 | // Prevent Internet Explorer from MIME-sniffing the content-type: 148 | res.setHeader('X-Content-Type-Options', 'nosniff'); 149 | } 150 | nodeStatic.Server.prototype.respond 151 | .call(this, pathname, status, _headers, files, stat, req, res, finish); 152 | }; 153 | FileInfo.prototype.validate = function () { 154 | if (options.minFileSize && options.minFileSize > this.size) { 155 | this.error = 'minFileSize'; 156 | } else if (options.maxFileSize && options.maxFileSize < this.size) { 157 | this.error = 'maxFileSize'; 158 | } else if (!options.acceptFileTypes.test(this.name)) { 159 | this.error = 'acceptFileTypes'; 160 | } 161 | return !this.error; 162 | }; 163 | FileInfo.prototype.safeName = function () { 164 | // Prevent directory traversal and creating hidden system files: 165 | this.name = path.basename(this.name).replace(/^\.+/, ''); 166 | // Prevent overwriting existing files: 167 | while (_existsSync(options.uploadDir + '/' + this.name)) { 168 | this.name = this.name.replace(nameCountRegexp, nameCountFunc); 169 | } 170 | }; 171 | FileInfo.prototype.initUrls = function (req) { 172 | if (!this.error) { 173 | var that = this, 174 | baseUrl = (options.ssl ? 'https:' : 'http:') + 175 | '//' + req.headers.host + options.uploadUrl; 176 | this.url = this.delete_url = baseUrl + encodeURIComponent(this.name); 177 | Object.keys(options.imageVersions).forEach(function (version) { 178 | if (_existsSync( 179 | options.uploadDir + '/' + version + '/' + that.name 180 | )) { 181 | that[version + '_url'] = baseUrl + version + '/' + 182 | encodeURIComponent(that.name); 183 | } 184 | }); 185 | } 186 | }; 187 | UploadHandler.prototype.get = function () { 188 | var handler = this, 189 | files = []; 190 | fs.readdir(options.uploadDir, function (err, list) { 191 | list.forEach(function (name) { 192 | var stats = fs.statSync(options.uploadDir + '/' + name), 193 | fileInfo; 194 | if (stats.isFile()) { 195 | fileInfo = new FileInfo({ 196 | name: name, 197 | size: stats.size 198 | }); 199 | fileInfo.initUrls(handler.req); 200 | files.push(fileInfo); 201 | } 202 | }); 203 | handler.callback(files); 204 | }); 205 | }; 206 | UploadHandler.prototype.post = function () { 207 | var handler = this, 208 | form = new formidable.IncomingForm(), 209 | tmpFiles = [], 210 | files = [], 211 | map = {}, 212 | counter = 1, 213 | redirect, 214 | finish = function () { 215 | counter -= 1; 216 | if (!counter) { 217 | files.forEach(function (fileInfo) { 218 | fileInfo.initUrls(handler.req); 219 | }); 220 | handler.callback(files, redirect); 221 | } 222 | }; 223 | form.uploadDir = options.tmpDir; 224 | form.on('fileBegin', function (name, file) { 225 | tmpFiles.push(file.path); 226 | var fileInfo = new FileInfo(file, handler.req, true); 227 | fileInfo.safeName(); 228 | map[path.basename(file.path)] = fileInfo; 229 | files.push(fileInfo); 230 | }).on('field', function (name, value) { 231 | if (name === 'redirect') { 232 | redirect = value; 233 | } 234 | }).on('file', function (name, file) { 235 | var fileInfo = map[path.basename(file.path)]; 236 | fileInfo.size = file.size; 237 | if (!fileInfo.validate()) { 238 | fs.unlink(file.path); 239 | return; 240 | } 241 | fs.renameSync(file.path, options.uploadDir + '/' + fileInfo.name); 242 | if (options.imageTypes.test(fileInfo.name)) { 243 | Object.keys(options.imageVersions).forEach(function (version) { 244 | counter += 1; 245 | var opts = options.imageVersions[version]; 246 | imageMagick.resize({ 247 | width: opts.width, 248 | height: opts.height, 249 | srcPath: options.uploadDir + '/' + fileInfo.name, 250 | dstPath: options.uploadDir + '/' + version + '/' + 251 | fileInfo.name 252 | }, finish); 253 | }); 254 | } 255 | }).on('aborted', function () { 256 | tmpFiles.forEach(function (file) { 257 | fs.unlink(file); 258 | }); 259 | }).on('progress', function (bytesReceived, bytesExpected) { 260 | if (bytesReceived > options.maxPostSize) { 261 | handler.req.connection.destroy(); 262 | } 263 | }).on('end', finish).parse(handler.req); 264 | }; 265 | UploadHandler.prototype.destroy = function () { 266 | var handler = this, 267 | fileName; 268 | if (handler.req.url.slice(0, options.uploadUrl.length) === options.uploadUrl) { 269 | fileName = path.basename(decodeURIComponent(handler.req.url)); 270 | fs.unlink(options.uploadDir + '/' + fileName, function (ex) { 271 | Object.keys(options.imageVersions).forEach(function (version) { 272 | fs.unlink(options.uploadDir + '/' + version + '/' + fileName); 273 | }); 274 | handler.callback(!ex); 275 | }); 276 | } else { 277 | handler.callback(false); 278 | } 279 | }; 280 | if (options.ssl) { 281 | require('https').createServer(options.ssl, serve).listen(port); 282 | } else { 283 | require('http').createServer(serve).listen(port); 284 | } 285 | }(8888)); 286 | -------------------------------------------------------------------------------- /server/node/tmp/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/node/tmp/.gitignore -------------------------------------------------------------------------------- /server/php/config_liquen.ini: -------------------------------------------------------------------------------- 1 | ; config_liquen.ini 2 | ; for now it's empty 3 | cacheFolder = files/ 4 | sourceFolder = files/ -------------------------------------------------------------------------------- /server/php/files/.htaccess: -------------------------------------------------------------------------------- 1 | ForceType application/octet-stream 2 | 3 | ForceType none 4 | -------------------------------------------------------------------------------- /server/php/files/DSC02004 - agaricus arvensis.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/php/files/DSC02004 - agaricus arvensis.JPG -------------------------------------------------------------------------------- /server/php/files/DSC_9066 -rl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/php/files/DSC_9066 -rl.jpg -------------------------------------------------------------------------------- /server/php/files/DSC_9066 -rl.jpg_w900_cx475_cy254_cw869_ch483.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/php/files/DSC_9066 -rl.jpg_w900_cx475_cy254_cw869_ch483.jpg -------------------------------------------------------------------------------- /server/php/files/DSC_9073 - COLLIGUAY. Colliguaya odorifera.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/php/files/DSC_9073 - COLLIGUAY. Colliguaya odorifera.JPG -------------------------------------------------------------------------------- /server/php/files/DSC_9095.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/php/files/DSC_9095.JPG -------------------------------------------------------------------------------- /server/php/files/DSC_9114.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/php/files/DSC_9114.JPG -------------------------------------------------------------------------------- /server/php/image_crop_and_size.php: -------------------------------------------------------------------------------- 1 | dire: '.substr( $upload_handler->getOption('relative_upload_dir'). urldecode(array_pop(array_splice(explode('/','http://localhost/jQuery-File-Upload-and-Crop/server/php/files/DSC02004%20-%20agaricus%20arvensis.JPG'),-1))),1).' 12 |
isfile:'.is_file( substr( $upload_handler->getOption('relative_upload_dir'). urldecode(array_pop(array_splice(explode('/','http://localhost/jQuery-File-Upload-and-Crop/server/php/files/DSC02004%20-%20agaricus%20arvensis.JPG'),-1))),1) ).' 13 |
';*/ 14 | if(isset($_POST['source'])){ 15 | $thePicture = substr( $upload_handler->getOption('relative_upload_dir'). urldecode(array_pop(array_splice(explode('/',$_POST['source']['file']),-1))),1); 16 | }else{ 17 | $thePicture = substr( $upload_handler->getOption('relative_upload_dir'). urldecode(array_pop(array_splice(explode('/',$_POST['file']),-1))),1); 18 | $_POST['url']=$thePicture; 19 | } 20 | 21 | if (!is_file($thePicture)) exit('ERROR: Source image file not found'); 22 | 23 | if(!isset($_POST['source'])){ 24 | $newFile = $lii->genImage($_POST); 25 | 26 | $thumb = $lii->genImage(array( 27 | 'url' => $newFile, 28 | 'outputFolder' => 'thumbnails/', 29 | 'rename' => 'false', 30 | 'oc' => '1', 31 | 'width' => 80 32 | )); 33 | 34 | echo json_encode(array('newFile'=>$newFile)); 35 | exit(); 36 | } 37 | 38 | $size=getimagesize($thePicture); 39 | $sizeRatio=$size[0]/$_POST['source']['width']; 40 | 41 | $newFile = $lii->genImage(array( 42 | 'url'=>$thePicture, 43 | 'width'=>$_POST['source']['endWidth'], 44 | //'height'=>$_POST['source']['endHeight'], 45 | 'oc' => '1', 46 | 'cx' => floor($_POST['c']['x']*$sizeRatio), 47 | 'cy' => floor($_POST['c']['y']*$sizeRatio), 48 | 'cw' => floor($_POST['c']['w']*$sizeRatio), 49 | 'ch' => floor($_POST['c']['h']*$sizeRatio) 50 | )); 51 | 52 | //$lii2 = new LiquenImg(); 53 | $thumb = $lii->genImage(array( 54 | 'url' => $newFile, 55 | 'outputFolder' => 'thumbnails/', 56 | 'rename' => 'false', 57 | 'oc' => '1', 58 | 'width' => 80//, 59 | //'height' => 60//, 60 | //'crop' => false 61 | )); 62 | 63 | echo json_encode(array('newFile'=>$newFile)); 64 | ?> -------------------------------------------------------------------------------- /server/php/index.php: -------------------------------------------------------------------------------- 1 | get(); 33 | break; 34 | case 'POST': 35 | if (isset($_REQUEST['_method']) && $_REQUEST['_method'] === 'DELETE') { 36 | $upload_handler->delete(); 37 | } else { 38 | $upload_handler->post(); 39 | } 40 | break; 41 | case 'DELETE': 42 | $upload_handler->delete(); 43 | break; 44 | default: 45 | header('HTTP/1.1 405 Method Not Allowed'); 46 | } 47 | -------------------------------------------------------------------------------- /server/php/thumbnails/.htaccess: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/php/thumbnails/.htaccess -------------------------------------------------------------------------------- /server/php/thumbnails/DSC02004 - agaricus arvensis.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/php/thumbnails/DSC02004 - agaricus arvensis.JPG -------------------------------------------------------------------------------- /server/php/thumbnails/DSC02004 - agaricus arvensis.JPG_w932_cx48_cy612_cw2696_ch923.jpg_w80.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/php/thumbnails/DSC02004 - agaricus arvensis.JPG_w932_cx48_cy612_cw2696_ch923.jpg_w80.jpg -------------------------------------------------------------------------------- /server/php/thumbnails/DSC_9066 -rl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/php/thumbnails/DSC_9066 -rl.jpg -------------------------------------------------------------------------------- /server/php/thumbnails/DSC_9066 -rl.jpg_w900_cx475_cy254_cw869_ch483.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/php/thumbnails/DSC_9066 -rl.jpg_w900_cx475_cy254_cw869_ch483.jpg -------------------------------------------------------------------------------- /server/php/thumbnails/DSC_9073 - COLLIGUAY. Colliguaya odorifera.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/php/thumbnails/DSC_9073 - COLLIGUAY. Colliguaya odorifera.JPG -------------------------------------------------------------------------------- /server/php/thumbnails/DSC_9095.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/php/thumbnails/DSC_9095.JPG -------------------------------------------------------------------------------- /server/php/thumbnails/DSC_9114.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baamenabar/jQuery-File-Upload-and-Crop/38875dbeb901ddead7f4d54cc683e24dafa4523b/server/php/thumbnails/DSC_9114.JPG -------------------------------------------------------------------------------- /server/php/upload.class.php: -------------------------------------------------------------------------------- 1 | options = array( 20 | 'script_url' => $this->getFullUrl().'/', 21 | 'relative_upload_dir' => $this->_relative_upload_dir, 22 | 'upload_dir' => dirname($_SERVER['SCRIPT_FILENAME']).$this->_relative_upload_dir, 23 | 'upload_url' => $this->getFullUrl().$this->_relative_upload_dir, 24 | 'param_name' => 'files', 25 | // Set the following option to 'POST', if your server does not support 26 | // DELETE requests. This is a parameter sent to the client: 27 | 'delete_type' => 'DELETE', 28 | // The php.ini settings upload_max_filesize and post_max_size 29 | // take precedence over the following max_file_size setting: 30 | 'max_file_size' => null, 31 | 'min_file_size' => 1, 32 | 'accept_file_types' => '/\.(gif|jpe?g|png)$/i', 33 | // The maximum number of files for the upload directory: 34 | 'max_number_of_files' => null, 35 | // Image resolution restrictions: 36 | 'max_width' => null, 37 | 'max_height' => null, 38 | 'min_width' => 1, 39 | 'min_height' => 1, 40 | // Set the following option to false to enable resumable uploads: 41 | 'discard_aborted_uploads' => true, 42 | // Set to true to rotate images based on EXIF meta data, if available: 43 | 'orient_image' => false, 44 | 'image_versions' => array( 45 | // Uncomment the following version to restrict the size of 46 | // uploaded images. You can also add additional versions with 47 | // their own upload directories: 48 | /* 49 | 'large' => array( 50 | 'upload_dir' => dirname($_SERVER['SCRIPT_FILENAME']).'/files/', 51 | 'upload_url' => $this->getFullUrl().'/files/', 52 | 'max_width' => 1920, 53 | 'max_height' => 1200, 54 | 'jpeg_quality' => 95 55 | ), 56 | */ 57 | 'thumbnail' => array( 58 | 'upload_dir' => dirname($_SERVER['SCRIPT_FILENAME']).'/thumbnails/', 59 | 'upload_url' => $this->getFullUrl().'/thumbnails/', 60 | 'max_width' => 80, 61 | 'max_height' => 80 62 | ) 63 | ) 64 | ); 65 | if ($options) { 66 | $this->options = array_replace_recursive($this->options, $options); 67 | } 68 | } 69 | 70 | protected function getFullUrl() { 71 | $https = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'; 72 | return 73 | ($https ? 'https://' : 'http://'). 74 | (!empty($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'].'@' : ''). 75 | (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ($_SERVER['SERVER_NAME']. 76 | ($https && $_SERVER['SERVER_PORT'] === 443 || 77 | $_SERVER['SERVER_PORT'] === 80 ? '' : ':'.$_SERVER['SERVER_PORT']))). 78 | substr($_SERVER['SCRIPT_NAME'],0, strrpos($_SERVER['SCRIPT_NAME'], '/')); 79 | } 80 | 81 | protected function getRootUrl() { 82 | $https = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'; 83 | return 84 | ($https ? 'https://' : 'http://'). 85 | (!empty($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'].'@' : ''). 86 | (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ($_SERVER['SERVER_NAME']. 87 | ($https && $_SERVER['SERVER_PORT'] === 443 || 88 | $_SERVER['SERVER_PORT'] === 80 ? '' : ':'.$_SERVER['SERVER_PORT']))).'/'; 89 | } 90 | 91 | protected function set_file_delete_url($file) { 92 | $file->delete_url = $this->options['script_url'] 93 | .'?file='.rawurlencode($file->name); 94 | $file->delete_type = $this->options['delete_type']; 95 | if ($file->delete_type !== 'DELETE') { 96 | $file->delete_url .= '&_method=DELETE'; 97 | } 98 | } 99 | 100 | protected function get_file_object($file_name) { 101 | $file_path = $this->options['upload_dir'].$file_name; 102 | if (is_file($file_path) && $file_name[0] !== '.') { 103 | $file = new stdClass(); 104 | $file->name = $file_name; 105 | $file->size = filesize($file_path); 106 | $file->url = $this->options['upload_url'].rawurlencode($file->name); 107 | foreach($this->options['image_versions'] as $version => $options) { 108 | if (is_file($options['upload_dir'].$file_name)) { 109 | $file->{$version.'_url'} = $options['upload_url'] 110 | .rawurlencode($file->name); 111 | } 112 | } 113 | $this->set_file_delete_url($file); 114 | return $file; 115 | } 116 | return null; 117 | } 118 | 119 | protected function get_file_objects() { 120 | return array_values(array_filter(array_map( 121 | array($this, 'get_file_object'), 122 | scandir($this->options['upload_dir']) 123 | ))); 124 | } 125 | 126 | protected function create_scaled_image($file_name, $options) { 127 | $file_path = $this->options['upload_dir'].$file_name; 128 | $new_file_path = $options['upload_dir'].$file_name; 129 | list($img_width, $img_height) = @getimagesize($file_path); 130 | if (!$img_width || !$img_height) { 131 | return false; 132 | } 133 | $scale = min( 134 | $options['max_width'] / $img_width, 135 | $options['max_height'] / $img_height 136 | ); 137 | if ($scale >= 1) { 138 | if ($file_path !== $new_file_path) { 139 | return copy($file_path, $new_file_path); 140 | } 141 | return true; 142 | } 143 | $new_width = $img_width * $scale; 144 | $new_height = $img_height * $scale; 145 | $new_img = @imagecreatetruecolor($new_width, $new_height); 146 | switch (strtolower(substr(strrchr($file_name, '.'), 1))) { 147 | case 'jpg': 148 | case 'jpeg': 149 | $src_img = @imagecreatefromjpeg($file_path); 150 | $write_image = 'imagejpeg'; 151 | $image_quality = isset($options['jpeg_quality']) ? 152 | $options['jpeg_quality'] : 75; 153 | break; 154 | case 'gif': 155 | @imagecolortransparent($new_img, @imagecolorallocate($new_img, 0, 0, 0)); 156 | $src_img = @imagecreatefromgif($file_path); 157 | $write_image = 'imagegif'; 158 | $image_quality = null; 159 | break; 160 | case 'png': 161 | @imagecolortransparent($new_img, @imagecolorallocate($new_img, 0, 0, 0)); 162 | @imagealphablending($new_img, false); 163 | @imagesavealpha($new_img, true); 164 | $src_img = @imagecreatefrompng($file_path); 165 | $write_image = 'imagepng'; 166 | $image_quality = isset($options['png_quality']) ? 167 | $options['png_quality'] : 9; 168 | break; 169 | default: 170 | $src_img = null; 171 | } 172 | $success = $src_img && @imagecopyresampled( 173 | $new_img, 174 | $src_img, 175 | 0, 0, 0, 0, 176 | $new_width, 177 | $new_height, 178 | $img_width, 179 | $img_height 180 | ) && $write_image($new_img, $new_file_path, $image_quality); 181 | // Free up memory (imagedestroy does not delete files): 182 | @imagedestroy($src_img); 183 | @imagedestroy($new_img); 184 | return $success; 185 | } 186 | 187 | protected function validate($uploaded_file, $file, $error, $index) { 188 | if ($error) { 189 | $file->error = $error; 190 | return false; 191 | } 192 | if (!$file->name) { 193 | $file->error = 'missingFileName'; 194 | return false; 195 | } 196 | if (!preg_match($this->options['accept_file_types'], $file->name)) { 197 | $file->error = 'acceptFileTypes'; 198 | return false; 199 | } 200 | //DEACTIVATE THIS IS YOU WANT TO UPLOAD THINGS OTHER THAN IMAGES 201 | if(!@exif_imagetype($uploaded_file)){ 202 | $file->error = 'acceptFileTypes'; 203 | return false; 204 | } 205 | if ($uploaded_file && is_uploaded_file($uploaded_file)) { 206 | $file_size = filesize($uploaded_file); 207 | } else { 208 | $file_size = $_SERVER['CONTENT_LENGTH']; 209 | } 210 | if ($this->options['max_file_size'] && ( 211 | $file_size > $this->options['max_file_size'] || 212 | $file->size > $this->options['max_file_size']) 213 | ) { 214 | $file->error = 'maxFileSize'; 215 | return false; 216 | } 217 | if ($this->options['min_file_size'] && 218 | $file_size < $this->options['min_file_size']) { 219 | $file->error = 'minFileSize'; 220 | return false; 221 | } 222 | if (is_int($this->options['max_number_of_files']) && ( 223 | count($this->get_file_objects()) >= $this->options['max_number_of_files']) 224 | ) { 225 | $file->error = 'maxNumberOfFiles'; 226 | return false; 227 | } 228 | list($img_width, $img_height) = @getimagesize($uploaded_file); 229 | if (is_int($img_width)) { 230 | if ($this->options['max_width'] && $img_width > $this->options['max_width'] || 231 | $this->options['max_height'] && $img_height > $this->options['max_height']) { 232 | $file->error = 'maxResolution'; 233 | return false; 234 | } 235 | if ($this->options['min_width'] && $img_width < $this->options['min_width'] || 236 | $this->options['min_height'] && $img_height < $this->options['min_height']) { 237 | $file->error = 'minResolution'; 238 | return false; 239 | } 240 | } 241 | return true; 242 | } 243 | 244 | protected function upcount_name_callback($matches) { 245 | $index = isset($matches[1]) ? intval($matches[1]) + 1 : 1; 246 | $ext = isset($matches[2]) ? $matches[2] : ''; 247 | return ' ('.$index.')'.$ext; 248 | } 249 | 250 | protected function upcount_name($name) { 251 | return preg_replace_callback( 252 | '/(?:(?: \(([\d]+)\))?(\.[^.]+))?$/', 253 | array($this, 'upcount_name_callback'), 254 | $name, 255 | 1 256 | ); 257 | } 258 | 259 | protected function trim_file_name($name, $type, $index) { 260 | // Remove path information and dots around the filename, to prevent uploading 261 | // into different directories or replacing hidden system files. 262 | // Also remove control characters and spaces (\x00..\x20) around the filename: 263 | $file_name = trim(basename(stripslashes($name)), ".\x00..\x20"); 264 | // Add missing file extension for known image types: 265 | if (strpos($file_name, '.') === false && 266 | preg_match('/^image\/(gif|jpe?g|png)/', $type, $matches)) { 267 | $file_name .= '.'.$matches[1]; 268 | } 269 | if ($this->options['discard_aborted_uploads']) { 270 | while(is_file($this->options['upload_dir'].$file_name)) { 271 | $file_name = $this->upcount_name($file_name); 272 | } 273 | } 274 | return $file_name; 275 | } 276 | 277 | protected function handle_form_data($file, $index) { 278 | // Handle form data, e.g. $_REQUEST['description'][$index] 279 | } 280 | 281 | protected function orient_image($file_path) { 282 | $exif = @exif_read_data($file_path); 283 | if ($exif === false) { 284 | return false; 285 | } 286 | $orientation = intval(@$exif['Orientation']); 287 | if (!in_array($orientation, array(3, 6, 8))) { 288 | return false; 289 | } 290 | $image = @imagecreatefromjpeg($file_path); 291 | switch ($orientation) { 292 | case 3: 293 | $image = @imagerotate($image, 180, 0); 294 | break; 295 | case 6: 296 | $image = @imagerotate($image, 270, 0); 297 | break; 298 | case 8: 299 | $image = @imagerotate($image, 90, 0); 300 | break; 301 | default: 302 | return false; 303 | } 304 | $success = imagejpeg($image, $file_path); 305 | // Free up memory (imagedestroy does not delete files): 306 | @imagedestroy($image); 307 | return $success; 308 | } 309 | 310 | protected function handle_file_upload($uploaded_file, $name, $size, $type, $error, $index = null) { 311 | $file = new stdClass(); 312 | $file->name = $this->trim_file_name($name, $type, $index); 313 | $file->size = intval($size); 314 | $file->type = $type; 315 | if ($this->validate($uploaded_file, $file, $error, $index)) { 316 | $this->handle_form_data($file, $index); 317 | $file_path = $this->options['upload_dir'].$file->name; 318 | $append_file = !$this->options['discard_aborted_uploads'] && 319 | is_file($file_path) && $file->size > filesize($file_path); 320 | clearstatcache(); 321 | if ($uploaded_file && is_uploaded_file($uploaded_file)) { 322 | // multipart/formdata uploads (POST method uploads) 323 | if ($append_file) { 324 | file_put_contents( 325 | $file_path, 326 | fopen($uploaded_file, 'r'), 327 | FILE_APPEND 328 | ); 329 | } else { 330 | move_uploaded_file($uploaded_file, $file_path); 331 | } 332 | } else { 333 | // Non-multipart uploads (PUT method support) 334 | file_put_contents( 335 | $file_path, 336 | fopen('php://input', 'r'), 337 | $append_file ? FILE_APPEND : 0 338 | ); 339 | } 340 | $file_size = filesize($file_path); 341 | if ($file_size === $file->size) { 342 | if ($this->options['orient_image']) { 343 | $this->orient_image($file_path); 344 | } 345 | $file->url = $this->options['upload_url'].rawurlencode($file->name); 346 | foreach($this->options['image_versions'] as $version => $options) { 347 | if ($this->create_scaled_image($file->name, $options)) { 348 | if ($this->options['upload_dir'] !== $options['upload_dir']) { 349 | $file->{$version.'_url'} = $options['upload_url'] 350 | .rawurlencode($file->name); 351 | } else { 352 | clearstatcache(); 353 | $file_size = filesize($file_path); 354 | } 355 | } 356 | } 357 | } else if ($this->options['discard_aborted_uploads']) { 358 | unlink($file_path); 359 | $file->error = 'abort'; 360 | } 361 | $file->size = $file_size; 362 | $this->set_file_delete_url($file); 363 | } 364 | return $file; 365 | } 366 | 367 | public function get() { 368 | $file_name = isset($_REQUEST['file']) ? 369 | basename(stripslashes($_REQUEST['file'])) : null; 370 | if ($file_name) { 371 | $info = $this->get_file_object($file_name); 372 | } else { 373 | $info = $this->get_file_objects(); 374 | } 375 | header('Content-type: application/json'); 376 | echo json_encode($info); 377 | } 378 | 379 | public function post() { 380 | if (isset($_REQUEST['_method']) && $_REQUEST['_method'] === 'DELETE') { 381 | return $this->delete(); 382 | } 383 | $upload = isset($_FILES[$this->options['param_name']]) ? 384 | $_FILES[$this->options['param_name']] : null; 385 | $info = array(); 386 | if ($upload && is_array($upload['tmp_name'])) { 387 | // param_name is an array identifier like "files[]", 388 | // $_FILES is a multi-dimensional array: 389 | foreach ($upload['tmp_name'] as $index => $value) { 390 | $info[] = $this->handle_file_upload( 391 | $upload['tmp_name'][$index], 392 | isset($_SERVER['HTTP_X_FILE_NAME']) ? 393 | $_SERVER['HTTP_X_FILE_NAME'] : $upload['name'][$index], 394 | isset($_SERVER['HTTP_X_FILE_SIZE']) ? 395 | $_SERVER['HTTP_X_FILE_SIZE'] : $upload['size'][$index], 396 | isset($_SERVER['HTTP_X_FILE_TYPE']) ? 397 | $_SERVER['HTTP_X_FILE_TYPE'] : $upload['type'][$index], 398 | $upload['error'][$index], 399 | $index 400 | ); 401 | } 402 | } elseif ($upload || isset($_SERVER['HTTP_X_FILE_NAME'])) { 403 | // param_name is a single object identifier like "file", 404 | // $_FILES is a one-dimensional array: 405 | $info[] = $this->handle_file_upload( 406 | isset($upload['tmp_name']) ? $upload['tmp_name'] : null, 407 | isset($_SERVER['HTTP_X_FILE_NAME']) ? 408 | $_SERVER['HTTP_X_FILE_NAME'] : (isset($upload['name']) ? 409 | $upload['name'] : null), 410 | isset($_SERVER['HTTP_X_FILE_SIZE']) ? 411 | $_SERVER['HTTP_X_FILE_SIZE'] : (isset($upload['size']) ? 412 | $upload['size'] : null), 413 | isset($_SERVER['HTTP_X_FILE_TYPE']) ? 414 | $_SERVER['HTTP_X_FILE_TYPE'] : (isset($upload['type']) ? 415 | $upload['type'] : null), 416 | isset($upload['error']) ? $upload['error'] : null 417 | ); 418 | } 419 | header('Vary: Accept'); 420 | $json = json_encode($info); 421 | $redirect = isset($_REQUEST['redirect']) ? 422 | stripslashes($_REQUEST['redirect']) : null; 423 | if ($redirect) { 424 | header('Location: '.sprintf($redirect, rawurlencode($json))); 425 | return; 426 | } 427 | if (isset($_SERVER['HTTP_ACCEPT']) && 428 | (strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false)) { 429 | header('Content-type: application/json'); 430 | } else { 431 | header('Content-type: text/plain'); 432 | } 433 | echo $json; 434 | } 435 | 436 | public function delete() { 437 | $file_name = isset($_REQUEST['file']) ? 438 | basename(stripslashes($_REQUEST['file'])) : null; 439 | $file_path = $this->options['upload_dir'].$file_name; 440 | $success = is_file($file_path) && $file_name[0] !== '.' && unlink($file_path); 441 | if ($success) { 442 | foreach($this->options['image_versions'] as $version => $options) { 443 | $file = $options['upload_dir'].$file_name; 444 | if (is_file($file)) { 445 | unlink($file); 446 | } 447 | } 448 | } 449 | header('Content-type: application/json'); 450 | echo json_encode($success); 451 | } 452 | 453 | public function getOption($option_name){ 454 | if(isset($this->options[$option_name])){ 455 | return $this->options[$option_name]; 456 | }else{ 457 | return null; 458 | } 459 | } 460 | } 461 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | 18 | 19 | jQuery File Upload Plugin Test 20 | 21 | 22 | 23 | 24 |

jQuery File Upload Plugin Test

25 |

26 |
27 |

28 |
    29 |
    30 | 31 |
    32 | 33 |
    34 |
    35 | 36 | 37 | 38 | Add files... 39 | 40 | 41 | 45 | 49 | 53 | 54 |
    55 | 56 |
    57 | 58 |
    59 |
    60 |
    61 | 62 |
     
    63 |
    64 |
    65 | 66 |
    67 |
    68 | 69 | 70 |
    71 |
    72 | 73 | 103 | 104 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | --------------------------------------------------------------------------------