├── Lib └── empty ├── Test ├── Fixture │ └── empty └── Case │ ├── View │ └── Helper │ │ └── empty │ ├── Model │ └── Behavior │ │ └── empty │ └── Controller │ └── Component │ └── empty ├── Config ├── Schema │ └── empty └── bootstrap.php ├── Model ├── Behavior │ └── empty ├── Datasource │ └── empty └── AjaxMultiUploadAppModel.php ├── .gitignore ├── Console └── Command │ └── Task │ └── empty ├── View ├── Upload │ └── upload.ctp └── Helper │ └── UploadHelper.php ├── webroot ├── css │ ├── loading.gif │ └── dropzone.css ├── img │ ├── delete.png │ ├── loading.gif │ └── fileicons │ │ ├── 7z.png │ │ ├── ai.png │ │ ├── asc.png │ │ ├── bin.png │ │ ├── bz2.png │ │ ├── c.png │ │ ├── cfc.png │ │ ├── cfm.png │ │ ├── chm.png │ │ ├── cpp.png │ │ ├── cs.png │ │ ├── css.png │ │ ├── csv.png │ │ ├── deb.png │ │ ├── doc.png │ │ ├── dot.png │ │ ├── eml.png │ │ ├── enc.png │ │ ├── gif.png │ │ ├── gz.png │ │ ├── hlp.png │ │ ├── htm.png │ │ ├── iso.png │ │ ├── jar.png │ │ ├── jpg.png │ │ ├── js.png │ │ ├── lua.png │ │ ├── m.png │ │ ├── mm.png │ │ ├── mov.png │ │ ├── mp3.png │ │ ├── mp4.png │ │ ├── mpg.png │ │ ├── odc.png │ │ ├── odf.png │ │ ├── odg.png │ │ ├── odi.png │ │ ├── odp.png │ │ ├── ods.png │ │ ├── odt.png │ │ ├── ogg.png │ │ ├── pdf.png │ │ ├── pgp.png │ │ ├── php.png │ │ ├── pl.png │ │ ├── png.png │ │ ├── ppt.png │ │ ├── ps.png │ │ ├── py.png │ │ ├── ram.png │ │ ├── rar.png │ │ ├── rb.png │ │ ├── rm.png │ │ ├── rpm.png │ │ ├── rtf.png │ │ ├── sig.png │ │ ├── sql.png │ │ ├── swf.png │ │ ├── sxc.png │ │ ├── sxd.png │ │ ├── sxi.png │ │ ├── sxw.png │ │ ├── tar.png │ │ ├── tex.png │ │ ├── tgz.png │ │ ├── txt.png │ │ ├── vcf.png │ │ ├── vsd.png │ │ ├── wav.png │ │ ├── wma.png │ │ ├── wmv.png │ │ ├── xls.png │ │ ├── xml.png │ │ ├── xpi.png │ │ ├── zip.png │ │ ├── aiff.png │ │ ├── audio.png │ │ ├── class.png │ │ ├── conf.png │ │ ├── divx.png │ │ ├── file.png │ │ ├── html.png │ │ ├── image.png │ │ ├── java.png │ │ ├── jpeg.png │ │ ├── video.png │ │ ├── xvid.png │ │ └── README └── js │ └── dropzone.js ├── LICENSE ├── Controller ├── AjaxMultiUploadAppController.php ├── Component │ └── UploadComponent.php └── UploadsController.php └── README.md /Lib/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Test/Fixture/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Config/Schema/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Model/Behavior/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Model/Datasource/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /Console/Command/Task/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Test/Case/View/Helper/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Test/Case/Model/Behavior/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Test/Case/Controller/Component/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /View/Upload/upload.ctp: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /webroot/css/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/css/loading.gif -------------------------------------------------------------------------------- /webroot/img/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/delete.png -------------------------------------------------------------------------------- /webroot/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/loading.gif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Dual-licensed under GPL and MIT license. You are welcome to choose 2 | whichever one you prefer. 3 | 4 | -------------------------------------------------------------------------------- /webroot/img/fileicons/7z.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/7z.png -------------------------------------------------------------------------------- /webroot/img/fileicons/ai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/ai.png -------------------------------------------------------------------------------- /webroot/img/fileicons/asc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/asc.png -------------------------------------------------------------------------------- /webroot/img/fileicons/bin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/bin.png -------------------------------------------------------------------------------- /webroot/img/fileicons/bz2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/bz2.png -------------------------------------------------------------------------------- /webroot/img/fileicons/c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/c.png -------------------------------------------------------------------------------- /webroot/img/fileicons/cfc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/cfc.png -------------------------------------------------------------------------------- /webroot/img/fileicons/cfm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/cfm.png -------------------------------------------------------------------------------- /webroot/img/fileicons/chm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/chm.png -------------------------------------------------------------------------------- /webroot/img/fileicons/cpp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/cpp.png -------------------------------------------------------------------------------- /webroot/img/fileicons/cs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/cs.png -------------------------------------------------------------------------------- /webroot/img/fileicons/css.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/css.png -------------------------------------------------------------------------------- /webroot/img/fileicons/csv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/csv.png -------------------------------------------------------------------------------- /webroot/img/fileicons/deb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/deb.png -------------------------------------------------------------------------------- /webroot/img/fileicons/doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/doc.png -------------------------------------------------------------------------------- /webroot/img/fileicons/dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/dot.png -------------------------------------------------------------------------------- /webroot/img/fileicons/eml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/eml.png -------------------------------------------------------------------------------- /webroot/img/fileicons/enc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/enc.png -------------------------------------------------------------------------------- /webroot/img/fileicons/gif.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/gif.png -------------------------------------------------------------------------------- /webroot/img/fileicons/gz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/gz.png -------------------------------------------------------------------------------- /webroot/img/fileicons/hlp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/hlp.png -------------------------------------------------------------------------------- /webroot/img/fileicons/htm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/htm.png -------------------------------------------------------------------------------- /webroot/img/fileicons/iso.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/iso.png -------------------------------------------------------------------------------- /webroot/img/fileicons/jar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/jar.png -------------------------------------------------------------------------------- /webroot/img/fileicons/jpg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/jpg.png -------------------------------------------------------------------------------- /webroot/img/fileicons/js.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/js.png -------------------------------------------------------------------------------- /webroot/img/fileicons/lua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/lua.png -------------------------------------------------------------------------------- /webroot/img/fileicons/m.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/m.png -------------------------------------------------------------------------------- /webroot/img/fileicons/mm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/mm.png -------------------------------------------------------------------------------- /webroot/img/fileicons/mov.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/mov.png -------------------------------------------------------------------------------- /webroot/img/fileicons/mp3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/mp3.png -------------------------------------------------------------------------------- /webroot/img/fileicons/mp4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/mp4.png -------------------------------------------------------------------------------- /webroot/img/fileicons/mpg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/mpg.png -------------------------------------------------------------------------------- /webroot/img/fileicons/odc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/odc.png -------------------------------------------------------------------------------- /webroot/img/fileicons/odf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/odf.png -------------------------------------------------------------------------------- /webroot/img/fileicons/odg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/odg.png -------------------------------------------------------------------------------- /webroot/img/fileicons/odi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/odi.png -------------------------------------------------------------------------------- /webroot/img/fileicons/odp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/odp.png -------------------------------------------------------------------------------- /webroot/img/fileicons/ods.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/ods.png -------------------------------------------------------------------------------- /webroot/img/fileicons/odt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/odt.png -------------------------------------------------------------------------------- /webroot/img/fileicons/ogg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/ogg.png -------------------------------------------------------------------------------- /webroot/img/fileicons/pdf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/pdf.png -------------------------------------------------------------------------------- /webroot/img/fileicons/pgp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/pgp.png -------------------------------------------------------------------------------- /webroot/img/fileicons/php.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/php.png -------------------------------------------------------------------------------- /webroot/img/fileicons/pl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/pl.png -------------------------------------------------------------------------------- /webroot/img/fileicons/png.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/png.png -------------------------------------------------------------------------------- /webroot/img/fileicons/ppt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/ppt.png -------------------------------------------------------------------------------- /webroot/img/fileicons/ps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/ps.png -------------------------------------------------------------------------------- /webroot/img/fileicons/py.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/py.png -------------------------------------------------------------------------------- /webroot/img/fileicons/ram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/ram.png -------------------------------------------------------------------------------- /webroot/img/fileicons/rar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/rar.png -------------------------------------------------------------------------------- /webroot/img/fileicons/rb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/rb.png -------------------------------------------------------------------------------- /webroot/img/fileicons/rm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/rm.png -------------------------------------------------------------------------------- /webroot/img/fileicons/rpm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/rpm.png -------------------------------------------------------------------------------- /webroot/img/fileicons/rtf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/rtf.png -------------------------------------------------------------------------------- /webroot/img/fileicons/sig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/sig.png -------------------------------------------------------------------------------- /webroot/img/fileicons/sql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/sql.png -------------------------------------------------------------------------------- /webroot/img/fileicons/swf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/swf.png -------------------------------------------------------------------------------- /webroot/img/fileicons/sxc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/sxc.png -------------------------------------------------------------------------------- /webroot/img/fileicons/sxd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/sxd.png -------------------------------------------------------------------------------- /webroot/img/fileicons/sxi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/sxi.png -------------------------------------------------------------------------------- /webroot/img/fileicons/sxw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/sxw.png -------------------------------------------------------------------------------- /webroot/img/fileicons/tar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/tar.png -------------------------------------------------------------------------------- /webroot/img/fileicons/tex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/tex.png -------------------------------------------------------------------------------- /webroot/img/fileicons/tgz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/tgz.png -------------------------------------------------------------------------------- /webroot/img/fileicons/txt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/txt.png -------------------------------------------------------------------------------- /webroot/img/fileicons/vcf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/vcf.png -------------------------------------------------------------------------------- /webroot/img/fileicons/vsd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/vsd.png -------------------------------------------------------------------------------- /webroot/img/fileicons/wav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/wav.png -------------------------------------------------------------------------------- /webroot/img/fileicons/wma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/wma.png -------------------------------------------------------------------------------- /webroot/img/fileicons/wmv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/wmv.png -------------------------------------------------------------------------------- /webroot/img/fileicons/xls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/xls.png -------------------------------------------------------------------------------- /webroot/img/fileicons/xml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/xml.png -------------------------------------------------------------------------------- /webroot/img/fileicons/xpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/xpi.png -------------------------------------------------------------------------------- /webroot/img/fileicons/zip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/zip.png -------------------------------------------------------------------------------- /webroot/img/fileicons/aiff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/aiff.png -------------------------------------------------------------------------------- /webroot/img/fileicons/audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/audio.png -------------------------------------------------------------------------------- /webroot/img/fileicons/class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/class.png -------------------------------------------------------------------------------- /webroot/img/fileicons/conf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/conf.png -------------------------------------------------------------------------------- /webroot/img/fileicons/divx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/divx.png -------------------------------------------------------------------------------- /webroot/img/fileicons/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/file.png -------------------------------------------------------------------------------- /webroot/img/fileicons/html.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/html.png -------------------------------------------------------------------------------- /webroot/img/fileicons/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/image.png -------------------------------------------------------------------------------- /webroot/img/fileicons/java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/java.png -------------------------------------------------------------------------------- /webroot/img/fileicons/jpeg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/jpeg.png -------------------------------------------------------------------------------- /webroot/img/fileicons/video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/video.png -------------------------------------------------------------------------------- /webroot/img/fileicons/xvid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srs81/CakePHP-AjaxMultiUpload/HEAD/webroot/img/fileicons/xvid.png -------------------------------------------------------------------------------- /Model/AjaxMultiUploadAppModel.php: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /Controller/AjaxMultiUploadAppController.php: -------------------------------------------------------------------------------- 1 | 17 | Michael Klier 18 | Andreas Barton 19 | Hubert Chathi 20 | Johan Koehne 21 | Rudi von Staden 22 | Daniel Darvish 23 | Andy Pascall 24 | Seth 25 | David Carella 26 | Tom N. Harris 27 | Brandon Carmon Colvin 28 | -------------------------------------------------------------------------------- /Controller/Component/UploadComponent.php: -------------------------------------------------------------------------------- 1 | controller = $collection->getController(); 29 | $this->settings = $settings; 30 | } 31 | 32 | /** 33 | * Component startup method. 34 | * Called after the Controller::beforeFilter() and before the controller action 35 | * @param object $controller A reference to the instantiating controller object 36 | * @access public 37 | */ 38 | public function startup(Controller $controller) { 39 | if (!in_array('AjaxMultiUpload.Upload', $this->controller->helpers) && !array_key_exists('AjaxMultiUpload.Upload', $this->controller->helpers)) { 40 | $this->controller->helpers[] = 'AjaxMultiUpload.Upload'; 41 | } 42 | } 43 | 44 | public function deleteAll ($model, $id) { 45 | $dir = Configure::read('AMU.directory'); 46 | if (strlen($dir) < 1) $dir = "files"; 47 | 48 | $lastDir = $this->last_dir ($model, $id); 49 | $dirPath = WWW_ROOT . DS . $dir . DS . $lastDir . DS; 50 | $files = glob($dirPath . '*', GLOB_MARK); 51 | foreach ($files as $file) { 52 | unlink($file); 53 | } 54 | if (is_dir($dirPath)) rmdir($dirPath); 55 | } 56 | 57 | // The "last mile" of the directory path for where the files get uploaded 58 | public function last_dir ($model, $id) { 59 | return $model . "/" . $id; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Controller/UploadsController.php: -------------------------------------------------------------------------------- 1 | Auth->allow(array('upload','delete')); 23 | } 24 | 25 | public function upload($dir=null) { 26 | // max file size in bytes 27 | $size = Configure::read ('AMU.filesizeMB'); 28 | if ($size === "") $size = 4; 29 | $relPath = Configure::read ('AMU.directory'); 30 | if ($relPath === "") $relPath = "files"; 31 | 32 | $sizeLimit = $size * 1024 * 1024; 33 | $this->layout = "ajax"; 34 | Configure::write('debug', 0); 35 | $directory = WWW_ROOT . DS . $relPath; 36 | $result = array(); 37 | 38 | if ($dir === null) { 39 | $result = array("error" => "Upload controller was passed a null value."); 40 | } 41 | // Replace underscores delimiter with slash 42 | $dir = str_replace ("___", "/", $dir); 43 | $dir = $directory . DS . "$dir/"; 44 | if (!file_exists($dir)) { 45 | mkdir($dir, 0777, true); 46 | } 47 | if (!is_writable($dir)){ 48 | $result = array('error' => "Server error. Upload directory isn't writable. Please ask server admin to change permissions."); 49 | } 50 | if (!empty($_FILES)) { 51 | $tempFile = $_FILES['file']['tmp_name']; 52 | $targetPath = $dir; 53 | $targetFile = $targetPath . $_FILES['file']['name']; 54 | $fileSize = filesize($tempFile); 55 | if ($this->endsWith($targetFile, ".php")) { 56 | $result = array('error' => 'You are not allowed to upload PHP files for security reasons.'); 57 | } 58 | if ($fileSize > $sizeLimit) { 59 | $result = array('error' => 'File is too large. Please ask server admin to increase the file upload limit.'); 60 | } 61 | if (sizeof($result) == 0) { 62 | move_uploaded_file($tempFile, $targetFile); 63 | } 64 | } else { 65 | $result = array('error' => 'No files were uploaded.'); 66 | } 67 | 68 | if (sizeof($result) > 0) { 69 | // There was an issue with the upload 70 | $this->response->statusCode(400); 71 | } else { 72 | // The upload was a success 73 | $result = array('ok' => 'upload success'); 74 | $this->response->statusCode(200); 75 | } 76 | $this->response->type('json'); 77 | $this->set("result", htmlspecialchars(json_encode($result), ENT_NOQUOTES)); 78 | } 79 | 80 | /** 81 | * delete a file 82 | * Thanks to traedamatic @ github 83 | */ 84 | public function delete($file = null) { 85 | if(is_null($file)) { 86 | $this->Session->setFlash(__('File parameter is missing')); 87 | $this->redirect($this->referer()); 88 | } 89 | $file = base64_decode($file); 90 | if(file_exists($file)) { 91 | if(unlink($file)) { 92 | $this->Session->setFlash(__('File deleted!')); 93 | } else { 94 | $this->Session->setFlash(__('Unable to delete File')); 95 | } 96 | } else { 97 | $this->Session->setFlash(__('File does not exist!')); 98 | } 99 | 100 | $this->redirect($this->referer()); 101 | } 102 | 103 | // From http://stackoverflow.com/a/10473026/2033901 104 | function endsWith($haystack, $needle) { 105 | // search forward starting from end minus needle length characters 106 | return $needle === "" || (($temp = strlen($haystack) - strlen($needle)) >= 0 && strpos($haystack, $needle, $temp) !== FALSE); 107 | } 108 | } 109 | 110 | ?> 111 | -------------------------------------------------------------------------------- /View/Helper/UploadHelper.php: -------------------------------------------------------------------------------- 1 | listing ($model, $id); 17 | 18 | $directory = $results['directory']; 19 | $baseUrl = $results['baseUrl']; 20 | $files = $results['files']; 21 | 22 | if (sizeof($files) == 0) { 23 | return ""; 24 | } 25 | 26 | $allIconFiles = array(); 27 | foreach (glob(ROOT . DS . "app/Plugin/AjaxMultiUpload/webroot/img/fileicons/*") as $iconFile) { 28 | $iconFile = pathinfo($iconFile, PATHINFO_FILENAME); 29 | $allIconFiles[] = str_replace(".png", "", $iconFile); 30 | } 31 | 32 | $str = "
" . __("Files") . "
\n"; 33 | $str .= "
\n"; 34 | $webroot = Router::url("/") . "ajax_multi_upload"; 35 | foreach ($files as $file) { 36 | $type = pathinfo($file, PATHINFO_EXTENSION); 37 | $filesize = $this->format_bytes (filesize ($file)); 38 | $f = basename($file); 39 | $url = $baseUrl . "/$f"; 40 | if ($edit) { 41 | $baseEncFile = base64_encode ($file); 42 | $delUrl = "$webroot/uploads/delete/$baseEncFile/"; 43 | $str .= "Delete "; 45 | } 46 | if (in_array($type, $allIconFiles)) { 47 | $str .= " "; 48 | } 49 | $str .= "" . $f . " ($filesize)"; 50 | $str .= "
\n"; 51 | } 52 | $str .= "
\n"; 53 | return $str; 54 | } 55 | 56 | public function listing ($model, $id) { 57 | $dir = Configure::read('AMU.directory'); 58 | if (strlen($dir) < 1) $dir = "files"; 59 | 60 | $lastDir = $this->last_dir ($model, $id); 61 | $directory = WWW_ROOT . DS . $dir . DS . $lastDir; 62 | $baseUrl = Router::url("/") . $dir . "/" . $lastDir; 63 | $files = glob ("$directory/*"); 64 | return array("baseUrl" => $baseUrl, "directory" => $directory, "files" => $files); 65 | } 66 | 67 | public function edit ($model, $id, $acceptedFiles=null) { 68 | $dir = Configure::read('AMU.directory'); 69 | if ($dir === "") $dir = "files"; 70 | $size = Configure::read ('AMU.filesizeMB'); 71 | if ($size === "") $size = 4; 72 | 73 | $str = $this->view ($model, $id, true); 74 | $webroot = Router::url("/") . "ajax_multi_upload"; 75 | // Replace / with underscores for Ajax controller 76 | $lastDir = str_replace ("/", "___", $this->last_dir ($model, $id)); 77 | if ($acceptedFiles == null) { 78 | $acceptedFilesStr = ""; 79 | } else { 80 | $acceptedFilesStr = "acceptedFiles: \"$acceptedFiles\""; 81 | } 82 | $str .= << 84 | 90 | 91 |
92 | END; 93 | return $str; 94 | } 95 | 96 | // The "last mile" of the directory path for where the files get uploaded 97 | public function last_dir ($model, $id) { 98 | return $model . "/" . $id; 99 | } 100 | 101 | // From http://php.net/manual/en/function.filesize.php 102 | public function format_bytes($size) { 103 | $units = array(' B', ' KB', ' MB', ' GB', ' TB'); 104 | for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024; 105 | return round($size, 2).$units[$i]; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AjaxMultiUpload Plugin for CakePHP 2 | 3 | A full-blown AJAX file uploader plugin for CakePHP 2.0.x and 2.1. 4 | Using this, you can add multiple file upload behaviour to any or all 5 | of your models without having to modify the database or schema. 6 | 7 | You can click on the Upload File button, or drag-and-drop files into 8 | it. You can upload multiple files at a time without having to click 9 | on any button, and it shows you a nice progress notification during 10 | uploads. You can also delete files in edit mode. 11 | 12 | As of May 2015, this now uses Dropzone.js to allow file uploads. 13 | 14 | ## How to Use 15 | 16 | ### Download or checkout 17 | 18 | You can either download the ZIP file: 19 | https://github.com/srs81/CakePHP-AjaxMultiUpload/zipball/master 20 | 21 | or checkout the code (leave the Password field blank): 22 | 23 | ``` 24 | git clone https://srs81@github.com/srs81/CakePHP-AjaxMultiUpload.git 25 | ``` 26 | 27 | ### Put it in the Plugin/ directory 28 | 29 | Unzip or move the contents of this to "Plugin/AjaxMultiUpload" under 30 | the app root. 31 | 32 | ### Add to bootstrap.php load 33 | 34 | Open Config/bootstrap.php and add this line: 35 | 36 | ```php 37 | CakePlugin::load('AjaxMultiUpload', array('bootstrap' => true)); 38 | ``` 39 | 40 | This will allow the plugin to load all the files that it needs including it's own bootstrap. 41 | 42 | ### Create file directory 43 | 44 | Make sure to create the correct files upload directory if it doesn't 45 | exist already: 46 |
 47 | cd cake-app-root
 48 | mkdir webroot/files
 49 | chmod -R 777 webroot/files
 50 | 
51 | 52 | The default upload directory is "files" under /webroot - but this can 53 | be changed (see FAQ below.) 54 | 55 | You don't have to give it a 777 permission - just make sure the web 56 | server user can write to this directory. 57 | 58 | ### Add to controller 59 | 60 | Add to Controller/AppController.php for use in all controllers, or 61 | in just your specific controller where you will use it as below: 62 | 63 | ```php 64 | public $components = array('Session', 'AjaxMultiUpload.Upload'); 65 | ``` 66 | The component will load the required helper automatically so you 67 | don't have to manually load it in your controllers. 68 | 69 | ### Add to views 70 | 71 | Let's say you had a "companies" table with a "id" primary key. 72 | 73 | Add this to your View/Companies/view.ctp: 74 | 75 | ```php 76 | echo $this->Upload->view('Company', $company['Company']['id']); 77 | ``` 78 | 79 | and this to your View/Companies/edit.ctp: 80 | 81 | ```php 82 | echo $this->Upload->edit('Company', $this->Form->fields['Company.id']); 83 | ``` 84 | 85 | ### Custom listing of files 86 | 87 | If you don't like the custom views that result from this->Upload->view(), you can use the listing() function to custom-list files, or use the file listing for other purposes (generating thumbnails, for instance). 88 | 89 | In your view, you can do this: 90 | 91 | ```php 92 | $results = $this->Upload->listing ($model, $id); 93 | 94 | $directory = $results['directory']; 95 | $baseUrl = $results['baseUrl']; 96 | $files = $results['files']; 97 | 98 | foreach ($files as $file) { 99 | $f = basename($file); 100 | $url = $baseUrl . "/$f"; 101 | echo "" . $f . "
\n"; 102 | } 103 | ``` 104 | 105 | and use the directory, baseUrl, and files data structures to display your files. Look at UploadHelper's view() function to see how the listing() function is used internally. 106 | 107 | ### Add to controllers 108 | 109 | Add the following to the delete() function of your Company controller where appropriate (either first line, or right after $this->Company->delete() check): 110 | 111 | ```php 112 | echo $this->Upload->deleteAll('Company', $id); 113 | ``` 114 | 115 | ### Restrict file types to upload 116 | 117 | Add a third parameter to the this->Upload->edit() function, which specifies which types you want to restrict the upload to. 118 | ```php 119 | echo $this->Upload->edit('Company', $this->Form->fields['Company.id'], "audio/*,image/*,.psd,.pdf"); 120 | ``` 121 | 122 | If you don't specify the third parameter, users will be able to upload all file types (so all files types are allowed by default.) 123 | 124 | Documentation on the string to use to specify files / types to upload is in this Stackoverflow answer about Dropzone allowed types: http://stackoverflow.com/a/17275873 125 | 126 | ## Some Gotchas 127 | 128 | Thanks to rscherf@github for the following two fixes. 129 | 130 | #### Using Auth 131 | 132 | If you are using Auth (either the CakePHP core Auth or some of the 133 | compatible or incompatible ones), you need to modify the controller 134 | to allow uploads to work. 135 | 136 | Add these lines to the UploadsController.php (you may have to modify 137 | slightly depending on your Auth setup). Thanks to @notoriousturtle for the fix for CakePHP 2.5 and above. 138 | 139 | ##### CakePHP 2.5 and above 140 | 141 | ```php 142 | public function beforeFilter() { 143 | parent::beforeFilter(); 144 | // Need to disable Security component 145 | $this->Security->unlockedActions = array('upload'); 146 | } 147 | ``` 148 | ##### Before CakePHP 2.5 149 | 150 | ```php 151 | public function isAuthorized() { 152 | return true; 153 | } 154 | 155 | public function beforeFilter() { 156 | $this->Auth->allow(array('upload','delete')); 157 | } 158 | ``` 159 | 160 | #### Subdomain 161 | 162 | If you are using a subdomain, you will have to set up the plugin 163 | correctly to work (depending, again, on how you have your sub-domains 164 | set up in your Apache/htaccess settings). 165 | 166 | These are the changes to be made to routes.php: 167 | ```php 168 | // AJAX Multi Upload plugin 169 | Router::connect('/:subdomain/ajax_multi_upload/:controller', array('plugin' => 'ajax_multi_upload'), $ops); 170 | Router::connect('/:subdomain/ajax_multi_upload/:controller/:action/*', array('plugin' => 'ajax_multi_upload'), $ops); 171 | ``` 172 | 173 | ## FAQ 174 | 175 | #### Dude! No database/table schema changes? 176 | 177 | Nope. :) Just drop this plugin in the right Plugin/ directory and add 178 | the code to the controller and views. Make sure the "files" directory 179 | under webroot is writable, otherwise uploads will fail. 180 | 181 | No tables/database changes are needed since the plugin uses a directory 182 | structure based on the model name and id to save the appropriate files 183 | for the model. 184 | 185 | #### Help! I get file upload or file size error messages! 186 | 187 | The default upload file size limit is set to a conservative 2 MB 188 | to make sure it works on all (including shared) hosting. To change 189 | this: 190 | 191 | * Open up Plugin/AjaxMultipUpload/Config/bootstrap.php and change the 192 | "AMU.filesizeMB" setting to whatever size in MB you like. 193 | * Make sure to also change the upload size setting ( 194 | upload_max_filesize and post_max_size) in your PHP settings ( 195 | php.ini) and reboot the web server! 196 | 197 | #### Change directory 198 | 199 | Are you stuck to the "files" directory under webroot? Nope. 200 | 201 | Open up Config/bootstrap.php under the Plugin/AjaxMultiUpload directory 202 | and change the "AMU.directory" setting. 203 | 204 | The directory will live under the app webroot directory - this is 205 | as per CakePHP conventions. 206 | 207 | #### Change directory paths 208 | 209 | By default, the plugin stores files into /webroot/files/$model/$id . It is possible 210 | to change the /files/ directory through the configuration setting mentioned above. 211 | To change the /$model/$id/ path though (say you want to change it to md5($model . $id)), 212 | look for this line in Controller/Component/UploadComponent.php AND View/Helper/UploadHelper.php: 213 | 214 | ```php 215 | public function last_dir ($model, $id) { 216 | ``` 217 | 218 | Change the function in both these files to do whatever you would like. Note that you have to make 219 | the changes in BOTH files for this to work. 220 | 221 | #### Multiple Uploads in same view/edit 222 | 223 | It is now possible to have multiple view/edit functions in the same CakePHP view. For example, for a Photo controller, add this to your view.ctp: 224 | 225 | ```php 226 | echo $this->Upload->view('Photo', "thumbs/" . $photo['Photo']['id']); 227 | echo $this->Upload->view('Photo', "highres/" . $photo['Photo']['id']); 228 | ``` 229 | 230 | and this to your View/Photos/edit.ctp: 231 | 232 | ```php 233 | echo $this->Upload->edit('Photo', "thumbs/" . $this->Form->fields['Photo.id']); 234 | echo $this->Upload->edit('Photo', "highres/" . $this->Form->fields['Photo.id']); 235 | ``` 236 | 237 | This allows you to upload and two sets of files to your same entity/object in a controller/view. 238 | 239 | ## ChangeLog 240 | 241 | * Version 1.1.1 / Jul 22 2015: you can now restrict file types that can be uploaded 242 | * Version 1.1.0 / May 21 2015: now uses Dropzone.js instead of the older file upload 243 | * Version 1.0.3 / Jul 30 2012: multiple view/edit on same views possible (thanks to bobartlett@github) 244 | * Version 1.0.2 / Jul 16 2012: deleteAll() and listing() functionality added 245 | * Version 1.0.1 / Apr 02 2012: Delete functionality - from view() - added 246 | * Version 1.0.0 / Mar 2012: Initial release 247 | 248 | ## Thanks 249 | 250 | This uses the Dropzone.js Javascript library for file uploads: http://www.dropzonejs.com/ and file icons from: http://www.splitbrain.org/projects/file_icons . (The plugin previously used an Ajax Upload script from: http://valums.com/ajax-upload/) 251 | 252 | Also, thanks to contributions from the following GitHub users: 253 | * @rscherf : Getting it to work with Auth and sub-domains 254 | * @bobartlett : Fix to allow multiple AMU helpers in same view 255 | * @notoriousturtle : Fix to Auth to get it working in CakePHP 2.5 and above 256 | 257 | ## Support 258 | 259 | If you find this plugin useful, please consider a [donation to Shen 260 | Yun Performing Arts](https://www.shenyunperformingarts.org/support) 261 | to support traditional and historic Chinese culture. 262 | 263 | 264 | -------------------------------------------------------------------------------- /webroot/css/dropzone.css: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * Copyright (c) 2012 Matias Meno 4 | */ 5 | @-webkit-keyframes passing-through { 6 | 0% { 7 | opacity: 0; 8 | -webkit-transform: translateY(40px); 9 | -moz-transform: translateY(40px); 10 | -ms-transform: translateY(40px); 11 | -o-transform: translateY(40px); 12 | transform: translateY(40px); } 13 | 30%, 70% { 14 | opacity: 1; 15 | -webkit-transform: translateY(0px); 16 | -moz-transform: translateY(0px); 17 | -ms-transform: translateY(0px); 18 | -o-transform: translateY(0px); 19 | transform: translateY(0px); } 20 | 100% { 21 | opacity: 0; 22 | -webkit-transform: translateY(-40px); 23 | -moz-transform: translateY(-40px); 24 | -ms-transform: translateY(-40px); 25 | -o-transform: translateY(-40px); 26 | transform: translateY(-40px); } } 27 | @-moz-keyframes passing-through { 28 | 0% { 29 | opacity: 0; 30 | -webkit-transform: translateY(40px); 31 | -moz-transform: translateY(40px); 32 | -ms-transform: translateY(40px); 33 | -o-transform: translateY(40px); 34 | transform: translateY(40px); } 35 | 30%, 70% { 36 | opacity: 1; 37 | -webkit-transform: translateY(0px); 38 | -moz-transform: translateY(0px); 39 | -ms-transform: translateY(0px); 40 | -o-transform: translateY(0px); 41 | transform: translateY(0px); } 42 | 100% { 43 | opacity: 0; 44 | -webkit-transform: translateY(-40px); 45 | -moz-transform: translateY(-40px); 46 | -ms-transform: translateY(-40px); 47 | -o-transform: translateY(-40px); 48 | transform: translateY(-40px); } } 49 | @keyframes passing-through { 50 | 0% { 51 | opacity: 0; 52 | -webkit-transform: translateY(40px); 53 | -moz-transform: translateY(40px); 54 | -ms-transform: translateY(40px); 55 | -o-transform: translateY(40px); 56 | transform: translateY(40px); } 57 | 30%, 70% { 58 | opacity: 1; 59 | -webkit-transform: translateY(0px); 60 | -moz-transform: translateY(0px); 61 | -ms-transform: translateY(0px); 62 | -o-transform: translateY(0px); 63 | transform: translateY(0px); } 64 | 100% { 65 | opacity: 0; 66 | -webkit-transform: translateY(-40px); 67 | -moz-transform: translateY(-40px); 68 | -ms-transform: translateY(-40px); 69 | -o-transform: translateY(-40px); 70 | transform: translateY(-40px); } } 71 | @-webkit-keyframes slide-in { 72 | 0% { 73 | opacity: 0; 74 | -webkit-transform: translateY(40px); 75 | -moz-transform: translateY(40px); 76 | -ms-transform: translateY(40px); 77 | -o-transform: translateY(40px); 78 | transform: translateY(40px); } 79 | 30% { 80 | opacity: 1; 81 | -webkit-transform: translateY(0px); 82 | -moz-transform: translateY(0px); 83 | -ms-transform: translateY(0px); 84 | -o-transform: translateY(0px); 85 | transform: translateY(0px); } } 86 | @-moz-keyframes slide-in { 87 | 0% { 88 | opacity: 0; 89 | -webkit-transform: translateY(40px); 90 | -moz-transform: translateY(40px); 91 | -ms-transform: translateY(40px); 92 | -o-transform: translateY(40px); 93 | transform: translateY(40px); } 94 | 30% { 95 | opacity: 1; 96 | -webkit-transform: translateY(0px); 97 | -moz-transform: translateY(0px); 98 | -ms-transform: translateY(0px); 99 | -o-transform: translateY(0px); 100 | transform: translateY(0px); } } 101 | @keyframes slide-in { 102 | 0% { 103 | opacity: 0; 104 | -webkit-transform: translateY(40px); 105 | -moz-transform: translateY(40px); 106 | -ms-transform: translateY(40px); 107 | -o-transform: translateY(40px); 108 | transform: translateY(40px); } 109 | 30% { 110 | opacity: 1; 111 | -webkit-transform: translateY(0px); 112 | -moz-transform: translateY(0px); 113 | -ms-transform: translateY(0px); 114 | -o-transform: translateY(0px); 115 | transform: translateY(0px); } } 116 | @-webkit-keyframes pulse { 117 | 0% { 118 | -webkit-transform: scale(1); 119 | -moz-transform: scale(1); 120 | -ms-transform: scale(1); 121 | -o-transform: scale(1); 122 | transform: scale(1); } 123 | 10% { 124 | -webkit-transform: scale(1.1); 125 | -moz-transform: scale(1.1); 126 | -ms-transform: scale(1.1); 127 | -o-transform: scale(1.1); 128 | transform: scale(1.1); } 129 | 20% { 130 | -webkit-transform: scale(1); 131 | -moz-transform: scale(1); 132 | -ms-transform: scale(1); 133 | -o-transform: scale(1); 134 | transform: scale(1); } } 135 | @-moz-keyframes pulse { 136 | 0% { 137 | -webkit-transform: scale(1); 138 | -moz-transform: scale(1); 139 | -ms-transform: scale(1); 140 | -o-transform: scale(1); 141 | transform: scale(1); } 142 | 10% { 143 | -webkit-transform: scale(1.1); 144 | -moz-transform: scale(1.1); 145 | -ms-transform: scale(1.1); 146 | -o-transform: scale(1.1); 147 | transform: scale(1.1); } 148 | 20% { 149 | -webkit-transform: scale(1); 150 | -moz-transform: scale(1); 151 | -ms-transform: scale(1); 152 | -o-transform: scale(1); 153 | transform: scale(1); } } 154 | @keyframes pulse { 155 | 0% { 156 | -webkit-transform: scale(1); 157 | -moz-transform: scale(1); 158 | -ms-transform: scale(1); 159 | -o-transform: scale(1); 160 | transform: scale(1); } 161 | 10% { 162 | -webkit-transform: scale(1.1); 163 | -moz-transform: scale(1.1); 164 | -ms-transform: scale(1.1); 165 | -o-transform: scale(1.1); 166 | transform: scale(1.1); } 167 | 20% { 168 | -webkit-transform: scale(1); 169 | -moz-transform: scale(1); 170 | -ms-transform: scale(1); 171 | -o-transform: scale(1); 172 | transform: scale(1); } } 173 | .dropzone, .dropzone * { 174 | box-sizing: border-box; } 175 | 176 | .dropzone { 177 | min-height: 150px; 178 | border: 2px solid rgba(0, 0, 0, 0.3); 179 | background: white; 180 | padding: 20px 20px; } 181 | .dropzone.dz-clickable { 182 | cursor: pointer; } 183 | .dropzone.dz-clickable * { 184 | cursor: default; } 185 | .dropzone.dz-clickable .dz-message, .dropzone.dz-clickable .dz-message * { 186 | cursor: pointer; } 187 | .dropzone.dz-started .dz-message { 188 | display: none; } 189 | .dropzone.dz-drag-hover { 190 | border-style: solid; } 191 | .dropzone.dz-drag-hover .dz-message { 192 | opacity: 0.5; } 193 | .dropzone .dz-message { 194 | text-align: center; 195 | margin: 2em 0; } 196 | .dropzone .dz-preview { 197 | position: relative; 198 | display: inline-block; 199 | vertical-align: top; 200 | margin: 16px; 201 | min-height: 100px; } 202 | .dropzone .dz-preview:hover { 203 | z-index: 1000; } 204 | .dropzone .dz-preview:hover .dz-details { 205 | opacity: 1; } 206 | .dropzone .dz-preview.dz-file-preview .dz-image { 207 | border-radius: 20px; 208 | background: #999; 209 | background: linear-gradient(to bottom, #eee, #ddd); } 210 | .dropzone .dz-preview.dz-file-preview .dz-details { 211 | opacity: 1; } 212 | .dropzone .dz-preview.dz-image-preview { 213 | background: white; } 214 | .dropzone .dz-preview.dz-image-preview .dz-details { 215 | -webkit-transition: opacity 0.2s linear; 216 | -moz-transition: opacity 0.2s linear; 217 | -ms-transition: opacity 0.2s linear; 218 | -o-transition: opacity 0.2s linear; 219 | transition: opacity 0.2s linear; } 220 | .dropzone .dz-preview .dz-remove { 221 | font-size: 14px; 222 | text-align: center; 223 | display: block; 224 | cursor: pointer; 225 | border: none; } 226 | .dropzone .dz-preview .dz-remove:hover { 227 | text-decoration: underline; } 228 | .dropzone .dz-preview:hover .dz-details { 229 | opacity: 1; } 230 | .dropzone .dz-preview .dz-details { 231 | z-index: 20; 232 | position: absolute; 233 | top: 0; 234 | left: 0; 235 | opacity: 0; 236 | font-size: 13px; 237 | min-width: 100%; 238 | max-width: 100%; 239 | padding: 2em 1em; 240 | text-align: center; 241 | color: rgba(0, 0, 0, 0.9); 242 | line-height: 150%; } 243 | .dropzone .dz-preview .dz-details .dz-size { 244 | margin-bottom: 1em; 245 | font-size: 16px; } 246 | .dropzone .dz-preview .dz-details .dz-filename { 247 | white-space: nowrap; } 248 | .dropzone .dz-preview .dz-details .dz-filename:hover span { 249 | border: 1px solid rgba(200, 200, 200, 0.8); 250 | background-color: rgba(255, 255, 255, 0.8); } 251 | .dropzone .dz-preview .dz-details .dz-filename:not(:hover) { 252 | overflow: hidden; 253 | text-overflow: ellipsis; } 254 | .dropzone .dz-preview .dz-details .dz-filename:not(:hover) span { 255 | border: 1px solid transparent; } 256 | .dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span { 257 | background-color: rgba(255, 255, 255, 0.4); 258 | padding: 0 0.4em; 259 | border-radius: 3px; } 260 | .dropzone .dz-preview:hover .dz-image img { 261 | -webkit-transform: scale(1.05, 1.05); 262 | -moz-transform: scale(1.05, 1.05); 263 | -ms-transform: scale(1.05, 1.05); 264 | -o-transform: scale(1.05, 1.05); 265 | transform: scale(1.05, 1.05); 266 | -webkit-filter: blur(8px); 267 | filter: blur(8px); } 268 | .dropzone .dz-preview .dz-image { 269 | border-radius: 20px; 270 | overflow: hidden; 271 | width: 120px; 272 | height: 120px; 273 | position: relative; 274 | display: block; 275 | z-index: 10; } 276 | .dropzone .dz-preview .dz-image img { 277 | display: block; } 278 | .dropzone .dz-preview.dz-success .dz-success-mark { 279 | -webkit-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); 280 | -moz-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); 281 | -ms-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); 282 | -o-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); 283 | animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); } 284 | .dropzone .dz-preview.dz-error .dz-error-mark { 285 | opacity: 1; 286 | -webkit-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); 287 | -moz-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); 288 | -ms-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); 289 | -o-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); 290 | animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); } 291 | .dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark { 292 | pointer-events: none; 293 | opacity: 0; 294 | z-index: 500; 295 | position: absolute; 296 | display: block; 297 | top: 50%; 298 | left: 50%; 299 | margin-left: -27px; 300 | margin-top: -27px; } 301 | .dropzone .dz-preview .dz-success-mark svg, .dropzone .dz-preview .dz-error-mark svg { 302 | display: block; 303 | width: 54px; 304 | height: 54px; } 305 | .dropzone .dz-preview.dz-processing .dz-progress { 306 | opacity: 1; 307 | -webkit-transition: all 0.2s linear; 308 | -moz-transition: all 0.2s linear; 309 | -ms-transition: all 0.2s linear; 310 | -o-transition: all 0.2s linear; 311 | transition: all 0.2s linear; } 312 | .dropzone .dz-preview.dz-complete .dz-progress { 313 | opacity: 0; 314 | -webkit-transition: opacity 0.4s ease-in; 315 | -moz-transition: opacity 0.4s ease-in; 316 | -ms-transition: opacity 0.4s ease-in; 317 | -o-transition: opacity 0.4s ease-in; 318 | transition: opacity 0.4s ease-in; } 319 | .dropzone .dz-preview:not(.dz-processing) .dz-progress { 320 | -webkit-animation: pulse 6s ease infinite; 321 | -moz-animation: pulse 6s ease infinite; 322 | -ms-animation: pulse 6s ease infinite; 323 | -o-animation: pulse 6s ease infinite; 324 | animation: pulse 6s ease infinite; } 325 | .dropzone .dz-preview .dz-progress { 326 | opacity: 1; 327 | z-index: 1000; 328 | pointer-events: none; 329 | position: absolute; 330 | height: 16px; 331 | left: 50%; 332 | top: 50%; 333 | margin-top: -8px; 334 | width: 80px; 335 | margin-left: -40px; 336 | background: rgba(255, 255, 255, 0.9); 337 | -webkit-transform: scale(1); 338 | border-radius: 8px; 339 | overflow: hidden; } 340 | .dropzone .dz-preview .dz-progress .dz-upload { 341 | background: #333; 342 | background: linear-gradient(to bottom, #666, #444); 343 | position: absolute; 344 | top: 0; 345 | left: 0; 346 | bottom: 0; 347 | width: 0; 348 | -webkit-transition: width 300ms ease-in-out; 349 | -moz-transition: width 300ms ease-in-out; 350 | -ms-transition: width 300ms ease-in-out; 351 | -o-transition: width 300ms ease-in-out; 352 | transition: width 300ms ease-in-out; } 353 | .dropzone .dz-preview.dz-error .dz-error-message { 354 | display: block; } 355 | .dropzone .dz-preview.dz-error:hover .dz-error-message { 356 | opacity: 1; 357 | pointer-events: auto; } 358 | .dropzone .dz-preview .dz-error-message { 359 | pointer-events: none; 360 | z-index: 1000; 361 | position: absolute; 362 | display: block; 363 | display: none; 364 | opacity: 0; 365 | -webkit-transition: opacity 0.3s ease; 366 | -moz-transition: opacity 0.3s ease; 367 | -ms-transition: opacity 0.3s ease; 368 | -o-transition: opacity 0.3s ease; 369 | transition: opacity 0.3s ease; 370 | border-radius: 8px; 371 | font-size: 13px; 372 | top: 130px; 373 | left: -10px; 374 | width: 140px; 375 | background: #be2626; 376 | background: linear-gradient(to bottom, #be2626, #a92222); 377 | padding: 0.5em 1.2em; 378 | color: white; } 379 | .dropzone .dz-preview .dz-error-message:after { 380 | content: ''; 381 | position: absolute; 382 | top: -6px; 383 | left: 64px; 384 | width: 0; 385 | height: 0; 386 | border-left: 6px solid transparent; 387 | border-right: 6px solid transparent; 388 | border-bottom: 6px solid #be2626; } 389 | -------------------------------------------------------------------------------- /webroot/js/dropzone.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * More info at [www.dropzonejs.com](http://www.dropzonejs.com) 5 | * 6 | * Copyright (c) 2012, Matias Meno 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | * 26 | */ 27 | 28 | (function() { 29 | var Dropzone, Emitter, camelize, contentLoaded, detectVerticalSquash, drawImageIOSFix, noop, without, 30 | __slice = [].slice, 31 | __hasProp = {}.hasOwnProperty, 32 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; 33 | 34 | noop = function() {}; 35 | 36 | Emitter = (function() { 37 | function Emitter() {} 38 | 39 | Emitter.prototype.addEventListener = Emitter.prototype.on; 40 | 41 | Emitter.prototype.on = function(event, fn) { 42 | this._callbacks = this._callbacks || {}; 43 | if (!this._callbacks[event]) { 44 | this._callbacks[event] = []; 45 | } 46 | this._callbacks[event].push(fn); 47 | return this; 48 | }; 49 | 50 | Emitter.prototype.emit = function() { 51 | var args, callback, callbacks, event, _i, _len; 52 | event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 53 | this._callbacks = this._callbacks || {}; 54 | callbacks = this._callbacks[event]; 55 | if (callbacks) { 56 | for (_i = 0, _len = callbacks.length; _i < _len; _i++) { 57 | callback = callbacks[_i]; 58 | callback.apply(this, args); 59 | } 60 | } 61 | return this; 62 | }; 63 | 64 | Emitter.prototype.removeListener = Emitter.prototype.off; 65 | 66 | Emitter.prototype.removeAllListeners = Emitter.prototype.off; 67 | 68 | Emitter.prototype.removeEventListener = Emitter.prototype.off; 69 | 70 | Emitter.prototype.off = function(event, fn) { 71 | var callback, callbacks, i, _i, _len; 72 | if (!this._callbacks || arguments.length === 0) { 73 | this._callbacks = {}; 74 | return this; 75 | } 76 | callbacks = this._callbacks[event]; 77 | if (!callbacks) { 78 | return this; 79 | } 80 | if (arguments.length === 1) { 81 | delete this._callbacks[event]; 82 | return this; 83 | } 84 | for (i = _i = 0, _len = callbacks.length; _i < _len; i = ++_i) { 85 | callback = callbacks[i]; 86 | if (callback === fn) { 87 | callbacks.splice(i, 1); 88 | break; 89 | } 90 | } 91 | return this; 92 | }; 93 | 94 | return Emitter; 95 | 96 | })(); 97 | 98 | Dropzone = (function(_super) { 99 | var extend, resolveOption; 100 | 101 | __extends(Dropzone, _super); 102 | 103 | Dropzone.prototype.Emitter = Emitter; 104 | 105 | 106 | /* 107 | This is a list of all available events you can register on a dropzone object. 108 | 109 | You can register an event handler like this: 110 | 111 | dropzone.on("dragEnter", function() { }); 112 | */ 113 | 114 | Dropzone.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "addedfile", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached", "queuecomplete"]; 115 | 116 | Dropzone.prototype.defaultOptions = { 117 | url: null, 118 | method: "post", 119 | withCredentials: false, 120 | parallelUploads: 2, 121 | uploadMultiple: false, 122 | maxFilesize: 256, 123 | paramName: "file", 124 | createImageThumbnails: true, 125 | maxThumbnailFilesize: 10, 126 | thumbnailWidth: 120, 127 | thumbnailHeight: 120, 128 | filesizeBase: 1000, 129 | maxFiles: null, 130 | filesizeBase: 1000, 131 | params: {}, 132 | clickable: true, 133 | ignoreHiddenFiles: true, 134 | acceptedFiles: null, 135 | acceptedMimeTypes: null, 136 | autoProcessQueue: true, 137 | autoQueue: true, 138 | addRemoveLinks: false, 139 | previewsContainer: null, 140 | capture: null, 141 | dictDefaultMessage: "Drop files here to upload", 142 | dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.", 143 | dictFallbackText: "Please use the fallback form below to upload your files like in the olden days.", 144 | dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.", 145 | dictInvalidFileType: "You can't upload files of this type.", 146 | dictResponseError: "Server responded with {{statusCode}} code.", 147 | dictCancelUpload: "Cancel upload", 148 | dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?", 149 | dictRemoveFile: "Remove file", 150 | dictRemoveFileConfirmation: null, 151 | dictMaxFilesExceeded: "You can not upload any more files.", 152 | accept: function(file, done) { 153 | return done(); 154 | }, 155 | init: function() { 156 | return noop; 157 | }, 158 | forceFallback: false, 159 | fallback: function() { 160 | var child, messageElement, span, _i, _len, _ref; 161 | this.element.className = "" + this.element.className + " dz-browser-not-supported"; 162 | _ref = this.element.getElementsByTagName("div"); 163 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 164 | child = _ref[_i]; 165 | if (/(^| )dz-message($| )/.test(child.className)) { 166 | messageElement = child; 167 | child.className = "dz-message"; 168 | continue; 169 | } 170 | } 171 | if (!messageElement) { 172 | messageElement = Dropzone.createElement("
"); 173 | this.element.appendChild(messageElement); 174 | } 175 | span = messageElement.getElementsByTagName("span")[0]; 176 | if (span) { 177 | span.textContent = this.options.dictFallbackMessage; 178 | } 179 | return this.element.appendChild(this.getFallbackForm()); 180 | }, 181 | resize: function(file) { 182 | var info, srcRatio, trgRatio; 183 | info = { 184 | srcX: 0, 185 | srcY: 0, 186 | srcWidth: file.width, 187 | srcHeight: file.height 188 | }; 189 | srcRatio = file.width / file.height; 190 | info.optWidth = this.options.thumbnailWidth; 191 | info.optHeight = this.options.thumbnailHeight; 192 | if ((info.optWidth == null) && (info.optHeight == null)) { 193 | info.optWidth = info.srcWidth; 194 | info.optHeight = info.srcHeight; 195 | } else if (info.optWidth == null) { 196 | info.optWidth = srcRatio * info.optHeight; 197 | } else if (info.optHeight == null) { 198 | info.optHeight = (1 / srcRatio) * info.optWidth; 199 | } 200 | trgRatio = info.optWidth / info.optHeight; 201 | if (file.height < info.optHeight || file.width < info.optWidth) { 202 | info.trgHeight = info.srcHeight; 203 | info.trgWidth = info.srcWidth; 204 | } else { 205 | if (srcRatio > trgRatio) { 206 | info.srcHeight = file.height; 207 | info.srcWidth = info.srcHeight * trgRatio; 208 | } else { 209 | info.srcWidth = file.width; 210 | info.srcHeight = info.srcWidth / trgRatio; 211 | } 212 | } 213 | info.srcX = (file.width - info.srcWidth) / 2; 214 | info.srcY = (file.height - info.srcHeight) / 2; 215 | return info; 216 | }, 217 | 218 | /* 219 | Those functions register themselves to the events on init and handle all 220 | the user interface specific stuff. Overwriting them won't break the upload 221 | but can break the way it's displayed. 222 | You can overwrite them if you don't like the default behavior. If you just 223 | want to add an additional event handler, register it on the dropzone object 224 | and don't overwrite those options. 225 | */ 226 | drop: function(e) { 227 | return this.element.classList.remove("dz-drag-hover"); 228 | }, 229 | dragstart: noop, 230 | dragend: function(e) { 231 | return this.element.classList.remove("dz-drag-hover"); 232 | }, 233 | dragenter: function(e) { 234 | return this.element.classList.add("dz-drag-hover"); 235 | }, 236 | dragover: function(e) { 237 | return this.element.classList.add("dz-drag-hover"); 238 | }, 239 | dragleave: function(e) { 240 | return this.element.classList.remove("dz-drag-hover"); 241 | }, 242 | paste: noop, 243 | reset: function() { 244 | return this.element.classList.remove("dz-started"); 245 | }, 246 | addedfile: function(file) { 247 | var node, removeFileEvent, removeLink, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results; 248 | if (this.element === this.previewsContainer) { 249 | this.element.classList.add("dz-started"); 250 | } 251 | if (this.previewsContainer) { 252 | file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim()); 253 | file.previewTemplate = file.previewElement; 254 | this.previewsContainer.appendChild(file.previewElement); 255 | _ref = file.previewElement.querySelectorAll("[data-dz-name]"); 256 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 257 | node = _ref[_i]; 258 | node.textContent = file.name; 259 | } 260 | _ref1 = file.previewElement.querySelectorAll("[data-dz-size]"); 261 | for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { 262 | node = _ref1[_j]; 263 | node.innerHTML = this.filesize(file.size); 264 | } 265 | if (this.options.addRemoveLinks) { 266 | file._removeLink = Dropzone.createElement("" + this.options.dictRemoveFile + ""); 267 | file.previewElement.appendChild(file._removeLink); 268 | } 269 | removeFileEvent = (function(_this) { 270 | return function(e) { 271 | e.preventDefault(); 272 | e.stopPropagation(); 273 | if (file.status === Dropzone.UPLOADING) { 274 | return Dropzone.confirm(_this.options.dictCancelUploadConfirmation, function() { 275 | return _this.removeFile(file); 276 | }); 277 | } else { 278 | if (_this.options.dictRemoveFileConfirmation) { 279 | return Dropzone.confirm(_this.options.dictRemoveFileConfirmation, function() { 280 | return _this.removeFile(file); 281 | }); 282 | } else { 283 | return _this.removeFile(file); 284 | } 285 | } 286 | }; 287 | })(this); 288 | _ref2 = file.previewElement.querySelectorAll("[data-dz-remove]"); 289 | _results = []; 290 | for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { 291 | removeLink = _ref2[_k]; 292 | _results.push(removeLink.addEventListener("click", removeFileEvent)); 293 | } 294 | return _results; 295 | } 296 | }, 297 | removedfile: function(file) { 298 | var _ref; 299 | if (file.previewElement) { 300 | if ((_ref = file.previewElement) != null) { 301 | _ref.parentNode.removeChild(file.previewElement); 302 | } 303 | } 304 | return this._updateMaxFilesReachedClass(); 305 | }, 306 | thumbnail: function(file, dataUrl) { 307 | var thumbnailElement, _i, _len, _ref; 308 | if (file.previewElement) { 309 | file.previewElement.classList.remove("dz-file-preview"); 310 | _ref = file.previewElement.querySelectorAll("[data-dz-thumbnail]"); 311 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 312 | thumbnailElement = _ref[_i]; 313 | thumbnailElement.alt = file.name; 314 | thumbnailElement.src = dataUrl; 315 | } 316 | return setTimeout(((function(_this) { 317 | return function() { 318 | return file.previewElement.classList.add("dz-image-preview"); 319 | }; 320 | })(this)), 1); 321 | } 322 | }, 323 | error: function(file, message) { 324 | var node, _i, _len, _ref, _results; 325 | if (file.previewElement) { 326 | file.previewElement.classList.add("dz-error"); 327 | if (typeof message !== "String" && message.error) { 328 | message = message.error; 329 | } 330 | _ref = file.previewElement.querySelectorAll("[data-dz-errormessage]"); 331 | _results = []; 332 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 333 | node = _ref[_i]; 334 | _results.push(node.textContent = message); 335 | } 336 | return _results; 337 | } 338 | }, 339 | errormultiple: noop, 340 | processing: function(file) { 341 | if (file.previewElement) { 342 | file.previewElement.classList.add("dz-processing"); 343 | if (file._removeLink) { 344 | return file._removeLink.textContent = this.options.dictCancelUpload; 345 | } 346 | } 347 | }, 348 | processingmultiple: noop, 349 | uploadprogress: function(file, progress, bytesSent) { 350 | var node, _i, _len, _ref, _results; 351 | if (file.previewElement) { 352 | _ref = file.previewElement.querySelectorAll("[data-dz-uploadprogress]"); 353 | _results = []; 354 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 355 | node = _ref[_i]; 356 | if (node.nodeName === 'PROGRESS') { 357 | _results.push(node.value = progress); 358 | } else { 359 | _results.push(node.style.width = "" + progress + "%"); 360 | } 361 | } 362 | return _results; 363 | } 364 | }, 365 | totaluploadprogress: noop, 366 | sending: noop, 367 | sendingmultiple: noop, 368 | success: function(file) { 369 | if (file.previewElement) { 370 | return file.previewElement.classList.add("dz-success"); 371 | } 372 | }, 373 | successmultiple: noop, 374 | canceled: function(file) { 375 | return this.emit("error", file, "Upload canceled."); 376 | }, 377 | canceledmultiple: noop, 378 | complete: function(file) { 379 | if (file._removeLink) { 380 | file._removeLink.textContent = this.options.dictRemoveFile; 381 | } 382 | if (file.previewElement) { 383 | return file.previewElement.classList.add("dz-complete"); 384 | } 385 | }, 386 | completemultiple: noop, 387 | maxfilesexceeded: noop, 388 | maxfilesreached: noop, 389 | queuecomplete: noop, 390 | previewTemplate: "
\n
\n
\n
\n
\n
\n
\n
\n
\n \n Check\n \n \n \n \n \n
\n
\n \n Error\n \n \n \n \n \n \n \n
\n
" 391 | }; 392 | 393 | extend = function() { 394 | var key, object, objects, target, val, _i, _len; 395 | target = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 396 | for (_i = 0, _len = objects.length; _i < _len; _i++) { 397 | object = objects[_i]; 398 | for (key in object) { 399 | val = object[key]; 400 | target[key] = val; 401 | } 402 | } 403 | return target; 404 | }; 405 | 406 | function Dropzone(element, options) { 407 | var elementOptions, fallback, _ref; 408 | this.element = element; 409 | this.version = Dropzone.version; 410 | this.defaultOptions.previewTemplate = this.defaultOptions.previewTemplate.replace(/\n*/g, ""); 411 | this.clickableElements = []; 412 | this.listeners = []; 413 | this.files = []; 414 | if (typeof this.element === "string") { 415 | this.element = document.querySelector(this.element); 416 | } 417 | if (!(this.element && (this.element.nodeType != null))) { 418 | throw new Error("Invalid dropzone element."); 419 | } 420 | if (this.element.dropzone) { 421 | throw new Error("Dropzone already attached."); 422 | } 423 | Dropzone.instances.push(this); 424 | this.element.dropzone = this; 425 | elementOptions = (_ref = Dropzone.optionsForElement(this.element)) != null ? _ref : {}; 426 | this.options = extend({}, this.defaultOptions, elementOptions, options != null ? options : {}); 427 | if (this.options.forceFallback || !Dropzone.isBrowserSupported()) { 428 | return this.options.fallback.call(this); 429 | } 430 | if (this.options.url == null) { 431 | this.options.url = this.element.getAttribute("action"); 432 | } 433 | if (!this.options.url) { 434 | throw new Error("No URL provided."); 435 | } 436 | if (this.options.acceptedFiles && this.options.acceptedMimeTypes) { 437 | throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated."); 438 | } 439 | if (this.options.acceptedMimeTypes) { 440 | this.options.acceptedFiles = this.options.acceptedMimeTypes; 441 | delete this.options.acceptedMimeTypes; 442 | } 443 | this.options.method = this.options.method.toUpperCase(); 444 | if ((fallback = this.getExistingFallback()) && fallback.parentNode) { 445 | fallback.parentNode.removeChild(fallback); 446 | } 447 | if (this.options.previewsContainer !== false) { 448 | if (this.options.previewsContainer) { 449 | this.previewsContainer = Dropzone.getElement(this.options.previewsContainer, "previewsContainer"); 450 | } else { 451 | this.previewsContainer = this.element; 452 | } 453 | } 454 | if (this.options.clickable) { 455 | if (this.options.clickable === true) { 456 | this.clickableElements = [this.element]; 457 | } else { 458 | this.clickableElements = Dropzone.getElements(this.options.clickable, "clickable"); 459 | } 460 | } 461 | this.init(); 462 | } 463 | 464 | Dropzone.prototype.getAcceptedFiles = function() { 465 | var file, _i, _len, _ref, _results; 466 | _ref = this.files; 467 | _results = []; 468 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 469 | file = _ref[_i]; 470 | if (file.accepted) { 471 | _results.push(file); 472 | } 473 | } 474 | return _results; 475 | }; 476 | 477 | Dropzone.prototype.getRejectedFiles = function() { 478 | var file, _i, _len, _ref, _results; 479 | _ref = this.files; 480 | _results = []; 481 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 482 | file = _ref[_i]; 483 | if (!file.accepted) { 484 | _results.push(file); 485 | } 486 | } 487 | return _results; 488 | }; 489 | 490 | Dropzone.prototype.getFilesWithStatus = function(status) { 491 | var file, _i, _len, _ref, _results; 492 | _ref = this.files; 493 | _results = []; 494 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 495 | file = _ref[_i]; 496 | if (file.status === status) { 497 | _results.push(file); 498 | } 499 | } 500 | return _results; 501 | }; 502 | 503 | Dropzone.prototype.getQueuedFiles = function() { 504 | return this.getFilesWithStatus(Dropzone.QUEUED); 505 | }; 506 | 507 | Dropzone.prototype.getUploadingFiles = function() { 508 | return this.getFilesWithStatus(Dropzone.UPLOADING); 509 | }; 510 | 511 | Dropzone.prototype.getActiveFiles = function() { 512 | var file, _i, _len, _ref, _results; 513 | _ref = this.files; 514 | _results = []; 515 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 516 | file = _ref[_i]; 517 | if (file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED) { 518 | _results.push(file); 519 | } 520 | } 521 | return _results; 522 | }; 523 | 524 | Dropzone.prototype.init = function() { 525 | var eventName, noPropagation, setupHiddenFileInput, _i, _len, _ref, _ref1; 526 | if (this.element.tagName === "form") { 527 | this.element.setAttribute("enctype", "multipart/form-data"); 528 | } 529 | if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) { 530 | this.element.appendChild(Dropzone.createElement("
" + this.options.dictDefaultMessage + "
")); 531 | } 532 | if (this.clickableElements.length) { 533 | setupHiddenFileInput = (function(_this) { 534 | return function() { 535 | if (_this.hiddenFileInput) { 536 | document.body.removeChild(_this.hiddenFileInput); 537 | } 538 | _this.hiddenFileInput = document.createElement("input"); 539 | _this.hiddenFileInput.setAttribute("type", "file"); 540 | if ((_this.options.maxFiles == null) || _this.options.maxFiles > 1) { 541 | _this.hiddenFileInput.setAttribute("multiple", "multiple"); 542 | } 543 | _this.hiddenFileInput.className = "dz-hidden-input"; 544 | if (_this.options.acceptedFiles != null) { 545 | _this.hiddenFileInput.setAttribute("accept", _this.options.acceptedFiles); 546 | } 547 | if (_this.options.capture != null) { 548 | _this.hiddenFileInput.setAttribute("capture", _this.options.capture); 549 | } 550 | _this.hiddenFileInput.style.visibility = "hidden"; 551 | _this.hiddenFileInput.style.position = "absolute"; 552 | _this.hiddenFileInput.style.top = "0"; 553 | _this.hiddenFileInput.style.left = "0"; 554 | _this.hiddenFileInput.style.height = "0"; 555 | _this.hiddenFileInput.style.width = "0"; 556 | document.body.appendChild(_this.hiddenFileInput); 557 | return _this.hiddenFileInput.addEventListener("change", function() { 558 | var file, files, _i, _len; 559 | files = _this.hiddenFileInput.files; 560 | if (files.length) { 561 | for (_i = 0, _len = files.length; _i < _len; _i++) { 562 | file = files[_i]; 563 | _this.addFile(file); 564 | } 565 | } 566 | return setupHiddenFileInput(); 567 | }); 568 | }; 569 | })(this); 570 | setupHiddenFileInput(); 571 | } 572 | this.URL = (_ref = window.URL) != null ? _ref : window.webkitURL; 573 | _ref1 = this.events; 574 | for (_i = 0, _len = _ref1.length; _i < _len; _i++) { 575 | eventName = _ref1[_i]; 576 | this.on(eventName, this.options[eventName]); 577 | } 578 | this.on("uploadprogress", (function(_this) { 579 | return function() { 580 | return _this.updateTotalUploadProgress(); 581 | }; 582 | })(this)); 583 | this.on("removedfile", (function(_this) { 584 | return function() { 585 | return _this.updateTotalUploadProgress(); 586 | }; 587 | })(this)); 588 | this.on("canceled", (function(_this) { 589 | return function(file) { 590 | return _this.emit("complete", file); 591 | }; 592 | })(this)); 593 | this.on("complete", (function(_this) { 594 | return function(file) { 595 | if (_this.getUploadingFiles().length === 0 && _this.getQueuedFiles().length === 0) { 596 | return setTimeout((function() { 597 | return _this.emit("queuecomplete"); 598 | }), 0); 599 | } 600 | }; 601 | })(this)); 602 | noPropagation = function(e) { 603 | e.stopPropagation(); 604 | if (e.preventDefault) { 605 | return e.preventDefault(); 606 | } else { 607 | return e.returnValue = false; 608 | } 609 | }; 610 | this.listeners = [ 611 | { 612 | element: this.element, 613 | events: { 614 | "dragstart": (function(_this) { 615 | return function(e) { 616 | return _this.emit("dragstart", e); 617 | }; 618 | })(this), 619 | "dragenter": (function(_this) { 620 | return function(e) { 621 | noPropagation(e); 622 | return _this.emit("dragenter", e); 623 | }; 624 | })(this), 625 | "dragover": (function(_this) { 626 | return function(e) { 627 | var efct; 628 | try { 629 | efct = e.dataTransfer.effectAllowed; 630 | } catch (_error) {} 631 | e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy'; 632 | noPropagation(e); 633 | return _this.emit("dragover", e); 634 | }; 635 | })(this), 636 | "dragleave": (function(_this) { 637 | return function(e) { 638 | return _this.emit("dragleave", e); 639 | }; 640 | })(this), 641 | "drop": (function(_this) { 642 | return function(e) { 643 | noPropagation(e); 644 | return _this.drop(e); 645 | }; 646 | })(this), 647 | "dragend": (function(_this) { 648 | return function(e) { 649 | return _this.emit("dragend", e); 650 | }; 651 | })(this) 652 | } 653 | } 654 | ]; 655 | this.clickableElements.forEach((function(_this) { 656 | return function(clickableElement) { 657 | return _this.listeners.push({ 658 | element: clickableElement, 659 | events: { 660 | "click": function(evt) { 661 | if ((clickableElement !== _this.element) || (evt.target === _this.element || Dropzone.elementInside(evt.target, _this.element.querySelector(".dz-message")))) { 662 | return _this.hiddenFileInput.click(); 663 | } 664 | } 665 | } 666 | }); 667 | }; 668 | })(this)); 669 | this.enable(); 670 | return this.options.init.call(this); 671 | }; 672 | 673 | Dropzone.prototype.destroy = function() { 674 | var _ref; 675 | this.disable(); 676 | this.removeAllFiles(true); 677 | if ((_ref = this.hiddenFileInput) != null ? _ref.parentNode : void 0) { 678 | this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput); 679 | this.hiddenFileInput = null; 680 | } 681 | delete this.element.dropzone; 682 | return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1); 683 | }; 684 | 685 | Dropzone.prototype.updateTotalUploadProgress = function() { 686 | var activeFiles, file, totalBytes, totalBytesSent, totalUploadProgress, _i, _len, _ref; 687 | totalBytesSent = 0; 688 | totalBytes = 0; 689 | activeFiles = this.getActiveFiles(); 690 | if (activeFiles.length) { 691 | _ref = this.getActiveFiles(); 692 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 693 | file = _ref[_i]; 694 | totalBytesSent += file.upload.bytesSent; 695 | totalBytes += file.upload.total; 696 | } 697 | totalUploadProgress = 100 * totalBytesSent / totalBytes; 698 | } else { 699 | totalUploadProgress = 100; 700 | } 701 | return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent); 702 | }; 703 | 704 | Dropzone.prototype._getParamName = function(n) { 705 | if (typeof this.options.paramName === "function") { 706 | return this.options.paramName(n); 707 | } else { 708 | return "" + this.options.paramName + (this.options.uploadMultiple ? "[" + n + "]" : ""); 709 | } 710 | }; 711 | 712 | Dropzone.prototype.getFallbackForm = function() { 713 | var existingFallback, fields, fieldsString, form; 714 | if (existingFallback = this.getExistingFallback()) { 715 | return existingFallback; 716 | } 717 | fieldsString = "
"; 718 | if (this.options.dictFallbackText) { 719 | fieldsString += "

" + this.options.dictFallbackText + "

"; 720 | } 721 | fieldsString += "
"; 722 | fields = Dropzone.createElement(fieldsString); 723 | if (this.element.tagName !== "FORM") { 724 | form = Dropzone.createElement("
"); 725 | form.appendChild(fields); 726 | } else { 727 | this.element.setAttribute("enctype", "multipart/form-data"); 728 | this.element.setAttribute("method", this.options.method); 729 | } 730 | return form != null ? form : fields; 731 | }; 732 | 733 | Dropzone.prototype.getExistingFallback = function() { 734 | var fallback, getFallback, tagName, _i, _len, _ref; 735 | getFallback = function(elements) { 736 | var el, _i, _len; 737 | for (_i = 0, _len = elements.length; _i < _len; _i++) { 738 | el = elements[_i]; 739 | if (/(^| )fallback($| )/.test(el.className)) { 740 | return el; 741 | } 742 | } 743 | }; 744 | _ref = ["div", "form"]; 745 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 746 | tagName = _ref[_i]; 747 | if (fallback = getFallback(this.element.getElementsByTagName(tagName))) { 748 | return fallback; 749 | } 750 | } 751 | }; 752 | 753 | Dropzone.prototype.setupEventListeners = function() { 754 | var elementListeners, event, listener, _i, _len, _ref, _results; 755 | _ref = this.listeners; 756 | _results = []; 757 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 758 | elementListeners = _ref[_i]; 759 | _results.push((function() { 760 | var _ref1, _results1; 761 | _ref1 = elementListeners.events; 762 | _results1 = []; 763 | for (event in _ref1) { 764 | listener = _ref1[event]; 765 | _results1.push(elementListeners.element.addEventListener(event, listener, false)); 766 | } 767 | return _results1; 768 | })()); 769 | } 770 | return _results; 771 | }; 772 | 773 | Dropzone.prototype.removeEventListeners = function() { 774 | var elementListeners, event, listener, _i, _len, _ref, _results; 775 | _ref = this.listeners; 776 | _results = []; 777 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 778 | elementListeners = _ref[_i]; 779 | _results.push((function() { 780 | var _ref1, _results1; 781 | _ref1 = elementListeners.events; 782 | _results1 = []; 783 | for (event in _ref1) { 784 | listener = _ref1[event]; 785 | _results1.push(elementListeners.element.removeEventListener(event, listener, false)); 786 | } 787 | return _results1; 788 | })()); 789 | } 790 | return _results; 791 | }; 792 | 793 | Dropzone.prototype.disable = function() { 794 | var file, _i, _len, _ref, _results; 795 | this.clickableElements.forEach(function(element) { 796 | return element.classList.remove("dz-clickable"); 797 | }); 798 | this.removeEventListeners(); 799 | _ref = this.files; 800 | _results = []; 801 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 802 | file = _ref[_i]; 803 | _results.push(this.cancelUpload(file)); 804 | } 805 | return _results; 806 | }; 807 | 808 | Dropzone.prototype.enable = function() { 809 | this.clickableElements.forEach(function(element) { 810 | return element.classList.add("dz-clickable"); 811 | }); 812 | return this.setupEventListeners(); 813 | }; 814 | 815 | Dropzone.prototype.filesize = function(size) { 816 | var cutoff, i, selectedSize, selectedUnit, unit, units, _i, _len; 817 | units = ['TB', 'GB', 'MB', 'KB', 'b']; 818 | selectedSize = selectedUnit = null; 819 | for (i = _i = 0, _len = units.length; _i < _len; i = ++_i) { 820 | unit = units[i]; 821 | cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10; 822 | if (size >= cutoff) { 823 | selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i); 824 | selectedUnit = unit; 825 | break; 826 | } 827 | } 828 | selectedSize = Math.round(10 * selectedSize) / 10; 829 | return "" + selectedSize + " " + selectedUnit; 830 | }; 831 | 832 | Dropzone.prototype._updateMaxFilesReachedClass = function() { 833 | if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) { 834 | if (this.getAcceptedFiles().length === this.options.maxFiles) { 835 | this.emit('maxfilesreached', this.files); 836 | } 837 | return this.element.classList.add("dz-max-files-reached"); 838 | } else { 839 | return this.element.classList.remove("dz-max-files-reached"); 840 | } 841 | }; 842 | 843 | Dropzone.prototype.drop = function(e) { 844 | var files, items; 845 | if (!e.dataTransfer) { 846 | return; 847 | } 848 | this.emit("drop", e); 849 | files = e.dataTransfer.files; 850 | if (files.length) { 851 | items = e.dataTransfer.items; 852 | if (items && items.length && (items[0].webkitGetAsEntry != null)) { 853 | this._addFilesFromItems(items); 854 | } else { 855 | this.handleFiles(files); 856 | } 857 | } 858 | }; 859 | 860 | Dropzone.prototype.paste = function(e) { 861 | var items, _ref; 862 | if ((e != null ? (_ref = e.clipboardData) != null ? _ref.items : void 0 : void 0) == null) { 863 | return; 864 | } 865 | this.emit("paste", e); 866 | items = e.clipboardData.items; 867 | if (items.length) { 868 | return this._addFilesFromItems(items); 869 | } 870 | }; 871 | 872 | Dropzone.prototype.handleFiles = function(files) { 873 | var file, _i, _len, _results; 874 | _results = []; 875 | for (_i = 0, _len = files.length; _i < _len; _i++) { 876 | file = files[_i]; 877 | _results.push(this.addFile(file)); 878 | } 879 | return _results; 880 | }; 881 | 882 | Dropzone.prototype._addFilesFromItems = function(items) { 883 | var entry, item, _i, _len, _results; 884 | _results = []; 885 | for (_i = 0, _len = items.length; _i < _len; _i++) { 886 | item = items[_i]; 887 | if ((item.webkitGetAsEntry != null) && (entry = item.webkitGetAsEntry())) { 888 | if (entry.isFile) { 889 | _results.push(this.addFile(item.getAsFile())); 890 | } else if (entry.isDirectory) { 891 | _results.push(this._addFilesFromDirectory(entry, entry.name)); 892 | } else { 893 | _results.push(void 0); 894 | } 895 | } else if (item.getAsFile != null) { 896 | if ((item.kind == null) || item.kind === "file") { 897 | _results.push(this.addFile(item.getAsFile())); 898 | } else { 899 | _results.push(void 0); 900 | } 901 | } else { 902 | _results.push(void 0); 903 | } 904 | } 905 | return _results; 906 | }; 907 | 908 | Dropzone.prototype._addFilesFromDirectory = function(directory, path) { 909 | var dirReader, entriesReader; 910 | dirReader = directory.createReader(); 911 | entriesReader = (function(_this) { 912 | return function(entries) { 913 | var entry, _i, _len; 914 | for (_i = 0, _len = entries.length; _i < _len; _i++) { 915 | entry = entries[_i]; 916 | if (entry.isFile) { 917 | entry.file(function(file) { 918 | if (_this.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') { 919 | return; 920 | } 921 | file.fullPath = "" + path + "/" + file.name; 922 | return _this.addFile(file); 923 | }); 924 | } else if (entry.isDirectory) { 925 | _this._addFilesFromDirectory(entry, "" + path + "/" + entry.name); 926 | } 927 | } 928 | }; 929 | })(this); 930 | return dirReader.readEntries(entriesReader, function(error) { 931 | return typeof console !== "undefined" && console !== null ? typeof console.log === "function" ? console.log(error) : void 0 : void 0; 932 | }); 933 | }; 934 | 935 | Dropzone.prototype.accept = function(file, done) { 936 | if (file.size > this.options.maxFilesize * 1024 * 1024) { 937 | return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize)); 938 | } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) { 939 | return done(this.options.dictInvalidFileType); 940 | } else if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) { 941 | done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles)); 942 | return this.emit("maxfilesexceeded", file); 943 | } else { 944 | return this.options.accept.call(this, file, done); 945 | } 946 | }; 947 | 948 | Dropzone.prototype.addFile = function(file) { 949 | file.upload = { 950 | progress: 0, 951 | total: file.size, 952 | bytesSent: 0 953 | }; 954 | this.files.push(file); 955 | file.status = Dropzone.ADDED; 956 | this.emit("addedfile", file); 957 | this._enqueueThumbnail(file); 958 | return this.accept(file, (function(_this) { 959 | return function(error) { 960 | if (error) { 961 | file.accepted = false; 962 | _this._errorProcessing([file], error); 963 | } else { 964 | file.accepted = true; 965 | if (_this.options.autoQueue) { 966 | _this.enqueueFile(file); 967 | } 968 | } 969 | return _this._updateMaxFilesReachedClass(); 970 | }; 971 | })(this)); 972 | }; 973 | 974 | Dropzone.prototype.enqueueFiles = function(files) { 975 | var file, _i, _len; 976 | for (_i = 0, _len = files.length; _i < _len; _i++) { 977 | file = files[_i]; 978 | this.enqueueFile(file); 979 | } 980 | return null; 981 | }; 982 | 983 | Dropzone.prototype.enqueueFile = function(file) { 984 | if (file.status === Dropzone.ADDED && file.accepted === true) { 985 | file.status = Dropzone.QUEUED; 986 | if (this.options.autoProcessQueue) { 987 | return setTimeout(((function(_this) { 988 | return function() { 989 | return _this.processQueue(); 990 | }; 991 | })(this)), 0); 992 | } 993 | } else { 994 | throw new Error("This file can't be queued because it has already been processed or was rejected."); 995 | } 996 | }; 997 | 998 | Dropzone.prototype._thumbnailQueue = []; 999 | 1000 | Dropzone.prototype._processingThumbnail = false; 1001 | 1002 | Dropzone.prototype._enqueueThumbnail = function(file) { 1003 | if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) { 1004 | this._thumbnailQueue.push(file); 1005 | return setTimeout(((function(_this) { 1006 | return function() { 1007 | return _this._processThumbnailQueue(); 1008 | }; 1009 | })(this)), 0); 1010 | } 1011 | }; 1012 | 1013 | Dropzone.prototype._processThumbnailQueue = function() { 1014 | if (this._processingThumbnail || this._thumbnailQueue.length === 0) { 1015 | return; 1016 | } 1017 | this._processingThumbnail = true; 1018 | return this.createThumbnail(this._thumbnailQueue.shift(), (function(_this) { 1019 | return function() { 1020 | _this._processingThumbnail = false; 1021 | return _this._processThumbnailQueue(); 1022 | }; 1023 | })(this)); 1024 | }; 1025 | 1026 | Dropzone.prototype.removeFile = function(file) { 1027 | if (file.status === Dropzone.UPLOADING) { 1028 | this.cancelUpload(file); 1029 | } 1030 | this.files = without(this.files, file); 1031 | this.emit("removedfile", file); 1032 | if (this.files.length === 0) { 1033 | return this.emit("reset"); 1034 | } 1035 | }; 1036 | 1037 | Dropzone.prototype.removeAllFiles = function(cancelIfNecessary) { 1038 | var file, _i, _len, _ref; 1039 | if (cancelIfNecessary == null) { 1040 | cancelIfNecessary = false; 1041 | } 1042 | _ref = this.files.slice(); 1043 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 1044 | file = _ref[_i]; 1045 | if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) { 1046 | this.removeFile(file); 1047 | } 1048 | } 1049 | return null; 1050 | }; 1051 | 1052 | Dropzone.prototype.createThumbnail = function(file, callback) { 1053 | var fileReader; 1054 | fileReader = new FileReader; 1055 | fileReader.onload = (function(_this) { 1056 | return function() { 1057 | if (file.type === "image/svg+xml") { 1058 | _this.emit("thumbnail", file, fileReader.result); 1059 | if (callback != null) { 1060 | callback(); 1061 | } 1062 | return; 1063 | } 1064 | return _this.createThumbnailFromUrl(file, fileReader.result, callback); 1065 | }; 1066 | })(this); 1067 | return fileReader.readAsDataURL(file); 1068 | }; 1069 | 1070 | Dropzone.prototype.createThumbnailFromUrl = function(file, imageUrl, callback) { 1071 | var img; 1072 | img = document.createElement("img"); 1073 | img.onload = (function(_this) { 1074 | return function() { 1075 | var canvas, ctx, resizeInfo, thumbnail, _ref, _ref1, _ref2, _ref3; 1076 | file.width = img.width; 1077 | file.height = img.height; 1078 | resizeInfo = _this.options.resize.call(_this, file); 1079 | if (resizeInfo.trgWidth == null) { 1080 | resizeInfo.trgWidth = resizeInfo.optWidth; 1081 | } 1082 | if (resizeInfo.trgHeight == null) { 1083 | resizeInfo.trgHeight = resizeInfo.optHeight; 1084 | } 1085 | canvas = document.createElement("canvas"); 1086 | ctx = canvas.getContext("2d"); 1087 | canvas.width = resizeInfo.trgWidth; 1088 | canvas.height = resizeInfo.trgHeight; 1089 | drawImageIOSFix(ctx, img, (_ref = resizeInfo.srcX) != null ? _ref : 0, (_ref1 = resizeInfo.srcY) != null ? _ref1 : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, (_ref2 = resizeInfo.trgX) != null ? _ref2 : 0, (_ref3 = resizeInfo.trgY) != null ? _ref3 : 0, resizeInfo.trgWidth, resizeInfo.trgHeight); 1090 | thumbnail = canvas.toDataURL("image/png"); 1091 | _this.emit("thumbnail", file, thumbnail); 1092 | if (callback != null) { 1093 | return callback(); 1094 | } 1095 | }; 1096 | })(this); 1097 | if (callback != null) { 1098 | img.onerror = callback; 1099 | } 1100 | return img.src = imageUrl; 1101 | }; 1102 | 1103 | Dropzone.prototype.processQueue = function() { 1104 | var i, parallelUploads, processingLength, queuedFiles; 1105 | parallelUploads = this.options.parallelUploads; 1106 | processingLength = this.getUploadingFiles().length; 1107 | i = processingLength; 1108 | if (processingLength >= parallelUploads) { 1109 | return; 1110 | } 1111 | queuedFiles = this.getQueuedFiles(); 1112 | if (!(queuedFiles.length > 0)) { 1113 | return; 1114 | } 1115 | if (this.options.uploadMultiple) { 1116 | return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength)); 1117 | } else { 1118 | while (i < parallelUploads) { 1119 | if (!queuedFiles.length) { 1120 | return; 1121 | } 1122 | this.processFile(queuedFiles.shift()); 1123 | i++; 1124 | } 1125 | } 1126 | }; 1127 | 1128 | Dropzone.prototype.processFile = function(file) { 1129 | return this.processFiles([file]); 1130 | }; 1131 | 1132 | Dropzone.prototype.processFiles = function(files) { 1133 | var file, _i, _len; 1134 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1135 | file = files[_i]; 1136 | file.processing = true; 1137 | file.status = Dropzone.UPLOADING; 1138 | this.emit("processing", file); 1139 | } 1140 | if (this.options.uploadMultiple) { 1141 | this.emit("processingmultiple", files); 1142 | } 1143 | return this.uploadFiles(files); 1144 | }; 1145 | 1146 | Dropzone.prototype._getFilesWithXhr = function(xhr) { 1147 | var file, files; 1148 | return files = (function() { 1149 | var _i, _len, _ref, _results; 1150 | _ref = this.files; 1151 | _results = []; 1152 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 1153 | file = _ref[_i]; 1154 | if (file.xhr === xhr) { 1155 | _results.push(file); 1156 | } 1157 | } 1158 | return _results; 1159 | }).call(this); 1160 | }; 1161 | 1162 | Dropzone.prototype.cancelUpload = function(file) { 1163 | var groupedFile, groupedFiles, _i, _j, _len, _len1, _ref; 1164 | if (file.status === Dropzone.UPLOADING) { 1165 | groupedFiles = this._getFilesWithXhr(file.xhr); 1166 | for (_i = 0, _len = groupedFiles.length; _i < _len; _i++) { 1167 | groupedFile = groupedFiles[_i]; 1168 | groupedFile.status = Dropzone.CANCELED; 1169 | } 1170 | file.xhr.abort(); 1171 | for (_j = 0, _len1 = groupedFiles.length; _j < _len1; _j++) { 1172 | groupedFile = groupedFiles[_j]; 1173 | this.emit("canceled", groupedFile); 1174 | } 1175 | if (this.options.uploadMultiple) { 1176 | this.emit("canceledmultiple", groupedFiles); 1177 | } 1178 | } else if ((_ref = file.status) === Dropzone.ADDED || _ref === Dropzone.QUEUED) { 1179 | file.status = Dropzone.CANCELED; 1180 | this.emit("canceled", file); 1181 | if (this.options.uploadMultiple) { 1182 | this.emit("canceledmultiple", [file]); 1183 | } 1184 | } 1185 | if (this.options.autoProcessQueue) { 1186 | return this.processQueue(); 1187 | } 1188 | }; 1189 | 1190 | resolveOption = function() { 1191 | var args, option; 1192 | option = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 1193 | if (typeof option === 'function') { 1194 | return option.apply(this, args); 1195 | } 1196 | return option; 1197 | }; 1198 | 1199 | Dropzone.prototype.uploadFile = function(file) { 1200 | return this.uploadFiles([file]); 1201 | }; 1202 | 1203 | Dropzone.prototype.uploadFiles = function(files) { 1204 | var file, formData, handleError, headerName, headerValue, headers, i, input, inputName, inputType, key, method, option, progressObj, response, updateProgress, url, value, xhr, _i, _j, _k, _l, _len, _len1, _len2, _len3, _m, _ref, _ref1, _ref2, _ref3, _ref4, _ref5; 1205 | xhr = new XMLHttpRequest(); 1206 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1207 | file = files[_i]; 1208 | file.xhr = xhr; 1209 | } 1210 | method = resolveOption(this.options.method, files); 1211 | url = resolveOption(this.options.url, files); 1212 | xhr.open(method, url, true); 1213 | xhr.withCredentials = !!this.options.withCredentials; 1214 | response = null; 1215 | handleError = (function(_this) { 1216 | return function() { 1217 | var _j, _len1, _results; 1218 | _results = []; 1219 | for (_j = 0, _len1 = files.length; _j < _len1; _j++) { 1220 | file = files[_j]; 1221 | _results.push(_this._errorProcessing(files, response || _this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr)); 1222 | } 1223 | return _results; 1224 | }; 1225 | })(this); 1226 | updateProgress = (function(_this) { 1227 | return function(e) { 1228 | var allFilesFinished, progress, _j, _k, _l, _len1, _len2, _len3, _results; 1229 | if (e != null) { 1230 | progress = 100 * e.loaded / e.total; 1231 | for (_j = 0, _len1 = files.length; _j < _len1; _j++) { 1232 | file = files[_j]; 1233 | file.upload = { 1234 | progress: progress, 1235 | total: e.total, 1236 | bytesSent: e.loaded 1237 | }; 1238 | } 1239 | } else { 1240 | allFilesFinished = true; 1241 | progress = 100; 1242 | for (_k = 0, _len2 = files.length; _k < _len2; _k++) { 1243 | file = files[_k]; 1244 | if (!(file.upload.progress === 100 && file.upload.bytesSent === file.upload.total)) { 1245 | allFilesFinished = false; 1246 | } 1247 | file.upload.progress = progress; 1248 | file.upload.bytesSent = file.upload.total; 1249 | } 1250 | if (allFilesFinished) { 1251 | return; 1252 | } 1253 | } 1254 | _results = []; 1255 | for (_l = 0, _len3 = files.length; _l < _len3; _l++) { 1256 | file = files[_l]; 1257 | _results.push(_this.emit("uploadprogress", file, progress, file.upload.bytesSent)); 1258 | } 1259 | return _results; 1260 | }; 1261 | })(this); 1262 | xhr.onload = (function(_this) { 1263 | return function(e) { 1264 | var _ref; 1265 | if (files[0].status === Dropzone.CANCELED) { 1266 | return; 1267 | } 1268 | if (xhr.readyState !== 4) { 1269 | return; 1270 | } 1271 | response = xhr.responseText; 1272 | if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) { 1273 | try { 1274 | response = JSON.parse(response); 1275 | } catch (_error) { 1276 | e = _error; 1277 | response = "Invalid JSON response from server."; 1278 | } 1279 | } 1280 | updateProgress(); 1281 | if (!((200 <= (_ref = xhr.status) && _ref < 300))) { 1282 | return handleError(); 1283 | } else { 1284 | return _this._finished(files, response, e); 1285 | } 1286 | }; 1287 | })(this); 1288 | xhr.onerror = (function(_this) { 1289 | return function() { 1290 | if (files[0].status === Dropzone.CANCELED) { 1291 | return; 1292 | } 1293 | return handleError(); 1294 | }; 1295 | })(this); 1296 | progressObj = (_ref = xhr.upload) != null ? _ref : xhr; 1297 | progressObj.onprogress = updateProgress; 1298 | headers = { 1299 | "Accept": "application/json", 1300 | "Cache-Control": "no-cache", 1301 | "X-Requested-With": "XMLHttpRequest" 1302 | }; 1303 | if (this.options.headers) { 1304 | extend(headers, this.options.headers); 1305 | } 1306 | for (headerName in headers) { 1307 | headerValue = headers[headerName]; 1308 | xhr.setRequestHeader(headerName, headerValue); 1309 | } 1310 | formData = new FormData(); 1311 | if (this.options.params) { 1312 | _ref1 = this.options.params; 1313 | for (key in _ref1) { 1314 | value = _ref1[key]; 1315 | formData.append(key, value); 1316 | } 1317 | } 1318 | for (_j = 0, _len1 = files.length; _j < _len1; _j++) { 1319 | file = files[_j]; 1320 | this.emit("sending", file, xhr, formData); 1321 | } 1322 | if (this.options.uploadMultiple) { 1323 | this.emit("sendingmultiple", files, xhr, formData); 1324 | } 1325 | if (this.element.tagName === "FORM") { 1326 | _ref2 = this.element.querySelectorAll("input, textarea, select, button"); 1327 | for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { 1328 | input = _ref2[_k]; 1329 | inputName = input.getAttribute("name"); 1330 | inputType = input.getAttribute("type"); 1331 | if (input.tagName === "SELECT" && input.hasAttribute("multiple")) { 1332 | _ref3 = input.options; 1333 | for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { 1334 | option = _ref3[_l]; 1335 | if (option.selected) { 1336 | formData.append(inputName, option.value); 1337 | } 1338 | } 1339 | } else if (!inputType || ((_ref4 = inputType.toLowerCase()) !== "checkbox" && _ref4 !== "radio") || input.checked) { 1340 | formData.append(inputName, input.value); 1341 | } 1342 | } 1343 | } 1344 | for (i = _m = 0, _ref5 = files.length - 1; 0 <= _ref5 ? _m <= _ref5 : _m >= _ref5; i = 0 <= _ref5 ? ++_m : --_m) { 1345 | formData.append(this._getParamName(i), files[i], files[i].name); 1346 | } 1347 | return xhr.send(formData); 1348 | }; 1349 | 1350 | Dropzone.prototype._finished = function(files, responseText, e) { 1351 | var file, _i, _len; 1352 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1353 | file = files[_i]; 1354 | file.status = Dropzone.SUCCESS; 1355 | this.emit("success", file, responseText, e); 1356 | this.emit("complete", file); 1357 | } 1358 | if (this.options.uploadMultiple) { 1359 | this.emit("successmultiple", files, responseText, e); 1360 | this.emit("completemultiple", files); 1361 | } 1362 | if (this.options.autoProcessQueue) { 1363 | return this.processQueue(); 1364 | } 1365 | }; 1366 | 1367 | Dropzone.prototype._errorProcessing = function(files, message, xhr) { 1368 | var file, _i, _len; 1369 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1370 | file = files[_i]; 1371 | file.status = Dropzone.ERROR; 1372 | this.emit("error", file, message, xhr); 1373 | this.emit("complete", file); 1374 | } 1375 | if (this.options.uploadMultiple) { 1376 | this.emit("errormultiple", files, message, xhr); 1377 | this.emit("completemultiple", files); 1378 | } 1379 | if (this.options.autoProcessQueue) { 1380 | return this.processQueue(); 1381 | } 1382 | }; 1383 | 1384 | return Dropzone; 1385 | 1386 | })(Emitter); 1387 | 1388 | Dropzone.version = "4.0.1"; 1389 | 1390 | Dropzone.options = {}; 1391 | 1392 | Dropzone.optionsForElement = function(element) { 1393 | if (element.getAttribute("id")) { 1394 | return Dropzone.options[camelize(element.getAttribute("id"))]; 1395 | } else { 1396 | return void 0; 1397 | } 1398 | }; 1399 | 1400 | Dropzone.instances = []; 1401 | 1402 | Dropzone.forElement = function(element) { 1403 | if (typeof element === "string") { 1404 | element = document.querySelector(element); 1405 | } 1406 | if ((element != null ? element.dropzone : void 0) == null) { 1407 | throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone."); 1408 | } 1409 | return element.dropzone; 1410 | }; 1411 | 1412 | Dropzone.autoDiscover = true; 1413 | 1414 | Dropzone.discover = function() { 1415 | var checkElements, dropzone, dropzones, _i, _len, _results; 1416 | if (document.querySelectorAll) { 1417 | dropzones = document.querySelectorAll(".dropzone"); 1418 | } else { 1419 | dropzones = []; 1420 | checkElements = function(elements) { 1421 | var el, _i, _len, _results; 1422 | _results = []; 1423 | for (_i = 0, _len = elements.length; _i < _len; _i++) { 1424 | el = elements[_i]; 1425 | if (/(^| )dropzone($| )/.test(el.className)) { 1426 | _results.push(dropzones.push(el)); 1427 | } else { 1428 | _results.push(void 0); 1429 | } 1430 | } 1431 | return _results; 1432 | }; 1433 | checkElements(document.getElementsByTagName("div")); 1434 | checkElements(document.getElementsByTagName("form")); 1435 | } 1436 | _results = []; 1437 | for (_i = 0, _len = dropzones.length; _i < _len; _i++) { 1438 | dropzone = dropzones[_i]; 1439 | if (Dropzone.optionsForElement(dropzone) !== false) { 1440 | _results.push(new Dropzone(dropzone)); 1441 | } else { 1442 | _results.push(void 0); 1443 | } 1444 | } 1445 | return _results; 1446 | }; 1447 | 1448 | Dropzone.blacklistedBrowsers = [/opera.*Macintosh.*version\/12/i]; 1449 | 1450 | Dropzone.isBrowserSupported = function() { 1451 | var capableBrowser, regex, _i, _len, _ref; 1452 | capableBrowser = true; 1453 | if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) { 1454 | if (!("classList" in document.createElement("a"))) { 1455 | capableBrowser = false; 1456 | } else { 1457 | _ref = Dropzone.blacklistedBrowsers; 1458 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 1459 | regex = _ref[_i]; 1460 | if (regex.test(navigator.userAgent)) { 1461 | capableBrowser = false; 1462 | continue; 1463 | } 1464 | } 1465 | } 1466 | } else { 1467 | capableBrowser = false; 1468 | } 1469 | return capableBrowser; 1470 | }; 1471 | 1472 | without = function(list, rejectedItem) { 1473 | var item, _i, _len, _results; 1474 | _results = []; 1475 | for (_i = 0, _len = list.length; _i < _len; _i++) { 1476 | item = list[_i]; 1477 | if (item !== rejectedItem) { 1478 | _results.push(item); 1479 | } 1480 | } 1481 | return _results; 1482 | }; 1483 | 1484 | camelize = function(str) { 1485 | return str.replace(/[\-_](\w)/g, function(match) { 1486 | return match.charAt(1).toUpperCase(); 1487 | }); 1488 | }; 1489 | 1490 | Dropzone.createElement = function(string) { 1491 | var div; 1492 | div = document.createElement("div"); 1493 | div.innerHTML = string; 1494 | return div.childNodes[0]; 1495 | }; 1496 | 1497 | Dropzone.elementInside = function(element, container) { 1498 | if (element === container) { 1499 | return true; 1500 | } 1501 | while (element = element.parentNode) { 1502 | if (element === container) { 1503 | return true; 1504 | } 1505 | } 1506 | return false; 1507 | }; 1508 | 1509 | Dropzone.getElement = function(el, name) { 1510 | var element; 1511 | if (typeof el === "string") { 1512 | element = document.querySelector(el); 1513 | } else if (el.nodeType != null) { 1514 | element = el; 1515 | } 1516 | if (element == null) { 1517 | throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element."); 1518 | } 1519 | return element; 1520 | }; 1521 | 1522 | Dropzone.getElements = function(els, name) { 1523 | var e, el, elements, _i, _j, _len, _len1, _ref; 1524 | if (els instanceof Array) { 1525 | elements = []; 1526 | try { 1527 | for (_i = 0, _len = els.length; _i < _len; _i++) { 1528 | el = els[_i]; 1529 | elements.push(this.getElement(el, name)); 1530 | } 1531 | } catch (_error) { 1532 | e = _error; 1533 | elements = null; 1534 | } 1535 | } else if (typeof els === "string") { 1536 | elements = []; 1537 | _ref = document.querySelectorAll(els); 1538 | for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { 1539 | el = _ref[_j]; 1540 | elements.push(el); 1541 | } 1542 | } else if (els.nodeType != null) { 1543 | elements = [els]; 1544 | } 1545 | if (!((elements != null) && elements.length)) { 1546 | throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those."); 1547 | } 1548 | return elements; 1549 | }; 1550 | 1551 | Dropzone.confirm = function(question, accepted, rejected) { 1552 | if (window.confirm(question)) { 1553 | return accepted(); 1554 | } else if (rejected != null) { 1555 | return rejected(); 1556 | } 1557 | }; 1558 | 1559 | Dropzone.isValidFile = function(file, acceptedFiles) { 1560 | var baseMimeType, mimeType, validType, _i, _len; 1561 | if (!acceptedFiles) { 1562 | return true; 1563 | } 1564 | acceptedFiles = acceptedFiles.split(","); 1565 | mimeType = file.type; 1566 | baseMimeType = mimeType.replace(/\/.*$/, ""); 1567 | for (_i = 0, _len = acceptedFiles.length; _i < _len; _i++) { 1568 | validType = acceptedFiles[_i]; 1569 | validType = validType.trim(); 1570 | if (validType.charAt(0) === ".") { 1571 | if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) { 1572 | return true; 1573 | } 1574 | } else if (/\/\*$/.test(validType)) { 1575 | if (baseMimeType === validType.replace(/\/.*$/, "")) { 1576 | return true; 1577 | } 1578 | } else { 1579 | if (mimeType === validType) { 1580 | return true; 1581 | } 1582 | } 1583 | } 1584 | return false; 1585 | }; 1586 | 1587 | if (typeof jQuery !== "undefined" && jQuery !== null) { 1588 | jQuery.fn.dropzone = function(options) { 1589 | return this.each(function() { 1590 | return new Dropzone(this, options); 1591 | }); 1592 | }; 1593 | } 1594 | 1595 | if (typeof module !== "undefined" && module !== null) { 1596 | module.exports = Dropzone; 1597 | } else { 1598 | window.Dropzone = Dropzone; 1599 | } 1600 | 1601 | Dropzone.ADDED = "added"; 1602 | 1603 | Dropzone.QUEUED = "queued"; 1604 | 1605 | Dropzone.ACCEPTED = Dropzone.QUEUED; 1606 | 1607 | Dropzone.UPLOADING = "uploading"; 1608 | 1609 | Dropzone.PROCESSING = Dropzone.UPLOADING; 1610 | 1611 | Dropzone.CANCELED = "canceled"; 1612 | 1613 | Dropzone.ERROR = "error"; 1614 | 1615 | Dropzone.SUCCESS = "success"; 1616 | 1617 | 1618 | /* 1619 | 1620 | Bugfix for iOS 6 and 7 1621 | Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios 1622 | based on the work of https://github.com/stomita/ios-imagefile-megapixel 1623 | */ 1624 | 1625 | detectVerticalSquash = function(img) { 1626 | var alpha, canvas, ctx, data, ey, ih, iw, py, ratio, sy; 1627 | iw = img.naturalWidth; 1628 | ih = img.naturalHeight; 1629 | canvas = document.createElement("canvas"); 1630 | canvas.width = 1; 1631 | canvas.height = ih; 1632 | ctx = canvas.getContext("2d"); 1633 | ctx.drawImage(img, 0, 0); 1634 | data = ctx.getImageData(0, 0, 1, ih).data; 1635 | sy = 0; 1636 | ey = ih; 1637 | py = ih; 1638 | while (py > sy) { 1639 | alpha = data[(py - 1) * 4 + 3]; 1640 | if (alpha === 0) { 1641 | ey = py; 1642 | } else { 1643 | sy = py; 1644 | } 1645 | py = (ey + sy) >> 1; 1646 | } 1647 | ratio = py / ih; 1648 | if (ratio === 0) { 1649 | return 1; 1650 | } else { 1651 | return ratio; 1652 | } 1653 | }; 1654 | 1655 | drawImageIOSFix = function(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) { 1656 | var vertSquashRatio; 1657 | vertSquashRatio = detectVerticalSquash(img); 1658 | return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio); 1659 | }; 1660 | 1661 | 1662 | /* 1663 | * contentloaded.js 1664 | * 1665 | * Author: Diego Perini (diego.perini at gmail.com) 1666 | * Summary: cross-browser wrapper for DOMContentLoaded 1667 | * Updated: 20101020 1668 | * License: MIT 1669 | * Version: 1.2 1670 | * 1671 | * URL: 1672 | * http://javascript.nwbox.com/ContentLoaded/ 1673 | * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE 1674 | */ 1675 | 1676 | contentLoaded = function(win, fn) { 1677 | var add, doc, done, init, poll, pre, rem, root, top; 1678 | done = false; 1679 | top = true; 1680 | doc = win.document; 1681 | root = doc.documentElement; 1682 | add = (doc.addEventListener ? "addEventListener" : "attachEvent"); 1683 | rem = (doc.addEventListener ? "removeEventListener" : "detachEvent"); 1684 | pre = (doc.addEventListener ? "" : "on"); 1685 | init = function(e) { 1686 | if (e.type === "readystatechange" && doc.readyState !== "complete") { 1687 | return; 1688 | } 1689 | (e.type === "load" ? win : doc)[rem](pre + e.type, init, false); 1690 | if (!done && (done = true)) { 1691 | return fn.call(win, e.type || e); 1692 | } 1693 | }; 1694 | poll = function() { 1695 | var e; 1696 | try { 1697 | root.doScroll("left"); 1698 | } catch (_error) { 1699 | e = _error; 1700 | setTimeout(poll, 50); 1701 | return; 1702 | } 1703 | return init("poll"); 1704 | }; 1705 | if (doc.readyState !== "complete") { 1706 | if (doc.createEventObject && root.doScroll) { 1707 | try { 1708 | top = !win.frameElement; 1709 | } catch (_error) {} 1710 | if (top) { 1711 | poll(); 1712 | } 1713 | } 1714 | doc[add](pre + "DOMContentLoaded", init, false); 1715 | doc[add](pre + "readystatechange", init, false); 1716 | return win[add](pre + "load", init, false); 1717 | } 1718 | }; 1719 | 1720 | Dropzone._autoDiscoverFunction = function() { 1721 | if (Dropzone.autoDiscover) { 1722 | return Dropzone.discover(); 1723 | } 1724 | }; 1725 | 1726 | contentLoaded(window, Dropzone._autoDiscoverFunction); 1727 | 1728 | }).call(this); 1729 | --------------------------------------------------------------------------------