├── fileupload ├── __init__.py ├── tests.py ├── static │ └── fileupload │ │ ├── images │ │ ├── spritemap.png │ │ └── spritemap@2x.png │ │ ├── css │ │ └── dropzone.css │ │ └── js │ │ └── dropzone.js ├── admin.py ├── models.py ├── views.py ├── templates │ └── fileupload │ │ └── picture_form.html └── response.py ├── .gitignore ├── django_dropzone_upload ├── __init__.py ├── urls.py ├── wsgi.py └── settings.py ├── requirements.txt ├── manage.py ├── LICENSE └── README.md /fileupload/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /pictures 2 | /venv 3 | -------------------------------------------------------------------------------- /django_dropzone_upload/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | django<1.7 2 | pillow 3 | -------------------------------------------------------------------------------- /fileupload/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /fileupload/static/fileupload/images/spritemap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurdga/django-dropzone-upload/HEAD/fileupload/static/fileupload/images/spritemap.png -------------------------------------------------------------------------------- /fileupload/static/fileupload/images/spritemap@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurdga/django-dropzone-upload/HEAD/fileupload/static/fileupload/images/spritemap@2x.png -------------------------------------------------------------------------------- /fileupload/admin.py: -------------------------------------------------------------------------------- 1 | from fileupload.models import Picture 2 | from django.contrib import admin 3 | 4 | class PictureAdmin(admin.ModelAdmin): 5 | list_display = ('__unicode__',) 6 | 7 | admin.site.register(Picture, PictureAdmin) 8 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_dropzone_upload.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /django_dropzone_upload/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, include, url 2 | from fileupload.views import PictureCreateView 3 | 4 | from django.contrib import admin 5 | admin.autodiscover() 6 | 7 | urlpatterns = patterns('', 8 | url(r'^$', PictureCreateView.as_view(), name='home'), 9 | url(r'^admin/', include(admin.site.urls)), 10 | ) 11 | -------------------------------------------------------------------------------- /fileupload/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | 4 | class Picture(models.Model): 5 | """ 6 | This is a small demo using just two fields. ImageField depends on PIL or 7 | pillow (where Pillow is easily installable in a virtualenv. If you have 8 | problems installing pillow, use a more generic FileField instead. 9 | """ 10 | 11 | file = models.ImageField(upload_to="pictures") 12 | 13 | def __unicode__(self): 14 | return self.file.name 15 | -------------------------------------------------------------------------------- /fileupload/views.py: -------------------------------------------------------------------------------- 1 | #from django.shortcuts import render 2 | from django.views.generic import CreateView 3 | from .models import Picture 4 | from .response import JSONResponse, response_mimetype 5 | 6 | class PictureCreateView(CreateView): 7 | model = Picture 8 | 9 | def form_valid(self, form): 10 | self.object = form.save() 11 | data = {'status': 'success'} 12 | response = JSONResponse(data, mimetype=response_mimetype(self.request)) 13 | return response 14 | -------------------------------------------------------------------------------- /django_dropzone_upload/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for django_dropzone_upload project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_dropzone_upload.settings") 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | application = get_wsgi_application() 15 | -------------------------------------------------------------------------------- /fileupload/templates/fileupload/picture_form.html: -------------------------------------------------------------------------------- 1 | {% load staticfiles %} 2 | 3 | 4 | 5 | Upload pictures 6 | 7 | 8 | 9 |
10 | {% csrf_token %} 11 |
12 | 13 |
14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Sigurd Gartmann 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /fileupload/response.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | from django.http import HttpResponse 3 | import json 4 | 5 | MIMEANY = '*/*' 6 | MIMEJSON = 'application/json' 7 | MIMETEXT = 'text/plain' 8 | 9 | 10 | def response_mimetype(request): 11 | """response_mimetype -- Return a proper response mimetype, accordingly to 12 | what the client accepts, as available in the `HTTP_ACCEPT` header. 13 | 14 | request -- a HttpRequest instance. 15 | 16 | """ 17 | can_json = MIMEJSON in request.META['HTTP_ACCEPT'] 18 | can_json |= MIMEANY in request.META['HTTP_ACCEPT'] 19 | return MIMEJSON if can_json else MIMETEXT 20 | 21 | 22 | class JSONResponse(HttpResponse): 23 | """JSONResponse -- Extends HTTPResponse to handle JSON format response. 24 | 25 | This response can be used in any view that should return a json stream of 26 | data. 27 | 28 | Usage: 29 | 30 | def a_iew(request): 31 | content = {'key': 'value'} 32 | return JSONResponse(content, mimetype=response_mimetype(request)) 33 | 34 | """ 35 | def __init__(self, obj='', json_opts=None, mimetype=MIMEJSON, *args, **kwargs): 36 | json_opts = json_opts if isinstance(json_opts, dict) else {} 37 | content = json.dumps(obj, **json_opts) 38 | super(JSONResponse, self).__init__(content, mimetype, *args, **kwargs) 39 | -------------------------------------------------------------------------------- /django_dropzone_upload/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for django_dropzone_upload project. 3 | 4 | For more information on this file, see 5 | https://docs.djangoproject.com/en/1.6/topics/settings/ 6 | 7 | For the full list of settings and their values, see 8 | https://docs.djangoproject.com/en/1.6/ref/settings/ 9 | """ 10 | 11 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 12 | import os 13 | BASE_DIR = os.path.dirname(os.path.dirname(__file__)) 14 | 15 | 16 | # Quick-start development settings - unsuitable for production 17 | # See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/ 18 | 19 | # SECURITY WARNING: keep the secret key used in production secret! 20 | SECRET_KEY = 'im6wk^#s^tl#&32&+$-lci^qnq@luaeoqxk_c5umk8j!3#tnoe' 21 | 22 | # SECURITY WARNING: don't run with debug turned on in production! 23 | DEBUG = True 24 | 25 | TEMPLATE_DEBUG = True 26 | 27 | ALLOWED_HOSTS = [] 28 | 29 | 30 | # Application definition 31 | 32 | INSTALLED_APPS = ( 33 | 'django.contrib.admin', 34 | 'django.contrib.auth', 35 | 'django.contrib.contenttypes', 36 | 'django.contrib.sessions', 37 | 'django.contrib.messages', 38 | 'django.contrib.staticfiles', 39 | 'fileupload', 40 | ) 41 | 42 | MIDDLEWARE_CLASSES = ( 43 | 'django.contrib.sessions.middleware.SessionMiddleware', 44 | 'django.middleware.common.CommonMiddleware', 45 | 'django.middleware.csrf.CsrfViewMiddleware', 46 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 47 | 'django.contrib.messages.middleware.MessageMiddleware', 48 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 49 | ) 50 | 51 | ROOT_URLCONF = 'django_dropzone_upload.urls' 52 | 53 | WSGI_APPLICATION = 'django_dropzone_upload.wsgi.application' 54 | 55 | 56 | # Database 57 | # https://docs.djangoproject.com/en/1.6/ref/settings/#databases 58 | 59 | DATABASES = { 60 | 'default': { 61 | 'ENGINE': 'django.db.backends.sqlite3', 62 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 63 | } 64 | } 65 | 66 | # Internationalization 67 | # https://docs.djangoproject.com/en/1.6/topics/i18n/ 68 | 69 | LANGUAGE_CODE = 'en-us' 70 | 71 | TIME_ZONE = 'UTC' 72 | 73 | USE_I18N = True 74 | 75 | USE_L10N = True 76 | 77 | USE_TZ = True 78 | 79 | 80 | # Static files (CSS, JavaScript, Images) 81 | # https://docs.djangoproject.com/en/1.6/howto/static-files/ 82 | 83 | STATIC_URL = '/static/' 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Django dropzone upload 2 | ====================== 3 | 4 | Example project for integrating [Dropzone.js](http://www.dropzonejs.com) with 5 | [Django](https://www.djangoproject.com/). 6 | 7 | Introduction 8 | ------------ 9 | 10 | [Dropzone.js](http://www.dropzonejs.com) by [Matias 11 | Meno](https://github.com/enyo) is a javascript library for drag and drop file 12 | uploading. It is very light and simple to configure and extend. This example uses ImageField, but you can easily change that to using FileField instead. 13 | 14 | I have earlier created 15 | [django-jquery-file-upload](https://github.com/sigurdga/django-jquery-file-upload), 16 | which integrates [jquery-file-upload](https://github.com/blueimp/jquery-file-upload) by 17 | [Sebastian Tschan](https://github.com/blueimp) with Django. That project has a 18 | lot of functionality and tries to be a complete package of all you need. It also works on older browsers. 19 | 20 | Django-dropzone-upload tries to be as minimal and simple to understand as 21 | possible, as it should be fairly easy to with Dropzone.js functionality. 22 | 23 | Howto 24 | ----- 25 | 26 | We assume you have git, python and python-virtualenv already installed. 27 | 28 | * Clone this repository: git clone https://github.com/sigurdga/django-dropzone-upload.git 29 | * Change directory: cd django-dropzone-upload 30 | * Create virtualenv: virtualenv venv 31 | * Activate virtualenv: source venv/bin/activate 32 | * Install dependencies into virtualenv: pip install -r requirements.txt 33 | * Setup database: python manage.py syncdb 34 | * Run development server: python manage.py runserver 35 | * Open browser at localhost:8000 36 | 37 | Limitations 38 | ----------- 39 | 40 | Dropzone.js claims to work for modern browsers: 41 | 42 | * Chrome 7+ 43 | * Firefox 4+ 44 | * IE 10+ 45 | * Opera 12+ (Version 12 for MacOS is disabled because their API is buggy) 46 | * Safari 6+ 47 | 48 | Django-dropzone-upload does not try to do anything more than Dropzone in 49 | its simplest form, so no delete, no listing of already uploaded, etc. in this 50 | project. 51 | 52 | Credits 53 | ------- 54 | 55 | * [Sigurd Gartmann](https://github.com/sigurdga) for initial setup 56 | * [João Paulo Dubas](https://github.com/joaodubas) created the `fileupload/response.py` initially for django-jquery-file-upload. 57 | 58 | License 59 | ------- 60 | 61 | Released under the [MIT license](https://github.com/sigurdga/django-dropzone-upload/blob/master/LICENSE) 62 | -------------------------------------------------------------------------------- /fileupload/static/fileupload/css/dropzone.css: -------------------------------------------------------------------------------- 1 | /* The MIT License */ 2 | .dropzone, 3 | .dropzone *, 4 | .dropzone-previews, 5 | .dropzone-previews * { 6 | -webkit-box-sizing: border-box; 7 | -moz-box-sizing: border-box; 8 | box-sizing: border-box; 9 | } 10 | .dropzone { 11 | position: relative; 12 | border: 1px solid rgba(0,0,0,0.08); 13 | background: rgba(0,0,0,0.02); 14 | padding: 1em; 15 | } 16 | .dropzone.dz-clickable { 17 | cursor: pointer; 18 | } 19 | .dropzone.dz-clickable .dz-message, 20 | .dropzone.dz-clickable .dz-message span { 21 | cursor: pointer; 22 | } 23 | .dropzone.dz-clickable * { 24 | cursor: default; 25 | } 26 | .dropzone .dz-message { 27 | opacity: 1; 28 | -ms-filter: none; 29 | filter: none; 30 | } 31 | .dropzone.dz-drag-hover { 32 | border-color: rgba(0,0,0,0.15); 33 | background: rgba(0,0,0,0.04); 34 | } 35 | .dropzone.dz-started .dz-message { 36 | display: none; 37 | } 38 | .dropzone .dz-preview, 39 | .dropzone-previews .dz-preview { 40 | background: rgba(255,255,255,0.8); 41 | position: relative; 42 | display: inline-block; 43 | margin: 17px; 44 | vertical-align: top; 45 | border: 1px solid #acacac; 46 | padding: 6px 6px 6px 6px; 47 | } 48 | .dropzone .dz-preview.dz-file-preview [data-dz-thumbnail], 49 | .dropzone-previews .dz-preview.dz-file-preview [data-dz-thumbnail] { 50 | display: none; 51 | } 52 | .dropzone .dz-preview .dz-details, 53 | .dropzone-previews .dz-preview .dz-details { 54 | width: 100px; 55 | height: 100px; 56 | position: relative; 57 | background: #ebebeb; 58 | padding: 5px; 59 | margin-bottom: 22px; 60 | } 61 | .dropzone .dz-preview .dz-details .dz-filename, 62 | .dropzone-previews .dz-preview .dz-details .dz-filename { 63 | overflow: hidden; 64 | height: 100%; 65 | } 66 | .dropzone .dz-preview .dz-details img, 67 | .dropzone-previews .dz-preview .dz-details img { 68 | position: absolute; 69 | top: 0; 70 | left: 0; 71 | width: 100px; 72 | height: 100px; 73 | } 74 | .dropzone .dz-preview .dz-details .dz-size, 75 | .dropzone-previews .dz-preview .dz-details .dz-size { 76 | position: absolute; 77 | bottom: -28px; 78 | left: 3px; 79 | height: 28px; 80 | line-height: 28px; 81 | } 82 | .dropzone .dz-preview.dz-error .dz-error-mark, 83 | .dropzone-previews .dz-preview.dz-error .dz-error-mark { 84 | display: block; 85 | } 86 | .dropzone .dz-preview.dz-success .dz-success-mark, 87 | .dropzone-previews .dz-preview.dz-success .dz-success-mark { 88 | display: block; 89 | } 90 | .dropzone .dz-preview:hover .dz-details img, 91 | .dropzone-previews .dz-preview:hover .dz-details img { 92 | display: none; 93 | } 94 | .dropzone .dz-preview .dz-success-mark, 95 | .dropzone-previews .dz-preview .dz-success-mark, 96 | .dropzone .dz-preview .dz-error-mark, 97 | .dropzone-previews .dz-preview .dz-error-mark { 98 | display: none; 99 | position: absolute; 100 | width: 40px; 101 | height: 40px; 102 | font-size: 30px; 103 | text-align: center; 104 | right: -10px; 105 | top: -10px; 106 | } 107 | .dropzone .dz-preview .dz-success-mark, 108 | .dropzone-previews .dz-preview .dz-success-mark { 109 | color: #8cc657; 110 | } 111 | .dropzone .dz-preview .dz-error-mark, 112 | .dropzone-previews .dz-preview .dz-error-mark { 113 | color: #ee162d; 114 | } 115 | .dropzone .dz-preview .dz-progress, 116 | .dropzone-previews .dz-preview .dz-progress { 117 | position: absolute; 118 | top: 100px; 119 | left: 6px; 120 | right: 6px; 121 | height: 6px; 122 | background: #d7d7d7; 123 | display: none; 124 | } 125 | .dropzone .dz-preview .dz-progress .dz-upload, 126 | .dropzone-previews .dz-preview .dz-progress .dz-upload { 127 | display: block; 128 | position: absolute; 129 | top: 0; 130 | bottom: 0; 131 | left: 0; 132 | width: 0%; 133 | background-color: #8cc657; 134 | } 135 | .dropzone .dz-preview.dz-processing .dz-progress, 136 | .dropzone-previews .dz-preview.dz-processing .dz-progress { 137 | display: block; 138 | } 139 | .dropzone .dz-preview .dz-error-message, 140 | .dropzone-previews .dz-preview .dz-error-message { 141 | display: none; 142 | position: absolute; 143 | top: -5px; 144 | left: -20px; 145 | background: rgba(245,245,245,0.8); 146 | padding: 8px 10px; 147 | color: #800; 148 | min-width: 140px; 149 | max-width: 500px; 150 | z-index: 500; 151 | } 152 | .dropzone .dz-preview:hover.dz-error .dz-error-message, 153 | .dropzone-previews .dz-preview:hover.dz-error .dz-error-message { 154 | display: block; 155 | } 156 | .dropzone { 157 | border: 1px solid rgba(0,0,0,0.03); 158 | min-height: 360px; 159 | -webkit-border-radius: 3px; 160 | border-radius: 3px; 161 | background: rgba(0,0,0,0.03); 162 | padding: 23px; 163 | } 164 | .dropzone .dz-default.dz-message { 165 | opacity: 1; 166 | -ms-filter: none; 167 | filter: none; 168 | -webkit-transition: opacity 0.3s ease-in-out; 169 | -moz-transition: opacity 0.3s ease-in-out; 170 | -o-transition: opacity 0.3s ease-in-out; 171 | -ms-transition: opacity 0.3s ease-in-out; 172 | transition: opacity 0.3s ease-in-out; 173 | background-image: url("../images/spritemap.png"); 174 | background-repeat: no-repeat; 175 | background-position: 0 0; 176 | position: absolute; 177 | width: 428px; 178 | height: 123px; 179 | margin-left: -214px; 180 | margin-top: -61.5px; 181 | top: 50%; 182 | left: 50%; 183 | } 184 | @media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) { 185 | .dropzone .dz-default.dz-message { 186 | background-image: url("../images/spritemap@2x.png"); 187 | -webkit-background-size: 428px 406px; 188 | -moz-background-size: 428px 406px; 189 | background-size: 428px 406px; 190 | } 191 | } 192 | .dropzone .dz-default.dz-message span { 193 | display: none; 194 | } 195 | .dropzone.dz-square .dz-default.dz-message { 196 | background-position: 0 -123px; 197 | width: 268px; 198 | margin-left: -134px; 199 | height: 174px; 200 | margin-top: -87px; 201 | } 202 | .dropzone.dz-drag-hover .dz-message { 203 | opacity: 0.15; 204 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=15)"; 205 | filter: alpha(opacity=15); 206 | } 207 | .dropzone.dz-started .dz-message { 208 | display: block; 209 | opacity: 0; 210 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; 211 | filter: alpha(opacity=0); 212 | } 213 | .dropzone .dz-preview, 214 | .dropzone-previews .dz-preview { 215 | -webkit-box-shadow: 1px 1px 4px rgba(0,0,0,0.16); 216 | box-shadow: 1px 1px 4px rgba(0,0,0,0.16); 217 | font-size: 14px; 218 | } 219 | .dropzone .dz-preview.dz-image-preview:hover .dz-details img, 220 | .dropzone-previews .dz-preview.dz-image-preview:hover .dz-details img { 221 | display: block; 222 | opacity: 0.1; 223 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=10)"; 224 | filter: alpha(opacity=10); 225 | } 226 | .dropzone .dz-preview.dz-success .dz-success-mark, 227 | .dropzone-previews .dz-preview.dz-success .dz-success-mark { 228 | opacity: 1; 229 | -ms-filter: none; 230 | filter: none; 231 | } 232 | .dropzone .dz-preview.dz-error .dz-error-mark, 233 | .dropzone-previews .dz-preview.dz-error .dz-error-mark { 234 | opacity: 1; 235 | -ms-filter: none; 236 | filter: none; 237 | } 238 | .dropzone .dz-preview.dz-error .dz-progress .dz-upload, 239 | .dropzone-previews .dz-preview.dz-error .dz-progress .dz-upload { 240 | background: #ee1e2d; 241 | } 242 | .dropzone .dz-preview .dz-error-mark, 243 | .dropzone-previews .dz-preview .dz-error-mark, 244 | .dropzone .dz-preview .dz-success-mark, 245 | .dropzone-previews .dz-preview .dz-success-mark { 246 | display: block; 247 | opacity: 0; 248 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; 249 | filter: alpha(opacity=0); 250 | -webkit-transition: opacity 0.4s ease-in-out; 251 | -moz-transition: opacity 0.4s ease-in-out; 252 | -o-transition: opacity 0.4s ease-in-out; 253 | -ms-transition: opacity 0.4s ease-in-out; 254 | transition: opacity 0.4s ease-in-out; 255 | background-image: url("../images/spritemap.png"); 256 | background-repeat: no-repeat; 257 | } 258 | @media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) { 259 | .dropzone .dz-preview .dz-error-mark, 260 | .dropzone-previews .dz-preview .dz-error-mark, 261 | .dropzone .dz-preview .dz-success-mark, 262 | .dropzone-previews .dz-preview .dz-success-mark { 263 | background-image: url("../images/spritemap@2x.png"); 264 | -webkit-background-size: 428px 406px; 265 | -moz-background-size: 428px 406px; 266 | background-size: 428px 406px; 267 | } 268 | } 269 | .dropzone .dz-preview .dz-error-mark span, 270 | .dropzone-previews .dz-preview .dz-error-mark span, 271 | .dropzone .dz-preview .dz-success-mark span, 272 | .dropzone-previews .dz-preview .dz-success-mark span { 273 | display: none; 274 | } 275 | .dropzone .dz-preview .dz-error-mark, 276 | .dropzone-previews .dz-preview .dz-error-mark { 277 | background-position: -268px -123px; 278 | } 279 | .dropzone .dz-preview .dz-success-mark, 280 | .dropzone-previews .dz-preview .dz-success-mark { 281 | background-position: -268px -163px; 282 | } 283 | .dropzone .dz-preview .dz-progress .dz-upload, 284 | .dropzone-previews .dz-preview .dz-progress .dz-upload { 285 | -webkit-animation: loading 0.4s linear infinite; 286 | -moz-animation: loading 0.4s linear infinite; 287 | -o-animation: loading 0.4s linear infinite; 288 | -ms-animation: loading 0.4s linear infinite; 289 | animation: loading 0.4s linear infinite; 290 | -webkit-transition: width 0.3s ease-in-out; 291 | -moz-transition: width 0.3s ease-in-out; 292 | -o-transition: width 0.3s ease-in-out; 293 | -ms-transition: width 0.3s ease-in-out; 294 | transition: width 0.3s ease-in-out; 295 | -webkit-border-radius: 2px; 296 | border-radius: 2px; 297 | position: absolute; 298 | top: 0; 299 | left: 0; 300 | width: 0%; 301 | height: 100%; 302 | background-image: url("../images/spritemap.png"); 303 | background-repeat: repeat-x; 304 | background-position: 0px -400px; 305 | } 306 | @media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) { 307 | .dropzone .dz-preview .dz-progress .dz-upload, 308 | .dropzone-previews .dz-preview .dz-progress .dz-upload { 309 | background-image: url("../images/spritemap@2x.png"); 310 | -webkit-background-size: 428px 406px; 311 | -moz-background-size: 428px 406px; 312 | background-size: 428px 406px; 313 | } 314 | } 315 | .dropzone .dz-preview.dz-success .dz-progress, 316 | .dropzone-previews .dz-preview.dz-success .dz-progress { 317 | display: block; 318 | opacity: 0; 319 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; 320 | filter: alpha(opacity=0); 321 | -webkit-transition: opacity 0.4s ease-in-out; 322 | -moz-transition: opacity 0.4s ease-in-out; 323 | -o-transition: opacity 0.4s ease-in-out; 324 | -ms-transition: opacity 0.4s ease-in-out; 325 | transition: opacity 0.4s ease-in-out; 326 | } 327 | .dropzone .dz-preview .dz-error-message, 328 | .dropzone-previews .dz-preview .dz-error-message { 329 | display: block; 330 | opacity: 0; 331 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; 332 | filter: alpha(opacity=0); 333 | -webkit-transition: opacity 0.3s ease-in-out; 334 | -moz-transition: opacity 0.3s ease-in-out; 335 | -o-transition: opacity 0.3s ease-in-out; 336 | -ms-transition: opacity 0.3s ease-in-out; 337 | transition: opacity 0.3s ease-in-out; 338 | } 339 | .dropzone .dz-preview:hover.dz-error .dz-error-message, 340 | .dropzone-previews .dz-preview:hover.dz-error .dz-error-message { 341 | opacity: 1; 342 | -ms-filter: none; 343 | filter: none; 344 | } 345 | .dropzone a.dz-remove, 346 | .dropzone-previews a.dz-remove { 347 | background-image: -webkit-linear-gradient(top, #fafafa, #eee); 348 | background-image: -moz-linear-gradient(top, #fafafa, #eee); 349 | background-image: -o-linear-gradient(top, #fafafa, #eee); 350 | background-image: -ms-linear-gradient(top, #fafafa, #eee); 351 | background-image: linear-gradient(to bottom, #fafafa, #eee); 352 | -webkit-border-radius: 2px; 353 | border-radius: 2px; 354 | border: 1px solid #eee; 355 | text-decoration: none; 356 | display: block; 357 | padding: 4px 5px; 358 | text-align: center; 359 | color: #aaa; 360 | margin-top: 26px; 361 | } 362 | .dropzone a.dz-remove:hover, 363 | .dropzone-previews a.dz-remove:hover { 364 | color: #666; 365 | } 366 | @-moz-keyframes loading { 367 | 0% { 368 | background-position: 0 -400px; 369 | } 370 | 371 | 100% { 372 | background-position: -7px -400px; 373 | } 374 | } 375 | @-webkit-keyframes loading { 376 | 0% { 377 | background-position: 0 -400px; 378 | } 379 | 380 | 100% { 381 | background-position: -7px -400px; 382 | } 383 | } 384 | @-o-keyframes loading { 385 | 0% { 386 | background-position: 0 -400px; 387 | } 388 | 389 | 100% { 390 | background-position: -7px -400px; 391 | } 392 | } 393 | @-ms-keyframes loading { 394 | 0% { 395 | background-position: 0 -400px; 396 | } 397 | 398 | 100% { 399 | background-position: -7px -400px; 400 | } 401 | } 402 | @keyframes loading { 403 | 0% { 404 | background-position: 0 -400px; 405 | } 406 | 407 | 100% { 408 | background-position: -7px -400px; 409 | } 410 | } 411 | -------------------------------------------------------------------------------- /fileupload/static/fileupload/js/dropzone.js: -------------------------------------------------------------------------------- 1 | ;(function(){ 2 | 3 | /** 4 | * Require the given path. 5 | * 6 | * @param {String} path 7 | * @return {Object} exports 8 | * @api public 9 | */ 10 | 11 | function require(path, parent, orig) { 12 | var resolved = require.resolve(path); 13 | 14 | // lookup failed 15 | if (null == resolved) { 16 | orig = orig || path; 17 | parent = parent || 'root'; 18 | var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); 19 | err.path = orig; 20 | err.parent = parent; 21 | err.require = true; 22 | throw err; 23 | } 24 | 25 | var module = require.modules[resolved]; 26 | 27 | // perform real require() 28 | // by invoking the module's 29 | // registered function 30 | if (!module._resolving && !module.exports) { 31 | var mod = {}; 32 | mod.exports = {}; 33 | mod.client = mod.component = true; 34 | module._resolving = true; 35 | module.call(this, mod.exports, require.relative(resolved), mod); 36 | delete module._resolving; 37 | module.exports = mod.exports; 38 | } 39 | 40 | return module.exports; 41 | } 42 | 43 | /** 44 | * Registered modules. 45 | */ 46 | 47 | require.modules = {}; 48 | 49 | /** 50 | * Registered aliases. 51 | */ 52 | 53 | require.aliases = {}; 54 | 55 | /** 56 | * Resolve `path`. 57 | * 58 | * Lookup: 59 | * 60 | * - PATH/index.js 61 | * - PATH.js 62 | * - PATH 63 | * 64 | * @param {String} path 65 | * @return {String} path or null 66 | * @api private 67 | */ 68 | 69 | require.resolve = function(path) { 70 | if (path.charAt(0) === '/') path = path.slice(1); 71 | 72 | var paths = [ 73 | path, 74 | path + '.js', 75 | path + '.json', 76 | path + '/index.js', 77 | path + '/index.json' 78 | ]; 79 | 80 | for (var i = 0; i < paths.length; i++) { 81 | var path = paths[i]; 82 | if (require.modules.hasOwnProperty(path)) return path; 83 | if (require.aliases.hasOwnProperty(path)) return require.aliases[path]; 84 | } 85 | }; 86 | 87 | /** 88 | * Normalize `path` relative to the current path. 89 | * 90 | * @param {String} curr 91 | * @param {String} path 92 | * @return {String} 93 | * @api private 94 | */ 95 | 96 | require.normalize = function(curr, path) { 97 | var segs = []; 98 | 99 | if ('.' != path.charAt(0)) return path; 100 | 101 | curr = curr.split('/'); 102 | path = path.split('/'); 103 | 104 | for (var i = 0; i < path.length; ++i) { 105 | if ('..' == path[i]) { 106 | curr.pop(); 107 | } else if ('.' != path[i] && '' != path[i]) { 108 | segs.push(path[i]); 109 | } 110 | } 111 | 112 | return curr.concat(segs).join('/'); 113 | }; 114 | 115 | /** 116 | * Register module at `path` with callback `definition`. 117 | * 118 | * @param {String} path 119 | * @param {Function} definition 120 | * @api private 121 | */ 122 | 123 | require.register = function(path, definition) { 124 | require.modules[path] = definition; 125 | }; 126 | 127 | /** 128 | * Alias a module definition. 129 | * 130 | * @param {String} from 131 | * @param {String} to 132 | * @api private 133 | */ 134 | 135 | require.alias = function(from, to) { 136 | if (!require.modules.hasOwnProperty(from)) { 137 | throw new Error('Failed to alias "' + from + '", it does not exist'); 138 | } 139 | require.aliases[to] = from; 140 | }; 141 | 142 | /** 143 | * Return a require function relative to the `parent` path. 144 | * 145 | * @param {String} parent 146 | * @return {Function} 147 | * @api private 148 | */ 149 | 150 | require.relative = function(parent) { 151 | var p = require.normalize(parent, '..'); 152 | 153 | /** 154 | * lastIndexOf helper. 155 | */ 156 | 157 | function lastIndexOf(arr, obj) { 158 | var i = arr.length; 159 | while (i--) { 160 | if (arr[i] === obj) return i; 161 | } 162 | return -1; 163 | } 164 | 165 | /** 166 | * The relative require() itself. 167 | */ 168 | 169 | function localRequire(path) { 170 | var resolved = localRequire.resolve(path); 171 | return require(resolved, parent, path); 172 | } 173 | 174 | /** 175 | * Resolve relative to the parent. 176 | */ 177 | 178 | localRequire.resolve = function(path) { 179 | var c = path.charAt(0); 180 | if ('/' == c) return path.slice(1); 181 | if ('.' == c) return require.normalize(p, path); 182 | 183 | // resolve deps by returning 184 | // the dep in the nearest "deps" 185 | // directory 186 | var segs = parent.split('/'); 187 | var i = lastIndexOf(segs, 'deps') + 1; 188 | if (!i) i = 0; 189 | path = segs.slice(0, i + 1).join('/') + '/deps/' + path; 190 | return path; 191 | }; 192 | 193 | /** 194 | * Check if module is defined at `path`. 195 | */ 196 | 197 | localRequire.exists = function(path) { 198 | return require.modules.hasOwnProperty(localRequire.resolve(path)); 199 | }; 200 | 201 | return localRequire; 202 | }; 203 | require.register("component-emitter/index.js", function(exports, require, module){ 204 | 205 | /** 206 | * Expose `Emitter`. 207 | */ 208 | 209 | module.exports = Emitter; 210 | 211 | /** 212 | * Initialize a new `Emitter`. 213 | * 214 | * @api public 215 | */ 216 | 217 | function Emitter(obj) { 218 | if (obj) return mixin(obj); 219 | }; 220 | 221 | /** 222 | * Mixin the emitter properties. 223 | * 224 | * @param {Object} obj 225 | * @return {Object} 226 | * @api private 227 | */ 228 | 229 | function mixin(obj) { 230 | for (var key in Emitter.prototype) { 231 | obj[key] = Emitter.prototype[key]; 232 | } 233 | return obj; 234 | } 235 | 236 | /** 237 | * Listen on the given `event` with `fn`. 238 | * 239 | * @param {String} event 240 | * @param {Function} fn 241 | * @return {Emitter} 242 | * @api public 243 | */ 244 | 245 | Emitter.prototype.on = function(event, fn){ 246 | this._callbacks = this._callbacks || {}; 247 | (this._callbacks[event] = this._callbacks[event] || []) 248 | .push(fn); 249 | return this; 250 | }; 251 | 252 | /** 253 | * Adds an `event` listener that will be invoked a single 254 | * time then automatically removed. 255 | * 256 | * @param {String} event 257 | * @param {Function} fn 258 | * @return {Emitter} 259 | * @api public 260 | */ 261 | 262 | Emitter.prototype.once = function(event, fn){ 263 | var self = this; 264 | this._callbacks = this._callbacks || {}; 265 | 266 | function on() { 267 | self.off(event, on); 268 | fn.apply(this, arguments); 269 | } 270 | 271 | fn._off = on; 272 | this.on(event, on); 273 | return this; 274 | }; 275 | 276 | /** 277 | * Remove the given callback for `event` or all 278 | * registered callbacks. 279 | * 280 | * @param {String} event 281 | * @param {Function} fn 282 | * @return {Emitter} 283 | * @api public 284 | */ 285 | 286 | Emitter.prototype.off = 287 | Emitter.prototype.removeListener = 288 | Emitter.prototype.removeAllListeners = function(event, fn){ 289 | this._callbacks = this._callbacks || {}; 290 | var callbacks = this._callbacks[event]; 291 | if (!callbacks) return this; 292 | 293 | // remove all handlers 294 | if (1 == arguments.length) { 295 | delete this._callbacks[event]; 296 | return this; 297 | } 298 | 299 | // remove specific handler 300 | var i = callbacks.indexOf(fn._off || fn); 301 | if (~i) callbacks.splice(i, 1); 302 | return this; 303 | }; 304 | 305 | /** 306 | * Emit `event` with the given args. 307 | * 308 | * @param {String} event 309 | * @param {Mixed} ... 310 | * @return {Emitter} 311 | */ 312 | 313 | Emitter.prototype.emit = function(event){ 314 | this._callbacks = this._callbacks || {}; 315 | var args = [].slice.call(arguments, 1) 316 | , callbacks = this._callbacks[event]; 317 | 318 | if (callbacks) { 319 | callbacks = callbacks.slice(0); 320 | for (var i = 0, len = callbacks.length; i < len; ++i) { 321 | callbacks[i].apply(this, args); 322 | } 323 | } 324 | 325 | return this; 326 | }; 327 | 328 | /** 329 | * Return array of callbacks for `event`. 330 | * 331 | * @param {String} event 332 | * @return {Array} 333 | * @api public 334 | */ 335 | 336 | Emitter.prototype.listeners = function(event){ 337 | this._callbacks = this._callbacks || {}; 338 | return this._callbacks[event] || []; 339 | }; 340 | 341 | /** 342 | * Check if this emitter has `event` handlers. 343 | * 344 | * @param {String} event 345 | * @return {Boolean} 346 | * @api public 347 | */ 348 | 349 | Emitter.prototype.hasListeners = function(event){ 350 | return !! this.listeners(event).length; 351 | }; 352 | 353 | }); 354 | require.register("dropzone/index.js", function(exports, require, module){ 355 | 356 | 357 | /** 358 | * Exposing dropzone 359 | */ 360 | module.exports = require("./lib/dropzone.js"); 361 | 362 | }); 363 | require.register("dropzone/lib/dropzone.js", function(exports, require, module){ 364 | /* 365 | # 366 | # More info at [www.dropzonejs.com](http://www.dropzonejs.com) 367 | # 368 | # Copyright (c) 2012, Matias Meno 369 | # 370 | # Permission is hereby granted, free of charge, to any person obtaining a copy 371 | # of this software and associated documentation files (the "Software"), to deal 372 | # in the Software without restriction, including without limitation the rights 373 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 374 | # copies of the Software, and to permit persons to whom the Software is 375 | # furnished to do so, subject to the following conditions: 376 | # 377 | # The above copyright notice and this permission notice shall be included in 378 | # all copies or substantial portions of the Software. 379 | # 380 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 381 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 382 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 383 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 384 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 385 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 386 | # THE SOFTWARE. 387 | # 388 | */ 389 | 390 | 391 | (function() { 392 | var Dropzone, Em, camelize, contentLoaded, noop, without, 393 | __hasProp = {}.hasOwnProperty, 394 | __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; }, 395 | __slice = [].slice; 396 | 397 | Em = typeof Emitter !== "undefined" && Emitter !== null ? Emitter : require("emitter"); 398 | 399 | noop = function() {}; 400 | 401 | Dropzone = (function(_super) { 402 | var extend; 403 | 404 | __extends(Dropzone, _super); 405 | 406 | /* 407 | This is a list of all available events you can register on a dropzone object. 408 | 409 | You can register an event handler like this: 410 | 411 | dropzone.on("dragEnter", function() { }); 412 | */ 413 | 414 | 415 | Dropzone.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "selectedfiles", "addedfile", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached"]; 416 | 417 | Dropzone.prototype.defaultOptions = { 418 | url: null, 419 | method: "post", 420 | withCredentials: false, 421 | parallelUploads: 2, 422 | uploadMultiple: false, 423 | maxFilesize: 256, 424 | paramName: "file", 425 | createImageThumbnails: true, 426 | maxThumbnailFilesize: 10, 427 | thumbnailWidth: 100, 428 | thumbnailHeight: 100, 429 | maxFiles: null, 430 | params: {}, 431 | clickable: true, 432 | ignoreHiddenFiles: true, 433 | acceptedFiles: null, 434 | acceptedMimeTypes: null, 435 | autoProcessQueue: true, 436 | addRemoveLinks: false, 437 | previewsContainer: null, 438 | dictDefaultMessage: "Drop files here to upload", 439 | dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.", 440 | dictFallbackText: "Please use the fallback form below to upload your files like in the olden days.", 441 | dictFileTooBig: "File is too big ({{filesize}}MB). Max filesize: {{maxFilesize}}MB.", 442 | dictInvalidFileType: "You can't upload files of this type.", 443 | dictResponseError: "Server responded with {{statusCode}} code.", 444 | dictCancelUpload: "Cancel upload", 445 | dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?", 446 | dictRemoveFile: "Remove file", 447 | dictRemoveFileConfirmation: null, 448 | dictMaxFilesExceeded: "You can not upload any more files.", 449 | accept: function(file, done) { 450 | return done(); 451 | }, 452 | init: function() { 453 | return noop; 454 | }, 455 | forceFallback: false, 456 | fallback: function() { 457 | var child, messageElement, span, _i, _len, _ref; 458 | this.element.className = "" + this.element.className + " dz-browser-not-supported"; 459 | _ref = this.element.getElementsByTagName("div"); 460 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 461 | child = _ref[_i]; 462 | if (/(^| )dz-message($| )/.test(child.className)) { 463 | messageElement = child; 464 | child.className = "dz-message"; 465 | continue; 466 | } 467 | } 468 | if (!messageElement) { 469 | messageElement = Dropzone.createElement("
"); 470 | this.element.appendChild(messageElement); 471 | } 472 | span = messageElement.getElementsByTagName("span")[0]; 473 | if (span) { 474 | span.textContent = this.options.dictFallbackMessage; 475 | } 476 | return this.element.appendChild(this.getFallbackForm()); 477 | }, 478 | resize: function(file) { 479 | var info, srcRatio, trgRatio; 480 | info = { 481 | srcX: 0, 482 | srcY: 0, 483 | srcWidth: file.width, 484 | srcHeight: file.height 485 | }; 486 | srcRatio = file.width / file.height; 487 | trgRatio = this.options.thumbnailWidth / this.options.thumbnailHeight; 488 | if (file.height < this.options.thumbnailHeight || file.width < this.options.thumbnailWidth) { 489 | info.trgHeight = info.srcHeight; 490 | info.trgWidth = info.srcWidth; 491 | } else { 492 | if (srcRatio > trgRatio) { 493 | info.srcHeight = file.height; 494 | info.srcWidth = info.srcHeight * trgRatio; 495 | } else { 496 | info.srcWidth = file.width; 497 | info.srcHeight = info.srcWidth / trgRatio; 498 | } 499 | } 500 | info.srcX = (file.width - info.srcWidth) / 2; 501 | info.srcY = (file.height - info.srcHeight) / 2; 502 | return info; 503 | }, 504 | /* 505 | Those functions register themselves to the events on init and handle all 506 | the user interface specific stuff. Overwriting them won't break the upload 507 | but can break the way it's displayed. 508 | You can overwrite them if you don't like the default behavior. If you just 509 | want to add an additional event handler, register it on the dropzone object 510 | and don't overwrite those options. 511 | */ 512 | 513 | drop: function(e) { 514 | return this.element.classList.remove("dz-drag-hover"); 515 | }, 516 | dragstart: noop, 517 | dragend: function(e) { 518 | return this.element.classList.remove("dz-drag-hover"); 519 | }, 520 | dragenter: function(e) { 521 | return this.element.classList.add("dz-drag-hover"); 522 | }, 523 | dragover: function(e) { 524 | return this.element.classList.add("dz-drag-hover"); 525 | }, 526 | dragleave: function(e) { 527 | return this.element.classList.remove("dz-drag-hover"); 528 | }, 529 | selectedfiles: function(files) { 530 | if (this.element === this.previewsContainer) { 531 | return this.element.classList.add("dz-started"); 532 | } 533 | }, 534 | reset: function() { 535 | return this.element.classList.remove("dz-started"); 536 | }, 537 | addedfile: function(file) { 538 | var node, _i, _j, _len, _len1, _ref, _ref1, 539 | _this = this; 540 | file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim()); 541 | file.previewTemplate = file.previewElement; 542 | this.previewsContainer.appendChild(file.previewElement); 543 | _ref = file.previewElement.querySelectorAll("[data-dz-name]"); 544 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 545 | node = _ref[_i]; 546 | node.textContent = file.name; 547 | } 548 | _ref1 = file.previewElement.querySelectorAll("[data-dz-size]"); 549 | for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { 550 | node = _ref1[_j]; 551 | node.innerHTML = this.filesize(file.size); 552 | } 553 | if (this.options.addRemoveLinks) { 554 | file._removeLink = Dropzone.createElement("" + this.options.dictRemoveFile + ""); 555 | file._removeLink.addEventListener("click", function(e) { 556 | e.preventDefault(); 557 | e.stopPropagation(); 558 | if (file.status === Dropzone.UPLOADING) { 559 | return Dropzone.confirm(_this.options.dictCancelUploadConfirmation, function() { 560 | return _this.removeFile(file); 561 | }); 562 | } else { 563 | if (_this.options.dictRemoveFileConfirmation) { 564 | return Dropzone.confirm(_this.options.dictRemoveFileConfirmation, function() { 565 | return _this.removeFile(file); 566 | }); 567 | } else { 568 | return _this.removeFile(file); 569 | } 570 | } 571 | }); 572 | return file.previewElement.appendChild(file._removeLink); 573 | } 574 | }, 575 | removedfile: function(file) { 576 | var _ref; 577 | if ((_ref = file.previewElement) != null) { 578 | _ref.parentNode.removeChild(file.previewElement); 579 | } 580 | return this._updateMaxFilesReachedClass(); 581 | }, 582 | thumbnail: function(file, dataUrl) { 583 | var thumbnailElement, _i, _len, _ref, _results; 584 | file.previewElement.classList.remove("dz-file-preview"); 585 | file.previewElement.classList.add("dz-image-preview"); 586 | _ref = file.previewElement.querySelectorAll("[data-dz-thumbnail]"); 587 | _results = []; 588 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 589 | thumbnailElement = _ref[_i]; 590 | thumbnailElement.alt = file.name; 591 | _results.push(thumbnailElement.src = dataUrl); 592 | } 593 | return _results; 594 | }, 595 | error: function(file, message) { 596 | var node, _i, _len, _ref, _results; 597 | file.previewElement.classList.add("dz-error"); 598 | if (typeof message !== "String" && message.error) { 599 | message = message.error; 600 | } 601 | _ref = file.previewElement.querySelectorAll("[data-dz-errormessage]"); 602 | _results = []; 603 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 604 | node = _ref[_i]; 605 | _results.push(node.textContent = message); 606 | } 607 | return _results; 608 | }, 609 | errormultiple: noop, 610 | processing: function(file) { 611 | file.previewElement.classList.add("dz-processing"); 612 | if (file._removeLink) { 613 | return file._removeLink.textContent = this.options.dictCancelUpload; 614 | } 615 | }, 616 | processingmultiple: noop, 617 | uploadprogress: function(file, progress, bytesSent) { 618 | var node, _i, _len, _ref, _results; 619 | _ref = file.previewElement.querySelectorAll("[data-dz-uploadprogress]"); 620 | _results = []; 621 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 622 | node = _ref[_i]; 623 | _results.push(node.style.width = "" + progress + "%"); 624 | } 625 | return _results; 626 | }, 627 | totaluploadprogress: noop, 628 | sending: noop, 629 | sendingmultiple: noop, 630 | success: function(file) { 631 | return file.previewElement.classList.add("dz-success"); 632 | }, 633 | successmultiple: noop, 634 | canceled: function(file) { 635 | return this.emit("error", file, "Upload canceled."); 636 | }, 637 | canceledmultiple: noop, 638 | complete: function(file) { 639 | if (file._removeLink) { 640 | return file._removeLink.textContent = this.options.dictRemoveFile; 641 | } 642 | }, 643 | completemultiple: noop, 644 | maxfilesexceeded: noop, 645 | maxfilesreached: noop, 646 | previewTemplate: "
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
" 647 | }; 648 | 649 | extend = function() { 650 | var key, object, objects, target, val, _i, _len; 651 | target = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 652 | for (_i = 0, _len = objects.length; _i < _len; _i++) { 653 | object = objects[_i]; 654 | for (key in object) { 655 | val = object[key]; 656 | target[key] = val; 657 | } 658 | } 659 | return target; 660 | }; 661 | 662 | function Dropzone(element, options) { 663 | var elementOptions, fallback, _ref; 664 | this.element = element; 665 | this.version = Dropzone.version; 666 | this.defaultOptions.previewTemplate = this.defaultOptions.previewTemplate.replace(/\n*/g, ""); 667 | this.clickableElements = []; 668 | this.listeners = []; 669 | this.files = []; 670 | if (typeof this.element === "string") { 671 | this.element = document.querySelector(this.element); 672 | } 673 | if (!(this.element && (this.element.nodeType != null))) { 674 | throw new Error("Invalid dropzone element."); 675 | } 676 | if (this.element.dropzone) { 677 | throw new Error("Dropzone already attached."); 678 | } 679 | Dropzone.instances.push(this); 680 | this.element.dropzone = this; 681 | elementOptions = (_ref = Dropzone.optionsForElement(this.element)) != null ? _ref : {}; 682 | this.options = extend({}, this.defaultOptions, elementOptions, options != null ? options : {}); 683 | if (this.options.forceFallback || !Dropzone.isBrowserSupported()) { 684 | return this.options.fallback.call(this); 685 | } 686 | if (this.options.url == null) { 687 | this.options.url = this.element.getAttribute("action"); 688 | } 689 | if (!this.options.url) { 690 | throw new Error("No URL provided."); 691 | } 692 | if (this.options.acceptedFiles && this.options.acceptedMimeTypes) { 693 | throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated."); 694 | } 695 | if (this.options.acceptedMimeTypes) { 696 | this.options.acceptedFiles = this.options.acceptedMimeTypes; 697 | delete this.options.acceptedMimeTypes; 698 | } 699 | this.options.method = this.options.method.toUpperCase(); 700 | if ((fallback = this.getExistingFallback()) && fallback.parentNode) { 701 | fallback.parentNode.removeChild(fallback); 702 | } 703 | if (this.options.previewsContainer) { 704 | this.previewsContainer = Dropzone.getElement(this.options.previewsContainer, "previewsContainer"); 705 | } else { 706 | this.previewsContainer = this.element; 707 | } 708 | if (this.options.clickable) { 709 | if (this.options.clickable === true) { 710 | this.clickableElements = [this.element]; 711 | } else { 712 | this.clickableElements = Dropzone.getElements(this.options.clickable, "clickable"); 713 | } 714 | } 715 | this.init(); 716 | } 717 | 718 | Dropzone.prototype.getAcceptedFiles = function() { 719 | var file, _i, _len, _ref, _results; 720 | _ref = this.files; 721 | _results = []; 722 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 723 | file = _ref[_i]; 724 | if (file.accepted) { 725 | _results.push(file); 726 | } 727 | } 728 | return _results; 729 | }; 730 | 731 | Dropzone.prototype.getRejectedFiles = function() { 732 | var file, _i, _len, _ref, _results; 733 | _ref = this.files; 734 | _results = []; 735 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 736 | file = _ref[_i]; 737 | if (!file.accepted) { 738 | _results.push(file); 739 | } 740 | } 741 | return _results; 742 | }; 743 | 744 | Dropzone.prototype.getQueuedFiles = function() { 745 | var file, _i, _len, _ref, _results; 746 | _ref = this.files; 747 | _results = []; 748 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 749 | file = _ref[_i]; 750 | if (file.status === Dropzone.QUEUED) { 751 | _results.push(file); 752 | } 753 | } 754 | return _results; 755 | }; 756 | 757 | Dropzone.prototype.getUploadingFiles = function() { 758 | var file, _i, _len, _ref, _results; 759 | _ref = this.files; 760 | _results = []; 761 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 762 | file = _ref[_i]; 763 | if (file.status === Dropzone.UPLOADING) { 764 | _results.push(file); 765 | } 766 | } 767 | return _results; 768 | }; 769 | 770 | Dropzone.prototype.init = function() { 771 | var eventName, noPropagation, setupHiddenFileInput, _i, _len, _ref, _ref1, 772 | _this = this; 773 | if (this.element.tagName === "form") { 774 | this.element.setAttribute("enctype", "multipart/form-data"); 775 | } 776 | if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) { 777 | this.element.appendChild(Dropzone.createElement("
" + this.options.dictDefaultMessage + "
")); 778 | } 779 | if (this.clickableElements.length) { 780 | setupHiddenFileInput = function() { 781 | if (_this.hiddenFileInput) { 782 | document.body.removeChild(_this.hiddenFileInput); 783 | } 784 | _this.hiddenFileInput = document.createElement("input"); 785 | _this.hiddenFileInput.setAttribute("type", "file"); 786 | if ((_this.options.maxFiles == null) || _this.options.maxFiles > 1) { 787 | _this.hiddenFileInput.setAttribute("multiple", "multiple"); 788 | } 789 | if (_this.options.acceptedFiles != null) { 790 | _this.hiddenFileInput.setAttribute("accept", _this.options.acceptedFiles); 791 | } 792 | _this.hiddenFileInput.style.visibility = "hidden"; 793 | _this.hiddenFileInput.style.position = "absolute"; 794 | _this.hiddenFileInput.style.top = "0"; 795 | _this.hiddenFileInput.style.left = "0"; 796 | _this.hiddenFileInput.style.height = "0"; 797 | _this.hiddenFileInput.style.width = "0"; 798 | document.body.appendChild(_this.hiddenFileInput); 799 | return _this.hiddenFileInput.addEventListener("change", function() { 800 | var files; 801 | files = _this.hiddenFileInput.files; 802 | if (files.length) { 803 | _this.emit("selectedfiles", files); 804 | _this.handleFiles(files); 805 | } 806 | return setupHiddenFileInput(); 807 | }); 808 | }; 809 | setupHiddenFileInput(); 810 | } 811 | this.URL = (_ref = window.URL) != null ? _ref : window.webkitURL; 812 | _ref1 = this.events; 813 | for (_i = 0, _len = _ref1.length; _i < _len; _i++) { 814 | eventName = _ref1[_i]; 815 | this.on(eventName, this.options[eventName]); 816 | } 817 | this.on("uploadprogress", function() { 818 | return _this.updateTotalUploadProgress(); 819 | }); 820 | this.on("removedfile", function() { 821 | return _this.updateTotalUploadProgress(); 822 | }); 823 | this.on("canceled", function(file) { 824 | return _this.emit("complete", file); 825 | }); 826 | noPropagation = function(e) { 827 | e.stopPropagation(); 828 | if (e.preventDefault) { 829 | return e.preventDefault(); 830 | } else { 831 | return e.returnValue = false; 832 | } 833 | }; 834 | this.listeners = [ 835 | { 836 | element: this.element, 837 | events: { 838 | "dragstart": function(e) { 839 | return _this.emit("dragstart", e); 840 | }, 841 | "dragenter": function(e) { 842 | noPropagation(e); 843 | return _this.emit("dragenter", e); 844 | }, 845 | "dragover": function(e) { 846 | var efct; 847 | efct = e.dataTransfer.effectAllowed; 848 | e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy'; 849 | noPropagation(e); 850 | return _this.emit("dragover", e); 851 | }, 852 | "dragleave": function(e) { 853 | return _this.emit("dragleave", e); 854 | }, 855 | "drop": function(e) { 856 | noPropagation(e); 857 | return _this.drop(e); 858 | }, 859 | "dragend": function(e) { 860 | return _this.emit("dragend", e); 861 | } 862 | } 863 | } 864 | ]; 865 | this.clickableElements.forEach(function(clickableElement) { 866 | return _this.listeners.push({ 867 | element: clickableElement, 868 | events: { 869 | "click": function(evt) { 870 | if ((clickableElement !== _this.element) || (evt.target === _this.element || Dropzone.elementInside(evt.target, _this.element.querySelector(".dz-message")))) { 871 | return _this.hiddenFileInput.click(); 872 | } 873 | } 874 | } 875 | }); 876 | }); 877 | this.enable(); 878 | return this.options.init.call(this); 879 | }; 880 | 881 | Dropzone.prototype.destroy = function() { 882 | var _ref; 883 | this.disable(); 884 | this.removeAllFiles(true); 885 | if ((_ref = this.hiddenFileInput) != null ? _ref.parentNode : void 0) { 886 | this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput); 887 | this.hiddenFileInput = null; 888 | } 889 | delete this.element.dropzone; 890 | return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1); 891 | }; 892 | 893 | Dropzone.prototype.updateTotalUploadProgress = function() { 894 | var acceptedFiles, file, totalBytes, totalBytesSent, totalUploadProgress, _i, _len, _ref; 895 | totalBytesSent = 0; 896 | totalBytes = 0; 897 | acceptedFiles = this.getAcceptedFiles(); 898 | if (acceptedFiles.length) { 899 | _ref = this.getAcceptedFiles(); 900 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 901 | file = _ref[_i]; 902 | totalBytesSent += file.upload.bytesSent; 903 | totalBytes += file.upload.total; 904 | } 905 | totalUploadProgress = 100 * totalBytesSent / totalBytes; 906 | } else { 907 | totalUploadProgress = 100; 908 | } 909 | return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent); 910 | }; 911 | 912 | Dropzone.prototype.getFallbackForm = function() { 913 | var existingFallback, fields, fieldsString, form; 914 | if (existingFallback = this.getExistingFallback()) { 915 | return existingFallback; 916 | } 917 | fieldsString = "
"; 918 | if (this.options.dictFallbackText) { 919 | fieldsString += "

" + this.options.dictFallbackText + "

"; 920 | } 921 | fieldsString += "
"; 922 | fields = Dropzone.createElement(fieldsString); 923 | if (this.element.tagName !== "FORM") { 924 | form = Dropzone.createElement("
"); 925 | form.appendChild(fields); 926 | } else { 927 | this.element.setAttribute("enctype", "multipart/form-data"); 928 | this.element.setAttribute("method", this.options.method); 929 | } 930 | return form != null ? form : fields; 931 | }; 932 | 933 | Dropzone.prototype.getExistingFallback = function() { 934 | var fallback, getFallback, tagName, _i, _len, _ref; 935 | getFallback = function(elements) { 936 | var el, _i, _len; 937 | for (_i = 0, _len = elements.length; _i < _len; _i++) { 938 | el = elements[_i]; 939 | if (/(^| )fallback($| )/.test(el.className)) { 940 | return el; 941 | } 942 | } 943 | }; 944 | _ref = ["div", "form"]; 945 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 946 | tagName = _ref[_i]; 947 | if (fallback = getFallback(this.element.getElementsByTagName(tagName))) { 948 | return fallback; 949 | } 950 | } 951 | }; 952 | 953 | Dropzone.prototype.setupEventListeners = function() { 954 | var elementListeners, event, listener, _i, _len, _ref, _results; 955 | _ref = this.listeners; 956 | _results = []; 957 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 958 | elementListeners = _ref[_i]; 959 | _results.push((function() { 960 | var _ref1, _results1; 961 | _ref1 = elementListeners.events; 962 | _results1 = []; 963 | for (event in _ref1) { 964 | listener = _ref1[event]; 965 | _results1.push(elementListeners.element.addEventListener(event, listener, false)); 966 | } 967 | return _results1; 968 | })()); 969 | } 970 | return _results; 971 | }; 972 | 973 | Dropzone.prototype.removeEventListeners = function() { 974 | var elementListeners, event, listener, _i, _len, _ref, _results; 975 | _ref = this.listeners; 976 | _results = []; 977 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 978 | elementListeners = _ref[_i]; 979 | _results.push((function() { 980 | var _ref1, _results1; 981 | _ref1 = elementListeners.events; 982 | _results1 = []; 983 | for (event in _ref1) { 984 | listener = _ref1[event]; 985 | _results1.push(elementListeners.element.removeEventListener(event, listener, false)); 986 | } 987 | return _results1; 988 | })()); 989 | } 990 | return _results; 991 | }; 992 | 993 | Dropzone.prototype.disable = function() { 994 | var file, _i, _len, _ref, _results; 995 | this.clickableElements.forEach(function(element) { 996 | return element.classList.remove("dz-clickable"); 997 | }); 998 | this.removeEventListeners(); 999 | _ref = this.files; 1000 | _results = []; 1001 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 1002 | file = _ref[_i]; 1003 | _results.push(this.cancelUpload(file)); 1004 | } 1005 | return _results; 1006 | }; 1007 | 1008 | Dropzone.prototype.enable = function() { 1009 | this.clickableElements.forEach(function(element) { 1010 | return element.classList.add("dz-clickable"); 1011 | }); 1012 | return this.setupEventListeners(); 1013 | }; 1014 | 1015 | Dropzone.prototype.filesize = function(size) { 1016 | var string; 1017 | if (size >= 1024 * 1024 * 1024 * 1024 / 10) { 1018 | size = size / (1024 * 1024 * 1024 * 1024 / 10); 1019 | string = "TiB"; 1020 | } else if (size >= 1024 * 1024 * 1024 / 10) { 1021 | size = size / (1024 * 1024 * 1024 / 10); 1022 | string = "GiB"; 1023 | } else if (size >= 1024 * 1024 / 10) { 1024 | size = size / (1024 * 1024 / 10); 1025 | string = "MiB"; 1026 | } else if (size >= 1024 / 10) { 1027 | size = size / (1024 / 10); 1028 | string = "KiB"; 1029 | } else { 1030 | size = size * 10; 1031 | string = "b"; 1032 | } 1033 | return "" + (Math.round(size) / 10) + " " + string; 1034 | }; 1035 | 1036 | Dropzone.prototype._updateMaxFilesReachedClass = function() { 1037 | if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) { 1038 | if (this.getAcceptedFiles().length === this.options.maxFiles) { 1039 | this.emit('maxfilesreached', this.files); 1040 | } 1041 | return this.element.classList.add("dz-max-files-reached"); 1042 | } else { 1043 | return this.element.classList.remove("dz-max-files-reached"); 1044 | } 1045 | }; 1046 | 1047 | Dropzone.prototype.drop = function(e) { 1048 | var files, items; 1049 | if (!e.dataTransfer) { 1050 | return; 1051 | } 1052 | this.emit("drop", e); 1053 | files = e.dataTransfer.files; 1054 | this.emit("selectedfiles", files); 1055 | if (files.length) { 1056 | items = e.dataTransfer.items; 1057 | if (items && items.length && ((items[0].webkitGetAsEntry != null) || (items[0].getAsEntry != null))) { 1058 | this.handleItems(items); 1059 | } else { 1060 | this.handleFiles(files); 1061 | } 1062 | } 1063 | }; 1064 | 1065 | Dropzone.prototype.handleFiles = function(files) { 1066 | var file, _i, _len, _results; 1067 | _results = []; 1068 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1069 | file = files[_i]; 1070 | _results.push(this.addFile(file)); 1071 | } 1072 | return _results; 1073 | }; 1074 | 1075 | Dropzone.prototype.handleItems = function(items) { 1076 | var entry, item, _i, _len; 1077 | for (_i = 0, _len = items.length; _i < _len; _i++) { 1078 | item = items[_i]; 1079 | if (item.webkitGetAsEntry != null) { 1080 | entry = item.webkitGetAsEntry(); 1081 | if (entry.isFile) { 1082 | this.addFile(item.getAsFile()); 1083 | } else if (entry.isDirectory) { 1084 | this.addDirectory(entry, entry.name); 1085 | } 1086 | } else { 1087 | this.addFile(item.getAsFile()); 1088 | } 1089 | } 1090 | }; 1091 | 1092 | Dropzone.prototype.accept = function(file, done) { 1093 | if (file.size > this.options.maxFilesize * 1024 * 1024) { 1094 | return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize)); 1095 | } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) { 1096 | return done(this.options.dictInvalidFileType); 1097 | } else if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) { 1098 | done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles)); 1099 | return this.emit("maxfilesexceeded", file); 1100 | } else { 1101 | return this.options.accept.call(this, file, done); 1102 | } 1103 | }; 1104 | 1105 | Dropzone.prototype.addFile = function(file) { 1106 | var _this = this; 1107 | file.upload = { 1108 | progress: 0, 1109 | total: file.size, 1110 | bytesSent: 0 1111 | }; 1112 | this.files.push(file); 1113 | file.status = Dropzone.ADDED; 1114 | this.emit("addedfile", file); 1115 | if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) { 1116 | this.createThumbnail(file); 1117 | } 1118 | return this.accept(file, function(error) { 1119 | if (error) { 1120 | file.accepted = false; 1121 | _this._errorProcessing([file], error); 1122 | } else { 1123 | _this.enqueueFile(file); 1124 | } 1125 | return _this._updateMaxFilesReachedClass(); 1126 | }); 1127 | }; 1128 | 1129 | Dropzone.prototype.enqueueFiles = function(files) { 1130 | var file, _i, _len; 1131 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1132 | file = files[_i]; 1133 | this.enqueueFile(file); 1134 | } 1135 | return null; 1136 | }; 1137 | 1138 | Dropzone.prototype.enqueueFile = function(file) { 1139 | var _this = this; 1140 | file.accepted = true; 1141 | if (file.status === Dropzone.ADDED) { 1142 | file.status = Dropzone.QUEUED; 1143 | if (this.options.autoProcessQueue) { 1144 | return setTimeout((function() { 1145 | return _this.processQueue(); 1146 | }), 1); 1147 | } 1148 | } else { 1149 | throw new Error("This file can't be queued because it has already been processed or was rejected."); 1150 | } 1151 | }; 1152 | 1153 | Dropzone.prototype.addDirectory = function(entry, path) { 1154 | var dirReader, entriesReader, 1155 | _this = this; 1156 | dirReader = entry.createReader(); 1157 | entriesReader = function(entries) { 1158 | var _i, _len; 1159 | for (_i = 0, _len = entries.length; _i < _len; _i++) { 1160 | entry = entries[_i]; 1161 | if (entry.isFile) { 1162 | entry.file(function(file) { 1163 | if (_this.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') { 1164 | return; 1165 | } 1166 | file.fullPath = "" + path + "/" + file.name; 1167 | return _this.addFile(file); 1168 | }); 1169 | } else if (entry.isDirectory) { 1170 | _this.addDirectory(entry, "" + path + "/" + entry.name); 1171 | } 1172 | } 1173 | }; 1174 | return dirReader.readEntries(entriesReader, function(error) { 1175 | return typeof console !== "undefined" && console !== null ? typeof console.log === "function" ? console.log(error) : void 0 : void 0; 1176 | }); 1177 | }; 1178 | 1179 | Dropzone.prototype.removeFile = function(file) { 1180 | if (file.status === Dropzone.UPLOADING) { 1181 | this.cancelUpload(file); 1182 | } 1183 | this.files = without(this.files, file); 1184 | this.emit("removedfile", file); 1185 | if (this.files.length === 0) { 1186 | return this.emit("reset"); 1187 | } 1188 | }; 1189 | 1190 | Dropzone.prototype.removeAllFiles = function(cancelIfNecessary) { 1191 | var file, _i, _len, _ref; 1192 | if (cancelIfNecessary == null) { 1193 | cancelIfNecessary = false; 1194 | } 1195 | _ref = this.files.slice(); 1196 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 1197 | file = _ref[_i]; 1198 | if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) { 1199 | this.removeFile(file); 1200 | } 1201 | } 1202 | return null; 1203 | }; 1204 | 1205 | Dropzone.prototype.createThumbnail = function(file) { 1206 | var fileReader, 1207 | _this = this; 1208 | fileReader = new FileReader; 1209 | fileReader.onload = function() { 1210 | var img; 1211 | img = document.createElement("img"); 1212 | img.onload = function() { 1213 | var canvas, ctx, resizeInfo, thumbnail, _ref, _ref1, _ref2, _ref3; 1214 | file.width = img.width; 1215 | file.height = img.height; 1216 | resizeInfo = _this.options.resize.call(_this, file); 1217 | if (resizeInfo.trgWidth == null) { 1218 | resizeInfo.trgWidth = _this.options.thumbnailWidth; 1219 | } 1220 | if (resizeInfo.trgHeight == null) { 1221 | resizeInfo.trgHeight = _this.options.thumbnailHeight; 1222 | } 1223 | canvas = document.createElement("canvas"); 1224 | ctx = canvas.getContext("2d"); 1225 | canvas.width = resizeInfo.trgWidth; 1226 | canvas.height = resizeInfo.trgHeight; 1227 | ctx.drawImage(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); 1228 | thumbnail = canvas.toDataURL("image/png"); 1229 | return _this.emit("thumbnail", file, thumbnail); 1230 | }; 1231 | return img.src = fileReader.result; 1232 | }; 1233 | return fileReader.readAsDataURL(file); 1234 | }; 1235 | 1236 | Dropzone.prototype.processQueue = function() { 1237 | var i, parallelUploads, processingLength, queuedFiles; 1238 | parallelUploads = this.options.parallelUploads; 1239 | processingLength = this.getUploadingFiles().length; 1240 | i = processingLength; 1241 | if (processingLength >= parallelUploads) { 1242 | return; 1243 | } 1244 | queuedFiles = this.getQueuedFiles(); 1245 | if (!(queuedFiles.length > 0)) { 1246 | return; 1247 | } 1248 | if (this.options.uploadMultiple) { 1249 | return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength)); 1250 | } else { 1251 | while (i < parallelUploads) { 1252 | if (!queuedFiles.length) { 1253 | return; 1254 | } 1255 | this.processFile(queuedFiles.shift()); 1256 | i++; 1257 | } 1258 | } 1259 | }; 1260 | 1261 | Dropzone.prototype.processFile = function(file) { 1262 | return this.processFiles([file]); 1263 | }; 1264 | 1265 | Dropzone.prototype.processFiles = function(files) { 1266 | var file, _i, _len; 1267 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1268 | file = files[_i]; 1269 | file.processing = true; 1270 | file.status = Dropzone.UPLOADING; 1271 | this.emit("processing", file); 1272 | } 1273 | if (this.options.uploadMultiple) { 1274 | this.emit("processingmultiple", files); 1275 | } 1276 | return this.uploadFiles(files); 1277 | }; 1278 | 1279 | Dropzone.prototype._getFilesWithXhr = function(xhr) { 1280 | var file, files; 1281 | return files = (function() { 1282 | var _i, _len, _ref, _results; 1283 | _ref = this.files; 1284 | _results = []; 1285 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 1286 | file = _ref[_i]; 1287 | if (file.xhr === xhr) { 1288 | _results.push(file); 1289 | } 1290 | } 1291 | return _results; 1292 | }).call(this); 1293 | }; 1294 | 1295 | Dropzone.prototype.cancelUpload = function(file) { 1296 | var groupedFile, groupedFiles, _i, _j, _len, _len1, _ref; 1297 | if (file.status === Dropzone.UPLOADING) { 1298 | groupedFiles = this._getFilesWithXhr(file.xhr); 1299 | for (_i = 0, _len = groupedFiles.length; _i < _len; _i++) { 1300 | groupedFile = groupedFiles[_i]; 1301 | groupedFile.status = Dropzone.CANCELED; 1302 | } 1303 | file.xhr.abort(); 1304 | for (_j = 0, _len1 = groupedFiles.length; _j < _len1; _j++) { 1305 | groupedFile = groupedFiles[_j]; 1306 | this.emit("canceled", groupedFile); 1307 | } 1308 | if (this.options.uploadMultiple) { 1309 | this.emit("canceledmultiple", groupedFiles); 1310 | } 1311 | } else if ((_ref = file.status) === Dropzone.ADDED || _ref === Dropzone.QUEUED) { 1312 | file.status = Dropzone.CANCELED; 1313 | this.emit("canceled", file); 1314 | if (this.options.uploadMultiple) { 1315 | this.emit("canceledmultiple", [file]); 1316 | } 1317 | } 1318 | if (this.options.autoProcessQueue) { 1319 | return this.processQueue(); 1320 | } 1321 | }; 1322 | 1323 | Dropzone.prototype.uploadFile = function(file) { 1324 | return this.uploadFiles([file]); 1325 | }; 1326 | 1327 | Dropzone.prototype.uploadFiles = function(files) { 1328 | var file, formData, handleError, headerName, headerValue, headers, input, inputName, inputType, key, option, progressObj, response, updateProgress, value, xhr, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref, _ref1, _ref2, _ref3, _ref4, 1329 | _this = this; 1330 | xhr = new XMLHttpRequest(); 1331 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1332 | file = files[_i]; 1333 | file.xhr = xhr; 1334 | } 1335 | xhr.open(this.options.method, this.options.url, true); 1336 | xhr.withCredentials = !!this.options.withCredentials; 1337 | response = null; 1338 | handleError = function() { 1339 | var _j, _len1, _results; 1340 | _results = []; 1341 | for (_j = 0, _len1 = files.length; _j < _len1; _j++) { 1342 | file = files[_j]; 1343 | _results.push(_this._errorProcessing(files, response || _this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr)); 1344 | } 1345 | return _results; 1346 | }; 1347 | updateProgress = function(e) { 1348 | var allFilesFinished, progress, _j, _k, _l, _len1, _len2, _len3, _results; 1349 | if (e != null) { 1350 | progress = 100 * e.loaded / e.total; 1351 | for (_j = 0, _len1 = files.length; _j < _len1; _j++) { 1352 | file = files[_j]; 1353 | file.upload = { 1354 | progress: progress, 1355 | total: e.total, 1356 | bytesSent: e.loaded 1357 | }; 1358 | } 1359 | } else { 1360 | allFilesFinished = true; 1361 | progress = 100; 1362 | for (_k = 0, _len2 = files.length; _k < _len2; _k++) { 1363 | file = files[_k]; 1364 | if (!(file.upload.progress === 100 && file.upload.bytesSent === file.upload.total)) { 1365 | allFilesFinished = false; 1366 | } 1367 | file.upload.progress = progress; 1368 | file.upload.bytesSent = file.upload.total; 1369 | } 1370 | if (allFilesFinished) { 1371 | return; 1372 | } 1373 | } 1374 | _results = []; 1375 | for (_l = 0, _len3 = files.length; _l < _len3; _l++) { 1376 | file = files[_l]; 1377 | _results.push(_this.emit("uploadprogress", file, progress, file.upload.bytesSent)); 1378 | } 1379 | return _results; 1380 | }; 1381 | xhr.onload = function(e) { 1382 | var _ref; 1383 | if (files[0].status === Dropzone.CANCELED) { 1384 | return; 1385 | } 1386 | if (xhr.readyState !== 4) { 1387 | return; 1388 | } 1389 | response = xhr.responseText; 1390 | if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) { 1391 | try { 1392 | response = JSON.parse(response); 1393 | } catch (_error) { 1394 | e = _error; 1395 | response = "Invalid JSON response from server."; 1396 | } 1397 | } 1398 | updateProgress(); 1399 | if (!((200 <= (_ref = xhr.status) && _ref < 300))) { 1400 | return handleError(); 1401 | } else { 1402 | return _this._finished(files, response, e); 1403 | } 1404 | }; 1405 | xhr.onerror = function() { 1406 | if (files[0].status === Dropzone.CANCELED) { 1407 | return; 1408 | } 1409 | return handleError(); 1410 | }; 1411 | progressObj = (_ref = xhr.upload) != null ? _ref : xhr; 1412 | progressObj.onprogress = updateProgress; 1413 | headers = { 1414 | "Accept": "application/json", 1415 | "Cache-Control": "no-cache", 1416 | "X-Requested-With": "XMLHttpRequest" 1417 | }; 1418 | if (this.options.headers) { 1419 | extend(headers, this.options.headers); 1420 | } 1421 | for (headerName in headers) { 1422 | headerValue = headers[headerName]; 1423 | xhr.setRequestHeader(headerName, headerValue); 1424 | } 1425 | formData = new FormData(); 1426 | if (this.options.params) { 1427 | _ref1 = this.options.params; 1428 | for (key in _ref1) { 1429 | value = _ref1[key]; 1430 | formData.append(key, value); 1431 | } 1432 | } 1433 | for (_j = 0, _len1 = files.length; _j < _len1; _j++) { 1434 | file = files[_j]; 1435 | this.emit("sending", file, xhr, formData); 1436 | } 1437 | if (this.options.uploadMultiple) { 1438 | this.emit("sendingmultiple", files, xhr, formData); 1439 | } 1440 | if (this.element.tagName === "FORM") { 1441 | _ref2 = this.element.querySelectorAll("input, textarea, select, button"); 1442 | for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { 1443 | input = _ref2[_k]; 1444 | inputName = input.getAttribute("name"); 1445 | inputType = input.getAttribute("type"); 1446 | if (input.tagName === "SELECT" && input.hasAttribute("multiple")) { 1447 | _ref3 = input.options; 1448 | for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { 1449 | option = _ref3[_l]; 1450 | if (option.selected) { 1451 | formData.append(inputName, option.value); 1452 | } 1453 | } 1454 | } else if (!inputType || ((_ref4 = inputType.toLowerCase()) !== "checkbox" && _ref4 !== "radio") || input.checked) { 1455 | formData.append(inputName, input.value); 1456 | } 1457 | } 1458 | } 1459 | for (_m = 0, _len4 = files.length; _m < _len4; _m++) { 1460 | file = files[_m]; 1461 | formData.append("" + this.options.paramName + (this.options.uploadMultiple ? "[]" : ""), file, file.name); 1462 | } 1463 | return xhr.send(formData); 1464 | }; 1465 | 1466 | Dropzone.prototype._finished = function(files, responseText, e) { 1467 | var file, _i, _len; 1468 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1469 | file = files[_i]; 1470 | file.status = Dropzone.SUCCESS; 1471 | this.emit("success", file, responseText, e); 1472 | this.emit("complete", file); 1473 | } 1474 | if (this.options.uploadMultiple) { 1475 | this.emit("successmultiple", files, responseText, e); 1476 | this.emit("completemultiple", files); 1477 | } 1478 | if (this.options.autoProcessQueue) { 1479 | return this.processQueue(); 1480 | } 1481 | }; 1482 | 1483 | Dropzone.prototype._errorProcessing = function(files, message, xhr) { 1484 | var file, _i, _len; 1485 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1486 | file = files[_i]; 1487 | file.status = Dropzone.ERROR; 1488 | this.emit("error", file, message, xhr); 1489 | this.emit("complete", file); 1490 | } 1491 | if (this.options.uploadMultiple) { 1492 | this.emit("errormultiple", files, message, xhr); 1493 | this.emit("completemultiple", files); 1494 | } 1495 | if (this.options.autoProcessQueue) { 1496 | return this.processQueue(); 1497 | } 1498 | }; 1499 | 1500 | return Dropzone; 1501 | 1502 | })(Em); 1503 | 1504 | Dropzone.version = "3.7.5-dev"; 1505 | 1506 | Dropzone.options = {}; 1507 | 1508 | Dropzone.optionsForElement = function(element) { 1509 | if (element.getAttribute("id")) { 1510 | return Dropzone.options[camelize(element.getAttribute("id"))]; 1511 | } else { 1512 | return void 0; 1513 | } 1514 | }; 1515 | 1516 | Dropzone.instances = []; 1517 | 1518 | Dropzone.forElement = function(element) { 1519 | if (typeof element === "string") { 1520 | element = document.querySelector(element); 1521 | } 1522 | if ((element != null ? element.dropzone : void 0) == null) { 1523 | 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."); 1524 | } 1525 | return element.dropzone; 1526 | }; 1527 | 1528 | Dropzone.autoDiscover = true; 1529 | 1530 | Dropzone.discover = function() { 1531 | var checkElements, dropzone, dropzones, _i, _len, _results; 1532 | if (document.querySelectorAll) { 1533 | dropzones = document.querySelectorAll(".dropzone"); 1534 | } else { 1535 | dropzones = []; 1536 | checkElements = function(elements) { 1537 | var el, _i, _len, _results; 1538 | _results = []; 1539 | for (_i = 0, _len = elements.length; _i < _len; _i++) { 1540 | el = elements[_i]; 1541 | if (/(^| )dropzone($| )/.test(el.className)) { 1542 | _results.push(dropzones.push(el)); 1543 | } else { 1544 | _results.push(void 0); 1545 | } 1546 | } 1547 | return _results; 1548 | }; 1549 | checkElements(document.getElementsByTagName("div")); 1550 | checkElements(document.getElementsByTagName("form")); 1551 | } 1552 | _results = []; 1553 | for (_i = 0, _len = dropzones.length; _i < _len; _i++) { 1554 | dropzone = dropzones[_i]; 1555 | if (Dropzone.optionsForElement(dropzone) !== false) { 1556 | _results.push(new Dropzone(dropzone)); 1557 | } else { 1558 | _results.push(void 0); 1559 | } 1560 | } 1561 | return _results; 1562 | }; 1563 | 1564 | Dropzone.blacklistedBrowsers = [/opera.*Macintosh.*version\/12/i]; 1565 | 1566 | Dropzone.isBrowserSupported = function() { 1567 | var capableBrowser, regex, _i, _len, _ref; 1568 | capableBrowser = true; 1569 | if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) { 1570 | if (!("classList" in document.createElement("a"))) { 1571 | capableBrowser = false; 1572 | } else { 1573 | _ref = Dropzone.blacklistedBrowsers; 1574 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 1575 | regex = _ref[_i]; 1576 | if (regex.test(navigator.userAgent)) { 1577 | capableBrowser = false; 1578 | continue; 1579 | } 1580 | } 1581 | } 1582 | } else { 1583 | capableBrowser = false; 1584 | } 1585 | return capableBrowser; 1586 | }; 1587 | 1588 | without = function(list, rejectedItem) { 1589 | var item, _i, _len, _results; 1590 | _results = []; 1591 | for (_i = 0, _len = list.length; _i < _len; _i++) { 1592 | item = list[_i]; 1593 | if (item !== rejectedItem) { 1594 | _results.push(item); 1595 | } 1596 | } 1597 | return _results; 1598 | }; 1599 | 1600 | camelize = function(str) { 1601 | return str.replace(/[\-_](\w)/g, function(match) { 1602 | return match[1].toUpperCase(); 1603 | }); 1604 | }; 1605 | 1606 | Dropzone.createElement = function(string) { 1607 | var div; 1608 | div = document.createElement("div"); 1609 | div.innerHTML = string; 1610 | return div.childNodes[0]; 1611 | }; 1612 | 1613 | Dropzone.elementInside = function(element, container) { 1614 | if (element === container) { 1615 | return true; 1616 | } 1617 | while (element = element.parentNode) { 1618 | if (element === container) { 1619 | return true; 1620 | } 1621 | } 1622 | return false; 1623 | }; 1624 | 1625 | Dropzone.getElement = function(el, name) { 1626 | var element; 1627 | if (typeof el === "string") { 1628 | element = document.querySelector(el); 1629 | } else if (el.nodeType != null) { 1630 | element = el; 1631 | } 1632 | if (element == null) { 1633 | throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element."); 1634 | } 1635 | return element; 1636 | }; 1637 | 1638 | Dropzone.getElements = function(els, name) { 1639 | var e, el, elements, _i, _j, _len, _len1, _ref; 1640 | if (els instanceof Array) { 1641 | elements = []; 1642 | try { 1643 | for (_i = 0, _len = els.length; _i < _len; _i++) { 1644 | el = els[_i]; 1645 | elements.push(this.getElement(el, name)); 1646 | } 1647 | } catch (_error) { 1648 | e = _error; 1649 | elements = null; 1650 | } 1651 | } else if (typeof els === "string") { 1652 | elements = []; 1653 | _ref = document.querySelectorAll(els); 1654 | for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { 1655 | el = _ref[_j]; 1656 | elements.push(el); 1657 | } 1658 | } else if (els.nodeType != null) { 1659 | elements = [els]; 1660 | } 1661 | if (!((elements != null) && elements.length)) { 1662 | throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those."); 1663 | } 1664 | return elements; 1665 | }; 1666 | 1667 | Dropzone.confirm = function(question, accepted, rejected) { 1668 | if (window.confirm(question)) { 1669 | return accepted(); 1670 | } else if (rejected != null) { 1671 | return rejected(); 1672 | } 1673 | }; 1674 | 1675 | Dropzone.isValidFile = function(file, acceptedFiles) { 1676 | var baseMimeType, mimeType, validType, _i, _len; 1677 | if (!acceptedFiles) { 1678 | return true; 1679 | } 1680 | acceptedFiles = acceptedFiles.split(","); 1681 | mimeType = file.type; 1682 | baseMimeType = mimeType.replace(/\/.*$/, ""); 1683 | for (_i = 0, _len = acceptedFiles.length; _i < _len; _i++) { 1684 | validType = acceptedFiles[_i]; 1685 | validType = validType.trim(); 1686 | if (validType.charAt(0) === ".") { 1687 | if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) { 1688 | return true; 1689 | } 1690 | } else if (/\/\*$/.test(validType)) { 1691 | if (baseMimeType === validType.replace(/\/.*$/, "")) { 1692 | return true; 1693 | } 1694 | } else { 1695 | if (mimeType === validType) { 1696 | return true; 1697 | } 1698 | } 1699 | } 1700 | return false; 1701 | }; 1702 | 1703 | if (typeof jQuery !== "undefined" && jQuery !== null) { 1704 | jQuery.fn.dropzone = function(options) { 1705 | return this.each(function() { 1706 | return new Dropzone(this, options); 1707 | }); 1708 | }; 1709 | } 1710 | 1711 | if (typeof module !== "undefined" && module !== null) { 1712 | module.exports = Dropzone; 1713 | } else { 1714 | window.Dropzone = Dropzone; 1715 | } 1716 | 1717 | Dropzone.ADDED = "added"; 1718 | 1719 | Dropzone.QUEUED = "queued"; 1720 | 1721 | Dropzone.ACCEPTED = Dropzone.QUEUED; 1722 | 1723 | Dropzone.UPLOADING = "uploading"; 1724 | 1725 | Dropzone.PROCESSING = Dropzone.UPLOADING; 1726 | 1727 | Dropzone.CANCELED = "canceled"; 1728 | 1729 | Dropzone.ERROR = "error"; 1730 | 1731 | Dropzone.SUCCESS = "success"; 1732 | 1733 | /* 1734 | # contentloaded.js 1735 | # 1736 | # Author: Diego Perini (diego.perini at gmail.com) 1737 | # Summary: cross-browser wrapper for DOMContentLoaded 1738 | # Updated: 20101020 1739 | # License: MIT 1740 | # Version: 1.2 1741 | # 1742 | # URL: 1743 | # http://javascript.nwbox.com/ContentLoaded/ 1744 | # http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE 1745 | */ 1746 | 1747 | 1748 | contentLoaded = function(win, fn) { 1749 | var add, doc, done, init, poll, pre, rem, root, top; 1750 | done = false; 1751 | top = true; 1752 | doc = win.document; 1753 | root = doc.documentElement; 1754 | add = (doc.addEventListener ? "addEventListener" : "attachEvent"); 1755 | rem = (doc.addEventListener ? "removeEventListener" : "detachEvent"); 1756 | pre = (doc.addEventListener ? "" : "on"); 1757 | init = function(e) { 1758 | if (e.type === "readystatechange" && doc.readyState !== "complete") { 1759 | return; 1760 | } 1761 | (e.type === "load" ? win : doc)[rem](pre + e.type, init, false); 1762 | if (!done && (done = true)) { 1763 | return fn.call(win, e.type || e); 1764 | } 1765 | }; 1766 | poll = function() { 1767 | var e; 1768 | try { 1769 | root.doScroll("left"); 1770 | } catch (_error) { 1771 | e = _error; 1772 | setTimeout(poll, 50); 1773 | return; 1774 | } 1775 | return init("poll"); 1776 | }; 1777 | if (doc.readyState !== "complete") { 1778 | if (doc.createEventObject && root.doScroll) { 1779 | try { 1780 | top = !win.frameElement; 1781 | } catch (_error) {} 1782 | if (top) { 1783 | poll(); 1784 | } 1785 | } 1786 | doc[add](pre + "DOMContentLoaded", init, false); 1787 | doc[add](pre + "readystatechange", init, false); 1788 | return win[add](pre + "load", init, false); 1789 | } 1790 | }; 1791 | 1792 | Dropzone._autoDiscoverFunction = function() { 1793 | if (Dropzone.autoDiscover) { 1794 | return Dropzone.discover(); 1795 | } 1796 | }; 1797 | 1798 | contentLoaded(window, Dropzone._autoDiscoverFunction); 1799 | 1800 | }).call(this); 1801 | 1802 | }); 1803 | require.alias("component-emitter/index.js", "dropzone/deps/emitter/index.js"); 1804 | require.alias("component-emitter/index.js", "emitter/index.js"); 1805 | if (typeof exports == "object") { 1806 | module.exports = require("dropzone"); 1807 | } else if (typeof define == "function" && define.amd) { 1808 | define(function(){ return require("dropzone"); }); 1809 | } else { 1810 | this["Dropzone"] = require("dropzone"); 1811 | }})(); --------------------------------------------------------------------------------