Django项目:CRM(客户关系管理系统)--61--51PerfectCRM实现CRM客户报名流程学生合同上传照片

Posted ujq3

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django项目:CRM(客户关系管理系统)--61--51PerfectCRM实现CRM客户报名流程学生合同上传照片相关的知识,希望对你有一定的参考价值。

技术分享图片

 

技术分享图片
  1 # sales_views.py
  2 # ————————47PerfectCRM实现CRM客户报名流程————————
  3 from django.db import IntegrityError  #主动捕捉错误信息
  4 from django.shortcuts import render  #页面返回
  5 from crm import models    #数据库
  6 from bpm.bpm_auxiliary import bpm_forms   #自定制 forms
  7 
  8 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
  9 import random #随机
 10 import string #字母 数字
 11 from django.core.cache import cache  #缓存
 12 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
 13 
 14 #报名填写 销售
 15 def enrollment(request,customer_id):
 16     msgs={} #错误信息
 17     customer_obj=models.Customer.objects.get(id=customer_id)#取到客户信息记录 #返回到页面
 18 
 19     if request.method=="POST":
 20         enroll_form= bpm_forms.EnrollmentForm(request.POST)#获取数据
 21         if enroll_form.is_valid():#表单验证
 22 
 23             # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
 24             # msg = ‘‘‘请将此链接发给客户进行填写:
 25             #        http://127.0.0.1:8000/bpm/customer/registration/{enroll_obj_id}/
 26             #     ‘‘‘
 27             msg = ‘‘‘请将此链接发给客户进行填写:
 28                    http://127.0.0.1:8000/bpm/customer/registration/{enroll_obj_id}/{random_str}/ 
 29                 ‘‘‘
 30             random_str=‘‘.join(random.sample(string.ascii_lowercase+string.digits,8))#生成8位随机字符串 #URL使用
 31             url_str=‘‘‘customer/registration/{enroll_obj_id}/{random_str}/‘‘‘#报名链接
 32             # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
 33             try:
 34                 print(enroll_form.cleaned_data,cleaned)
 35                 enroll_form.cleaned_data[customer]=customer_obj#添加学员对象 记录
 36                 enroll_obj=models.Enrollment.objects.create(**enroll_form.cleaned_data)#创建记录
 37 
 38                 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
 39                 # msgs[‘msg‘]=msg.format(enroll_obj_id=enroll_obj.id)#报名记录对应的id,随机字符串,报名链接
 40                 sort_url=enroll_obj.id#获取报名表对应的ID
 41                 cache.set(enroll_obj.id,random_str,61000)#加入过期时间   #URL使用    # cache缓存
 42                 msgs[msg]=msg.format(enroll_obj_id=enroll_obj.id,random_str=random_str)#报名记录对应的id,随机字符串,报名链接
 43                 url_str=url_str.format(enroll_obj_id=enroll_obj.id,random_str=random_str)#报名链接
 44                 print(url_str)
 45                 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
 46 
 47             except IntegrityError as e:
 48                 #取到这条记录
 49                 enroll_obj=models.Enrollment.objects.get(customer_id=customer_obj.id,
 50                                                          enrolled_class_id=enroll_form.cleaned_data[enrolled_class].id)
 51 #
 52                 enroll_form.add_error(__all__,记录已经存在,不能重复创建!)
 53                 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
 54                 # msgs[‘msg‘]=msg.format(enroll_obj_id=enroll_obj.id)#报名记录对应的id
 55                 cache.set(enroll_obj.id,random_str,61000)#加入过期时间  #URL使用    # cache缓存
 56                 msgs[msg]=msg.format(enroll_obj_id=enroll_obj.id,random_str=random_str)#报名记录对应的id
 57                 url_str=url_str.format(enroll_obj_id=enroll_obj.id,random_str=random_str)#报名链接
 58 
 59                 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
 60     else:
 61         enroll_form= bpm_forms.EnrollmentForm()#modelform表单
 62     return render(request, bpm_sales/enrollment.html, locals())
 63 
 64 # ————————47PerfectCRM实现CRM客户报名流程————————
 65 
 66 
 67 
 68 # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
 69 import os
 70 from PerfectCRM import settings
 71 import json
 72 # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
 73 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
 74 #学员合同签定
 75 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
 76 from django.shortcuts import HttpResponse #页面返回
 77 # def stu_registration(request,enroll_id):
 78 #     enroll_obj=models.Enrollment.objects.get(id=enroll_id)#获取报名记录
 79 def stu_registration(request,enroll_id,random_str):
 80     if cache.get(enroll_id) == random_str:  # 判断链接失效了没有
 81         enroll_obj = models.Enrollment.objects.get(id=enroll_id)  # 报名记录
 82 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
 83         # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
 84         enrolled_path=%s/%s/%(settings.ENROLLED_DATA,enroll_id)#证件上传路径
 85         img_file_len=0  #文件
 86         if os.path.exists(enrolled_path):#判断目录是否存在
 87             img_file_list=os.listdir(enrolled_path)#取目录 下的文件
 88             img_file_len=len(img_file_list)
 89         if request.method=="POST":
 90             ret=False
 91             data=request.POST.get(data)
 92             if data:#如果有删除动作
 93                 del_img_path="%s/%s/%s"%(settings.ENROLLED_DATA,enroll_id,data)#路径
 94                 print(del_img_path,=-=-=-=-=-=)
 95                 os.remove(del_img_path)
 96                 ret=True
 97                 return HttpResponse(json.dumps(ret))
 98             if request.is_ajax():#ajax上传图片 #异步提交
 99                 print(ajax上传图片 #异步提交中。。。 ,request.FILES)
100                 enroll_data_dir="%s/%s"%(settings.ENROLLED_DATA,enroll_id)#路径  #重要信息不能放在静态文件中
101                 if not os.path.exists(enroll_data_dir):#如果不存目录
102                     os.makedirs(enroll_data_dir,exist_ok=True)#创建目录
103                 for k,file_obj in request.FILES.items():   #循环字典 #上传的文件
104                     with open("%s/%s"%(enroll_data_dir,file_obj.name),wb) as f: #打开一个文件#路径#获取文件名
105                         for chunk in file_obj.chunks():#循环写入文件 # chunks块
106                             f.write(chunk)  #保存文件
107                 return HttpResponse(上传完成!)
108         # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
109         # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
110     # ————————49PerfectCRM实现CRM客户报名流程学生合同表单验证————————
111 # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
112     #     if request.method == "POST":
113 # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
114             customer_form = bpm_forms.CustomerForm(request.POST, instance=enroll_obj.customer)  # 生成表单验证
115             if customer_form.is_valid():  # 表单验证通过
116                 customer_form.save()  # 保存
117                 enroll_obj.contract_agreed = True  # 同意协议
118                 enroll_obj.save()  # 保存
119                 status = 1  # 修改报名状态 # 1 已经报名
120                 return render(request, bpm_sales/stu_registration.html, locals())
121 
122         else:
123             if enroll_obj.contract_agreed == True:  # 如果协议已经签订
124                 status = 1  # 修改报名状态 # 1 已经报名
125             else:
126                 status = 0
127             customer_form = bpm_forms.CustomerForm(instance=enroll_obj.customer)  # 生成表单
128     # customer_form = bpm_forms.CustomerForm(instance=enroll_obj.customer)  # 生成表单
129     # ————————49PerfectCRM实现CRM客户报名流程学生合同表单验证————————
130 
131         return render(request,bpm_sales/stu_registration.html,locals())
132 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
133     else:
134         return HttpResponse(链接失效,非法链接,请自重!)
135 
136         # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
# sales_views.py

 

 

技术分享图片

技术分享图片

 

技术分享图片

 

技术分享图片

 

技术分享图片
  1 {#stu_registration.html#}
  2 {## ————————48PerfectCRM实现CRM客户报名流程学生合同————————#}
  3 {% extends ‘bpm_master/bpm_sample.html‘ %}
  4 {% load bpm_tags %}
  5 {% block right-container-content %} {#自定义内容开始 右边页面内容#}
  6     <div class="container col-lg-7 col-md-offset-2">
  7         <div class="panel panel-warning">
  8             <div class=" panel-heading">
  9                 <h3 class="panel-title container">报名入学|信息填写</h3>
 10             </div>
 11             <div class="panel-body "><!--返回提交函数-->
 12                 {## ————————49PerfectCRM实现CRM客户报名流程学生合同表单验证————————#}
 13                 {% if status != 1 %}
 14                     <span class="errors">{{ customer_form.errors }}</span><!--错误提示-->
 15                     {## ————————49PerfectCRM实现CRM客户报名流程学生合同表单验证————————#}
 16                     {## ————————49PerfectCRM实现CRM客户报名流程学生合同表单验证————————#}
 17                     {#                <form method="post" class="form-horizontal" role="form">{% csrf_token %}#}
 18                     <form method="post" class="form-horizontal" role="form"
 19                           onsubmit="return RegisterFormCheck()">{% csrf_token %}
 20                         {## ————————49PerfectCRM实现CRM客户报名流程学生合同表单验证————————#}
 21                         {% for foo in customer_form %}
 22                             <div class="form-group">
 23                                 <label for="inputEmail3" class="col-sm-2 control-label">{{ foo.label }}</label>
 24                                 <div class="col-sm-8">
 25                                     {{ foo }}
 26                                 </div>
 27                             </div>
 28                         {% endfor %}
 29                         <hr>
 30                         {#返回06学员报名信息表的数据#}
 31                         <div class="form-group">
 32                             <label for="inputEmail3" class="col-sm-2 control-label">所报班级</label>
 33                             <div class="col-sm-8">
 34                                 {{ enroll_obj.enrolled_class }}
 35                             </div>
 36                         </div>
 37                         <div class="form-group">
 38                             <label for="inputEmail3" class="col-sm-2 control-label">课程费用</label>
 39                             <div class="col-sm-8">
 40                                 {{ enroll_obj.enrolled_class.course.price }}
 41                             </div>
 42                         </div>
 43                         <div class="form-group">
 44                             <label for="inputEmail3" class="col-sm-2 control-label">开课日期</label>
 45                             <div class="col-sm-8">
 46                                 {{ enroll_obj.enrolled_class.start_date }}
 47                             </div>
 48                         </div>
 49                         <div class="form-group">
 50                             <label for="inputEmail3" class="col-sm-2 control-label">合同</label>
 51                             <div class="col-sm-10">
 52                                 <div style="width: 550px">
 53                                     <pre style="height: 300px">{% render_enrolled_contract enroll_obj %}  </pre>
 54                                 </div>
 55 
 56                             </div>
 57                         </div>
 58                         <div class="form-group">
 59                             <div class="col-sm-12">
 60                                 <input type="checkbox" value="{{ enroll_obj.contract_agreed }}" name="contract_agreed"
 61                                        checked>
 62                                 我已经认真阅读完协议并接受所有条款
 63                             </div>
 64                         </div>
 65                         <div class="text-center">
 66                             <input type="submit" class="btn btn-info" value="提交">
 67                         </div>
 68                     </form>
 69 
 70                     {## ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————#}
 71                     <div class="row">
 72                         <div class="col-xs-6 col-md-3">
 73                             {% for img_file in img_file_list %}
 74                                 <div class="right">
 75                                     <a href="#" class="thumbnail" name="{{ img_file }}">
 76                                         <img src="/static/enrolled_data/{{ enroll_id }}/{{ img_file }}" alt="...">
 77                                     </a>
 78                                     <a class="del_img">删除</a>
 79                                     <span class="img_f hide">{{ img_file }}</span>
 80                                 </div>
 81                             {% endfor %}
 82                         </div>
 83                     </div>
 84                     <p>请上传身份证反面照片</p>
 85                     <form action="{{ request.path }}" class="dropzone form-group" id="filerdropzone" method="post"
 86                           enctype="multipart/form-data">{% csrf_token %}
 87 
 88                         <input type="hidden" name="file_id" ng-model="file_id" id="file_id"/>
 89                     </form>
 90                     {## ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————#}
 91 
 92                     {## ————————49PerfectCRM实现CRM客户报名流程学生合同表单验证————————#}
 93                 {% else %}
 94                     <h3>报名成功,同合进入审核流程,感谢您的选择!</h3>
 95                 {% endif %}
 96                 {## ————————49PerfectCRM实现CRM客户报名流程学生合同表单验证————————#}
 97             </div>
 98             <div class="panel-footer">
 99                 <input type="button" class="btn btn-danger right" value="关闭" onclick="CloseWebPage()">
100             </div>
101         </div>
102     </div>
103 {% endblock %}
104 
105 {% block js %}
106     <script>
107         function CloseWebPage() {
108             if (confirm("您确定要关闭本页吗?")) {
109                 window.opener = null;
110                 window.open(‘‘, _self);
111                 window.close();
112             }
113             else {
114             }
115         }
116 
117         {## ————————49PerfectCRM实现CRM客户报名流程学生合同表单验证————————#}
118 
119         function RegisterFormCheck() {
120             {## ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————#}
121             if (myDropzone.files.length < 2) {
122                 alert(请上传身份证正反面!2张!));
123                 return false;
124             }
125             {## ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————#}
126             if ($(form :checkbox).prop("checked")) {
127                 $("form").find("[disabled]").removeAttr("disabled");//移除不可修改 便于提交表单  #qq
128                 return true;
129             } else {
130                 alert(请认真阅读并且同意条款,才可以报名);
131                 return false;
132             }
133         }
134 
135         {## ————————49PerfectCRM实现CRM客户报名流程学生合同表单验证————————#}
136 
137         {## ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————#}
138         {##————————cookies删除文件JS事件————————#}
139         $(.del_img).click(function () {
140             s = $(this);
141             texts = s.parent().children("span").text();
142             $.ajax({
143                 url: "{{ request.path }}",
144                 type: "post",
145                 data: {"data": texts},
146                 headers: {X-CSRFtoken: $.cookie(csrftoken)},
147                 success: function (arg) {
148                     if (arg) {
149                         alert(删除成功!);
150                         s.parent(div).addClass(hide);
151                     }
152                 }
153             })
154         });
155         {##————————cookies删除文件JS事件————————#}
156         {##————————dropzone上传文件插件————————#}
157         Dropzone.autoDiscover = false;
158         appElement = document.querySelector(div .inmodal);
159         myDropzone = new Dropzone("#filerdropzone", {
160             url: {{ request.path }},//路径为 当前页
161             paramName: "file", //默认为file
162             method: "post",
163             maxFilesize: 1,//MB 兆# 1048576字节
164             addRemoveLinks: true,
165             maxFiles: 2,
166             acceptedFiles: ".jpg,.gif,.png,.jpeg", //上传的类型
167             uploadMultiple: true,
168             parallelUploads: 1,//一次上传的文件数量
169             dictDefaultMessage: 请将照片拖到这里或点击上传,
170             dictMaxFilesExceeded: "您最多只能上传2个文件!",
171             dictResponseError: 文件上传失败!,
172             dictInvalidFileType: "文件类型只能是*.zip,*.7z。",
173             dictFallbackMessage: "浏览器不受支持",
174             dictFileTooBig: "文件过大上传文件最大支持.",
175             dictRemoveLinks: "删除",
176             dictCancelUpload: "取消",
177             init: function () {
178                 this.on("addedfile", function (file) {
179                     //上传文件时触发的事件
180                     document.querySelector(div .dz-default).style.display = none;
181                 });
182                 this.on("success", function (file, data) {
183                     //上传成功触发的事件
184                     console.log(ok);
185                     // angular.element(appElement).scope().file_id = data.data.id;
186                 });
187                 this.on("error", function (file, data) {
188                     //上传失败触发的事件
189                     console.log(fail);
190                     var message = ‘‘;
191                     //lavarel框架有一个表单验证,
192                     //对于ajax请求,JSON 响应会发送一个 422 HTTP 状态码,
193                     //对应file.accepted的值是false,在这里捕捉表单验证的错误提示
194                     if (file.accepted) {
195                         $.each(data, function (key, val) {
196                             message = message + val[0] + ;;
197                         });
198                         //控制器层面的错误提示,file.accepted = true的时候;
199                         alert(message);
200                     }
201                 });
202                 this.on("removedfile", function (file) {
203                     //删除文件时触发的方法
204 
205                     document.querySelector(div .dz-default).style.display = block;
206                 });
207             }
208         });
209         {##————————dropzone上传文件插件————————#}
210         {## ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————#}
211     </script>
212 
213 
214 
215 {% endblock %}
216 {## ————————48PerfectCRM实现CRM客户报名流程学生合同————————#}
{#stu_registration.html#}

 

 

技术分享图片

 

 

技术分享图片
  1 /*!
  2  * jQuery Cookie Plugin v1.4.1
  3  * https://github.com/carhartl/jquery-cookie
  4  *
  5  * Copyright 2013 Klaus Hartl
  6  * Released under the MIT license
  7  */
  8 (function (factory) {
  9     if (typeof define === ‘function‘ && define.amd) {
 10         // AMD
 11         define([‘jquery‘], factory);
 12     } else if (typeof exports === ‘object‘) {
 13         // CommonJS
 14         factory(require(‘jquery‘));
 15     } else {
 16         // Browser globals
 17         factory(jQuery);
 18     }
 19 }(function ($) {
 20 
 21     var pluses = /\\+/g;
 22 
 23     function encode(s) {
 24         return config.raw ? s : encodeURIComponent(s);
 25     }
 26 
 27     function decode(s) {
 28         return config.raw ? s : decodeURIComponent(s);
 29     }
 30 
 31     function stringifyCookieValue(value) {
 32         return encode(config.json ? JSON.stringify(value) : String(value));
 33     }
 34 
 35     function parseCookieValue(s) {
 36         if (s.indexOf(‘"‘) === 0) {
 37             // This is a quoted cookie as according to RFC2068, unescape...
 38             s = s.slice(1, -1).replace(/\\\\"/g, ‘"‘).replace(/\\\\\\\\/g, ‘\\\\‘);
 39         }
 40 
 41         try {
 42             // Replace server-side written pluses with spaces.
 43             // If we can‘t decode the cookie, ignore it, it‘s unusable.
 44             // If we can‘t parse the cookie, ignore it, it‘s unusable.
 45             s = decodeURIComponent(s.replace(pluses, ‘ ‘));
 46             return config.json ? JSON.parse(s) : s;
 47         } catch(e) {}
 48     }
 49 
 50     function read(s, converter) {
 51         var value = config.raw ? s : parseCookieValue(s);
 52         return $.isFunction(converter) ? converter(value) : value;
 53     }
 54 
 55     var config = $.cookie = function (key, value, options) {
 56 
 57         // Write
 58 
 59         if (value !== undefined && !$.isFunction(value)) {
 60             options = $.extend({}, config.defaults, options);
 61 
 62             if (typeof options.expires === ‘number‘) {
 63                 var days = options.expires, t = options.expires = new Date();
 64                 t.setTime(+t + days * 864e+5);
 65             }
 66 
 67             return (document.cookie = [
 68                 encode(key), ‘=‘, stringifyCookieValue(value),
 69                 options.expires ? ‘; expires=‘ + options.expires.toUTCString() : ‘‘, // use expires attribute, max-age is not supported by IE
 70                 options.path    ? ‘; path=‘ + options.path : ‘‘,
 71                 options.domain  ? ‘; domain=‘ + options.domain : ‘‘,
 72                 options.secure  ? ‘; secure‘ : ‘‘
 73             ].join(‘‘));
 74         }
 75 
 76         // Read
 77 
 78         var result = key ? undefined : {};
 79 
 80         // To prevent the for loop in the first place assign an empty array
 81         // in case there are no cookies at all. Also prevents odd result when
 82         // calling $.cookie().
 83         var cookies = document.cookie ? document.cookie.split(‘; ‘) : [];
 84 
 85         for (var i = 0, l = cookies.length; i < l; i++) {
 86             var parts = cookies[i].split(‘=‘);
 87             var name = decode(parts.shift());
 88             var cookie = parts.join(‘=‘);
 89 
 90             if (key && key === name) {
 91                 // If second argument (value) is a function it‘s a converter...
 92                 result = read(cookie, value);
 93                 break;
 94             }
 95 
 96             // Prevent storing a cookie that we couldn‘t decode.
 97             if (!key && (cookie = read(cookie)) !== undefined) {
 98                 result[name] = cookie;
 99             }
100         }
101 
102         return result;
103     };
104 
105     config.defaults = {};
106 
107     $.removeCookie = function (key, options) {
108         if ($.cookie(key) === undefined) {
109             return false;
110         }
111 
112         // Must not alter options, thus extending a fresh object...
113         $.cookie(key, ‘‘, $.extend({}, options, { expires: -1 }));
114         return !$.cookie(key);
115     };
116 
117 }));
jQueryCookie.js

 

 

技术分享图片
  1 @-webkit-keyframes passing-through {
  2   0% {
  3     opacity: 0;
  4     -webkit-transform: translateY(40px);
  5     -moz-transform: translateY(40px);
  6     -ms-transform: translateY(40px);
  7     -o-transform: translateY(40px);
  8     transform: translateY(40px); }
  9   30%, 70% {
 10     opacity: 1;
 11     -webkit-transform: translateY(0px);
 12     -moz-transform: translateY(0px);
 13     -ms-transform: translateY(0px);
 14     -o-transform: translateY(0px);
 15     transform: translateY(0px); }
 16   100% {
 17     opacity: 0;
 18     -webkit-transform: translateY(-40px);
 19     -moz-transform: translateY(-40px);
 20     -ms-transform: translateY(-40px);
 21     -o-transform: translateY(-40px);
 22     transform: translateY(-40px); } }
 23 @-moz-keyframes passing-through {
 24   0% {
 25     opacity: 0;
 26     -webkit-transform: translateY(40px);
 27     -moz-transform: translateY(40px);
 28     -ms-transform: translateY(40px);
 29     -o-transform: translateY(40px);
 30     transform: translateY(40px); }
 31   30%, 70% {
 32     opacity: 1;
 33     -webkit-transform: translateY(0px);
 34     -moz-transform: translateY(0px);
 35     -ms-transform: translateY(0px);
 36     -o-transform: translateY(0px);
 37     transform: translateY(0px); }
 38   100% {
 39     opacity: 0;
 40     -webkit-transform: translateY(-40px);
 41     -moz-transform: translateY(-40px);
 42     -ms-transform: translateY(-40px);
 43     -o-transform: translateY(-40px);
 44     transform: translateY(-40px); } }
 45 @keyframes passing-through {
 46   0% {
 47     opacity: 0;
 48     -webkit-transform: translateY(40px);
 49     -moz-transform: translateY(40px);
 50     -ms-transform: translateY(40px);
 51     -o-transform: translateY(40px);
 52     transform: translateY(40px); }
 53   30%, 70% {
 54     opacity: 1;
 55     -webkit-transform: translateY(0px);
 56     -moz-transform: translateY(0px);
 57     -ms-transform: translateY(0px);
 58     -o-transform: translateY(0px);
 59     transform: translateY(0px); }
 60   100% {
 61     opacity: 0;
 62     -webkit-transform: translateY(-40px);
 63     -moz-transform: translateY(-40px);
 64     -ms-transform: translateY(-40px);
 65     -o-transform: translateY(-40px);
 66     transform: translateY(-40px); } }
 67 @-webkit-keyframes slide-in {
 68   0% {
 69     opacity: 0;
 70     -webkit-transform: translateY(40px);
 71     -moz-transform: translateY(40px);
 72     -ms-transform: translateY(40px);
 73     -o-transform: translateY(40px);
 74     transform: translateY(40px); }
 75   30% {
 76     opacity: 1;
 77     -webkit-transform: translateY(0px);
 78     -moz-transform: translateY(0px);
 79     -ms-transform: translateY(0px);
 80     -o-transform: translateY(0px);
 81     transform: translateY(0px); } }
 82 @-moz-keyframes slide-in {
 83   0% {
 84     opacity: 0;
 85     -webkit-transform: translateY(40px);
 86     -moz-transform: translateY(40px);
 87     -ms-transform: translateY(40px);
 88     -o-transform: translateY(40px);
 89     transform: translateY(40px); }
 90   30% {
 91     opacity: 1;
 92     -webkit-transform: translateY(0px);
 93     -moz-transform: translateY(0px);
 94     -ms-transform: translateY(0px);
 95     -o-transform: translateY(0px);
 96     transform: translateY(0px); } }
 97 @keyframes slide-in {
 98   0% {
 99     opacity: 0;
100     -webkit-transform: translateY(40px);
101     -moz-transform: translateY(40px);
102     -ms-transform: translateY(40px);
103     -o-transform: translateY(40px);
104     transform: translateY(40px); }
105   30% {
106     opacity: 1;
107     -webkit-transform: translateY(0px);
108     -moz-transform: translateY(0px);
109     -ms-transform: translateY(0px);
110     -o-transform: translateY(0px);
111     transform: translateY(0px); } }
112 @-webkit-keyframes pulse {
113   0% {
114     -webkit-transform: scale(1);
115     -moz-transform: scale(1);
116     -ms-transform: scale(1);
117     -o-transform: scale(1);
118     transform: scale(1); }
119   10% {
120     -webkit-transform: scale(1.1);
121     -moz-transform: scale(1.1);
122     -ms-transform: scale(1.1);
123     -o-transform: scale(1.1);
124     transform: scale(1.1); }
125   20% {
126     -webkit-transform: scale(1);
127     -moz-transform: scale(1);
128     -ms-transform: scale(1);
129     -o-transform: scale(1);
130     transform: scale(1); } }
131 @-moz-keyframes pulse {
132   0% {
133     -webkit-transform: scale(1);
134     -moz-transform: scale(1);
135     -ms-transform: scale(1);
136     -o-transform: scale(1);
137     transform: scale(1); }
138   10% {
139     -webkit-transform: scale(1.1);
140     -moz-transform: scale(1.1);
141     -ms-transform: scale(1.1);
142     -o-transform: scale(1.1);
143     transform: scale(1.1); }
144   20% {
145     -webkit-transform: scale(1);
146     -moz-transform: scale(1);
147     -ms-transform: scale(1);
148     -o-transform: scale(1);
149     transform: scale(1); } }
150 @keyframes pulse {
151   0% {
152     -webkit-transform: scale(1);
153     -moz-transform: scale(1);
154     -ms-transform: scale(1);
155     -o-transform: scale(1);
156     transform: scale(1); }
157   10% {
158     -webkit-transform: scale(1.1);
159     -moz-transform: scale(1.1);
160     -ms-transform: scale(1.1);
161     -o-transform: scale(1.1);
162     transform: scale(1.1); }
163   20% {
164     -webkit-transform: scale(1);
165     -moz-transform: scale(1);
166     -ms-transform: scale(1);
167     -o-transform: scale(1);
168     transform: scale(1); } }
169 .dropzone, .dropzone * {
170   box-sizing: border-box; }
171 
172 .dropzone {
173   min-height: 150px;
174   border: 2px solid rgba(0, 0, 0, 0.3);
175   background: white;
176   padding: 54px 54px; }
177   .dropzone.dz-clickable {
178     cursor: pointer; }
179     .dropzone.dz-clickable * {
180       cursor: default; }
181     .dropzone.dz-clickable .dz-message, .dropzone.dz-clickable .dz-message * {
182       cursor: pointer; }
183   .dropzone.dz-started .dz-message {
184     display: none; }
185   .dropzone.dz-drag-hover {
186     border-style: solid; }
187     .dropzone.dz-drag-hover .dz-message {
188       opacity: 0.5; }
189   .dropzone .dz-message {
190     text-align: center;
191     margin: 2em 0; }
192   .dropzone .dz-preview {
193     position: relative;
194     display: inline-block;
195     vertical-align: top;
196     margin: 16px;
197     min-height: 100px; }
198     .dropzone .dz-preview:hover {
199       z-index: 1000; }
200       .dropzone .dz-preview:hover .dz-details {
201         opacity: 1; }
202     .dropzone .dz-preview.dz-file-preview .dz-image {
203       border-radius: 20px;
204       background: #999;
205       background: linear-gradient(to bottom, #eee, #ddd); }
206     .dropzone .dz-preview.dz-file-preview .dz-details {
207       opacity: 1; }
208     .dropzone .dz-preview.dz-image-preview {
209       background: white; }
210       .dropzone .dz-preview.dz-image-preview .dz-details {
211         -webkit-transition: opacity 0.2s linear;
212         -moz-transition: opacity 0.2s linear;
213         -ms-transition: opacity 0.2s linear;
214         -o-transition: opacity 0.2s linear;
215         transition: opacity 0.2s linear; }
216     .dropzone .dz-preview .dz-remove {
217       font-size: 14px;
218       text-align: center;
219       display: block;
220       cursor: pointer;
221       border: none; }
222       .dropzone .dz-preview .dz-remove:hover {
223         text-decoration: underline; }
224     .dropzone .dz-preview:hover .dz-details {
225       opacity: 1; }
226     .dropzone .dz-preview .dz-details {
227       z-index: 20;
228       position: absolute;
229       top: 0;
230       left: 0;
231       opacity: 0;
232       font-size: 13px;
233       min-width: 100%;
234       max-width: 100%;
235       padding: 2em 1em;
236       text-align: center;
237       color: rgba(0, 0, 0, 0.9);
238       line-height: 150%; }
239       .dropzone .dz-preview .dz-details .dz-size {
240         margin-bottom: 1em;
241         font-size: 16px; }
242       .dropzone .dz-preview .dz-details .dz-filename {
243         white-space: nowrap; }
244         .dropzone .dz-preview .dz-details .dz-filename:hover span {
245           border: 1px solid rgba(200, 200, 200, 0.8);
246           background-color: rgba(255, 255, 255, 0.8); }
247         .dropzone .dz-preview .dz-details .dz-filename:not(:hover) {
248           overflow: hidden;
249           text-overflow: ellipsis; }
250           .dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
251             border: 1px solid transparent; }
252       .dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {
253         background-color: rgba(255, 255, 255, 0.4);
254         padding: 0 0.4em;
255         border-radius: 3px; }
256     .dropzone .dz-preview:hover .dz-image img {
257       -webkit-transform: scale(1.05, 1.05);
258       -moz-transform: scale(1.05, 1.05);
259       -ms-transform: scale(1.05, 1.05);
260       -o-transform: scale(1.05, 1.05);
261       transform: scale(1.05, 1.05);
262       -webkit-filter: blur(8px);
263       filter: blur(8px); }
264     .dropzone .dz-preview .dz-image {
265       border-radius: 20px;
266       overflow: hidden;
267       width: 120px;
268       height: 120px;
269       position: relative;
270       display: block;
271       z-index: 10; }
272       .dropzone .dz-preview .dz-image img {
273         display: block; }
274     .dropzone .dz-preview.dz-success .dz-success-mark {
275       -webkit-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
276       -moz-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
277       -ms-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
278       -o-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
279       animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); }
280     .dropzone .dz-preview.dz-error .dz-error-mark {
281       opacity: 1;
282       -webkit-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
283       -moz-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
284       -ms-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
285       -o-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
286       animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); }
287     .dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {
288       pointer-events: none;
289       opacity: 0;
290       z-index: 500;
291       position: absolute;
292       display: block;
293       top: 50%;
294       left: 50%;
295       margin-left: -27px;
296       margin-top: -27px; }
297       .dropzone .dz-preview .dz-success-mark svg, .dropzone .dz-preview .dz-error-mark svg {
298         display: block;
299         width: 54px;
300         height: 54px; }
301     .dropzone .dz-preview.dz-processing .dz-progress {
302       opacity: 1;
303       -webkit-transition: all 0.2s linear;
304       -moz-transition: all 0.2s linear;
305       -ms-transition: all 0.2s linear;
306       -o-transition: all 0.2s linear;
307       transition: all 0.2s linear; }
308     .dropzone .dz-preview.dz-complete .dz-progress {
309       opacity: 0;
310       -webkit-transition: opacity 0.4s ease-in;
311       -moz-transition: opacity 0.4s ease-in;
312       -ms-transition: opacity 0.4s ease-in;
313       -o-transition: opacity 0.4s ease-in;
314       transition: opacity 0.4s ease-in; }
315     .dropzone .dz-preview:not(.dz-processing) .dz-progress {
316       -webkit-animation: pulse 6s ease infinite;
317       -moz-animation: pulse 6s ease infinite;
318       -ms-animation: pulse 6s ease infinite;
319       -o-animation: pulse 6s ease infinite;
320       animation: pulse 6s ease infinite; }
321     .dropzone .dz-preview .dz-progress {
322       opacity: 1;
323       z-index: 1000;
324       pointer-events: none;
325       position: absolute;
326       height: 16px;
327       left: 50%;
328       top: 50%;
329       margin-top: -8px;
330       width: 80px;
331       margin-left: -40px;
332       background: rgba(255, 255, 255, 0.9);
333       -webkit-transform: scale(1);
334       border-radius: 8px;
335       overflow: hidden; }
336       .dropzone .dz-preview .dz-progress .dz-upload {
337         background: #333;
338         background: linear-gradient(to bottom, #666, #444);
339         position: absolute;
340         top: 0;
341         left: 0;
342         bottom: 0;
343         width: 0;
344         -webkit-transition: width 300ms ease-in-out;
345         -moz-transition: width 300ms ease-in-out;
346         -ms-transition: width 300ms ease-in-out;
347         -o-transition: width 300ms ease-in-out;
348         transition: width 300ms ease-in-out; }
349     .dropzone .dz-preview.dz-error .dz-error-message {
350       display: block; }
351     .dropzone .dz-preview.dz-error:hover .dz-error-message {
352       opacity: 1;
353       pointer-events: auto; }
354     .dropzone .dz-preview .dz-error-message {
355       pointer-events: none;
356       z-index: 1000;
357       position: absolute;
358       display: block;
359       display: none;
360       opacity: 0;
361       -webkit-transition: opacity 0.3s ease;
362       -moz-transition: opacity 0.3s ease;
363       -ms-transition: opacity 0.3s ease;
364       -o-transition: opacity 0.3s ease;
365       transition: opacity 0.3s ease;
366       border-radius: 8px;
367       font-size: 13px;
368       top: 130px;
369       left: -10px;
370       width: 140px;
371       background: #be2626;
372       background: linear-gradient(to bottom, #be2626, #a92222);
373       padding: 0.5em 1.2em;
374       color: white; }
375       .dropzone .dz-preview .dz-error-message:after {
376         content: ‘‘;
377         position: absolute;
378         top: -6px;
379         left: 64px;
380         width: 0;
381         height: 0;
382         border-left: 6px solid transparent;
383         border-right: 6px solid transparent;
384         border-bottom: 6px solid #be2626; }
dropzone.css

 

 

技术分享图片
   1 /*
   2  *
   3  * More info at [www.dropzonejs.com](http://www.dropzonejs.com)
   4  *
   5  * Copyright (c) 2012, Matias Meno
   6  *
   7  * Permission is hereby granted, free of charge, to any person obtaining a copy
   8  * of this software and associated documentation files (the "Software"), to deal
   9  * in the Software without restriction, including without limitation the rights
  10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11  * copies of the Software, and to permit persons to whom the Software is
  12  * furnished to do so, subject to the following conditions:
  13  *
  14  * The above copyright notice and this permission notice shall be included in
  15  * all copies or substantial portions of the Software.
  16  *
  17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23  * THE SOFTWARE.
  24  *
  25  *   *特此授予许可,免费的,任何的人获得一份
  26   *这个软件和相关文档的文件(“软件”),交易
  27   *在软件没有限制,包括但不限于权利
  28   *使用、复制、修改、合并、出版、发行、有偿和/或出售
  29   *软件的副本,并允许他们的软件
  30   *提供,应当具备下列条件:
  31   *
  32   *上述版权声明和本许可声明应当包含在
  33   *所有副本或实质性部分的软件。
  34   *
  35   *提供的软件是“是”,没有任何类型的保证,明示或
  36   *暗示的保证,包括但不限于适销性的保证,
  37   *健身为特定目的和无侵犯。在任何事件应当的
  38   *作者或版权所有者承担任何索赔、损害或其他
  39   *责任,无论是在一个动作的合同,侵权或否则,因,
  40   *在连接或WI
  41 
  42  */
  43 
  44 (function() {
  45   var Dropzone, Emitter, ExifRestore, camelize, contentLoaded, detectVerticalSquash, drawImageiosFix, noop, without,
  46     slice = [].slice,
  47     extend1 = 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; },
  48     hasProp = {}.hasOwnProperty;
  49 
  50   noop = function() {};
  51 
  52   Emitter = (function() {
  53     function Emitter() {}
  54 
  55     Emitter.prototype.addEventListener = Emitter.prototype.on;
  56 
  57     Emitter.prototype.on = function(event, fn) {
  58       this._callbacks = this._callbacks || {};
  59       if (!this._callbacks[event]) {
  60         this._callbacks[event] = [];
  61       }
  62       this._callbacks[event].push(fn);
  63       return this;
  64     };
  65 
  66     Emitter.prototype.emit = function() {
  67       var args, callback, callbacks, event, j, len;
  68       event = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
  69       this._callbacks = this._callbacks || {};
  70       callbacks = this._callbacks[event];
  71       if (callbacks) {
  72         for (j = 0, len = callbacks.length; j < len; j++) {
  73           callback = callbacks[j];
  74           callback.apply(this, args);
  75         }
  76       }
  77       return this;
  78     };
  79 
  80     Emitter.prototype.removeListener = Emitter.prototype.off;
  81 
  82     Emitter.prototype.removeAllListeners = Emitter.prototype.off;
  83 
  84     Emitter.prototype.removeEventListener = Emitter.prototype.off;
  85 
  86     Emitter.prototype.off = function(event, fn) {
  87       var callback, callbacks, i, j, len;
  88       if (!this._callbacks || arguments.length === 0) {
  89         this._callbacks = {};
  90         return this;
  91       }
  92       callbacks = this._callbacks[event];
  93       if (!callbacks) {
  94         return this;
  95       }
  96       if (arguments.length === 1) {
  97         delete this._callbacks[event];
  98         return this;
  99       }
 100       for (i = j = 0, len = callbacks.length; j < len; i = ++j) {
 101         callback = callbacks[i];
 102         if (callback === fn) {
 103           callbacks.splice(i, 1);
 104           break;
 105         }
 106       }
 107       return this;
 108     };
 109 
 110     return Emitter;
 111 
 112   })();
 113 
 114   Dropzone = (function(superClass) {
 115     var extend, resolveOption;
 116 
 117     extend1(Dropzone, superClass);
 118 
 119     Dropzone.prototype.Emitter = Emitter;
 120 
 121 
 122     /*
 123     This is a list of all available events you can register on a dropzone object.
 124     
 125     You can register an event handler like this:
 126     
 127         dropzone.on("dragEnter", function() { });
 128      */
 129 
 130     Dropzone.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "addedfile", "addedfiles", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached", "queuecomplete"];
 131 
 132     Dropzone.prototype.defaultOptions = {
 133       url: null,
 134       method: "post",
 135       withCredentials: false,
 136       timeout: 30000,
 137       parallelUploads: 2,
 138       uploadMultiple: false,
 139       maxFilesize: 256,
 140       paramName: "file",
 141       createImageThumbnails: true,
 142       maxThumbnailFilesize: 10,
 143       thumbnailWidth: 120,
 144       thumbnailHeight: 120,
 145       thumbnailMethod: ‘crop‘,
 146       resizeWidth: null,
 147       resizeHeight: null,
 148       resizeMimeType: null,
 149       resizeQuality: 0.8,
 150       resizeMethod: ‘contain‘,
 151       filesizeBase: 1000,
 152       maxFiles: null,
 153       params: {},
 154       headers: null,
 155       clickable: true,
 156       ignoreHiddenFiles: true,
 157       acceptedFiles: null,
 158       acceptedMimeTypes: null,
 159       autoProcessQueue: true,
 160       autoQueue: true,
 161       addRemoveLinks: false,
 162       previewsContainer: null,
 163       hiddenInputContainer: "body",
 164       capture: null,
 165       renameFilename: null,
 166       renameFile: null,
 167       forceFallback: false,
 168       dictDefaultMessage: "Drop files here to upload",
 169       dictFallbackMessage: "Your browser does not support drag‘n‘drop file uploads.",
 170       dictFallbackText: "Please use the fallback form below to upload your files like in the olden days.",
 171       dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",
 172       dictInvalidFileType: "You can‘t upload files of this type.",
 173       dictResponseError: "Server responded with {{statusCode}} code.",
 174       dictCancelUpload: "Cancel upload",
 175       dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?",
 176       dictRemoveFile: "Remove file",
 177       dictRemoveFileConfirmation: null,
 178       dictMaxFilesExceeded: "You can not upload any more files.",
 179       dictFileSizeUnits: {
 180         tb: "TB",
 181         gb: "GB",
 182         mb: "MB",
 183         kb: "KB",
 184         b: "b"
 185       },
 186       init: function() {
 187         return noop;
 188       },
 189       accept: function(file, done) {
 190         return done();
 191       },
 192       fallback: function() {
 193         var child, j, len, messageElement, ref, span;
 194         this.element.className = this.element.className + " dz-browser-not-supported";
 195         ref = this.element.getElementsByTagName("div");
 196         for (j = 0, len = ref.length; j < len; j++) {
 197           child = ref[j];
 198           if (/(^| )dz-message($| )/.test(child.className)) {
 199             messageElement = child;
 200             child.className = "dz-message";
 201             continue;
 202           }
 203         }
 204         if (!messageElement) {
 205           messageElement = Dropzone.createElement("<div class=\\"dz-message\\"><span></span></div>");
 206           this.element.appendChild(messageElement);
 207         }
 208         span = messageElement.getElementsByTagName("span")[0];
 209         if (span) {
 210           if (span.textContent != null) {
 211             span.textContent = this.options.dictFallbackMessage;
 212           } else if (span.innerText != null) {
 213             span.innerText = this.options.dictFallbackMessage;
 214           }
 215         }
 216         return this.element.appendChild(this.getFallbackForm());
 217       },
 218       resize: function(file, width, height, resizeMethod) {
 219         var info, srcRatio, trgRatio;
 220         info = {
 221           srcX: 0,
 222           srcY: 0,
 223           srcWidth: file.width,
 224           srcHeight: file.height
 225         };
 226         srcRatio = file.width / file.height;
 227         if ((width == null) && (height == null)) {
 228           width = info.srcWidth;
 229           height = info.srcHeight;
 230         } else if (width == null) {
 231           width = height * srcRatio;
 232         } else if (height == null) {
 233           height = width / srcRatio;
 234         }
 235         width = Math.min(width, info.srcWidth);
 236         height = Math.min(height, info.srcHeight);
 237         trgRatio = width / height;
 238         if (info.srcWidth > width || info.srcHeight > height) {
 239           if (resizeMethod === ‘crop‘) {
 240             if (srcRatio > trgRatio) {
 241               info.srcHeight = file.height;
 242               info.srcWidth = info.srcHeight * trgRatio;
 243             } else {
 244               info.srcWidth = file.width;
 245               info.srcHeight = info.srcWidth / trgRatio;
 246             }
 247           } else if (resizeMethod === ‘contain‘) {
 248             if (srcRatio > trgRatio) {
 249               height = width / srcRatio;
 250             } else {
 251               width = height * srcRatio;
 252             }
 253           } else {
 254             throw new Error("Unknown resizeMethod ‘" + resizeMethod + "‘");
 255           }
 256         }
 257         info.srcX = (file.width - info.srcWidth) / 2;
 258         info.srcY = (file.height - info.srcHeight) / 2;
 259         info.trgWidth = width;
 260         info.trgHeight = height;
 261         return info;
 262       },
 263       transformFile: function(file, done) {
 264         if ((this.options.resizeWidth || this.options.resizeHeight) && file.type.match(/image.*/)) {
 265           return this.resizeImage(file, this.options.resizeWidth, this.options.resizeHeight, this.options.resizeMethod, done);
 266         } else {
 267           return done(file);
 268         }
 269       },
 270       previewTemplate: "<div class=\\"dz-preview dz-file-preview\\">\\n  <div class=\\"dz-image\\"><img data-dz-thumbnail /></div>\\n  <div class=\\"dz-details\\">\\n    <div class=\\"dz-size\\"><span data-dz-size></span></div>\\n    <div class=\\"dz-filename\\"><span data-dz-name></span></div>\\n  </div>\\n  <div class=\\"dz-progress\\"><span class=\\"dz-upload\\" data-dz-uploadprogress></span></div>\\n  <div class=\\"dz-error-message\\"><span data-dz-errormessage></span></div>\\n  <div class=\\"dz-success-mark\\">\\n    <svg width=\\"54px\\" height=\\"54px\\" viewBox=\\"0 0 54 54\\" version=\\"1.1\\" xmlns=\\"http://www.w3.org/2000/svg\\" xmlns:xlink=\\"http://www.w3.org/1999/xlink\\" xmlns:sketch=\\"http://www.bohemiancoding.com/sketch/ns\\">\\n      <title>Check</title>\\n      <defs></defs>\\n      <g id=\\"Page-1\\" stroke=\\"none\\" stroke-width=\\"1\\" fill=\\"none\\" fill-rule=\\"evenodd\\" sketch:type=\\"MSPage\\">\\n        <path d=\\"M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\\" id=\\"Oval-2\\" stroke-opacity=\\"0.198794158\\" stroke=\\"#747474\\" fill-opacity=\\"0.816519475\\" fill=\\"#FFFFFF\\" sketch:type=\\"MSShapeGroup\\"></path>\\n      </g>\\n    </svg>\\n  </div>\\n  <div class=\\"dz-error-mark\\">\\n    <svg width=\\"54px\\" height=\\"54px\\" viewBox=\\"0 0 54 54\\" version=\\"1.1\\" xmlns=\\"http://www.w3.org/2000/svg\\" xmlns:xlink=\\"http://www.w3.org/1999/xlink\\" xmlns:sketch=\\"http://www.bohemiancoding.com/sketch/ns\\">\\n      <title>Error</title>\\n      <defs></defs>\\n      <g id=\\"Page-1\\" stroke=\\"none\\" stroke-width=\\"1\\" fill=\\"none\\" fill-rule=\\"evenodd\\" sketch:type=\\"MSPage\\">\\n        <g id=\\"Check-+-Oval-2\\" sketch:type=\\"MSLayerGroup\\" stroke=\\"#747474\\" stroke-opacity=\\"0.198794158\\" fill=\\"#FFFFFF\\" fill-opacity=\\"0.816519475\\">\\n          <path d=\\"M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\\" id=\\"Oval-2\\" sketch:type=\\"MSShapeGroup\\"></path>\\n        </g>\\n      </g>\\n    </svg>\\n  </div>\\n</div>",
 271 
 272       /*
 273       Those functions register themselves to the events on init and handle all
 274       the user interface specific stuff. Overwriting them won‘t break the upload
 275       but can break the way it‘s displayed.
 276       You can overwrite them if you don‘t like the default behavior. If you just
 277       want to add an additional event handler, register it on the dropzone object
 278       and don‘t overwrite those options.
 279        */
 280       drop: function(e) {
 281         return this.element.classList.remove("dz-drag-hover");
 282       },
 283       dragstart: noop,
 284       dragend: function(e) {
 285         return this.element.classList.remove("dz-drag-hover");
 286       },
 287       dragenter: function(e) {
 288         return this.element.classList.add("dz-drag-hover");
 289       },
 290       dragover: function(e) {
 291         return this.element.classList.add("dz-drag-hover");
 292       },
 293       dragleave: function(e) {
 294         return this.element.classList.remove("dz-drag-hover");
 295       },
 296       paste: noop,
 297       reset: function() {
 298         return this.element.classList.remove("dz-started");
 299       },
 300       addedfile: function(file) {
 301         var j, k, l, len, len1, len2, node, ref, ref1, ref2, removeFileEvent, removeLink, results;
 302         if (this.element === this.previewsContainer) {
 303           this.element.classList.add("dz-started");
 304         }
 305         if (this.previewsContainer) {
 306           file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim());
 307           file.previewTemplate = file.previewElement;
 308           this.previewsContainer.appendChild(file.previewElement);
 309           ref = file.previewElement.querySelectorAll("[data-dz-name]");
 310           for (j = 0, len = ref.length; j < len; j++) {
 311             node = ref[j];
 312             node.textContent = file.name;
 313           }
 314           ref1 = file.previewElement.querySelectorAll("[data-dz-size]");
 315           for (k = 0, len1 = ref1.length; k < len1; k++) {
 316             node = ref1[k];
 317             node.innerHTML = this.filesize(file.size);
 318           }
 319           if (this.options.addRemoveLinks) {
 320             file._removeLink = Dropzone.createElement("<a class=\\"dz-remove\\" href=\\"javascript:undefined;\\" data-dz-remove>" + this.options.dictRemoveFile + "</a>");
 321             file.previewElement.appendChild(file._removeLink);
 322           }
 323           removeFileEvent = (function(_this) {
 324             return function(e) {
 325               e.preventDefault();
 326               e.stopPropagation();
 327               if (file.status === Dropzone.UPLOADING) {
 328                 return Dropzone.confirm(_this.options.dictCancelUploadConfirmation, function() {
 329                   return _this.removeFile(file);
 330                 });
 331               } else {
 332                 if (_this.options.dictRemoveFileConfirmation) {
 333                   return Dropzone.confirm(_this.options.dictRemoveFileConfirmation, function() {
 334                     return _this.removeFile(file);
 335                   });
 336                 } else {
 337                   return _this.removeFile(file);
 338                 }
 339               }
 340             };
 341           })(this);
 342           ref2 = file.previewElement.querySelectorAll("[data-dz-remove]");
 343           results = [];
 344           for (l = 0, len2 = ref2.length; l < len2; l++) {
 345             removeLink = ref2[l];
 346             results.push(removeLink.addEventListener("click", removeFileEvent));
 347           }
 348           return results;
 349         }
 350       },
 351       removedfile: function(file) {
 352         var ref;
 353         if (file.previewElement) {
 354           if ((ref = file.previewElement) != null) {
 355             ref.parentNode.removeChild(file.previewElement);
 356           }
 357         }
 358         return this._updateMaxFilesReachedClass();
 359       },
 360       thumbnail: function(file, dataUrl) {
 361         var j, len, ref, thumbnailElement;
 362         if (file.previewElement) {
 363           file.previewElement.classList.remove("dz-file-preview");
 364           ref = file.previewElement.querySelectorAll("[data-dz-thumbnail]");
 365           for (j = 0, len = ref.length; j < len; j++) {
 366             thumbnailElement = ref[j];
 367             thumbnailElement.alt = file.name;
 368             thumbnailElement.src = dataUrl;
 369           }
 370           return setTimeout(((function(_this) {
 371             return function() {
 372               return file.previewElement.classList.add("dz-image-preview");
 373             };
 374           })(this)), 1);
 375         }
 376       },
 377       error: function(file, message) {
 378         var j, len, node, ref, results;
 379         if (file.previewElement) {
 380           file.previewElement.classList.add("dz-error");
 381           if (typeof message !== "String" && message.error) {
 382             message = message.error;
 383           }
 384           ref = file.previewElement.querySelectorAll("[data-dz-errormessage]");
 385           results = [];
 386           for (j = 0, len = ref.length; j < len; j++) {
 387             node = ref[j];
 388             results.push(node.textContent = message);
 389           }
 390           return results;
 391         }
 392       },
 393       errormultiple: noop,
 394       processing: function(file) {
 395         if (file.previewElement) {
 396           file.previewElement.classList.add("dz-processing");
 397           if (file._removeLink) {
 398             return file._removeLink.textContent = this.options.dictCancelUpload;
 399           }
 400         }
 401       },
 402       processingmultiple: noop,
 403       uploadprogress: function(file, progress, bytesSent) {
 404         var j, len, node, ref, results;
 405         if (file.previewElement) {
 406           ref = file.previewElement.querySelectorAll("[data-dz-uploadprogress]");
 407           results = [];
 408           for (j = 0, len = ref.length; j < len; j++) {
 409             node = ref[j];
 410             if (node.nodeName === ‘PROGRESS‘) {
 411               results.push(node.value = progress);
 412             } else {
 413               results.push(node.style.width = progress + "%");
 414             }
 415           }
 416           return results;
 417         }
 418       },
 419       totaluploadprogress: noop,
 420       sending: noop,
 421       sendingmultiple: noop,
 422       success: function(file) {
 423         if (file.previewElement) {
 424           return file.previewElement.classList.add("dz-success");
 425         }
 426       },
 427       successmultiple: noop,
 428       canceled: function(file) {
 429         return this.emit("error", file, "Upload canceled.");
 430       },
 431       canceledmultiple: noop,
 432       complete: function(file) {
 433         if (file._removeLink) {
 434           file._removeLink.textContent = this.options.dictRemoveFile;
 435         }
 436         if (file.previewElement) {
 437           return file.previewElement.classList.add("dz-complete");
 438         }
 439       },
 440       completemultiple: noop,
 441       maxfilesexceeded: noop,
 442       maxfilesreached: noop,
 443       queuecomplete: noop,
 444       addedfiles: noop
 445     };
 446 
 447     extend = function() {
 448       var j, key, len, object, objects, target, val;
 449       target = arguments[0], objects = 2 <= arguments.length ? slice.call(arguments, 1) : [];
 450       for (j = 0, len = objects.length; j < len; j++) {
 451         object = objects[j];
 452         for (key in object) {
 453           val = object[key];
 454           target[key] = val;
 455         }
 456       }
 457       return target;
 458     };
 459 
 460     function Dropzone(element1, options) {
 461       var elementOptions, fallback, ref;
 462       this.element = element1;
 463       this.version = Dropzone.version;
 464       this.defaultOptions.previewTemplate = this.defaultOptions.previewTemplate.replace(/\\n*/g, "");
 465       this.clickableElements = [];
 466       this.listeners = [];
 467       this.files = [];
 468       if (typeof this.element === "string") {
 469         this.element = document.querySelector(this.element);
 470       }
 471       if (!(this.element && (this.element.nodeType != null))) {
 472         throw new Error("Invalid dropzone element.");
 473       }
 474       if (this.element.dropzone) {
 475         throw new Error("Dropzone already attached.");
 476       }
 477       Dropzone.instances.push(this);
 478       this.element.dropzone = this;
 479       elementOptions = (ref = Dropzone.optionsForElement(this.element)) != null ? ref : {};
 480       this.options = extend({}, this.defaultOptions, elementOptions, options != null ? options : {});
 481       if (this.options.forceFallback || !Dropzone.isBrowserSupported()) {
 482         return this.options.fallback.call(this);
 483       }
 484       if (this.options.url == null) {
 485         this.options.url = this.element.getAttribute("action");
 486       }
 487       if (!this.options.url) {
 488         throw new Error("No URL provided.");
 489       }
 490       if (this.options.acceptedFiles && this.options.acceptedMimeTypes) {
 491         throw new Error("You can‘t provide both ‘acceptedFiles‘ and ‘acceptedMimeTypes‘. ‘acceptedMimeTypes‘ is deprecated.");
 492       }
 493       if (this.options.acceptedMimeTypes) {
 494         this.options.acceptedFiles = this.options.acceptedMimeTypes;
 495         delete this.options.acceptedMimeTypes;
 496       }
 497       if (this.options.renameFilename != null) {
 498         this.options.renameFile = (function(_this) {
 499           return function(file) {
 500             return _this.options.renameFilename.call(_this, file.name, file);
 501           };
 502         })(this);
 503       }
 504       this.options.method = this.options.method.toUpperCase();
 505       if ((fallback = this.getExistingFallback()) && fallback.parentNode) {
 506         fallback.parentNode.removeChild(fallback);
 507       }
 508       if (this.options.previewsContainer !== false) {
 509         if (this.options.previewsContainer) {
 510           this.previewsContainer = Dropzone.getElement(this.options.previewsContainer, "previewsContainer");
 511         } else {
 512           this.previewsContainer = this.element;
 513         }
 514       }
 515       if (this.options.clickable) {
 516         if (this.options.clickable === true) {
 517           this.clickableElements = [this.element];
 518         } else {
 519           this.clickableElements = Dropzone.getElements(this.options.clickable, "clickable");
 520         }
 521       }
 522       this.init();
 523     }
 524 
 525     Dropzone.prototype.getAcceptedFiles = function() {
 526       var file, j, len, ref, results;
 527       ref = this.files;
 528       results = [];
 529       for (j = 0, len = ref.length; j < len; j++) {
 530         file = ref[j];
 531         if (file.accepted) {
 532           results.push(file);
 533         }
 534       }
 535       return results;
 536     };
 537 
 538     Dropzone.prototype.getRejectedFiles = function() {
 539       var file, j, len, ref, results;
 540       ref = this.files;
 541       results = [];
 542       for (j = 0, len = ref.length; j < len; j++) {
 543         file = ref[j];
 544         if (!file.accepted) {
 545           results.push(file);
 546         }
 547       }
 548       return results;
 549     };
 550 
 551     Dropzone.prototype.getFilesWithStatus = function(status) {
 552       var file, j, len, ref, results;
 553       ref = this.files;
 554       results = [];
 555       for (j = 0, len = ref.length; j < len; j++) {
 556         file = ref[j];
 557         if (file.status === status) {
 558           results.push(file);
 559         }
 560       }
 561       return results;
 562     };
 563 
 564     Dropzone.prototype.getQueuedFiles = function() {
 565       return this.getFilesWithStatus(Dropzone.QUEUED);
 566     };
 567 
 568     Dropzone.prototype.getUploadingFiles = function() {
 569       return this.getFilesWithStatus(Dropzone.UPLOADING);
 570     };
 571 
 572     Dropzone.prototype.getAddedFiles = function() {
 573       return this.getFilesWithStatus(Dropzone.ADDED);
 574     };
 575 
 576     Dropzone.prototype.getActiveFiles = function() {
 577       var file, j, len, ref, results;
 578       ref = this.files;
 579       results = [];
 580       for (j = 0, len = ref.length; j < len; j++) {
 581         file = ref[j];
 582         if (file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED) {
 583           results.push(file);
 584         }
 585       }
 586       return results;
 587     };
 588 
 589     Dropzone.prototype.init = function() {
 590       var eventName, j, len, noPropagation, ref, ref1, setupHiddenFileInput;
 591       if (this.element.tagName === "form") {
 592         this.element.setAttribute("enctype", "multipart/form-data");
 593       }
 594       if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) {
 595         this.element.appendChild(Dropzone.createElement("<div class=\\"dz-default dz-message\\"><span>" + this.options.dictDefaultMessage + "</span></div>"));
 596       }
 597       if (this.clickableElements.length) {
 598         setupHiddenFileInput = (function(_this) {
 599           return function() {
 600             if (_this.hiddenFileInput) {
 601               _this.hiddenFileInput.parentNode.removeChild(_this.hiddenFileInput);
 602             }
 603             _this.hiddenFileInput = document.createElement("input");
 604             _this.hiddenFileInput.setAttribute("type", "file");
 605             if ((_this.options.maxFiles == null) || _this.options.maxFiles > 1) {
 606               _this.hiddenFileInput.setAttribute("multiple", "multiple");
 607             }
 608             _this.hiddenFileInput.className = "dz-hidden-input";
 609             if (_this.options.acceptedFiles != null) {
 610               _this.hiddenFileInput.setAttribute("accept", _this.options.acceptedFiles);
 611             }
 612             if (_this.options.capture != null) {
 613               _this.hiddenFileInput.setAttribute("capture", _this.options.capture);
 614             }
 615             _this.hiddenFileInput.style.visibility = "hidden";
 616             _this.hiddenFileInput.style.position = "absolute";
 617             _this.hiddenFileInput.style.top = "0";
 618             _this.hiddenFileInput.style.left = "0";
 619             _this.hiddenFileInput.style.height = "0";
 620             _this.hiddenFileInput.style.width = "0";
 621             document.querySelector(_this.options.hiddenInputContainer).appendChild(_this.hiddenFileInput);
 622             return _this.hiddenFileInput.addEventListener("change", function() {
 623               var file, files, j, len;
 624               files = _this.hiddenFileInput.files;
 625               if (files.length) {
 626                 for (j = 0, len = files.length; j < len; j++) {
 627                   file = files[j];
 628                   _this.addFile(file);
 629                 }
 630               }
 631               _this.emit("addedfiles", files);
 632               return setupHiddenFileInput();
 633             });
 634           };
 635         })(this);
 636         setupHiddenFileInput();
 637       }
 638       this.URL = (ref = window.URL) != null ? ref : window.webkitURL;
 639       ref1 = this.events;
 640       for (j = 0, len = ref1.length; j < len; j++) {
 641         eventName = ref1[j];
 642         this.on(eventName, this.options[eventName]);
 643       }
 644       this.on("uploadprogress", (function(_this) {
 645         return function() {
 646           return _this.updateTotalUploadProgress();
 647         };
 648       })(this));
 649       this.on("removedfile", (function(_this) {
 650         return function() {
 651           return _this.updateTotalUploadProgress();
 652         };
 653       })(this));
 654       this.on("canceled", (function(_this) {
 655         return function(file) {
 656           return _this.emit("complete", file);
 657         };
 658       })(this));
 659       this.on("complete", (function(_this) {
 660         return function(file) {
 661           if (_this.getAddedFiles().length === 0 && _this.getUploadingFiles().length === 0 && _this.getQueuedFiles().length === 0) {
 662             return setTimeout((function() {
 663               return _this.emit("queuecomplete");
 664             }), 0);
 665           }
 666         };
 667       })(this));
 668       noPropagation = function(e) {
 669         e.stopPropagation();
 670         if (e.preventDefault) {
 671           return e.preventDefault();
 672         } else {
 673           return e.returnValue = false;
 674         }
 675       };
 676       this.listeners = [
 677         {
 678           element: this.element,
 679           events: {
 680             "dragstart": (function(_this) {
 681               return function(e) {
 682                 return _this.emit("dragstart", e);
 683               };
 684             })(this),
 685             "dragenter": (function(_this) {
 686               return function(e) {
 687                 noPropagation(e);
 688                 return _this.emit("dragenter", e);
 689               };
 690             })(this),
 691             "dragover": (function(_this) {
 692               return function(e) {
 693                 var efct;
 694                 try {
 695                   efct = e.dataTransfer.effectAllowed;
 696                 } catch (undefined) {}
 697                 e.dataTransfer.dropEffect = ‘move‘ === efct || ‘linkMove‘ === efct ? ‘move‘ : ‘copy‘;
 698                 noPropagation(e);
 699                 return _this.emit("dragover", e);
 700               };
 701             })(this),
 702             "dragleave": (function(_this) {
 703               return function(e) {
 704                 return _this.emit("dragleave", e);
 705               };
 706             })(this),
 707             "drop": (function(_this) {
 708               return function(e) {
 709                 noPropagation(e);
 710                 return _this.drop(e);
 711               };
 712             })(this),
 713             "dragend": (function(_this) {
 714               return function(e) {
 715                 return _this.emit("dragend", e);
 716               };
 717             })(this)
 718           }
 719         }
 720       ];
 721       this.clickableElements.forEach((function(_this) {
 722         return function(clickableElement) {
 723           return _this.listeners.push({
 724             element: clickableElement,
 725             events: {
 726               "click": function(evt) {
 727                 if ((clickableElement !== _this.element) || (evt.target === _this.element || Dropzone.elementInside(evt.target, _this.element.querySelector(".dz-message")))) {
 728                   _this.hiddenFileInput.click();
 729                 }
 730                 return true;
 731               }
 732             }
 733           });
 734         };
 735       })(this));
 736       this.enable();
 737       return this.options.init.call(this);
 738     };
 739 
 740     Dropzone.prototype.destroy = function() {
 741       var ref;
 742       this.disable();
 743       this.removeAllFiles(true);
 744       if ((ref = this.hiddenFileInput) != null ? ref.parentNode : void 0) {
 745         this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);
 746         this.hiddenFileInput = null;
 747       }
 748       delete this.element.dropzone;
 749       return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1);
 750     };
 751 
 752     Dropzone.prototype.updateTotalUploadProgress = function() {
 753       var activeFiles, file, j, len, ref, totalBytes, totalBytesSent, totalUploadProgress;
 754       totalBytesSent = 0;
 755       totalBytes = 0;
 756       activeFiles = this.getActiveFiles();
 757       if (activeFiles.length) {
 758         ref = this.getActiveFiles();
 759         for (j = 0, len = ref.length; j < len; j++) {
 760           file = ref[j];
 761           totalBytesSent += file.upload.bytesSent;
 762           totalBytes += file.upload.total;
 763         }
 764         totalUploadProgress = 100 * totalBytesSent / totalBytes;
 765       } else {
 766         totalUploadProgress = 100;
 767       }
 768       return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent);
 769     };
 770 
 771     Dropzone.prototype._getParamName = function(n) {
 772       if (typeof this.options.paramName === "function") {
 773         return this.options.paramName(n);
 774       } else {
 775         return "" + this.options.paramName + (this.options.uploadMultiple ? "[" + n + "]" : "");
 776       }
 777     };
 778 
 779     Dropzone.prototype._renameFile = function(file) {
 780       if (typeof this.options.renameFile !== "function") {
 781         return file.name;
 782       }
 783       return this.options.renameFile(file);
 784     };
 785 
 786     Dropzone.prototype.getFallbackForm = function() {
 787       var existingFallback, fields, fieldsString, form;
 788       if (existingFallback = this.getExistingFallback()) {
 789         return existingFallback;
 790       }
 791       fieldsString = "<div class=\\"dz-fallback\\">";
 792       if (this.options.dictFallbackText) {
 793         fieldsString += "<p>" + this.options.dictFallbackText + "</p>";
 794       }
 795       fieldsString += "<input type=\\"file\\" name=\\"" + (this._getParamName(0)) + "\\" " + (this.options.uploadMultiple ? ‘multiple="multiple"‘ : void 0) + " /><input type=\\"submit\\" value=\\"Upload!\\"></div>";
 796       fields = Dropzone.createElement(fieldsString);
 797       if (this.element.tagName !== "FORM") {
 798         form = Dropzone.createElement("<form action=\\"" + this.options.url + "\\" enctype=\\"multipart/form-data\\" method=\\"" + this.options.method + "\\"></form>");
 799         form.appendChild(fields);
 800       } else {
 801         this.element.setAttribute("enctype", "multipart/form-data");
 802         this.element.setAttribute("method", this.options.method);
 803       }
 804       return form != null ? form : fields;
 805     };
 806 
 807     Dropzone.prototype.getExistingFallback = function() {
 808       var fallback, getFallback, j, len, ref, tagName;
 809       getFallback = function(elements) {
 810         var el, j, len;
 811         for (j = 0, len = elements.length; j < len; j++) {
 812           el = elements[j];
 813           if (/(^| )fallback($| )/.test(el.className)) {
 814             return el;
 815           }
 816         }
 817       };
 818       ref = ["div", "form"];
 819       for (j = 0, len = ref.length; j < len; j++) {
 820         tagName = ref[j];
 821         if (fallback = getFallback(this.element.getElementsByTagName(tagName))) {
 822           return fallback;
 823         }
 824       }
 825     };
 826 
 827     Dropzone.prototype.setupEventListeners = function() {
 828       var elementListeners, event, j, len, listener, ref, results;
 829       ref = this.listeners;
 830       results = [];
 831       for (j = 0, len = ref.length; j < len; j++) {
 832         elementListeners = ref[j];
 833         results.push((function() {
 834           var ref1, results1;
 835           ref1 = elementListeners.events;
 836           results1 = [];
 837           for (event in ref1) {
 838             listener = ref1[event];
 839             results1.push(elementListeners.element.addEventListener(event, listener, false));
 840           }
 841           return results1;
 842         })());
 843       }
 844       return results;
 845     };
 846 
 847     Dropzone.prototype.removeEventListeners = function() {
 848       var elementListeners, event, j, len, listener, ref, results;
 849       ref = this.listeners;
 850       results = [];
 851       for (j = 0, len = ref.length; j < len; j++) {
 852         elementListeners = ref[j];
 853         results.push((function() {
 854           var ref1, results1;
 855           ref1 = elementListeners.events;
 856           results1 = [];
 857           for (event in ref1) {
 858             listener = ref1[event];
 859             results1.push(elementListeners.element.removeEventListener(event, listener, false));
 860           }
 861           return results1;
 862         })());
 863       }
 864       return results;
 865     };
 866 
 867     Dropzone.prototype.disable = function() {
 868       var file, j, len, ref, results;
 869       this.clickableElements.forEach(function(element) {
 870         return element.classList.remove("dz-clickable");
 871       });
 872       this.removeEventListeners();
 873       ref = this.files;
 874       results = [];
 875       for (j = 0, len = ref.length; j < len; j++) {
 876         file = ref[j];
 877         results.push(this.cancelUpload(file));
 878       }
 879       return results;
 880     };
 881 
 882     Dropzone.prototype.enable = function() {
 883       this.clickableElements.forEach(function(element) {
 884         return element.classList.add("dz-clickable");
 885       });
 886       return this.setupEventListeners();
 887     };
 888 
 889     Dropzone.prototype.filesize = function(size) {
 890       var cutoff, i, j, len, selectedSize, selectedUnit, unit, units;
 891       selectedSize = 0;
 892       selectedUnit = "b";
 893       if (size > 0) {
 894         units = [‘tb‘, ‘gb‘, ‘mb‘, ‘kb‘, ‘b‘];
 895         for (i = j = 0, len = units.length; j < len; i = ++j) {
 896           unit = units[i];
 897           cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10;
 898           if (size >= cutoff) {
 899             selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i);
 900             selectedUnit = unit;
 901             break;
 902           }
 903         }
 904         selectedSize = Math.round(10 * selectedSize) / 10;
 905       }
 906       return "<strong>" + selectedSize + "</strong> " + this.options.dictFileSizeUnits[selectedUnit];
 907     };
 908 
 909     Dropzone.prototype._updateMaxFilesReachedClass = function() {
 910       if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) {
 911         if (this.getAcceptedFiles().length === this.options.maxFiles) {
 912           this.emit(‘maxfilesreached‘, this.files);
 913         }
 914         return this.element.classList.add("dz-max-files-reached");
 915       } else {
 916         return this.element.classList.remove("dz-max-files-reached");
 917       }
 918     };
 919 
 920     Dropzone.prototype.drop = function(e) {
 921       var files, items;
 922       if (!e.dataTransfer) {
 923         return;
 924       }
 925       this.emit("drop", e);
 926       files = e.dataTransfer.files;
 927       this.emit("addedfiles", files);
 928       if (files.length) {
 929         items = e.dataTransfer.items;
 930         if (items && items.length && (items[0].webkitGetAsEntry != null)) {
 931           this._addFilesFromItems(items);
 932         } else {
 933           this.handleFiles(files);
 934         }
 935       }
 936     };
 937 
 938     Dropzone.prototype.paste = function(e) {
 939       var items, ref;
 940       if ((e != null ? (ref = e.clipboardData) != null ? ref.items : void 0 : void 0) == null) {
 941         return;
 942       }
 943       this.emit("paste", e);
 944       items = e.clipboardData.items;
 945       if (items.length) {
 946         return this._addFilesFromItems(items);
 947       }
 948     };
 949 
 950     Dropzone.prototype.handleFiles = function(files) {
 951       var file, j, len, results;
 952       results = [];
 953       for (j = 0, len = files.length; j < len; j++) {
 954         file = files[j];
 955         results.push(this.addFile(file));
 956       }
 957       return results;
 958     };
 959 
 960     Dropzone.prototype._addFilesFromItems = function(items) {
 961       var entry, item, j, len, results;
 962       results = [];
 963       for (j = 0, len = items.length; j < len; j++) {
 964         item = items[j];
 965         if ((item.webkitGetAsEntry != null) && (entry = item.webkitGetAsEntry())) {
 966           if (entry.isFile) {
 967             results.push(this.addFile(item.getAsFile()));
 968           } else if (entry.isDirectory) {
 969             results.push(this._addFilesFromDirectory(entry, entry.name));
 970           } else {
 971             results.push(void 0);
 972           }
 973         } else if (item.getAsFile != null) {
 974           if ((item.kind == null) || item.kind === "file") {
 975             results.push(this.addFile(item.getAsFile()));
 976           } else {
 977             results.push(void 0);
 978           }
 979         } else {
 980           results.push(void 0);
 981         }
 982       }
 983       return results;
 984     };
 985 
 986     Dropzone.prototype._addFilesFromDirectory = function(directory, path) {
 987       var dirReader, errorHandler, readEntries;
 988       dirReader = directory.createReader();
 989       errorHandler = function(error) {
 990         return typeof console !== "undefined" && console !== null ? typeof console.log === "function" ? console.log(error) : void 0 : void 0;
 991       };
 992       readEntries = (function(_this) {
 993         return function() {
 994           return dirReader.readEntries(function(entries) {
 995             var entry, j, len;
 996             if (entries.length > 0) {
 997               for (j = 0, len = entries.length; j < len; j++) {
 998                 entry = entries[j];
 999                 if (entry.isFile) {
1000                   entry.file(function(file) {
1001                     if (_this.options.ignoreHiddenFiles && file.name.substring(0, 1) === ‘.‘) {
1002                       return;
1003                     }
1004                     file.fullPath = path + "/" + file.name;
1005                     return _this.addFile(file);
1006                   });
1007                 } else if (entry.isDirectory) {
1008                   _this._addFilesFromDirectory(entry, path + "/" + entry.name);
1009                 }
1010               }
1011               readEntries();
1012             }
1013             return null;
1014           }, errorHandler);
1015         };
1016       })(this);
1017       return readEntries();
1018     };
1019 
1020     Dropzone.prototype.accept = function(file, done) {
1021       if (file.size > this.options.maxFilesize * 1024 * 1024) {
1022         return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize));
1023       } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) {
1024         return done(this.options.dictInvalidFileType);
1025       } else if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) {
1026         done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles));
1027         return this.emit("maxfilesexceeded", file);
1028       } else {
1029         return this.options.accept.call(this, file, done);
1030       }
1031     };
1032 
1033     Dropzone.prototype.addFile = function(file) {
1034       file.upload = {
1035         progress: 0,
1036         total: file.size,
1037         bytesSent: 0,
1038         filename: this._renameFile(file)
1039       };
1040       this.files.push(file);
1041       file.status = Dropzone.ADDED;
1042       this.emit("addedfile", file);
1043       this._enqueueThumbnail(file);
1044       return this.accept(file, (function(_this) {
1045         return function(error) {
1046           if (error) {
1047             file.accepted = false;
1048             _this._errorProcessing([file], error);
1049           } else {
1050             file.accepted = true;
1051             if (_this.options.autoQueue) {
1052               _this.enqueueFile(file);
1053             }
1054           }
1055           return _this._updateMaxFilesReachedClass();
1056         };
1057       })(this));
1058     };
1059 
1060     Dropzone.prototype.enqueueFiles = function(files) {
1061       var file, j, len;
1062       for (j = 0, len = files.length; j < len; j++) {
1063         file = files[j];
1064         this.enqueueFile(file);
1065       }
1066       return null;
1067     };
1068 
1069     Dropzone.prototype.enqueueFile = function(file) {
1070       if (file.status === Dropzone.ADDED && file.accepted === true) {
1071         file.status = Dropzone.QUEUED;
1072         if (this.options.autoProcessQueue) {
1073           return setTimeout(((function(_this) {
1074             return function() {
1075               return _this.processQueue();
1076             };
1077           })(this)), 0);
1078         }
1079       } else {
1080         throw new Error("This file can‘t be queued because it has already been processed or was rejected.");
1081       }
1082     };
1083 
1084     Dropzone.prototype._thumbnailQueue = [];
1085 
1086     Dropzone.prototype._processingThumbnail = false;
1087 
1088     Dropzone.prototype._enqueueThumbnail = function(file) {
1089       if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) {
1090         this._thumbnailQueue.push(file);
1091         return setTimeout(((function(_this) {
1092           return function() {
1093             return _this._processThumbnailQueue();
1094           };
1095         })(this)), 0);
1096       }
1097     };
1098 
1099     Dropzone.prototype._processThumbnailQueue = function() {
1100       var file;
1101       if (this._processingThumbnail || this._thumbnailQueue.length === 0) {
1102         return;
1103       }
1104       this._processingThumbnail = true;
1105       file = this._thumbnailQueue.shift();
1106       return this.createThumbnail(file, this.options.thumbnailWidth, this.options.thumbnailHeight, this.options.thumbnailMethod, true, (function(_this) {
1107         return function(dataUrl) {
1108           _this.emit("thumbnail", file, dataUrl);
1109           _this._processingThumbnail = false;
1110           return _this._processThumbnailQueue();
1111         };
1112       })(this));
1113     };
1114 
1115     Dropzone.prototype.removeFile = function(file) {
1116       if (file.status === Dropzone.UPLOADING) {
1117         this.cancelUpload(file);
1118       }
1119       this.files = without(this.files, file);
1120       this.emit("removedfile", file);
1121       if (this.files.length === 0) {
1122         return this.emit("reset");
1123       }
1124     };
1125 
1126     Dropzone.prototype.removeAllFiles = function(cancelIfNecessary) {
1127       var file, j, len, ref;
1128       if (cancelIfNecessary == null) {
1129         cancelIfNecessary = false;
1130       }
1131       ref = this.files.slice();
1132       for (j = 0, len = ref.length; j < len; j++) {
1133         file = ref[j];
1134         if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) {
1135           this.removeFile(file);
1136         }
1137       }
1138       return null;
1139     };
1140 
1141     Dropzone.prototype.resizeImage = function(file, width, height, resizeMethod, callback) {
1142       return this.createThumbnail(file, width, height, resizeMethod, false, (function(_this) {
1143         return function(dataUrl, canvas) {
1144           var resizeMimeType, resizedDataURL;
1145           if (canvas === null) {
1146             return callback(file);
1147           } else {
1148             resizeMimeType = _this.options.resizeMimeType;
1149             if (resizeMimeType == null) {
1150               resizeMimeType = file.type;
1151             }
1152             resizedDataURL = canvas.toDataURL(resizeMimeType, _this.options.resizeQuality);
1153             if (resizeMimeType === ‘image/jpeg‘ || resizeMimeType === ‘image/jpg‘) {
1154               resizedDataURL = ExifRestore.restore(file.dataURL, resizedDataURL);
1155             }
1156             return callback(Dropzone.dataURItoBlob(resizedDataURL));
1157           }
1158         };
1159       })(this));
1160     };
1161 
1162     Dropzone.prototype.createThumbnail = function(file, width, height, resizeMethod, fixOrientation, callback) {
1163       var fileReader;
1164       fileReader = new FileReader;
1165       fileReader.onload = (function(_this) {
1166         return function() {
1167           file.dataURL = fileReader.result;
1168           if (file.type === "image/svg+xml") {
1169             if (callback != null) {
1170               callback(fileReader.result);
1171             }
1172             return;
1173           }
1174           return _this.createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback);
1175         };
1176       })(this);
1177       return fileReader.readAsDataURL(file);
1178     };
1179 
1180     Dropzone.prototype.createThumbnailFromUrl = function(file, width, height, resizeMethod, fixOrientation, callback, crossOrigin) {
1181       var img;
1182       img = document.createElement("img");
1183       if (crossOrigin) {
1184         img.crossOrigin = crossOrigin;
1185       }
1186       img.onload = (function(_this) {
1187         return function() {
1188           var loadExif;
1189           loadExif = function(callback) {
1190             return callback(1);
1191           };
1192           if ((typeof EXIF !== "undefined" && EXIF !== null) && fixOrientation) {
1193             loadExif = function(callback) {
1194               return EXIF.getData(img, function() {
1195                 return callback(EXIF.getTag(this, ‘Orientation‘));
1196               });
1197             };
1198           }
1199           return loadExif(function(orientation) {
1200             var canvas, ctx, ref, ref1, ref2, ref3, resizeInfo, thumbnail;
1201             file.width = img.width;
1202             file.height = img.height;
1203             resizeInfo = _this.options.resize.call(_this, file, width, height, resizeMethod);
1204             canvas = document.createElement("canvas");
1205             ctx = canvas.getContext("2d");
1206             canvas.width = resizeInfo.trgWidth;
1207             canvas.height = resizeInfo.trgHeight;
1208             if (orientation > 4) {
1209               canvas.width = resizeInfo.trgHeight;
1210               canvas.height = resizeInfo.trgWidth;
1211             }
1212             switch (orientation) {
1213               case 2:
1214                 ctx.translate(canvas.width, 0);
1215                 ctx.scale(-1, 1);
1216                 break;
1217               case 3:
1218                 ctx.translate(canvas.width, canvas.height);
1219                 ctx.rotate(Math.PI);
1220                 break;
1221               case 4:
1222                 ctx.translate(0, canvas.height);
1223                 ctx.scale(1, -1);
1224                 break;
1225               case 5:
1226                 ctx.rotate(0.5 * Math.PI);
1227                 ctx.scale(1, -1);
1228                 break;
1229               case 6:
1230                 ctx.rotate(0.5 * Math.PI);
1231                 ctx.translate(0, -canvas.height);
1232                 break;
1233               case 7:
1234                 ctx.rotate(0.5 * Math.PI);
1235                 ctx.translate(canvas.width, -canvas.height);
1236                 ctx.scale(-1, 1);
1237                 break;
1238               case 8:
1239                 ctx.rotate(-0.5 * Math.PI);
1240                 ctx.translate(-canvas.width, 0);
1241             }
1242             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);
1243             thumbnail = canvas.toDataURL("image/png");
1244             if (callback != null) {
1245               return callback(thumbnail, canvas);
1246             }
1247           });
1248         };
1249       })(this);
1250       if (callback != null) {
1251         img.onerror = callback;
1252       }
1253       return img.src = file.dataURL;
1254     };
1255 
1256     Dropzone.prototype.processQueue = function() {
1257       var i, parallelUploads, processingLength, queuedFiles;
1258       parallelUploads = this.options.parallelUploads;
1259       processingLength = this.getUploadingFiles().length;
1260       i = processingLength;
1261       if (processingLength >= parallelUploads) {
1262         return;
1263       }
1264       queuedFiles = this.getQueuedFiles();
1265       if (!(queuedFiles.length > 0)) {
1266         return;
1267       }
1268       if (this.options.uploadMultiple) {
1269         return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength));
1270       } else {
1271         while (i < parallelUploads) {
1272           if (!queuedFiles.length) {
1273             return;
1274           }
1275           this.processFile(queuedFiles.shift());
1276           i++;
1277         }
1278       }
1279     };
1280 
1281     Dropzone.prototype.processFile = function(file) {
1282       return this.processFiles([file]);
1283     };
1284 
1285     Dropzone.prototype.processFiles = function(files) {
1286       var file, j, len;
1287       for (j = 0, len = files.length; j < len; j++) {
1288         file = files[j];
1289         file.processing = true;
1290         file.status = Dropzone.UPLOADING;
1291         this.emit("processing", file);
1292       }
1293       if (this.options.uploadMultiple) {
1294         this.emit("processingmultiple", files);
1295       }
1296       return this.uploadFiles(files);
1297     };
1298 
1299     Dropzone.prototype._getFilesWithXhr = function(xhr) {
1300       var file, files;
1301       return files = (function() {
1302         var j, len, ref, results;
1303         ref = this.files;
1304         results = [];
1305         for (j = 0, len = ref.length; j < len; j++) {
1306           file = ref[j];
1307           if (file.xhr === xhr) {
1308             results.push(file);
1309           }
1310         }
1311         return results;
1312       }).call(this);
1313     };
1314 
1315     Dropzone.prototype.cancelUpload = function(file) {
1316       var groupedFile, groupedFiles, j, k, len, len1, ref;
1317       if (file.status === Dropzone.UPLOADING) {
1318         groupedFiles = this._getFilesWithXhr(file.xhr);
1319         for (j = 0, len = groupedFiles.length; j < len; j++) {
1320           groupedFile = groupedFiles[j];
1321           groupedFile.status = Dropzone.CANCELED;
1322         }
1323         file.xhr.abort();
1324         for (k = 0, len1 = groupedFiles.length; k < len1; k++) {
1325           groupedFile = groupedFiles[k];
1326           this.emit("canceled", groupedFile);
1327         }
1328         if (this.options.uploadMultiple) {
1329           this.emit("canceledmultiple", groupedFiles);
1330         }
1331       } else if ((ref = file.status) === Dropzone.ADDED || ref === Dropzone.QUEUED) {
1332         file.status = Dropzone.CANCELED;
1333         this.emit("canceled", file);
1334         if (this.options.uploadMultiple) {
1335           this.emit("canceledmultiple", [file]);
1336         }
1337       }
1338       if (this.options.autoProcessQueue) {
1339         return this.processQueue();
1340       }
1341     };
1342 
1343     resolveOption = function() {
1344       var args, option;
1345       option = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
1346       if (typeof option === ‘function‘) {
1347         return option.apply(this, args);
1348       }
1349       return option;
1350     };
1351 
1352     Dropzone.prototype.uploadFile = function(file) {
1353       return this.uploadFiles([file]);
1354     };
1355 
1356     Dropzone.prototype.uploadFiles = function(files) {
1357       var doneCounter, doneFunction, file, formData, handleError, headerName, headerValue, headers, i, input, inputName, inputType, j, k, key, l, len, len1, len2, len3, m, method, o, option, progressObj, ref, ref1, ref2, ref3, ref4, ref5, response, results, updateProgress, url, value, xhr;
1358       xhr = new XMLHttpRequest();
1359       for (j = 0, len = files.length; j < len; j++) {
1360         file = files[j];
1361         file.xhr = xhr;
1362       }
1363       method = resolveOption(this.options.method, files);
1364       url = resolveOption(this.options.url, files);
1365       xhr.open(method, url, true);
1366       xhr.timeout = resolveOption(this.options.timeout, files);
1367       xhr.withCredentials = !!this.options.withCredentials;
1368       response = null;
1369       handleError = (function(_this) {
1370         return function() {
1371           var k, len1, results;
1372           results = [];
1373           for (k = 0, len1 = files.length; k < len1; k++) {
1374             file = files[k];
1375             results.push(_this._errorProcessing(files, response || _this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr));
1376           }
1377           return results;
1378         };
1379       })(this);
1380       updateProgress = (function(_this) {
1381         return function(e) {
1382           var allFilesFinished, k, l, len1, len2, len3, m, progress, results;
1383           if (e != null) {
1384             progress = 100 * e.loaded / e.total;
1385             for (k = 0, len1 = files.length; k < len1; k++) {
1386               file = files[k];
1387               file.upload.progress = progress;
1388               file.upload.total = e.total;
1389               file.upload.bytesSent = e.loaded;
1390             }
1391           } else {
1392             allFilesFinished = true;
1393             progress = 100;
1394             for (l = 0, len2 = files.length; l < len2; l++) {
1395               file = files[l];
1396               if (!(file.upload.progress === 100 && file.upload.bytesSent === file.upload.total)) {
1397                 allFilesFinished = false;
1398               }
1399               file.upload.progress = progress;
1400               file.upload.bytesSent = file.upload.total;
1401             }
1402             if (allFilesFinished) {
1403               return;
1404             }
1405           }
1406           results = [];
1407           for (m = 0, len3 = files.length; m < len3; m++) {
1408             file = files[m];
1409             results.push(_this.emit("uploadprogress", file, progress, file.upload.bytesSent));
1410           }
1411           return results;
1412         };
1413       })(this);
1414       xhr.onload = (function(_this) {
1415         return function(e) {
1416           var error1, ref;
1417           if (files[0].status === Dropzone.CANCELED) {
1418             return;
1419           }
1420           if (xhr.readyState !== 4) {
1421             return;
1422           }
1423           if (xhr.responseType !== ‘arraybuffer‘ && xhr.responseType !== ‘blob‘) {
1424             response = xhr.responseText;
1425             if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) {
1426               try {
1427                 response = JSON.parse(response);
1428               } catch (error1) {
1429                 e = error1;
1430                 response = "Invalid JSON response from server.";
1431               }
1432             }
1433           }
1434           updateProgress();
1435           if (!((200 <= (ref = xhr.status) && ref < 300))) {
1436             return handleError();
1437           } else {
1438             return _this._finished(files, response, e);
1439           }
1440         };
1441       })(this);
1442       xhr.onerror = (function(_this) {
1443         return function() {
1444           if (files[0].status === Dropzone.CANCELED) {
1445             return;
1446           }
1447           return handleError();
1448         };
1449       })(this);
1450       progressObj = (ref = xhr.upload) != null ? ref : xhr;
1451       progressObj.onprogress = updateProgress;
1452       headers = {
1453         "Accept": "application/json",
1454         "Cache-Control": "no-cache",
1455         "X-Requested-With": "XMLHttpRequest"
1456       };
1457       if (this.options.headers) {
1458         extend(headers, this.options.headers);
1459       }
1460       for (headerName in headers) {
1461         headerValue = headers[headerName];
1462         if (headerValue) {
1463           xhr.setRequestHeader(headerName, headerValue);
1464         }
1465       }
1466       formData = new FormData();
1467       if (this.options.params) {
1468         ref1 = this.options.params;
1469         for (key in ref1) {
1470           value = ref1[key];
1471           formData.append(key, value);
1472         }
1473       }
1474       for (k = 0, len1 = files.length; k < len1; k++) {
1475         file = files[k];
1476         this.emit("sending", file, xhr, formData);
1477       }
1478       if (this.options.uploadMultiple) {
1479         this.emit("sendingmultiple", files, xhr, formData);
1480       }
1481       if (this.element.tagName === "FORM") {
1482         ref2 = this.element.querySelectorAll("input, textarea, select, button");
1483         for (l = 0, len2 = ref2.length; l < len2; l++) {
1484           input = ref2[l];
1485           inputName = input.getAttribute("name");
1486           inputType = input.getAttribute("type");
1487           if (input.tagName === "SELECT" && input.hasAttribute("multiple")) {
1488             ref3 = input.options;
1489             for (m = 0, len3 = ref3.length; m < len3; m++) {
1490               option = ref3[m];
1491               if (option.selected) {
1492                 formData.append(inputName, option.value);
1493               }
1494             }
1495           } else if (!inputType || ((ref4 = inputType.toLowerCase()) !== "checkbox" && ref4 !== "radio") || input.checked) {
1496             formData.append(inputName, input.value);
1497           }
1498         }
1499       }
1500       doneCounter = 0;
1501       results = [];
1502       for (i = o = 0, ref5 = files.length - 1; 0 <= ref5 ? o <= ref5 : o >= ref5; i = 0 <= ref5 ? ++o : --o) {
1503         doneFunction = (function(_this) {
1504           return function(file, paramName, fileName) {
1505             return function(transformedFile) {
1506               formData.append(paramName, transformedFile, fileName);
1507               if (++doneCounter === files.length) {
1508                 return _this.submitRequest(xhr, formData, files);
1509               }
1510             };
1511           };
1512         })(this);
1513         results.push(this.options.transformFile.call(this, files[i], doneFunction(files[i], this._getParamName(i), files[i].upload.filename)));
1514       }
1515       return results;
1516     };
1517 
1518     Dropzone.prototype.submitRequest = function(xhr, formData, files) {
1519       return xhr.send(formData);
1520     };
1521 
1522     Dropzone.prototype._finished = function(files, responseText, e) {
1523       var file, j, len;
1524       for (j = 0, len = files.length; j < len; j++) {
1525         file = files[j];
1526         file.status = Dropzone.SUCCESS;
1527         this.emit("success", file, responseText, e);
1528         this.emit("complete", file);
1529       }
1530       if (this.options.uploadMultiple) {
1531         this.emit("successmultiple", files, responseText, e);
1532         this.emit("completemultiple", files);
1533       }
1534       if (this.options.autoProcessQueue) {
1535         return this.processQueue();
1536       }
1537     };
1538 
1539     Dropzone.prototype._errorProcessing = function(files, message, xhr) {
1540       var file, j, len;
1541       for (j = 0, len = files.length; j < len; j++) {
1542         file = files[j];
1543         file.status = Dropzone.ERROR;
1544         this.emit("error", file, message, xhr);
1545         this.emit("complete", file);
1546       }
1547       if (this.options.uploadMultiple) {
1548         this.emit("errormultiple", files, message, xhr);
1549         this.emit("completemultiple", files);
1550       }
1551       if (this.options.autoProcessQueue) {
1552         return this.processQueue();
1553       }
1554     };
1555 
1556     return Dropzone;
1557 
1558   })(Emitter);
1559 
1560   Dropzone.version = "5.1.1";
1561 
1562   Dropzone.options = {};
1563 
1564   Dropzone.optionsForElement = function(element) {
1565     if (element.getAttribute("id")) {
1566       return Dropzone.options[camelize(element.getAttribute("id"))];
1567     } else {
1568       return void 0;
1569     }
1570   };
1571 
1572   Dropzone.instances = [];
1573 
1574   Dropzone.forElement = function(element) {
1575     if (typeof element === "string") {
1576       element = document.querySelector(element);
1577     }
1578     if ((element != null ? element.dropzone : void 0) == null) {
1579       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.");
1580     }
1581     return element.dropzone;
1582   };
1583 
1584   Dropzone.autoDiscover = true;
1585 
1586   Dropzone.discover = function() {
1587     var checkElements, dropzone, dropzones, j, len, results;
1588     if (document.querySelectorAll) {
1589       dropzones = document.querySelectorAll(".dropzone");
1590     } else {
1591       dropzones = [];
1592       checkElements = function(elements) {
1593         var el, j, len, results;
1594         results = [];
1595         for (j = 0, len = elements.length; j < len; j++) {
1596           el = elements[j];
1597           if (/(^| )dropzone($| )/.test(el.className)) {
1598             results.push(dropzones.push(el));
1599           } else {
1600             results.push(void 0);
1601           }
1602         }
1603         return results;
1604       };
1605       checkElements(document.getElementsByTagName("div"));
1606       checkElements(document.getElementsByTagName("form"));
1607     }
1608     results = [];
1609     for (j = 0, len = dropzones.length; j < len; j++) {
1610       dropzone = dropzones[j];
1611       if (Dropzone.optionsForElement(dropzone) !== false) {
1612         results.push(new Dropzone(dropzone));
1613       } else {
1614         results.push(void 0);
1615       }
1616     }
1617     return results;
1618   };
1619 
1620   Dropzone.blacklistedBrowsers = [/opera.*Macintosh.*version\\/12/i];
1621 
1622   Dropzone.isBrowserSupported = function() {
1623     var capableBrowser, j, len, ref, regex;
1624     capableBrowser = true;
1625     if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) {
1626       if (!("classList" in document.createElement("a"))) {
1627         capableBrowser = false;
1628       } else {
1629         ref = Dropzone.blacklistedBrowsers;
1630         for (j = 0, len = ref.length; j < len; j++) {
1631           regex = ref[j];
1632           if (regex.test(navigator.userAgent)) {
1633             capableBrowser = false;
1634             continue;
1635           }
1636         }
1637       }
1638     } else {
1639       capableBrowser = false;
1640     }
1641     return capableBrowser;
1642   };
1643 
1644   Dropzone.dataURItoBlob = function(dataURI) {
1645     var ab, byteString, i, ia, j, mimeString, ref;
1646     byteString = atob(dataURI.split(‘,‘)[1]);
1647     mimeString = dataURI.split(‘,‘)[0].split(‘:‘)[1].split(‘;‘)[0];
1648     ab = new ArrayBuffer(byteString.length);
1649     ia = new Uint8Array(ab);
1650     for (i = j = 0, ref = byteString.length; 0 <= ref ? j <= ref : j >= ref; i = 0 <= ref ? ++j : --j) {
1651       ia[i] = byteString.charCodeAt(i);
1652     }
1653     return new Blob([ab], {
1654       type: mimeString
1655     });
1656   };
1657 
1658   without = function(list, rejectedItem) {
1659     var item, j, len, results;
1660     results = [];
1661     for (j = 0, len = list.length; j < len; j++) {
1662       item = list[j];
1663       if (item !== rejectedItem) {
1664         results.push(item);
1665       }
1666     }
1667     return results;
1668   };
1669 
1670   camelize = function(str) {
1671     return str.replace(/[\\-_](\\w)/g, function(match) {
1672       return match.charAt(1).toUpperCase();
1673     });
1674   };
1675 
1676   Dropzone.createElement = function(string) {
1677     var div;
1678     div = document.createElement("div");
1679     div.innerHTML = string;
1680     return div.childNodes[0];
1681   };
1682 
1683   Dropzone.elementInside = function(element, container) {
1684     if (element === container) {
1685       return true;
1686     }
1687     while (element = element.parentNode) {
1688       if (element === container) {
1689         return true;
1690       }
1691     }
1692     return false;
1693   };
1694 
1695   Dropzone.getElement = function(el, name) {
1696     var element;
1697     if (typeof el === "string") {
1698       element = document.querySelector(el);
1699     } else if (el.nodeType != null) {
1700       element = el;
1701     }
1702     if (element == null) {
1703       throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element.");
1704     }
1705     return element;
1706   };
1707 
1708   Dropzone.getElements = function(els, name) {
1709     var e, el, elements, error1, j, k, len, len1, ref;
1710     if (els instanceof Array) {
1711       elements = [];
1712       try {
1713         for (j = 0, len = els.length; j < len; j++) {
1714           el = els[j];
1715           elements.push(this.getElement(el, name));
1716         }
1717       } catch (error1) {
1718         e = error1;
1719         elements = null;
1720       }
1721     } else if (typeof els === "string") {
1722       elements = [];
1723       ref = document.querySelectorAll(els);
1724       for (k = 0, len1 = ref.length; k < len1; k++) {
1725         el = ref[k];
1726         elements.push(el);
1727       }
1728     } else if (els.nodeType != null) {
1729       elements = [els];
1730     }
1731     if (!((elements != null) && elements.length)) {
1732       throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");
1733     }
1734     return elements;
1735   };
1736 
1737   Dropzone.confirm = function(question, accepted, rejected) {
1738     if (window.confirm(question)) {
1739       return accepted();
1740     } else if (rejected != null) {
1741       return rejected();
1742     }
1743   };
1744 
1745   Dropzone.isValidFile = function(file, acceptedFiles) {
1746     var baseMimeType, j, len, mimeType, validType;
1747     if (!acceptedFiles) {
1748       return true;
1749     }
1750     acceptedFiles = acceptedFiles.split(",");
1751     mimeType = file.type;
1752     baseMimeType = mimeType.replace(/\\/.*$/, "");
1753     for (j = 0, len = acceptedFiles.length; j < len; j++) {
1754       validType = acceptedFiles[j];
1755       validType = validType.trim();
1756       if (validType.charAt(0) === ".") {
1757         if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {
1758           return true;
1759         }
1760       } else if (/\\/\\*$/.test(validType)) {
1761         if (baseMimeType === validType.replace(/\\/.*$/, "")) {
1762           return true;
1763         }
1764       } else {
1765         if (mimeType === validType) {
1766           return true;
1767         }
1768       }
1769     }
1770     return false;
1771   };
1772 
1773   if (typeof jQuery !== "undefined" && jQuery !== null) {
1774     jQuery.fn.dropzone = function(options) {
1775       return this.each(function() {
1776         return new Dropzone(this, options);
1777       });
1778     };
1779   }
1780 
1781   if (typeof module !== "undefined" && module !== null) {
1782     module.exports = Dropzone;
1783   } else {
1784     window.Dropzone = Dropzone;
1785   }
1786 
1787   Dropzone.ADDED = "added";
1788 
1789   Dropzone.QUEUED = "queued";
1790 
1791   Dropzone.ACCEPTED = Dropzone.QUEUED;
1792 
1793   Dropzone.UPLOADING = "uploading";
1794 
1795   Dropzone.PROCESSING = Dropzone.UPLOADING;
1796 
1797   Dropzone.CANCELED = "canceled";
1798 
1799   Dropzone.ERROR = "error";
1800 
1801   Dropzone.SUCCESS = "success";
1802 
1803 
1804   /*
1805   
1806   Bugfix for iOS 6 and 7
1807   Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios
1808   based on the work of https://github.com/stomita/ios-imagefile-megapixel
1809    */
1810 
1811   detectVerticalSquash = function(img) {
1812     var alpha, canvas, ctx, data, ey, ih, iw, py, ratio, sy;
1813     iw = img.naturalWidth;
1814     ih = img.naturalHeight;
1815     canvas = document.createElement("canvas");
1816     canvas.width = 1;
1817     canvas.height = ih;
1818     ctx = canvas.getContext("2d");
1819     ctx.drawImage(img, 0, 0);
1820     data = ctx.getImageData(1, 0, 1, ih).data;
1821     sy = 0;
1822     ey = ih;
1823     py = ih;
1824     while (py > sy) {
1825       alpha = data[(py - 1) * 4 + 3];
1826       if (alpha === 0) {
1827         ey = py;
1828       } else {
1829         sy = py;
1830       }
1831       py = (ey + sy) >> 1;
1832     }
1833     ratio = py / ih;
1834     if (ratio === 0) {
1835       return 1;
1836     } else {
1837       return ratio;
1838     }
1839   };
1840 
1841   drawImageIOSFix = function(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {
1842     var vertSquashRatio;
1843     vertSquashRatio = detectVerticalSquash(img);
1844     return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
1845   };
1846 
1847   ExifRestore = (function() {
1848     function ExifRestore() {}
1849 
1850     ExifRestore.KEY_STR = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=‘;
1851 
1852     ExifRestore.encode64 = function(input) {
1853       var chr1, chr2, chr3, enc1, enc2, enc3, enc4, i, output;
1854       output = ‘‘;
1855       chr1 = void 0;
1856       chr2 = void 0;
1857       chr3 = ‘‘;
1858       enc1 = void 0;
1859       enc2 = void 0;
1860       enc3 = void 0;
1861       enc4 = ‘‘;
1862       i = 0;
1863       while (true) {
1864         chr1 = input[i++];
1865         chr2 = input[i++];
1866         chr3 = input[i++];
1867         enc1 = chr1 >> 2;
1868         enc2 = (chr1 & 3) << 4 | chr2 >> 4;
1869         enc3 = (chr2 & 15) << 2 | chr3 >> 6;
1870         enc4 = chr3 & 63;
1871         if (isNaN(chr2)) {
1872           enc3 = enc4 = 64;
1873         } else if (isNaN(chr3)) {
1874           enc4 = 64;
1875         }
1876         output = output + this.KEY_STR.charAt(enc1) + this.KEY_STR.charAt(enc2) + this.KEY_STR.charAt(enc3) + this.KEY_STR.charAt(enc4);
1877         chr1 = chr2 = chr3 = ‘‘;
1878         enc1 = enc2 = enc3 = enc4 = ‘‘;
1879         if (!(i < input.length)) {
1880           break;
1881         }
1882       }
1883       return output;
1884     };
1885 
1886     ExifRestore.restore = function(origFileBase64, resizedFileBase64) {
1887       var image, rawImage, segments;
1888       if (!origFileBase64.match(‘data:image/jpeg;base64,‘)) {
1889         return resizedFileBase64;
1890       }
1891       rawImage = this.decode64(origFileBase64.replace(‘data:image/jpeg;base64,‘, ‘‘));
1892       segments = this.slice2Segments(rawImage);
1893       image = this.exifManipulation(resizedFileBase64, segments);
1894       return ‘data:image/jpeg;base64,‘ + this.encode64(image);
1895     };
1896 
1897     ExifRestore.exifManipulation = function(resizedFileBase64, segments) {
1898       var aBuffer, exifArray, newImageArray;
1899       exifArray = this.getExifArray(segments);
1900       newImageArray = this.insertExif(resizedFileBase64, exifArray);
1901       aBuffer = new Uint8Array(newImageArray);
1902       return aBuffer;
1903     };
1904 
1905     ExifRestore.getExifArray = function(segments) {
1906       var seg, x;
1907       seg = void 0;
1908       x = 0;
1909       while (x < segments.length) {
1910         seg = segments[x];
1911         if (seg[0] === 255 & seg[1] === 225) {
1912           return seg;
1913         }
1914         x++;
1915       }
1916       return [];
1917     };
1918 
1919     ExifRestore.insertExif = function(resizedFileBase64, exifArray) {
1920       var array, ato, buf, imageData, mae, separatePoint;
1921       imageData = resizedFileBase64.replace(‘data:image/jpeg;base64,‘, ‘‘);
1922       buf = this.decode64(imageData);
1923       separatePoint = buf.indexOf(255, 3);
1924       mae = buf.slice(0, separatePoint);
1925       ato = buf.slice(separatePoint);
1926       array = mae;
1927       array = array.concat(exifArray);
1928       array = array.concat(ato);
1929       return array;
1930     };
1931 
1932     ExifRestore.slice2Segments = function(rawImageArray) {
1933       var endPoint, head, length, seg, segments;
1934       head = 0;
1935       segments = [];
1936       while (true) {
1937         if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 218) {
1938           break;
1939         }
1940         if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 216) {
1941           head += 2;
1942         } else {
1943           length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3];
1944           endPoint = head + length + 2;
1945           seg = rawImageArray.slice(head, endPoint);
1946           segments.push(seg);
1947           head = endPoint;
1948         }
1949         if (head > rawImageArray.length) {
1950           break;
1951         }
1952       }
1953       return segments;
1954     };
1955 
1956     ExifRestore.decode64 = function(input) {
1957       var base64test, buf, chr1, chr2, chr3, enc1, enc2, enc3, enc4, i, output;
1958       output = ‘‘;
1959       chr1 = void 0;
1960       chr2 = void 0;
1961       chr3 = ‘‘;
1962       enc1 = void 0;
1963       enc2 = void 0;
1964       enc3 = void 0;
1965       enc4 = ‘‘;
1966       i = 0;
1967       buf = [];
1968       base64test = /[^A-Za-z0-9\\+\\/\\=]/g;
1969       if (base64test.exec(input)) {
1970         console.warning(‘There were invalid base64 characters in the input text.\\n‘ + ‘Valid base64 characters are A-Z, a-z, 0-9, \\‘+\\‘, \\‘/\\‘,and \\‘=\\‘\\n‘ + ‘Expect errors in decoding.‘);
1971       }
1972       input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, ‘‘);
1973       while (true) {
1974         enc1 = this.KEY_STR.indexOf(input.charAt(i++));
1975         enc2 = this.KEY_STR.indexOf(input.charAt(i++));
1976         enc3 = this.KEY_STR.indexOf(input.charAt(i++));
1977         enc4 = this.KEY_STR.indexOf(input.charAt(i++));
1978         chr1 = enc1 << 2 | enc2 >> 4;
1979         chr2 = (enc2 & 15) << 4 | enc3 >> 2;
1980         chr3 = (enc3 & 3) << 6 | enc4;
1981         buf.push(chr1);
1982         if (enc3 !== 64) {
1983           buf.push(chr2);
1984         }
1985         if (enc4 !== 64) {
1986           buf.push(chr3);
1987         }
1988         chr1 = chr2 = chr3 = ‘‘;
1989         enc1 = enc2 = enc3 = enc4 = ‘‘;
1990         if (!(i < input.length)) {
1991           break;
1992         }
1993       }
1994       return buf;
1995     };
1996 
1997     return ExifRestore;
1998 
1999   })();
2000 
2001 
2002   /*
2003    * contentloaded.js
2004    *
2005    * Author: Diego Perini (diego.perini at gmail.com)
2006    * Summary: cross-browser wrapper for DOMContentLoaded
2007    * Updated: 20101020
2008    * License: MIT
2009    * Version: 1.2
2010    *
2011    * URL:
2012    * http://javascript.nwbox.com/ContentLoaded/
2013    * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
2014    */
2015 
2016   contentLoaded = function(win, fn) {
2017     var add, doc, done, init, poll, pre, rem, root, top;
2018     done = false;
2019     top = true;
2020     doc = win.document;
2021     root = doc.documentElement;
2022     add = (doc.addEventListener ? "addEventListener" : "attachEvent");
2023     rem = (doc.addEventListener ? "removeEventListener" : "detachEvent");
2024     pre = (doc.addEventListener ? "" : "on");
2025     init = function(e) {
2026       if (e.type === "readystatechange" && doc.readyState !== "complete") {
2027         return;
2028       }
2029       (e.type === "load" ? win : doc)[rem](pre + e.type, init, false);
2030       if (!done && (done = true)) {
2031         return fn.call(win, e.type || e);
2032       }
2033     };
2034     poll = function() {
2035       var e, error1;
2036       try {
2037         root.doScroll("left");
2038       } catch (error1) {
2039         e = error1;
2040         setTimeout(poll, 50);
2041         return;
2042       }
2043       return init("poll");
2044     };
2045     if (doc.readyState !== "complete") {
2046       if (doc.createEventObject && root.doScroll) {
2047         try {
2048           top = !win.frameElement;
2049         } catch (undefined) {}
2050         if (top) {
2051           poll();
2052         }
2053       }
2054       doc[add](pre + "DOMContentLoaded", init, false);
2055       doc[add](pre + "readystatechange", init, false);
2056       return win[add](pre + "load", init, false);
2057     }
2058   };
2059 
2060   Dropzone._autoDiscoverFunction = function() {
2061     if (Dropzone.autoDiscover) {
2062       return Dropzone.discover();
2063     }
2064   };
2065 
2066   contentLoaded(window, Dropzone._autoDiscoverFunction);
2067 
2068 }).call(this);
dropzone.js

 

 

技术分享图片

 

技术分享图片

 

 

 

 

 

 

 

 

 

 

技术分享图片

 

技术分享图片
 1 {#bpm_base.html#}
 2 {## # ————————47PerfectCRM实现CRM客户报名流程————————#}
 3 {#模板文件 #}
 4 <!DOCTYPE html>
 5 <html lang="zh-CN">
 6     <head>
 7 {#      <meta> 元素可提供有关页面的元信息(meta-information),比如针对搜索引擎和更新频度的描述和关键词。#}
 8 {#      <meta> 标签位于文档的头部,不包含任何内容。<meta> 标签的属性定义了与文档相关联的名称/值对。#}
 9         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
10         <meta http-equiv="X-UA-Compatible" content="IE=edge">
11         <meta name="viewport" content="width=device-width, initial-scale=1">
12         <meta name="description" content="">
13         <meta name="author" content="">
14         <link rel="icon" href="/static/bpm_img/bpm_logo.jpg">{# icon,指的是图标 #}
15         <title>全局账号</title> {# 页面头部显示#}
16 {#        使用link来调用外部的css文件#}
17         <link rel="stylesheet"  href="/static/bpm_css/bootstrap.css"  /> {#导航栏样式#}
18         <link rel="stylesheet"  href="/static/bpm_css/dashboard.css" /> {#指示板样式#}
19         {##————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————#}
20         <link rel="stylesheet"  href="/static/bpm_plugins/dropzone/dropzone.css" /> {#上传文件的插件#}
21         {##————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————#}
22     </head>
23     <body>
24         {% block body %}{#自定义内容 body#}{% endblock %}
25 {#        将纯JavaScript的语句另外保存在一个"*.js"的文件中,需要时再调用。#}
26         <script src="/static/bpm_js/jquery.js"></script>   {# jQuery 是一个 JavaScript库,极大地简化了 JavaScript 编程。#}
27         <script src="/static/bpm_js/bootstrap.js"></script>  {#指示板JS事件#}
28         {##————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————#}
29         <script src="/static/bpm_js/jquery.cookie.js"></script>  {#删除文件JS事件#}
30         <script src="/static/bpm_plugins/dropzone/dropzone.js"></script>  {#上传文件的插件#}
31         {##————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————#}
32 
33         {% block js %}{#自定义内容 JS#}{% endblock %}
34 
35 
36     </body>
37 </html>
38 {## # ————————47PerfectCRM实现CRM客户报名流程————————#}
{#bpm_base.html#}

 

 

技术分享图片

 

技术分享图片
  1 # settings.py
  2 
  3 """
  4 Django settings for PerfectCRM project.
  5 
  6 Generated by ‘django-admin startproject‘ using Django 2.0.3.
  7 
  8 For more information on this file, see
  9 https://docs.djangoproject.com/en/2.0/topics/settings/
 10 
 11 For the full list of settings and their values, see
 12 https://docs.djangoproject.com/en/2.0/ref/settings/
 13 """
 14 
 15 import os
 16 
 17 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 18 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 19 
 20 
 21 # Quick-start development settings - unsuitable for production
 22 # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
 23 
 24 # SECURITY WARNING: keep the secret key used in production secret!
 25 SECRET_KEY = [email protected])p)[email protected]=chaa0$l_br
 26 
 27 # SECURITY WARNING: don‘t run with debug turned on in production!
 28 DEBUG = True
 29 
 30 ALLOWED_HOSTS = []
 31 
 32 
 33 # Application definition
 34 
 35 INSTALLED_APPS = [
 36     django.contrib.admin,
 37     django.contrib.auth,
 38     django.contrib.contenttypes,
 39     django.contrib.sessions,
 40     django.contrib.messages,
 41     django.contrib.staticfiles,
 42     
 43 # ————————04PerfectCRM实现King_admin注册功能————————
 44     # ‘crm.apps.CrmConfig‘,
 45     crm,
 46 # ————————04PerfectCRM实现King_admin注册功能————————
 47 
 48 # ————————02PerfectCRM创建ADMIN页面————————
 49     king_admin,
 50 # ————————02PerfectCRM创建ADMIN页面————————
 51     # ————————38PerfectCRM实现全局账号登录注销————————
 52     gbacc,
 53     # ————————38PerfectCRM实现全局账号登录注销————————
 54 
 55     # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
 56     bpm,
 57     # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
 58 ]
 59 
 60 MIDDLEWARE = [
 61     django.middleware.security.SecurityMiddleware,
 62     django.contrib.sessions.middleware.SessionMiddleware,
 63     django.middleware.common.CommonMiddleware,
 64     django.middleware.csrf.CsrfViewMiddleware,
 65     django.contrib.auth.middleware.AuthenticationMiddleware,
 66     django.contrib.messages.middleware.MessageMiddleware,
 67     django.middleware.clickjacking.XFrameOptionsMiddleware,
 68 ]
 69 
 70 ROOT_URLCONF = PerfectCRM.urls
 71 
 72 TEMPLATES = [
 73     {
 74         BACKEND: django.template.backends.django.DjangoTemplates,
 75 # ————————02PerfectCRM创建ADMIN页面————————
 76         DIRS: [os.path.join(BASE_DIR, templates),
 77                   os.path.join(BASE_DIR, king_admin/king_templates),
 78 
 79 # ————————03PerfectCRM创建基本数据————————
 80                   os.path.join(BASE_DIR, DBadd/DBadd_templates),
 81 # ————————03PerfectCRM创建基本数据————————
 82                 # ————————38PerfectCRM实现全局账号登录注销————————
 83                   os.path.join(BASE_DIR, gbacc/gbacc_templates),
 84                 # ————————38PerfectCRM实现全局账号登录注销————————
 85 
 86                 # ————————47PerfectCRM实现CRM客户报名流程————————
 87                 os.path.join(BASE_DIR, bpm/bpm_templates), ]
 88                 # ————————47PerfectCRM实现CRM客户报名流程————————
 89 
 90 ,
 91 # ————————02PerfectCRM创建ADMIN页面————————
 92         APP_DIRS: True,
 93         OPTIONS: {
 94             context_processors: [
 95                 django.template.context_processors.debug,
 96                 django.template.context_processors.request,
 97                 django.contrib.auth.context_processors.auth,
 98                 django.contrib.messages.context_processors.messages,
 99             ],
100         },
101     },
102 ]
103 
104 WSGI_APPLICATION = PerfectCRM.wsgi.application
105 
106 
107 # Database
108 # https://docs.djangoproject.com/en/2.0/ref/settings/#databases
109 
110 DATABASES = {
111     default: {
112         ENGINE: django.db.backends.sqlite3,
113         NAME: os.path.join(BASE_DIR, db.sqlite3),
114     }
115 }
116 
117 
118 # Password validation
119 # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
120 
121 AUTH_PASSWORD_VALIDATORS = [
122     {
123         NAME: django.contrib.auth.password_validation.UserAttributeSimilarityValidator,
124     },
125     {
126         NAME: django.contrib.auth.password_validation.MinimumLengthValidator,
127     },
128     {
129         NAME: django.contrib.auth.password_validation.CommonPasswordValidator,
130     },
131     {
132         NAME: django.contrib.auth.password_validation.NumericPasswordValidator,
133     },
134 ]
135 
136 
137 # Internationalization
138 # https://docs.djangoproject.com/en/2.0/topics/i18n/
139 
140 # ————————01PerfectCRM基本配置ADMIN————————
141 #LANGUAGE_CODE = ‘en-us‘
142 
143 #英文转中文方法
144 LANGUAGE_CODE = zh-Hans
145 # ————————01PerfectCRM基本配置ADMIN————————
146 
147 TIME_ZONE = UTC
148 
149 USE_I18N = True
150 
151 USE_L10N = True
152 
153 USE_TZ = True
154 
155 
156 # Static files (CSS, JavaScript, Images)
157 # https://docs.djangoproject.com/en/2.0/howto/static-files/
158 
159 STATIC_URL = /static/
160 
161 # ————————01PerfectCRM基本配置ADMIN————————
162 STATICFILES_DIRS = [os.path.join(BASE_DIR,king_admin/static),
163 # ————————01PerfectCRM基本配置ADMIN————————
164                     # ————————38PerfectCRM实现全局账号登录注销————————
165                     os.path.join(BASE_DIR, gbacc/static),
166                     # ————————38PerfectCRM实现全局账号登录注销————————
167                     
168                     # ————————47PerfectCRM实现CRM客户报名流程————————
169                     os.path.join(BASE_DIR, bpm/static),]
170                     # ————————47PerfectCRM实现CRM客户报名流程————————
171 
172 
173 # ————————34PerfectCRM实现CRM自定义用户————————
174 AUTH_USER_MODEL = crm.UserProfile#使用自定的admin 表单
175 # ————————34PerfectCRM实现CRM自定义用户————————
176 
177 
178 
179 # ————————44PerfectCRM实现账号快速注册登陆————————
180 # send e-mail
181 EMAIL_BACKEND = django.core.mail.backends.smtp.EmailBackend  #email后端
182 EMAIL_USE_TLS = False   #是否使用TLS安全传输协议
183 EMAIL_USE_SSL = True    #是否使用SSL加密,qq企业邮箱要求使用
184 EMAIL_HOST = smtp.sina.cn   #发送邮件的邮箱 的 SMTP服务器       #根据情况重新配置
185 EMAIL_PORT = 465                 #发件箱的SMTP服务器端口 #一般不需要修改465
186 EMAIL_HOST_USER = [email protected]    #发送邮件的邮箱账号     #根据情况重新配置  #[email protected]   [email protected]
187 EMAIL_HOST_PASSWORD = admin123456         #发送邮件的邮箱密码    #根据情况重新配置
188 
189 # ————————44PerfectCRM实现账号快速注册登陆————————
190 
191 
192 # ————————46PerfectCRM实现登陆后页面才能访问————————
193 LOGIN_URL = /gbacc/gbacc_login/# login_url 配置      #默认 /accounts/login/  #注意: / (绝对路径)
194 # ————————46PerfectCRM实现登陆后页面才能访问————————
195 
196 
197 
198 # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
199 ENROLLED_DATA=%s/bpm/static/enrolled_data%BASE_DIR#证件上传 # 上传路径
200 # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
# settings.py

 

 

 

 

 

 

 

 

技术分享图片

 

技术分享图片技术分享图片

 

以上是关于Django项目:CRM(客户关系管理系统)--61--51PerfectCRM实现CRM客户报名流程学生合同上传照片的主要内容,如果未能解决你的问题,请参考以下文章

Django项目:CRM(客户关系管理系统)--66--56PerfectCRM实现CRM客户首列进入更改页优化路径

Django CRM学员系统项目

Django项目:CRM(客户关系管理系统)--70--60PerfectCRM实现CRM学生上课记录

Django项目:CRM(客户关系管理系统)--72--62PerfectCRM实现CRM讲师讲课记录

Django项目:CRM(客户关系管理系统)--46--37PerfectCRM实现CRM用户注册

Django项目:CRM(客户关系管理系统)--64--54PerfectCRM实现CRM客户报名链接