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)qbpuvh[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

原文地址:https://www.cnblogs.com/ujq3/p/8893183.html

时间: 2024-11-10 21:54:26

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

Django项目:CRM(客户关系管理系统)--71--61PerfectCRM实现CRM学生上传作业

1 # student_urls.py 2 # --------60PerfectCRM实现CRM学生上课记录-------- 3 from django.conf.urls import url 4 from bpm.student import student_views 5 6 urlpatterns = [ 7 url(r'^student_course/$', student_views.student_course, name='student_course'), #学生报名的课程

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

1 #urls.py 2 3 """PerfectCRM URL Configuration 4 5 The `urlpatterns` list routes URLs to views. For more information please see: 6 https://docs.djangoproject.com/en/2.0/topics/http/urls/ 7 Examples: 8 Function views 9 1. Add an import: from

Django项目:CRM(客户关系管理系统)--82--72PerfectCRM实现CRM动态菜单和角色

1 #models.py 2 3 # --------01PerfectCRM基本配置ADMIN-------- 4 5 from django.db import models 6 # Create your models here. 7 8 """ 9 #运行 Terminal 10 # 生成 数据表 11 # python manage.py makemigrations 12 # 数据表 迁移 13 # python manage.py migrate 14 &quo

CRM客户关系管理系统商业项目

本课程共33讲,购买课程后,可以下载项目需求分析文档,数据库设计文档,完整的项目源代码,数据库文件等资料,系统采用jsp,servlet,js,ajax,jquery,easyui,mysql数据库等相关技术实现,所有代码均为原生态,无第三方插件,系统稳定,高效,快捷,本系统是专门针对各种中小型企业量身定做的CRM客户关系管理系统,为企业管客户,管商机,管销售,从而推动业务进展,提高工作效率,管理大数据. 项目主要功能有客户管理,合同管理,合同附件管理,合同预览(放大缩小),订单管理,商务洽谈,

CRM客户关系管理系统商业项目视频课程

本课程共33讲,购买课程后,可以下载项目需求分析文档,数据库设计文档,完整的项目源代码,数据库文件等资料,系统采用jsp,servlet,js,ajax,jquery,easyui,mysql数据库等相关技术实现,所有代码均为原生态,无第三方插件,系统稳定,高效,快捷,本系统是专门针对各种中小型企业量身定做的CRM客户关系管理系统,为企业管客户,管商机,管销售,从而推动业务进展,提高工作效率,管理大数据. 项目主要功能有客户管理,合同管理,合同附件管理,合同预览(放大缩小),订单管理,商务洽谈,

CRM客户关系管理系统如何分析客户的动态需求

由于激烈的市场竞争,对于怎样掌握客户的动态需求,怎样保持客户市场的稳定增长,对于企业来说已经成为普遍的关注点.CRM客户关系管理系统经过了10年的发展历程,怎样管理客户.了解客户成就了CRM客户关系管理系统的大市场. CRM供货商一般侧重于宣扬软件的特性及功用,而对其全体价值则没有做出了解的表述. 用户高档处理层一般从基础设施安顿而非运营和战略视点对待CRM客户关系管理系统施行. 由于无法从运营和战略视点安顿CRM客户关系管理系统,用户对CRM的价值认知只停留在技术功率层面上. 只需跨过技术和流

文献综述二十:基于UML技术的客户关系管理系统实现

一.基本信息 标题:基于UML技术的客户关系管理系统实现 时间:2015 出版源:电子设计工程 文件分类:uml技术的研究 二.研究背景 设计出可应用与银行和储户之间沟通的客户关系管理系统,从而实现对客户管理的信息化 ,提升了企业对客户维护的能力. 三.具体内容 文献的主要内容分为五个部分.基于UML建模技术的系统用例分析.系统功能设计.客户关系管理系统结构设计.系统开发工具.系统功能流程设计与实现代码. 基于UML建模技术的系统用例分析:包括银行客户经理系统用例图和管理员的用例分析.银行客户经

Django CRM客户关系管理系统

CRM需求分析 随着信息化时代带来的科技创新,CRM客户关系管理系统带来的效益在已经成为很多企业提高竞争优势的一分部,CRM客户关系管理系统将企业管理和客户关系管理集成到统一的平台,其系统功能主要体现在企业与客户之间的业务和企业内部之前部门之间的业务.因此CRM客户关系管理系统不但可以记录企业自内部信息,对于客户信息存储也是可以做到的,其中还涉及市场竞争对手的情报资料,还包括了企业进行营销.销售及支持服务所需的各种数据. 功能实现 (1)建议统一的信息编码系统; (2)设计能够良好反映事物特性的

CRM客户关系管理系统-需求概设和详设

大概设计 大概设计就是对需求进行一个整体性分析,把需要实现的功能都列出来,对于客户关系管理系统,我们需要从角色出发,从而确定有哪些需求,最好是画个思维导图 首先我们是为培训学校这么一个场景来开发的,所以有:学生,讲师,销售,老板这么四个角色,那接下来,我们就要对这几个角色需要实现哪些功能逐一分析了 第一个,学生,1.交作业 2.查成绩 3.请假 4.合同 5.我的推荐 6.投诉建议 第二个,讲师, 1.上课点名 2.批作业 3.创建上课记录 4.查看班级成绩 5.课时申报 6.问卷调查 第三个,