From e92abb8b8b2d64312171425d320312e11be1fbac Mon Sep 17 00:00:00 2001 From: ssbeefeater Date: Thu, 14 Nov 2019 23:54:03 +0200 Subject: [PATCH] v1.4.1: Fix bug in transform file --- dist/ssi-uploader/js/ssi-uploader.js | 74 +++++++++++--------- dist/ssi-uploader/js/ssi-uploader.min.js | 72 +++++++++---------- dist/ssi-uploader/js/ssi-uploader.min.js.map | 2 +- package.json | 2 +- src/ssi-uploader/js/ssi-uploader.js | 73 ++++++++++--------- 5 files changed, 118 insertions(+), 105 deletions(-) diff --git a/dist/ssi-uploader/js/ssi-uploader.js b/dist/ssi-uploader/js/ssi-uploader.js index 43c84c6..922e95c 100644 --- a/dist/ssi-uploader/js/ssi-uploader.js +++ b/dist/ssi-uploader/js/ssi-uploader.js @@ -419,12 +419,37 @@ }; - Ssi_upload.prototype.appendFileToFormData = function (formData, file) { + Ssi_upload.prototype.appendFileToFormData = function (file) { + var formData = new FormData();//set the form data + formData.append(this.inputName, file);//append the first file to the form data $.each(this.options.data, function (key, value) {// append all extra data formData.append(key, value); }); - this.$element.find('input.ssi-uploadInput').trigger('beforeUpload.ssi-uploader'); + return formData; + } + + + Ssi_upload.prototype.tryToTransform = function (file, callback) { + if (typeof this.options.transformFile === 'function') { + try { + file = this.options.transformFile(file);// execute the transformFile + if (file instanceof Promise) { + file.then(function (newFile) { + callback(newFile) + }) + } else { + callback(file) + } + } catch (err) { + if (!this.options.ignoreCallbackErrors) { + console.error('There is an error in transformFile'); + return console.error(err); + } + } + } else { + callback(file) + } } Ssi_upload.prototype.uploadFiles = function () {// upload the pending files if (this.pending > 0) { @@ -448,7 +473,6 @@ $clearBtn = this.$element.find('#ssi-clearBtn'); $uploadBtn.prop("disabled", true); var thisS = this, - formData = new FormData(),//set the form data i = this.totalFilesLength; if (this.totalFilesLength !== 0 && !this.options.preview) { setNamePreview(this); @@ -460,35 +484,15 @@ $clearBtn.prop("disabled", true); } - while (thisS.toUpload[i] === null || thisS.toUpload[i] === '') { // do it until you find a file + while (!thisS.toUpload[i]) { // do it until you find a file i++; } var file = thisS.toUpload[i] - if (typeof this.options.transformFile === 'function') { - try { - file = this.options.transformFile(thisS.toUpload[i]);// execute the transformFile - if (file instanceof Promise) { - file.then(function (file) { - thisS.appendFileToFormData(formData, file) - ajaxLoopRequest(formData, i) - }) - } else { - console.log("TCL: Ssi_upload.22222.uploadFiles -> thisS", thisS) - thisS.appendFileToFormData(formData, file) - ajaxLoopRequest(formData, i) - } - } catch (err) { - if (!this.options.ignoreCallbackErrors) { - console.error('There is an error in transformFile'); - return console.error(err); - } - } - } else { - thisS.appendFileToFormData(formData, file) + thisS.tryToTransform(file, function (newFile) { + var formData = thisS.appendFileToFormData(newFile) ajaxLoopRequest(formData, i) - } + }) } - //--------------start of ajax request----------------------- function ajaxLoopRequest(formData, ii) { var selector = 'table.ssi-imgToUploadTable'; @@ -526,6 +530,8 @@ async: true, beforeSend: function (xhr, settings) { thisS.uploadList[ii] = xhr; + console.log("TCL: ajaxLoopRequest -> thisS.toUpload", thisS.toUpload) + console.log("TCL: ajaxLoopRequest -> ii", ii) $uploadBtn.find('#ssi-up_loading') //add spiner to uploadbutton .html(''); var fileInfo = { @@ -562,6 +568,7 @@ } }, type: 'POST', + method: 'POST', data: formData, cache: false, contentType: false, @@ -683,16 +690,15 @@ i = ii; i++;//go to the next element - while (thisS.toUpload[i] === null || thisS.toUpload[i] === '') {// do it until you find a file + while (!thisS.toUpload[i] && typeof thisS.toUpload[i] !== 'undefined') {// do it until you find a file i++; } if (i < thisS.toUpload.length) {// if more files exist start the next request - formData = new FormData(); - $.each(thisS.options.data, function (key, value) { - formData.append(key, value); - }); - formData.append(thisS.inputName, thisS.toUpload[i]); - ajaxLoopRequest(formData, i); + const nextFile = thisS.toUpload[i] + thisS.tryToTransform(nextFile, function (newFile) { + var formData = thisS.appendFileToFormData(newFile) + ajaxLoopRequest(formData, i) + }) } } }; diff --git a/dist/ssi-uploader/js/ssi-uploader.min.js b/dist/ssi-uploader/js/ssi-uploader.min.js index ac8f40c..7af682c 100644 --- a/dist/ssi-uploader/js/ssi-uploader.min.js +++ b/dist/ssi-uploader/js/ssi-uploader.min.js @@ -1,39 +1,39 @@ -(function(g,w){"object"===typeof module&&module.exports?module.exports=w(require("jquery")):w(g.jQuery)})(this,function(g){function w(a,c,f){a=g(a);(c=c||a.data("title"))||(c=a.attr("title"));if(c){var b=g('
'+c+"
").appendTo(f.$element);a.one("mouseleave",function(){b.remove()});c=-16;a.hasClass("ssi-noPreviewSubMessage")&&(c=23);b.css({top:a.position().top-b.height()+c,left:a.position().left-b.width()/2}).removeClass("ssi-fadeOut");return b}} -var q=function(a,c){this.options=c;this.$element="";this.language=I[this.options.locale];this.uploadList=[];this.totalProgress=[];this.toUpload=[];this.imgNames=[];this.currentListLength=this.inProgress=this.pending=this.abortedWithError=this.aborted=this.successfulUpload=this.totalFilesLength=0;this.inputName="";this.init(a)};q.prototype.init=function(a){g(a).addClass("ssi-uploadInput").after(this.$element=g('
'));a=g('").append(a);var c=g(''),f=g('"),b=g('");this.options.inForm&& -c.hide();this.$element.append(g('
').append(a,b,c,f));if(this.options.preview){var d=g('
'+(this.options.dropZone?'
'+this.language.drag+"
":"")+'
?
');this.$element.append(d)}else{this.$element.addClass("ssi-uploaderNP");var k=g('
'), -l=g(''),p=g('
').append(l),h=g('
').append(k);d=g('
').append(p,h);this.$element.prepend(d)}var e=this,n=a.find(".ssi-uploadInput");this.inputName=n.attr("name")||"files";a.find("button").click(function(a){a.preventDefault(); -n.trigger("click")});n.on("change",function(){e.toUploadFiles(this.files);e.options.inForm||n.val("")});e.options.dropZone&&(d.on("drop",function(a){a.preventDefault();d.removeClass("ssi-dragOver");e.toUploadFiles(a.originalEvent.dataTransfer.files)}),d.on("dragover",function(a){a.preventDefault();d.addClass("ssi-dragOver");return!1}),d.on("dragleave",function(a){a.preventDefault();d.removeClass("ssi-dragOver");return!1}));e.options.preview||p.click(function(){1 "+e.language.completed+": "+(e.successfulUpload+e.aborted+e.abortedWithError)+"
"+e.language.inProgress+": "+e.inProgress,e)});d.on("click",".ssi-removeBtn",function(a){a.preventDefault();var b=g(a.currentTarget); -a=b.data("delete");e.pending--;e.currentListLength--;1>e.pending&&e.$element.find("#ssi-fileNumber").addClass("ssi-hidden");0===e.pending&&c.prop("disabled",!0);e.options.preview?b.parents("table.ssi-imgToUploadTable").remove():(b=b.parents("tr.ssi-toUploadTr"),l.html(e.currentListLength+" files"),b.prev().remove(),b.remove(),1===e.currentListLength&&C(e));e.toUpload[a]=null;e.imgNames[a]=null;0===e.currentListLength&&(e.options.dropZone||d.removeClass("ssi-uploadNoDropZone"),f.addClass("ssi-hidden"), -c.addClass("ssi-hidden"))});d.on("click",".ssi-abortUpload",function(a){a.preventDefault();a=g(a.currentTarget).data("delete");e.abort(a)});c.click(function(a){a.preventDefault();e.uploadFiles()});b.click(function(a){a.preventDefault();e.abortAll()})};q.prototype.abortAll=function(){for(var a=0;a'+b+'
'+ -x(c,d,15)+""};if("image"==u.type.split("/")[0]){l.prop("disabled",!0);p.prop("disabled",!0);var m=new FileReader;m.onload=function(){k+=g('');n[a]=m.result;b++;t===b?(f.$element.find("#ssi-fileNumber").removeClass("ssi-hidden"),e.append(k),setTimeout(function(){v();l.prop("disabled",!1);p.prop("disabled",!1)},10),l.prop("disabled",!1),p.prop("disabled",!1),k="",t=[]):t/2==Math.round(b)&&(e.append(k), -v(),k="")};m.readAsDataURL(u)}else n[a]=null,e.append(g('
')),b++}else p.prop("disabled",!1),f.$element.find(".ssi-namePreview").html(0===a?x(c,d,13):f.currentListLength+1+" "+f.language.files),h.append('
'+x(c,d,20)+ -'');var v=function(){for(var a=0;a=this.options.maxNumberOfFiles)){var f=this,b=0,d,k="",l=this.$element.find("#ssi-uploadBtn"), -p=this.$element.find("#ssi-clearBtn"),h=this.$element.find("#ssi-fileList"),e=this.$element.find(".ssi-uploadBox"),n=[];0===this.inProgress&&0===this.pending&&this.clear();var m=[],v=[],z="",t,r=d=t=a.length;"number"===typeof this.options.maxNumberOfFiles&&r>this.options.maxNumberOfFiles-(this.inProgress+this.pending)&&(r=t=this.options.maxNumberOfFiles-(this.inProgress+this.pending));for(var q=0;qr?r++:t--,-1=== -g.inArray(y,m)&&m.push(y)):(u.size*Math.pow(10,-6)).toFixed(2)>this.options.maxFileSize?(d>r?r++:t--,v.push(x(u.name,y,15))):this.options.allowDuplicates||-1===g.inArray(u.name,this.imgNames)?(l.prop("disabled",!1),c(u),this.pending++,this.currentListLength++):d>r?r++:t--}a=m.length;d=v.length;0'); -var d={name:b.toUpload[h].name,type:b.toUpload[h].type,size:(b.toUpload[h].size/1024).toFixed(2)};if("function"===typeof b.options.beforeEachUpload)try{var e=b.options.beforeEachUpload(d,a,f)}catch(r){"Error"==r.name?b.abort(h,void 0,r.message):b.options.ignoreCallbackErrors||(console.log("There is an error in beforeEachUpload callback. Filename:"+b.toUpload[h].name),console.log(r),b.abort(h,void 0,b.language.wentWrong));return}b.$element.find("input.ssi-uploadInput").trigger("beforeEachUpload.ssi-uploader", -[d]);0===a.status&&"canceled"===a.statusText&&("undefined"===typeof e&&(e=!1),b.abortedWithError++,b.abort(h,e))},type:"POST",data:d,cache:!1,contentType:!1,processData:!1,url:b.options.url,error:function(a,c){if("abort"!==c){n.addClass("ssi-canceledProgressBar");var d=b.language.error;b.abortedWithError++;b.totalProgress.splice(h,1);b.options.preview||(d='');A(b,h,"error",d,b.language.serverError);b.totalProgress[h]="";b.inProgress--;f.prop("disabled",!1);if("function"=== -typeof b.options.onEachUpload)try{b.options.onEachUpload({uploadStatus:"error",responseMsg:b.language.serverError,name:b.toUpload[h].name,size:(b.toUpload[h].size/1024).toFixed(2),type:b.toUpload[h].type})}catch(t){b.options.ignoreCallbackErrors||(console.log("There is an error in onEachUpload callback. File name:"+b.toUpload[h].name),console.log(t))}0===b.inProgress&&B(b);console.log(arguments);console.log(" Ajax error: "+c)}}},b.options.ajaxOptions);g.ajax(e).done(function(a,c,d){function e(a,c){a? -(p="success",k=b.language.success,q="check",b.successfulUpload++):(n.addClass("ssi-canceledProgressBar"),b.options.preview&&(k=b.language.error),b.abortedWithError++);l=c}var k,l="",p="error",q="exclamation";try{var m=g.parseJSON(a)}catch(D){m=a}b.options.responseValidation?(a=b.options.responseValidation,"object"===typeof a.validationKey&&"validationKey"==a.resultKey?m.hasOwnProperty(a.validationKey.success)?e(!0,m[a.validationKey.success]):e(!1,m[a.validationKey.error]):m[a.validationKey]==a.success? -e(!0,m[a.resultKey]):e(!1,m[a.resultKey])):200==d.status?e(!0,m):e(!1,m);b.options.preview||(k='');A(b,h,p,k,l);a={uploadStatus:p,responseMsg:l,name:b.toUpload[h].name,size:(b.toUpload[h].size/1024).toFixed(2),type:b.toUpload[h].type};if("function"===typeof b.options.onEachUpload)try{b.options.onEachUpload(a,m)}catch(D){console.log("There is an error in onEachUpload callback"),console.log(D)}b.$element.find("input.ssi-uploadInput").trigger("onEachUpload.ssi-uploader",[a]); -b.inProgress--;f.prop("disabled",!1);0===b.inProgress&&B(b);b.uploadList[h]="";b.toUpload[h]="";b.imgNames[h]=""});k=h;for(k++;null===b.toUpload[k]||""===b.toUpload[k];)k++;k thisS",b),b.appendFileToFormData(d,l),a(d,k))}catch(p){if(!this.options.ignoreCallbackErrors)return console.error("There is an error in transformFile"), -console.error(p)}else b.appendFileToFormData(d,l),a(d,k)}};var A=function(a,c,f,b,d){var g="",l="table.ssi-imgToUploadTable";a.options.preview||(g="ssi-noPreviewSubMessage",l="tr.ssi-toUploadTr",1===a.currentListLength&&(a.errors=d));a=a.$element.find(".ssi-abortUpload[data-delete='"+c+"']");a.parents(l).addClass("ssi-completed");a.after(H(f,b,d,g)).remove()},H=function(a,c,f,b){return''+c+""},C=function(a){var c=a.$element.find("#ssi-fileList").find("span").html(), -f=c.getExtension();a.$element.find(".ssi-uploadDetails").removeClass("ssi-uploadBoxOpened");a.$element.find(".ssi-namePreview").html(x(c,f,15))};q.prototype.abort=function(a,c,f){"undefined"===typeof c?(this.uploadList[a].abort(),this.totalProgress[a]="",c=f||"Aborted",this.aborted++):"string"!==typeof c&&(c="");f=this.language.aborted;this.options.preview||(f='');A(this,a,"error",f,c);this.$element.find("#ssi-uploadProgress"+a).removeClass("ssi-hidden").addClass("ssi-canceledProgressBar"); -this.toUpload[a]=void 0;this.uploadList[a]=void 0;this.imgNames[a]=void 0;this.$element.find("#ssi-clearBtn").prop("disabled",!1);this.inProgress--;0===this.inProgress&&B(this)};var B=function(a){a.$element.find("#ssi-abortBtn").addClass("ssi-hidden");if(!a.options.preview){var c="error",f="",b="";0'):0',f=a.language.aborted): -0',f=a.language.sucUpload);a.$element.find(".ssi-namePreview").append(H(c,b,f,"ssi-noPreviewMessage"));a.$element.find("#ssi-uploadProgressNoPreview").removeAttr("styles").addClass("ssi-hidden")}if("function"===typeof a.options.onUpload)try{a.options.onUpload(c)}catch(d){a.options.ignoreCallbackErrors||(console.log("There is an error in onUpload callback"),console.log(d))}a.$element.find("input.ssi-uploadInput").trigger("onUpload.ssi-uploader", -[c]);c=a.$element.find("#ssi-uploadBtn");a.$element.find("#ssi-clearBtn").prop("disabled",!1);c.prop("disabled",!1).find("#ssi-up_loading").empty();0===a.pending&&(c.addClass("ssi-hidden"),a.toUpload=[],a.imgNames=[],a.totalFilesLength=0);a.uploadList=[];a.totalProgress=[];a.currentListLength=a.inProgress+a.successfulUpload+a.aborted+a.abortedWithError+a.pending;a.inProgress=0};g.fn.ssi_uploader=function(a){var c=g.extend(!0,{allowDuplicates:!1,url:"",data:{},locale:"en",preview:!0,dropZone:!0,maxNumberOfFiles:"", -responseValidation:!1,ignoreCallbackErrors:!1,maxFileSize:2,inForm:!1,ajaxOptions:{},onUpload:function(){},onEachUpload:function(){},beforeUpload:function(){},beforeEachUpload:function(){},allowed:"",errorHandler:{method:function(a){alert(a)},success:"success",error:"error"}},a);c.allowed=c.allowed||["jpg","jpeg","png","bmp","gif"];return this.each(function(){var a=g(this);if(a.is('input[type="file"]')){if(!a.data("ssi_upload")){var b=new q(this,c);a.data("ssi_upload",b)}}else console.log("The targeted element is not file input.")})}; -String.prototype.replaceText=function(){for(var a=Array.apply(null,arguments),c=this,f=0;ff)){var b=c.length;return a.length-2>f?(a=a.substring(0,f),a=a.substring(0,a.length-b),a+"..."+c):a}},I={en:{success:"Success",sucUpload:"Successful upload",chooseFiles:"Choose files", -uploadFailed:"Upload failed",serverError:"Internal server error",error:"Error",abort:"Abort",aborted:"Aborted",files:"files",upload:"Upload",clear:"Clear",drag:"Drag n Drop",sizeError:"$1 exceed the size limit of $2",extError:"$1 file types are not supported",someErrorsOccurred:"Some errors occurred!",wentWrong:"Something went wrong!",pending:"Pending",completed:"Completed",inProgress:"In progress"},gr:{success:"\u0395\u03c0\u03b9\u03c4\u03c5\u03c7\u03af\u03b1",sucUpload:"\u0395\u03c0\u03b9\u03c4\u03c5\u03c7\u03ae\u03c2 \u03bc\u03b5\u03c4\u03b1\u03c6\u03cc\u03c1\u03c4\u03c9\u03c3\u03b7", +(function(h,x){"object"===typeof module&&module.exports?module.exports=x(require("jquery")):x(h.jQuery)})(this,function(h){function x(a,c,d){a=h(a);(c=c||a.data("title"))||(c=a.attr("title"));if(c){var b=h('
'+c+"
").appendTo(d.$element);a.one("mouseleave",function(){b.remove()});c=-16;a.hasClass("ssi-noPreviewSubMessage")&&(c=23);b.css({top:a.position().top-b.height()+c,left:a.position().left-b.width()/2}).removeClass("ssi-fadeOut");return b}} +var l=function(a,c){this.options=c;this.$element="";this.language=H[this.options.locale];this.uploadList=[];this.totalProgress=[];this.toUpload=[];this.imgNames=[];this.currentListLength=this.inProgress=this.pending=this.abortedWithError=this.aborted=this.successfulUpload=this.totalFilesLength=0;this.inputName="";this.init(a)};l.prototype.init=function(a){h(a).addClass("ssi-uploadInput").after(this.$element=h('
'));a=h('").append(a);var c=h(''),d=h('"),b=h('");this.options.inForm&& +c.hide();this.$element.append(h('
').append(a,b,c,d));if(this.options.preview){var f=h('
'+(this.options.dropZone?'
'+this.language.drag+"
":"")+'
?
');this.$element.append(f)}else{this.$element.addClass("ssi-uploaderNP");var n=h('
'), +g=h(''),m=h('
').append(g),z=h('
').append(n);f=h('
').append(m,z);this.$element.prepend(f)}var e=this,p=a.find(".ssi-uploadInput");this.inputName=p.attr("name")||"files";a.find("button").click(function(a){a.preventDefault(); +p.trigger("click")});p.on("change",function(){e.toUploadFiles(this.files);e.options.inForm||p.val("")});e.options.dropZone&&(f.on("drop",function(a){a.preventDefault();f.removeClass("ssi-dragOver");e.toUploadFiles(a.originalEvent.dataTransfer.files)}),f.on("dragover",function(a){a.preventDefault();f.addClass("ssi-dragOver");return!1}),f.on("dragleave",function(a){a.preventDefault();f.removeClass("ssi-dragOver");return!1}));e.options.preview||m.click(function(){1 "+e.language.completed+": "+(e.successfulUpload+e.aborted+e.abortedWithError)+"
"+e.language.inProgress+": "+e.inProgress,e)});f.on("click",".ssi-removeBtn",function(a){a.preventDefault();var b=h(a.currentTarget); +a=b.data("delete");e.pending--;e.currentListLength--;1>e.pending&&e.$element.find("#ssi-fileNumber").addClass("ssi-hidden");0===e.pending&&c.prop("disabled",!0);e.options.preview?b.parents("table.ssi-imgToUploadTable").remove():(b=b.parents("tr.ssi-toUploadTr"),g.html(e.currentListLength+" files"),b.prev().remove(),b.remove(),1===e.currentListLength&&C(e));e.toUpload[a]=null;e.imgNames[a]=null;0===e.currentListLength&&(e.options.dropZone||f.removeClass("ssi-uploadNoDropZone"),d.addClass("ssi-hidden"), +c.addClass("ssi-hidden"))});f.on("click",".ssi-abortUpload",function(a){a.preventDefault();a=h(a.currentTarget).data("delete");e.abort(a)});c.click(function(a){a.preventDefault();e.uploadFiles()});b.click(function(a){a.preventDefault();e.abortAll()})};l.prototype.abortAll=function(){for(var a=0;a'+b+'
'+ +y(c,f,15)+""};if("image"==k.type.split("/")[0]){g.prop("disabled",!0);m.prop("disabled",!0);var r=new FileReader;r.onload=function(){n+=h('');p[a]=r.result;b++;t===b?(d.$element.find("#ssi-fileNumber").removeClass("ssi-hidden"),e.append(n),setTimeout(function(){u();g.prop("disabled",!1);m.prop("disabled",!1)},10),g.prop("disabled",!1),m.prop("disabled",!1),n="",t=[]):t/2==Math.round(b)&&(e.append(n), +u(),n="")};r.readAsDataURL(k)}else p[a]=null,e.append(h('
')),b++}else m.prop("disabled",!1),d.$element.find(".ssi-namePreview").html(0===a?y(c,f,13):d.currentListLength+1+" "+d.language.files),z.append('
'+y(c,f,20)+ +'');var u=function(){for(var a=0;a=this.options.maxNumberOfFiles)){var d=this,b=0,f,n="",g=this.$element.find("#ssi-uploadBtn"), +m=this.$element.find("#ssi-clearBtn"),z=this.$element.find("#ssi-fileList"),e=this.$element.find(".ssi-uploadBox"),p=[];0===this.inProgress&&0===this.pending&&this.clear();var u=[],r=[],v="",t,q=f=t=a.length;"number"===typeof this.options.maxNumberOfFiles&&q>this.options.maxNumberOfFiles-(this.inProgress+this.pending)&&(q=t=this.options.maxNumberOfFiles-(this.inProgress+this.pending));for(var l=0;lq?q++:t--,-1=== +h.inArray(w,u)&&u.push(w)):(k.size*Math.pow(10,-6)).toFixed(2)>this.options.maxFileSize?(f>q?q++:t--,r.push(y(k.name,w,15))):this.options.allowDuplicates||-1===h.inArray(k.name,this.imgNames)?(g.prop("disabled",!1),c(k),this.pending++,this.currentListLength++):f>q?q++:t--}a=u.length;f=r.length;0 thisS.toUpload",b.toUpload);console.log("TCL: ajaxLoopRequest -> ii",g);c.find("#ssi-up_loading").html('');var e={name:b.toUpload[g].name,type:b.toUpload[g].type,size:(b.toUpload[g].size/1024).toFixed(2)};if("function"===typeof b.options.beforeEachUpload)try{var f=b.options.beforeEachUpload(e,a,d)}catch(v){"Error"== +v.name?b.abort(g,void 0,v.message):b.options.ignoreCallbackErrors||(console.log("There is an error in beforeEachUpload callback. Filename:"+b.toUpload[g].name),console.log(v),b.abort(g,void 0,b.language.wentWrong));return}b.$element.find("input.ssi-uploadInput").trigger("beforeEachUpload.ssi-uploader",[e]);0===a.status&&"canceled"===a.statusText&&("undefined"===typeof f&&(f=!1),b.abortedWithError++,b.abort(g,f))},type:"POST",method:"POST",data:n,cache:!1,contentType:!1,processData:!1,url:b.options.url, +error:function(a,c){if("abort"!==c){l.addClass("ssi-canceledProgressBar");var e=b.language.error;b.abortedWithError++;b.totalProgress.splice(g,1);b.options.preview||(e='');A(b,g,"error",e,b.language.serverError);b.totalProgress[g]="";b.inProgress--;d.prop("disabled",!1);if("function"===typeof b.options.onEachUpload)try{b.options.onEachUpload({uploadStatus:"error",responseMsg:b.language.serverError,name:b.toUpload[g].name,size:(b.toUpload[g].size/1024).toFixed(2), +type:b.toUpload[g].type})}catch(r){b.options.ignoreCallbackErrors||(console.log("There is an error in onEachUpload callback. File name:"+b.toUpload[g].name),console.log(r))}0===b.inProgress&&B(b);console.log(arguments);console.log(" Ajax error: "+c)}}},b.options.ajaxOptions);h.ajax(m).done(function(a,c,f){function e(a,c){a?(q="success",n=b.language.success,p="check",b.successfulUpload++):(l.addClass("ssi-canceledProgressBar"),b.options.preview&&(n=b.language.error),b.abortedWithError++);m=c}var n, +m="",q="error",p="exclamation";try{var k=h.parseJSON(a)}catch(w){k=a}b.options.responseValidation?(a=b.options.responseValidation,"object"===typeof a.validationKey&&"validationKey"==a.resultKey?k.hasOwnProperty(a.validationKey.success)?e(!0,k[a.validationKey.success]):e(!1,k[a.validationKey.error]):k[a.validationKey]==a.success?e(!0,k[a.resultKey]):e(!1,k[a.resultKey])):200==f.status?e(!0,k):e(!1,k);b.options.preview||(n='');A(b,g,q,n,m);a={uploadStatus:q,responseMsg:m, +name:b.toUpload[g].name,size:(b.toUpload[g].size/1024).toFixed(2),type:b.toUpload[g].type};if("function"===typeof b.options.onEachUpload)try{b.options.onEachUpload(a,k)}catch(w){console.log("There is an error in onEachUpload callback"),console.log(w)}b.$element.find("input.ssi-uploadInput").trigger("onEachUpload.ssi-uploader",[a]);b.inProgress--;d.prop("disabled",!1);0===b.inProgress&&B(b);b.uploadList[g]="";b.toUpload[g]="";b.imgNames[g]=""});f=g;for(f++;!b.toUpload[f]&&"undefined"!==typeof b.toUpload[f];)f++; +f'+c+""},C=function(a){var c=a.$element.find("#ssi-fileList").find("span").html(),d=c.getExtension();a.$element.find(".ssi-uploadDetails").removeClass("ssi-uploadBoxOpened"); +a.$element.find(".ssi-namePreview").html(y(c,d,15))};l.prototype.abort=function(a,c,d){"undefined"===typeof c?(this.uploadList[a].abort(),this.totalProgress[a]="",c=d||"Aborted",this.aborted++):"string"!==typeof c&&(c="");d=this.language.aborted;this.options.preview||(d='');A(this,a,"error",d,c);this.$element.find("#ssi-uploadProgress"+a).removeClass("ssi-hidden").addClass("ssi-canceledProgressBar");this.toUpload[a]=void 0;this.uploadList[a]=void 0;this.imgNames[a]=void 0; +this.$element.find("#ssi-clearBtn").prop("disabled",!1);this.inProgress--;0===this.inProgress&&B(this)};var B=function(a){a.$element.find("#ssi-abortBtn").addClass("ssi-hidden");if(!a.options.preview){var c="error",d="",b="";0'):0',d=a.language.aborted):0', +d=a.language.sucUpload);a.$element.find(".ssi-namePreview").append(G(c,b,d,"ssi-noPreviewMessage"));a.$element.find("#ssi-uploadProgressNoPreview").removeAttr("styles").addClass("ssi-hidden")}if("function"===typeof a.options.onUpload)try{a.options.onUpload(c)}catch(f){a.options.ignoreCallbackErrors||(console.log("There is an error in onUpload callback"),console.log(f))}a.$element.find("input.ssi-uploadInput").trigger("onUpload.ssi-uploader",[c]);c=a.$element.find("#ssi-uploadBtn");a.$element.find("#ssi-clearBtn").prop("disabled", +!1);c.prop("disabled",!1).find("#ssi-up_loading").empty();0===a.pending&&(c.addClass("ssi-hidden"),a.toUpload=[],a.imgNames=[],a.totalFilesLength=0);a.uploadList=[];a.totalProgress=[];a.currentListLength=a.inProgress+a.successfulUpload+a.aborted+a.abortedWithError+a.pending;a.inProgress=0};h.fn.ssi_uploader=function(a){var c=h.extend(!0,{allowDuplicates:!1,url:"",data:{},locale:"en",preview:!0,dropZone:!0,maxNumberOfFiles:"",responseValidation:!1,ignoreCallbackErrors:!1,maxFileSize:2,inForm:!1,ajaxOptions:{}, +onUpload:function(){},onEachUpload:function(){},beforeUpload:function(){},beforeEachUpload:function(){},allowed:"",errorHandler:{method:function(a){alert(a)},success:"success",error:"error"}},a);c.allowed=c.allowed||["jpg","jpeg","png","bmp","gif"];return this.each(function(){var a=h(this);if(a.is('input[type="file"]')){if(!a.data("ssi_upload")){var b=new l(this,c);a.data("ssi_upload",b)}}else console.log("The targeted element is not file input.")})};String.prototype.replaceText=function(){for(var a= +Array.apply(null,arguments),c=this,d=0;dd)){var b=c.length;return a.length-2>d?(a=a.substring(0,d),a=a.substring(0,a.length-b),a+"..."+c):a}},H={en:{success:"Success",sucUpload:"Successful upload",chooseFiles:"Choose files",uploadFailed:"Upload failed",serverError:"Internal server error", +error:"Error",abort:"Abort",aborted:"Aborted",files:"files",upload:"Upload",clear:"Clear",drag:"Drag n Drop",sizeError:"$1 exceed the size limit of $2",extError:"$1 file types are not supported",someErrorsOccurred:"Some errors occurred!",wentWrong:"Something went wrong!",pending:"Pending",completed:"Completed",inProgress:"In progress"},gr:{success:"\u0395\u03c0\u03b9\u03c4\u03c5\u03c7\u03af\u03b1",sucUpload:"\u0395\u03c0\u03b9\u03c4\u03c5\u03c7\u03ae\u03c2 \u03bc\u03b5\u03c4\u03b1\u03c6\u03cc\u03c1\u03c4\u03c9\u03c3\u03b7", chooseFiles:"\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03b1\u03c1\u03c7\u03b5\u03af\u03b1",uploadFailed:"\u0397 \u03bc\u03b5\u03c4\u03b1\u03c6\u03cc\u03c1\u03c4\u03c9\u03c3\u03b7 \u03b1\u03c0\u03ad\u03c4\u03c5\u03c7\u03b5!",serverError:"\u0395\u03c3\u03c9\u03c4\u03b5\u03c1\u03b9\u03ba\u03cc \u03c3\u03c6\u03ac\u03bb\u03bc\u03b1 \u03b4\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae!",error:"\u03a3\u03c6\u03ac\u03bb\u03bc\u03b1",abort:"\u0394\u03b9\u03b1\u03ba\u03bf\u03c0\u03ae",aborted:"\u0394\u03b9\u03b1\u03ba\u03cc\u03c0\u03b7\u03ba\u03b5", files:"\u03b1\u03c1\u03c7\u03b5\u03af\u03b1",upload:"\u039c\u03b5\u03c4\u03b1\u03c6\u03cc\u03c1\u03c4\u03c9\u03c3\u03b7",clear:"\u0395\u03ba\u03ba\u03b1\u03b8\u03ac\u03c1\u03b9\u03c3\u03b7",drag:"\u03a3\u03c5\u03c1\u03b5\u03c4\u03b5 \u03b5\u03b4\u03ce...",sizeError:"$1 \u03ad\u03c7\u03b5\u03b9 \u03be\u03b5\u03c0\u03b5\u03c1\u03ac\u03c3\u03b5\u03b9 \u03c4\u03bf \u03cc\u03c1\u03b9\u03bf \u03c4\u03c9\u03bd $2.",extError:"$1 \u03b1\u03c1\u03c7\u03b5\u03af\u03b1 \u03b4\u03b5\u03bd \u03c5\u03c0\u03bf\u03c3\u03c4\u03b7\u03c1\u03af\u03b6\u03bf\u03bd\u03c4\u03b1\u03b9.", someErrorsOccurred:"\u03a3\u03b7\u03bc\u03b5\u03b9\u03ce\u03b8\u03b7\u03ba\u03b1\u03bd \u03bf\u03c1\u03b9\u03c3\u03bc\u03ad\u03bd\u03b1 \u03bb\u03ac\u03b8\u03b7!",wentWrong:"\u039a\u03ac\u03c4\u03b9 \u03c0\u03ae\u03b3\u03b5 \u03c3\u03c4\u03c1\u03b1\u03b2\u03ac!",pending:"\u03a3\u03b5 \u03b5\u03ba\u03ba\u03c1\u03b5\u03bc\u03cc\u03c4\u03b7\u03c4\u03b1",completed:"\u039f\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03bf\u03bc\u03ad\u03bd\u03b1",inProgress:"\u03a3\u03b5 \u03b5\u03be\u03ad\u03bb\u03b9\u03be\u03b7"}, diff --git a/dist/ssi-uploader/js/ssi-uploader.min.js.map b/dist/ssi-uploader/js/ssi-uploader.min.js.map index 6079081..4d80a37 100644 --- a/dist/ssi-uploader/js/ssi-uploader.min.js.map +++ b/dist/ssi-uploader/js/ssi-uploader.min.js.map @@ -1 +1 @@ -{"version":3,"names":[],"mappings":"","sources":["ssi-uploader.js"],"sourcesContent":["\n(function (root, factory) {\n //@author http://ifandelse.com/its-not-hard-making-your-library-support-amd-and-commonjs/\n if (typeof module === \"object\" && module.exports) {\n module.exports = factory(require(\"jquery\"));\n } else {\n factory(root.jQuery);\n }\n}(this, function ($) {\n var Ssi_upload = function (element, options) {\n this.options = options;\n this.$element = '';\n this.language = locale[this.options.locale];\n this.uploadList = [];\n this.totalProgress = [];\n this.toUpload = [];\n this.imgNames = [];\n this.totalFilesLength = 0;\n this.successfulUpload = 0;\n this.aborted = 0;\n this.abortedWithError = 0;\n this.pending = 0;\n this.inProgress = 0;\n this.currentListLength = 0;\n this.inputName = '';\n this.init(element);\n };\n Ssi_upload.prototype.init = function (element) {\n $(element).addClass('ssi-uploadInput')\n .after(this.$element = $('
'));\n var $chooseBtn = $('' +\n '' +\n '' +\n '').append(element);\n var $uploadBtn = $('');\n var $clearBtn = $('');\n var $abortBtn = $('');\n if (this.options.inForm) {\n $uploadBtn.hide();\n }\n this.$element.append($('
').append($chooseBtn, $abortBtn, $uploadBtn, $clearBtn));\n var $uploadBox;\n if (!this.options.preview) {\n this.$element.addClass('ssi-uploaderNP');\n var $fileList = $('
');\n var $namePreview = $('');\n var $mainBox = $('
')\n .append($namePreview);\n var $uploadDetails = $('
').append($fileList);\n $uploadBox = $('
').append($mainBox, $uploadDetails);\n this.$element.prepend($uploadBox);\n } else {\n $uploadBox = $('
' + (this.options.dropZone ? '
' + this.language.drag + '
' : '') + '
?
');\n this.$element.append($uploadBox);\n }\n var thisS = this;\n var $input = $chooseBtn.find(\".ssi-uploadInput\");\n this.inputName = $input.attr('name') || 'files';\n $chooseBtn.find('button').click(function (e) {\n e.preventDefault();\n $input.trigger('click');\n });\n $input.on('change', function () { //choose files\n thisS.toUploadFiles(this.files);\n if (!thisS.options.inForm) {\n $input.val('');\n }\n });\n //drag n drop\n if (thisS.options.dropZone) {\n $uploadBox.on(\"drop\", function (e) {\n e.preventDefault();\n $uploadBox.removeClass(\"ssi-dragOver\");\n var files = e.originalEvent.dataTransfer.files;\n thisS.toUploadFiles(files);\n });\n $uploadBox.on(\"dragover\", function (e) {\n e.preventDefault();\n $uploadBox.addClass(\"ssi-dragOver\");\n return false;\n });\n $uploadBox.on(\"dragleave\", function (e) {\n e.preventDefault();\n $uploadBox.removeClass(\"ssi-dragOver\");\n return false;\n });\n }\n\n if (!thisS.options.preview) {\n $mainBox.click(function () {\n if (thisS.currentListLength > 1)\n $uploadDetails.toggleClass('ssi-uploadBoxOpened');\n })\n }\n\n $clearBtn.click(function (e) { //choose files completed and pending files\n e.preventDefault();\n thisS.clear();\n });\n\n $uploadBox.on('mouseenter', '.ssi-statusLabel', function (e) {\n var $eventTarget = $(e.currentTarget);\n var title = $eventTarget.attr('data-status');\n if (!title || title === '') {\n return;\n }\n tooltip($eventTarget, title, thisS);\n });\n $uploadBox.on('mouseenter', '#ssi-fileNumber', function (e) {\n var $eventTarget = $(e.currentTarget);\n\n var message = \" \" + thisS.language.pending + \": \" + thisS.pending + \"
\" + thisS.language.completed + \": \" + (thisS.successfulUpload + thisS.aborted + thisS.abortedWithError) + \"
\" + thisS.language.inProgress + \": \" + thisS.inProgress;\n tooltip($eventTarget, message, thisS);\n });\n\n $uploadBox.on('click', '.ssi-removeBtn', function (e) { //remove the file from list\n e.preventDefault();\n var $currentTarget = $(e.currentTarget);\n var index = $currentTarget.data('delete'); //get file's index\n thisS.pending--; //reduce pending number by 1\n thisS.currentListLength--; //reduce current list length by 1\n if (thisS.pending < 1) {\n thisS.$element.find('#ssi-fileNumber').addClass('ssi-hidden');\n }\n if (thisS.pending === 0) {\n $uploadBtn.prop('disabled', true); //if there is no more files disable upload button\n }\n if (thisS.options.preview) { //if preview is true\n $currentTarget.parents('table.ssi-imgToUploadTable').remove(); //remove table\n } else {\n var target = $currentTarget.parents('tr.ssi-toUploadTr'); //find the tr of file\n $namePreview.html((thisS.currentListLength) + ' files'); //set the main name to the remaining files\n target.prev().remove();// remove empty tr (using id for margin between rows)\n target.remove();// remove the file\n if (thisS.currentListLength === 1) { //if only one file left in the list\n setLastElementName(thisS); //set main preview to display the name\n }\n }\n thisS.toUpload[index] = null; //set the file's obj to null (we don't splice it because we need to keep the same indexes)\n thisS.imgNames[index] = null; //set the file's name to null\n\n if (thisS.currentListLength === 0) { // if no more files in the list\n if (!thisS.options.dropZone) { // if drag and drop is disabled\n $uploadBox.removeClass('ssi-uploadNoDropZone');\n }\n $clearBtn.addClass('ssi-hidden');\n $uploadBtn.addClass('ssi-hidden');\n }\n });\n $uploadBox.on('click', '.ssi-abortUpload', function (e) {//abort one element\n e.preventDefault();\n var $eventTarget = $(e.currentTarget);\n var index = $eventTarget.data('delete');// get the element id\n thisS.abort(index); // abort request\n });\n //----------------------------UPLOADFILES------------------------------------\n $uploadBtn.click(function (e) {// upload the files\n e.preventDefault();\n thisS.uploadFiles();\n });\n $abortBtn.click(function (e) { // abort all requests\n e.preventDefault();\n thisS.abortAll();\n });\n\n };\n function tooltip($target, text, thisS) {\n $target = $($target);\n text = text || $target.data('title');\n if (!text) text = $target.attr('title');\n if (!text) return;\n var $toolTip = $('
'\n + text +\n '
').appendTo(thisS.$element);\n $target.one('mouseleave', function () {\n $toolTip.remove();\n });\n var offset = -16;\n if ($target.hasClass('ssi-noPreviewSubMessage')) {\n offset = 23;\n }\n $toolTip.css({\n top: $target.position().top - $toolTip.height() + offset,\n left: $target.position().left - $toolTip.width() / 2\n })\n .removeClass('ssi-fadeOut');\n return $toolTip;\n }\n\n Ssi_upload.prototype.abortAll = function () {\n for (var i = 0; i < this.uploadList.length; i++) { //all element in the list\n if (typeof this.uploadList[i] === 'object') {// check if not deleted\n this.abort(i);\n }\n }\n };\n Ssi_upload.prototype.toUploadFiles = function (files) {\n if (typeof this.options.maxNumberOfFiles === 'number') {\n if ((this.inProgress + this.pending) >= this.options.maxNumberOfFiles) {// if in progress files + pending files are more than the number that we have define as max number of files pre download\n return;//don't do anything\n }\n }\n var thisS = this,\n j = 0,\n length,\n imgContent = '',\n $uploadBtn = this.$element.find('#ssi-uploadBtn'),\n $clearBtn = this.$element.find('#ssi-clearBtn'),\n $fileList = this.$element.find('#ssi-fileList'),\n $uploadBox = this.$element.find('.ssi-uploadBox'),\n imgs = [];\n if ((this.inProgress === 0 && this.pending === 0)) { //if no file are pending or are in progress\n this.clear(); //clear the list\n }\n var extErrors = [], sizeErrors = [], errorMessage = '';\n var toUploadLength, filesLength = length = toUploadLength = files.length;\n if (typeof this.options.maxNumberOfFiles === 'number') {//check if requested files agree with our arguments\n if (filesLength > this.options.maxNumberOfFiles - (this.inProgress + this.pending)) { //if requested files is more than we need\n filesLength = toUploadLength = this.options.maxNumberOfFiles - (this.inProgress + this.pending); // set variable to the number of files we need\n }\n }\n //\n for (var i = 0; i < filesLength; i++) {\n var file = files[i],\n ext = file.name.getExtension();// get file's extension\n\n if ($.inArray(ext, this.options.allowed) === -1) { // if requested file not allowed\n if (length > filesLength) {//there are more file we dont pick\n filesLength++;//the add 1 more loop\n } else {\n toUploadLength--;\n }\n if ($.inArray(ext, extErrors) === -1) {//if we see first time this extension\n extErrors.push(ext); //push it to extErrors variable\n }\n } else if ((file.size * Math.pow(10, -6)).toFixed(2) > this.options.maxFileSize) {//if file size is more than we ask\n if (length > filesLength) {\n filesLength++;\n } else {\n toUploadLength--;\n }\n sizeErrors.push(cutFileName(file.name, ext, 15));//register a size error\n } else if (this.options.allowDuplicates || $.inArray(file.name, this.imgNames) === -1) {// if the file is not already in the list\n $uploadBtn.prop(\"disabled\", false);\n setupReader(file);\n this.pending++; // we have one more file that is pending to be uploaded\n this.currentListLength++;// we have one more file in the list\n } else {\n if (length > filesLength) {\n filesLength++;\n } else {\n toUploadLength--;\n }\n }\n }\n var extErrorsLength = extErrors.length, sizeErrorsLength = sizeErrors.length;\n if (extErrorsLength + sizeErrorsLength > 0) { // in the end expose all errors\n if (extErrorsLength > 0) {\n errorMessage = this.language.extError.replaceText(extErrors.toString().replace(/,/g, ', '));\n }\n if (sizeErrorsLength > 0) {\n errorMessage += this.language.sizeError.replaceText(sizeErrors.toString().replace(/,/g, ', '), this.options.maxFileSize + 'mb');\n }\n this.options.errorHandler.method(errorMessage, this.options.errorHandler.error);\n }\n function setupReader() {\n var index = thisS.imgNames.length;\n if (index === 0) {//do it only the first time\n if (thisS.options.preview) {\n if (!thisS.options.dropZone) {\n $uploadBox.addClass('ssi-uploadNoDropZone')\n }\n }\n $uploadBtn.removeClass('ssi-hidden');\n $clearBtn.removeClass('ssi-hidden');\n }\n $clearBtn.prop('disabled', true);\n thisS.toUpload[index] = file;\n var filename = file.name;\n var ext = filename.getExtension(); //get file's extension\n thisS.imgNames[index] = filename; //register file's name\n if (thisS.options.preview) {\n var getTemplate = function (content) {\n return '' +\n '' +\n '' +\n '' +\n '
' + content + '
' + cutFileName(filename, ext, 15) + '
'\n };\n var fileType = file.type.split('/');\n if (fileType[0] == 'image') {\n $uploadBtn.prop(\"disabled\", true);\n $clearBtn.prop(\"disabled\", true);\n var fileReader = new FileReader();\n fileReader.onload = function () {\n imgContent += getTemplate(''); // set the files element without the img\n imgs[index] = fileReader.result;\n j++;\n if (toUploadLength === j) {// if all elements are in place lets load images\n thisS.$element.find('#ssi-fileNumber').removeClass('ssi-hidden');\n $uploadBox.append(imgContent);\n setTimeout(function () {\n setImg();//and load the images\n $uploadBtn.prop(\"disabled\", false);\n $clearBtn.prop(\"disabled\", false);\n }, 10);\n $uploadBtn.prop(\"disabled\", false);\n $clearBtn.prop(\"disabled\", false);\n\n imgContent = '';\n toUploadLength = [];\n } else if (toUploadLength / 2 == Math.round(j)) {\n $uploadBox.append(imgContent);\n setImg();//and load the images\n imgContent = '';\n }\n };\n fileReader.readAsDataURL(file);\n } else {\n imgs[index] = null;\n $uploadBox.append(getTemplate('
'));\n j++;\n }\n } else {\n $clearBtn.prop('disabled', false);\n thisS.$element.find('.ssi-namePreview').html((index === 0 ? cutFileName(filename, ext, 13) : (thisS.currentListLength + 1) + ' ' + thisS.language.files));//set name preview\n $fileList.append('' +//append files element to dom\n '
' +\n '' + cutFileName(filename, ext, 20) + '' +\n '');\n }\n\n var setImg = function () {//load the images\n for (var i = 0; i < imgs.length; i++) {\n if (imgs[i] !== null) {\n $uploadBox.find(\"#ssi-uploadProgress\" + i).parents('table.ssi-imgToUploadTable')\n .find('.ssi-imgToUpload')\n .attr('src', imgs[i]) //set src of the image\n .next().remove();//remove the spinner\n imgs[i] = null;\n }\n }\n imgs = [];\n };\n }\n };\n var clearCompleted = function (thisS) {//clear all completed files\n var $completed = thisS.$element.find('.ssi-completed');\n thisS.successfulUpload = 0;\n thisS.aborted = 0;\n thisS.abortedWithError = 0;\n if (!thisS.options.preview) $completed.prev('tr').remove();\n $completed.remove();\n };\n var clearPending = function (thisS) {//clear all pending files\n var $pending = thisS.$element.find('.ssi-pending');\n var length = thisS.imgNames.length;\n for (var i = 0; i < length; i++) {\n if (thisS.imgNames[i] === null) {\n thisS.toUpload.splice(i, 1);\n thisS.imgNames.splice(i, 1);\n }\n }\n thisS.toUpload.splice(-thisS.pending, thisS.pending);\n thisS.imgNames.splice(-thisS.pending, thisS.pending);\n thisS.pending = 0;\n if (!thisS.options.preview) $pending.prev('tr').remove();\n $pending.remove();\n };\n\n Ssi_upload.prototype.clear = function (action) {//clean the list of all non in progress files\n switch (action) {\n case 'pending':\n clearPending(this);\n break;\n case 'completed':\n clearCompleted(this);\n break;\n default:\n clearPending(this);\n clearCompleted(this);\n }\n var $uploadBtn = this.$element.find('#ssi-uploadBtn'),\n $clearBtn = this.$element.find('#ssi-clearBtn');\n this.currentListLength = getCurrentListLength(this);\n if (this.inProgress === 0) { //if no file are uploading right now\n this.totalProgress = [];\n }\n if ((this.currentListLength === 0)) { // if no items in the list\n $clearBtn.addClass('ssi-hidden');\n $uploadBtn.addClass('ssi-hidden');\n this.$element.find('#ssi-fileNumber').addClass('ssi-hidden');\n this.totalFilesLength = 0;\n if (!this.options.dropZone) {\n this.$element.find('.ssi-uploadBox').removeClass('ssi-uploadNoDropZone')\n }\n }\n $clearBtn.prop('disabled', true);\n $uploadBtn.prop('disabled', true);\n\n if (!this.options.preview) {\n setNamePreview(this);\n }\n };\n\n var setNamePreview = function (thisS) {//set the name preview according to the remaining elements in the list\n if (thisS.currentListLength > 1) {//if more than one element left\n thisS.$element.find('.ssi-namePreview').html(thisS.currentListLength + ' files'); // set the name preview to the length of the remaining items\n } else if (thisS.currentListLength === 1) {//if one left\n setLastElementName(thisS); // set the name of the element\n } else { //if no elements left\n thisS.$element.find('.ssi-uploadDetails').removeClass('ssi-uploadBoxOpened');\n thisS.$element.find('#ssi-fileList').empty();//empty list\n thisS.$element.find('.ssi-namePreview').empty();//empty the name preview\n }\n\n };\n\n Ssi_upload.prototype.appendFileToFormData = function (formData, file) {\n formData.append(this.inputName, file);//append the first file to the form data\n $.each(this.options.data, function (key, value) {// append all extra data\n formData.append(key, value);\n });\n this.$element.find('input.ssi-uploadInput').trigger('beforeUpload.ssi-uploader');\n }\n Ssi_upload.prototype.uploadFiles = function () {// upload the pending files\n if (this.pending > 0) {\n if (typeof this.options.beforeUpload === 'function') {\n try {\n this.options.beforeUpload();// execute the beforeUpload callback\n } catch (err) {\n if (!this.options.ignoreCallbackErrors) {\n console.log('There is an error in beforeUpload callback');\n return console.log(err);\n }\n }\n }\n this.$element.find('#ssi-abortBtn').removeClass('ssi-hidden');\n this.$element.find('.ssi-removeBtn')\n .addClass('ssi-abortUpload')\n .removeClass('ssi-removeBtn')\n .children('span').removeClass('trash7 trash10 trash')\n .addClass((this.options.preview ? 'ban7w' : 'ban7'));//transform remove button to abort button\n var $uploadBtn = this.$element.find('#ssi-uploadBtn'),\n $clearBtn = this.$element.find('#ssi-clearBtn');\n $uploadBtn.prop(\"disabled\", true);\n var thisS = this,\n formData = new FormData(),//set the form data\n i = this.totalFilesLength;\n if (this.totalFilesLength !== 0 && !this.options.preview) {\n setNamePreview(this);\n }\n this.inProgress += this.pending;// add pending to in progress\n this.totalFilesLength += this.pending;// this variable is to prevent id duplication during uploads\n this.pending = 0;\n if (this.inProgress === this.currentListLength) {// disable the clear button if no items in list we can be remove\n $clearBtn.prop(\"disabled\", true);\n }\n\n while (thisS.toUpload[i] === null || thisS.toUpload[i] === '') { // do it until you find a file\n i++;\n }\n var file = thisS.toUpload[i]\n if (typeof this.options.transformFile === 'function') {\n try {\n file = this.options.transformFile(thisS.toUpload[i]);// execute the transformFile\n if (file instanceof Promise) {\n file.then(function (file) {\n thisS.appendFileToFormData(formData, file)\n ajaxLoopRequest(formData, i)\n })\n } else {\n console.log(\"TCL: Ssi_upload.22222.uploadFiles -> thisS\", thisS)\n thisS.appendFileToFormData(formData, file)\n ajaxLoopRequest(formData, i)\n }\n } catch (err) {\n if (!this.options.ignoreCallbackErrors) {\n console.error('There is an error in transformFile');\n return console.error(err);\n }\n }\n } else {\n thisS.appendFileToFormData(formData, file)\n ajaxLoopRequest(formData, i)\n }\n }\n\n //--------------start of ajax request-----------------------\n function ajaxLoopRequest(formData, ii) {\n var selector = 'table.ssi-imgToUploadTable';\n if (!thisS.options.preview) {\n selector = 'tr.ssi-toUploadTr'\n }\n var uploadBar = thisS.$element.find('#ssi-uploadProgress' + ii);//get the file's progress bar\n uploadBar.removeClass('ssi-hidden') //make it visible\n .parents(selector).removeClass('ssi-pending');\n var ajaxOptions = $.extend({}, {//store the request to the uploadList variable\n xhr: function () {\n var xhr = new window.XMLHttpRequest();\n xhr.upload.addEventListener('progress', function (e) {// add event listener to progress\n if (e.lengthComputable) {\n var percentComplete = (e.loaded / e.total) * 100;// calculate the progress\n if (uploadBar) {\n uploadBar.css({\n width: percentComplete + '%'//update the progress bar width according to the progress\n });\n }\n thisS.totalProgress[ii] = percentComplete;//store the progress to the array\n var sum = arraySum(thisS.totalProgress) / (thisS.inProgress + thisS.successfulUpload);//and calculate the overall progress\n if (!thisS.options.preview) {\n thisS.$element.find('#ssi-uploadProgressNoPreview')\n .removeClass('ssi-hidden')\n .css({\n width: sum + '%'\n });\n }\n $uploadBtn.find('#ssi-up_loading').html(Math.ceil(sum) + '%');// add to upload button the current overall progress percent number\n }\n }, false);\n return xhr;\n },\n async: true,\n beforeSend: function (xhr, settings) {\n thisS.uploadList[ii] = xhr;\n $uploadBtn.find('#ssi-up_loading') //add spiner to uploadbutton\n .html('');\n var fileInfo = {\n name: thisS.toUpload[ii].name,//send some info of the file\n type: thisS.toUpload[ii].type,\n size: (thisS.toUpload[ii].size / 1024).toFixed(2)\n };\n if (typeof thisS.options.beforeEachUpload === 'function') {\n try {\n // execute the beforeEachUpload callback and save the returned value\n var msg = thisS.options.beforeEachUpload(fileInfo, xhr, settings);\n } catch (err) {\n if (err.name == 'Error') {\n thisS.abort(ii, undefined, err.message);//call the abort function\n } else {\n if (!thisS.options.ignoreCallbackErrors) {\n console.log('There is an error in beforeEachUpload callback. Filename:' + thisS.toUpload[ii].name);\n console.log(err);\n thisS.abort(ii, undefined, thisS.language.wentWrong);//call the abort function\n }\n }\n return;\n }\n }\n thisS.$element.find('input.ssi-uploadInput').trigger('beforeEachUpload.ssi-uploader', [fileInfo]);\n if (xhr.status === 0) {\n if (xhr.statusText === 'canceled') {//if user used beforeEachUpload to abort the request\n if (typeof msg === 'undefined') {//if no message\n msg = false; //because user have already aborted the request set to false or anything else except undefined to prevent to abort it again\n }\n thisS.abortedWithError++;// we have one error more\n thisS.abort(ii, msg);//call the abort function\n }\n }\n },\n type: 'POST',\n data: formData,\n cache: false,\n contentType: false,\n processData: false,\n url: thisS.options.url,\n error: function (request, error) {\n if (error !== 'abort') {\n uploadBar.addClass('ssi-canceledProgressBar');\n var msg = thisS.language.error;\n thisS.abortedWithError++;//add one more error\n thisS.totalProgress.splice(ii, 1); //remove from progress array\n if (!thisS.options.preview) {\n msg = '';\n }\n setElementMessage(thisS, ii, 'error', msg, thisS.language.serverError);\n thisS.totalProgress[ii] = '';\n thisS.inProgress--;\n $clearBtn.prop(\"disabled\", false);\n if (typeof thisS.options.onEachUpload === 'function') {//execute the onEachUpload callback\n try {\n thisS.options.onEachUpload({//and return some info\n uploadStatus: 'error',\n responseMsg: thisS.language.serverError,\n name: thisS.toUpload[ii].name,\n size: (thisS.toUpload[ii].size / 1024).toFixed(2),\n type: thisS.toUpload[ii].type\n });\n } catch (err) {\n if (!thisS.options.ignoreCallbackErrors) {\n console.log('There is an error in onEachUpload callback. File name:' + thisS.toUpload[ii].name);\n console.log(err);\n }\n }\n }\n if (getCompleteStatus(thisS)) {//if no more elements in progress\n finishUpload(thisS);\n }\n console.log(arguments);//log the error\n console.log(\" Ajax error: \" + error);\n }\n }\n }, thisS.options.ajaxOptions);\n $.ajax(ajaxOptions).done(function (responseData, textStatus, jqXHR) {\n var msg, title = '', dataType = 'error', spanClass = 'exclamation', data;\n try {\n data = $.parseJSON(responseData);\n } catch (err) {\n data = responseData;\n }\n if (thisS.options.responseValidation) {\n var valData = thisS.options.responseValidation;\n if (typeof valData.validationKey === 'object' && valData.resultKey == 'validationKey') {\n if (data.hasOwnProperty(valData.validationKey.success)) {\n cb(true, data[valData.validationKey.success]);\n } else {\n cb(false, data[valData.validationKey.error]);\n }\n } else {\n if (data[valData.validationKey] == valData.success) {\n cb(true, data[valData.resultKey]);\n } else {\n cb(false, data[valData.resultKey]);\n }\n }\n } else {\n if (jqXHR.status == 200) {\n cb(true, data);\n } else {\n cb(false, data);\n }\n }\n function cb(result, data) {\n if (result) {//if response type is success\n dataType = 'success';\n msg = thisS.language.success;\n spanClass = 'check';\n thisS.successfulUpload++;// one more successful upload\n } else {\n uploadBar.addClass('ssi-canceledProgressBar');\n if (thisS.options.preview) {\n msg = thisS.language.error;\n }\n thisS.abortedWithError++;\n }\n title = data;\n }\n\n if (!thisS.options.preview) {\n msg = '';\n }\n setElementMessage(thisS, ii, dataType, msg, title);\n var fileInfo = {//and return some info\n uploadStatus: dataType,\n responseMsg: title,\n name: thisS.toUpload[ii].name,\n size: (thisS.toUpload[ii].size / 1024).toFixed(2),\n type: thisS.toUpload[ii].type\n };\n if (typeof thisS.options.onEachUpload === 'function') {//execute the onEachUpload callback\n try {\n thisS.options.onEachUpload(fileInfo, data);\n } catch (err) {\n console.log('There is an error in onEachUpload callback');\n console.log(err);\n }\n }\n thisS.$element.find('input.ssi-uploadInput').trigger('onEachUpload.ssi-uploader', [fileInfo]);\n thisS.inProgress--;//one less in progress upload\n $clearBtn.prop(\"disabled\", false);\n if (getCompleteStatus(thisS)) {//if no more files in progress\n finishUpload(thisS);\n }\n // thisS.totalProgress[ii]='';\n thisS.uploadList[ii] = '';\n thisS.toUpload[ii] = '';\n thisS.imgNames[ii] = '';\n });\n //--------------end of ajax request-----------------------\n\n i = ii;\n i++;//go to the next element\n while (thisS.toUpload[i] === null || thisS.toUpload[i] === '') {// do it until you find a file\n i++;\n }\n if (i < thisS.toUpload.length) {// if more files exist start the next request\n formData = new FormData();\n $.each(thisS.options.data, function (key, value) {\n formData.append(key, value);\n });\n formData.append(thisS.inputName, thisS.toUpload[i]);\n ajaxLoopRequest(formData, i);\n }\n }\n };\n var setElementMessage = function (thisS, index, msgType, msg, title) {\n var className = '', elementSelector = 'table.ssi-imgToUploadTable', element;\n if (!thisS.options.preview) {\n className = 'ssi-noPreviewSubMessage';\n elementSelector = 'tr.ssi-toUploadTr';\n if (thisS.currentListLength === 1) {\n thisS.errors = title;\n }\n }\n\n element = thisS.$element.find(\".ssi-abortUpload[data-delete='\" + index + \"']\");\n element.parents(elementSelector).addClass('ssi-completed');\n element.after(getResultMessage(msgType, msg, title, className))\n .remove();\n };\n\n var getCompleteStatus = function (thisS) {//check if file are in progress\n return (thisS.inProgress === 0);\n };\n\n var getResultMessage = function (type, msg, title, classes) {//return a message label\n return '' + msg + '';\n };\n\n var getCurrentListLength = function (thisS) { //get the list length\n return (thisS.inProgress + thisS.successfulUpload + thisS.aborted + thisS.abortedWithError + thisS.pending);\n };\n var setLastElementName = function (thisS) { //if one file in list get the last file's name and put it to the name preview\n var fileName = thisS.$element.find('#ssi-fileList').find('span').html();//find the only span left\n var ext = fileName.getExtension();//get the extension\n thisS.$element.find('.ssi-uploadDetails').removeClass('ssi-uploadBoxOpened');\n thisS.$element.find('.ssi-namePreview').html(cutFileName(fileName, ext, 15));//short the name and put it to the name preview\n };\n Ssi_upload.prototype.abort = function (index, title, mmsg) {//abort a request\n if (typeof title === 'undefined') {//if no title\n this.uploadList[index].abort();// abort the element\n this.totalProgress[index] = '';\n title = mmsg || 'Aborted';\n this.aborted++;// one more aborted file\n } else if (typeof title !== 'string') {//if not string that means that the request aborted with the beforeEachUpload callback and no message returned\n title = '';\n }\n //nothing of the above happened that means the user aborted the request with the beforeUpload callback and returned a message\n var msg = this.language.aborted;\n if (!this.options.preview) {\n msg = '';\n }\n setElementMessage(this, index, 'error', msg, (title));\n this.$element.find('#ssi-uploadProgress' + index).removeClass('ssi-hidden').addClass('ssi-canceledProgressBar');\n this.toUpload[index] = undefined;\n this.uploadList[index] = undefined;\n this.imgNames[index] = undefined;\n this.$element.find('#ssi-clearBtn').prop(\"disabled\", false);\n this.inProgress--;//one less in progress file\n if (getCompleteStatus(this)) {//if no more file in progress\n finishUpload(this);\n }\n\n };\n\n var finishUpload = function (thisS) {//when every uplaod ends\n thisS.$element.find('#ssi-abortBtn').addClass('ssi-hidden');\n if (!thisS.options.preview) {//display tha main message in the name preview\n var type = 'error', title = '', msg = '';\n if (thisS.abortedWithError > 0) { //if no errors\n if (thisS.totalFilesLength === 1) {// if only one file in the list\n title = thisS.errors; //display the error\n } else {//else display something more general message\n title = thisS.language.someErrorsOccurred\n }\n msg = '';\n } else if (thisS.aborted > 0 && thisS.successfulUpload === 0) {//if all request aborted\n msg = '';\n title = thisS.language.aborted;\n } else if (thisS.successfulUpload > 0) {// all request were successfull\n type = 'success';\n msg = '';\n title = thisS.language.sucUpload;\n }\n thisS.$element.find('.ssi-namePreview').append(getResultMessage(type, msg, title, 'ssi-noPreviewMessage'));//show the message in the name preview\n thisS.$element.find('#ssi-uploadProgressNoPreview') //remove main overall progress bar\n .removeAttr('styles')\n .addClass('ssi-hidden');\n }\n if (typeof thisS.options.onUpload === 'function') {\n try {\n thisS.options.onUpload(type);//execute the on Upload callback\n } catch (err) {\n if (!thisS.options.ignoreCallbackErrors) {\n console.log('There is an error in onUpload callback');\n console.log(err);\n }\n }\n }\n thisS.$element.find('input.ssi-uploadInput').trigger('onUpload.ssi-uploader', [type]);\n var $uploadBtn = thisS.$element.find('#ssi-uploadBtn');\n thisS.$element.find('#ssi-clearBtn').prop(\"disabled\", false);\n $uploadBtn.prop(\"disabled\", false)\n .find('#ssi-up_loading')\n .empty();\n if (thisS.pending === 0) {\n $uploadBtn.addClass('ssi-hidden');\n thisS.toUpload = [];\n thisS.imgNames = [];\n thisS.totalFilesLength = 0;\n }\n thisS.uploadList = [];\n thisS.totalProgress = [];\n thisS.currentListLength = getCurrentListLength(thisS);\n thisS.inProgress = 0;\n };\n\n $.fn.ssi_uploader = function (opts) {\n var defaults = {\n allowDuplicates: false,\n url: '',\n data: {},\n locale: 'en',\n preview: true,\n dropZone: true,\n maxNumberOfFiles: '',\n responseValidation: false,\n ignoreCallbackErrors: false,\n maxFileSize: 2,\n inForm: false,\n ajaxOptions: {},\n onUpload: function () {\n },\n onEachUpload: function () {\n },\n beforeUpload: function () {\n },\n beforeEachUpload: function () {\n },\n allowed: '',\n errorHandler: {\n method: function (msg) {\n alert(msg);\n },\n success: 'success',\n error: 'error'\n }\n };\n var options = $.extend(true, defaults, opts);\n options.allowed = options.allowed || ['jpg', 'jpeg', 'png', 'bmp', 'gif'];\n return this.each(function () {\n var $element = $(this);\n if ($element.is('input[type=\"file\"]')) {\n if ($element.data('ssi_upload')) return;\n var ssi_upload = new Ssi_upload(this, options);\n $element.data('ssi_upload', ssi_upload);\n } else {\n console.log('The targeted element is not file input.')\n }\n });\n };\n //functions\n String.prototype.replaceText = function () {//replace $ with variables\n var args = Array.apply(null, arguments);\n var text = this;\n for (var i = 0; i < args.length; i++) {\n text = text.replace('$' + (i + 1), args[i])\n }\n return text;\n };\n String.prototype.getExtension = function () {//returns the extension of a path or file\n return this.split('.').pop().toLowerCase();\n };\n var cutFileName = function (word, ext, maxLength) {//shorten the name\n if (typeof ext === 'undefined') ext = '';\n if (typeof maxLength === 'undefined') maxLength = 10;\n var min = 4;\n if (maxLength < min) return;\n var extLength = ext.length;\n var wordLength = word.length;\n if ((wordLength - 2) > maxLength) {\n word = word.substring(0, maxLength);\n var wl = word.length - extLength;\n word = word.substring(0, wl);\n return word + '...' + ext;\n } else return word;\n };\n\n var arraySum = function (arr) {//return the sum of an array\n var sum = 0;\n for (var i = 0; i < arr.length; i++) {\n if (typeof arr[i] === 'number')\n sum += arr[i];\n }\n return sum;\n };\n\n var locale = {\n en: {\n success: 'Success',\n sucUpload: 'Successful upload',\n chooseFiles: 'Choose files',\n uploadFailed: 'Upload failed',\n serverError: 'Internal server error',\n error: 'Error',\n abort: 'Abort',\n aborted: 'Aborted',\n files: 'files',\n upload: 'Upload',\n clear: 'Clear',\n drag: 'Drag n Drop',\n sizeError: '$1 exceed the size limit of $2',// $1=file name ,$2=max ie( example.jpg has has exceed the size limit of 2mb)\n extError: '$1 file types are not supported',//$1=file extension ie(exe files are not supported)\n someErrorsOccurred: 'Some errors occurred!',\n wentWrong: 'Something went wrong!',\n pending: 'Pending',\n completed: 'Completed',\n inProgress: 'In progress'\n },\n gr: {\n success: 'Επιτυχία',\n sucUpload: 'Επιτυχής μεταφόρτωση',\n chooseFiles: 'Επιλέξτε αρχεία',\n uploadFailed: 'Η μεταφόρτωση απέτυχε!',\n serverError: 'Εσωτερικό σφάλμα διακομιστή!',\n error: 'Σφάλμα',\n abort: 'Διακοπή',\n aborted: 'Διακόπηκε',\n files: 'αρχεία',\n upload: 'Μεταφόρτωση',\n clear: 'Εκκαθάριση',\n drag: 'Συρετε εδώ...',\n sizeError: '$1 έχει ξεπεράσει το όριο των $2.',// $1=file name ,$2=max file size ie( example.jpg has has exceed the size limit of 2mb)\n extError: '$1 αρχεία δεν υποστηρίζονται.',// $1=file extension ie(exe files are not supported)\n someErrorsOccurred: 'Σημειώθηκαν ορισμένα λάθη!',\n wentWrong: 'Κάτι πήγε στραβά!',\n pending: 'Σε εκκρεμότητα',\n completed: 'Ολοκληρομένα',\n inProgress: 'Σε εξέλιξη'\n },\n fr: { //@author Badulesia\n success: 'Succès',\n sucUpload: 'Envoi réussi',\n chooseFiles: 'Choisissez fichiers',\n uploadFailed: 'Envoi échoué',\n serverError: 'Erreur interne du serveur',\n error: 'Erreur',\n abort: 'Annuler',\n aborted: 'Annulé',\n files: 'Fichiers',\n upload: 'Envoyer',\n clear: 'Effacer',\n drag: 'Glisser déposer',\n sizeError: '$1 excède la taille limite de $2',// $1=file name ,$2=max ie( example.jpg has has exceed the size limit of 2mb)\n extError: 'Types de fichier $1 non autorisé',//$1=file extension ie(exe files are not supported)\n someErrorsOccurred: 'Une erreur a eu lieu !',\n wentWrong: 'Une erreur a eu lieu !',\n pending: 'Εn attendant',\n completed: 'Terminé',\n inProgress: 'En cours'\n },\n zh_CN: {\n success: '上传成功',\n sucUpload: '上传成功',\n chooseFiles: '选择文件',\n uploadFailed: '上传失败',\n serverError: '服务器内部错误',\n error: '错误',\n abort: '中止',\n aborted: '已中止',\n files: '文件',\n upload: '上传',\n clear: '清空',\n drag: '将图片拖拽至此并释放',\n sizeError: '$1 超出了 $2 的大小限制',\n extError: '$1 类型不被支持',\n someErrorsOccurred: '发生了一些错误!',\n wentWrong: '出问题了哦!',\n pending: '等待上传',\n completed: '完成',\n inProgress: '正在上传'\n }\n };\n\n}));"],"file":"ssi-uploader.min.js"} \ No newline at end of file +{"version":3,"names":[],"mappings":"","sources":["ssi-uploader.js"],"sourcesContent":["\n(function (root, factory) {\n //@author http://ifandelse.com/its-not-hard-making-your-library-support-amd-and-commonjs/\n if (typeof module === \"object\" && module.exports) {\n module.exports = factory(require(\"jquery\"));\n } else {\n factory(root.jQuery);\n }\n}(this, function ($) {\n var Ssi_upload = function (element, options) {\n this.options = options;\n this.$element = '';\n this.language = locale[this.options.locale];\n this.uploadList = [];\n this.totalProgress = [];\n this.toUpload = [];\n this.imgNames = [];\n this.totalFilesLength = 0;\n this.successfulUpload = 0;\n this.aborted = 0;\n this.abortedWithError = 0;\n this.pending = 0;\n this.inProgress = 0;\n this.currentListLength = 0;\n this.inputName = '';\n this.init(element);\n };\n Ssi_upload.prototype.init = function (element) {\n $(element).addClass('ssi-uploadInput')\n .after(this.$element = $('
'));\n var $chooseBtn = $('' +\n '' +\n '' +\n '').append(element);\n var $uploadBtn = $('');\n var $clearBtn = $('');\n var $abortBtn = $('');\n if (this.options.inForm) {\n $uploadBtn.hide();\n }\n this.$element.append($('
').append($chooseBtn, $abortBtn, $uploadBtn, $clearBtn));\n var $uploadBox;\n if (!this.options.preview) {\n this.$element.addClass('ssi-uploaderNP');\n var $fileList = $('
');\n var $namePreview = $('');\n var $mainBox = $('
')\n .append($namePreview);\n var $uploadDetails = $('
').append($fileList);\n $uploadBox = $('
').append($mainBox, $uploadDetails);\n this.$element.prepend($uploadBox);\n } else {\n $uploadBox = $('
' + (this.options.dropZone ? '
' + this.language.drag + '
' : '') + '
?
');\n this.$element.append($uploadBox);\n }\n var thisS = this;\n var $input = $chooseBtn.find(\".ssi-uploadInput\");\n this.inputName = $input.attr('name') || 'files';\n $chooseBtn.find('button').click(function (e) {\n e.preventDefault();\n $input.trigger('click');\n });\n $input.on('change', function () { //choose files\n thisS.toUploadFiles(this.files);\n if (!thisS.options.inForm) {\n $input.val('');\n }\n });\n //drag n drop\n if (thisS.options.dropZone) {\n $uploadBox.on(\"drop\", function (e) {\n e.preventDefault();\n $uploadBox.removeClass(\"ssi-dragOver\");\n var files = e.originalEvent.dataTransfer.files;\n thisS.toUploadFiles(files);\n });\n $uploadBox.on(\"dragover\", function (e) {\n e.preventDefault();\n $uploadBox.addClass(\"ssi-dragOver\");\n return false;\n });\n $uploadBox.on(\"dragleave\", function (e) {\n e.preventDefault();\n $uploadBox.removeClass(\"ssi-dragOver\");\n return false;\n });\n }\n\n if (!thisS.options.preview) {\n $mainBox.click(function () {\n if (thisS.currentListLength > 1)\n $uploadDetails.toggleClass('ssi-uploadBoxOpened');\n })\n }\n\n $clearBtn.click(function (e) { //choose files completed and pending files\n e.preventDefault();\n thisS.clear();\n });\n\n $uploadBox.on('mouseenter', '.ssi-statusLabel', function (e) {\n var $eventTarget = $(e.currentTarget);\n var title = $eventTarget.attr('data-status');\n if (!title || title === '') {\n return;\n }\n tooltip($eventTarget, title, thisS);\n });\n $uploadBox.on('mouseenter', '#ssi-fileNumber', function (e) {\n var $eventTarget = $(e.currentTarget);\n\n var message = \" \" + thisS.language.pending + \": \" + thisS.pending + \"
\" + thisS.language.completed + \": \" + (thisS.successfulUpload + thisS.aborted + thisS.abortedWithError) + \"
\" + thisS.language.inProgress + \": \" + thisS.inProgress;\n tooltip($eventTarget, message, thisS);\n });\n\n $uploadBox.on('click', '.ssi-removeBtn', function (e) { //remove the file from list\n e.preventDefault();\n var $currentTarget = $(e.currentTarget);\n var index = $currentTarget.data('delete'); //get file's index\n thisS.pending--; //reduce pending number by 1\n thisS.currentListLength--; //reduce current list length by 1\n if (thisS.pending < 1) {\n thisS.$element.find('#ssi-fileNumber').addClass('ssi-hidden');\n }\n if (thisS.pending === 0) {\n $uploadBtn.prop('disabled', true); //if there is no more files disable upload button\n }\n if (thisS.options.preview) { //if preview is true\n $currentTarget.parents('table.ssi-imgToUploadTable').remove(); //remove table\n } else {\n var target = $currentTarget.parents('tr.ssi-toUploadTr'); //find the tr of file\n $namePreview.html((thisS.currentListLength) + ' files'); //set the main name to the remaining files\n target.prev().remove();// remove empty tr (using id for margin between rows)\n target.remove();// remove the file\n if (thisS.currentListLength === 1) { //if only one file left in the list\n setLastElementName(thisS); //set main preview to display the name\n }\n }\n thisS.toUpload[index] = null; //set the file's obj to null (we don't splice it because we need to keep the same indexes)\n thisS.imgNames[index] = null; //set the file's name to null\n\n if (thisS.currentListLength === 0) { // if no more files in the list\n if (!thisS.options.dropZone) { // if drag and drop is disabled\n $uploadBox.removeClass('ssi-uploadNoDropZone');\n }\n $clearBtn.addClass('ssi-hidden');\n $uploadBtn.addClass('ssi-hidden');\n }\n });\n $uploadBox.on('click', '.ssi-abortUpload', function (e) {//abort one element\n e.preventDefault();\n var $eventTarget = $(e.currentTarget);\n var index = $eventTarget.data('delete');// get the element id\n thisS.abort(index); // abort request\n });\n //----------------------------UPLOADFILES------------------------------------\n $uploadBtn.click(function (e) {// upload the files\n e.preventDefault();\n thisS.uploadFiles();\n });\n $abortBtn.click(function (e) { // abort all requests\n e.preventDefault();\n thisS.abortAll();\n });\n\n };\n function tooltip($target, text, thisS) {\n $target = $($target);\n text = text || $target.data('title');\n if (!text) text = $target.attr('title');\n if (!text) return;\n var $toolTip = $('
'\n + text +\n '
').appendTo(thisS.$element);\n $target.one('mouseleave', function () {\n $toolTip.remove();\n });\n var offset = -16;\n if ($target.hasClass('ssi-noPreviewSubMessage')) {\n offset = 23;\n }\n $toolTip.css({\n top: $target.position().top - $toolTip.height() + offset,\n left: $target.position().left - $toolTip.width() / 2\n })\n .removeClass('ssi-fadeOut');\n return $toolTip;\n }\n\n Ssi_upload.prototype.abortAll = function () {\n for (var i = 0; i < this.uploadList.length; i++) { //all element in the list\n if (typeof this.uploadList[i] === 'object') {// check if not deleted\n this.abort(i);\n }\n }\n };\n Ssi_upload.prototype.toUploadFiles = function (files) {\n if (typeof this.options.maxNumberOfFiles === 'number') {\n if ((this.inProgress + this.pending) >= this.options.maxNumberOfFiles) {// if in progress files + pending files are more than the number that we have define as max number of files pre download\n return;//don't do anything\n }\n }\n var thisS = this,\n j = 0,\n length,\n imgContent = '',\n $uploadBtn = this.$element.find('#ssi-uploadBtn'),\n $clearBtn = this.$element.find('#ssi-clearBtn'),\n $fileList = this.$element.find('#ssi-fileList'),\n $uploadBox = this.$element.find('.ssi-uploadBox'),\n imgs = [];\n if ((this.inProgress === 0 && this.pending === 0)) { //if no file are pending or are in progress\n this.clear(); //clear the list\n }\n var extErrors = [], sizeErrors = [], errorMessage = '';\n var toUploadLength, filesLength = length = toUploadLength = files.length;\n if (typeof this.options.maxNumberOfFiles === 'number') {//check if requested files agree with our arguments\n if (filesLength > this.options.maxNumberOfFiles - (this.inProgress + this.pending)) { //if requested files is more than we need\n filesLength = toUploadLength = this.options.maxNumberOfFiles - (this.inProgress + this.pending); // set variable to the number of files we need\n }\n }\n //\n for (var i = 0; i < filesLength; i++) {\n var file = files[i],\n ext = file.name.getExtension();// get file's extension\n\n if ($.inArray(ext, this.options.allowed) === -1) { // if requested file not allowed\n if (length > filesLength) {//there are more file we dont pick\n filesLength++;//the add 1 more loop\n } else {\n toUploadLength--;\n }\n if ($.inArray(ext, extErrors) === -1) {//if we see first time this extension\n extErrors.push(ext); //push it to extErrors variable\n }\n } else if ((file.size * Math.pow(10, -6)).toFixed(2) > this.options.maxFileSize) {//if file size is more than we ask\n if (length > filesLength) {\n filesLength++;\n } else {\n toUploadLength--;\n }\n sizeErrors.push(cutFileName(file.name, ext, 15));//register a size error\n } else if (this.options.allowDuplicates || $.inArray(file.name, this.imgNames) === -1) {// if the file is not already in the list\n $uploadBtn.prop(\"disabled\", false);\n setupReader(file);\n this.pending++; // we have one more file that is pending to be uploaded\n this.currentListLength++;// we have one more file in the list\n } else {\n if (length > filesLength) {\n filesLength++;\n } else {\n toUploadLength--;\n }\n }\n }\n var extErrorsLength = extErrors.length, sizeErrorsLength = sizeErrors.length;\n if (extErrorsLength + sizeErrorsLength > 0) { // in the end expose all errors\n if (extErrorsLength > 0) {\n errorMessage = this.language.extError.replaceText(extErrors.toString().replace(/,/g, ', '));\n }\n if (sizeErrorsLength > 0) {\n errorMessage += this.language.sizeError.replaceText(sizeErrors.toString().replace(/,/g, ', '), this.options.maxFileSize + 'mb');\n }\n this.options.errorHandler.method(errorMessage, this.options.errorHandler.error);\n }\n function setupReader() {\n var index = thisS.imgNames.length;\n if (index === 0) {//do it only the first time\n if (thisS.options.preview) {\n if (!thisS.options.dropZone) {\n $uploadBox.addClass('ssi-uploadNoDropZone')\n }\n }\n $uploadBtn.removeClass('ssi-hidden');\n $clearBtn.removeClass('ssi-hidden');\n }\n $clearBtn.prop('disabled', true);\n thisS.toUpload[index] = file;\n var filename = file.name;\n var ext = filename.getExtension(); //get file's extension\n thisS.imgNames[index] = filename; //register file's name\n if (thisS.options.preview) {\n var getTemplate = function (content) {\n return '' +\n '' +\n '' +\n '' +\n '
' + content + '
' + cutFileName(filename, ext, 15) + '
'\n };\n var fileType = file.type.split('/');\n if (fileType[0] == 'image') {\n $uploadBtn.prop(\"disabled\", true);\n $clearBtn.prop(\"disabled\", true);\n var fileReader = new FileReader();\n fileReader.onload = function () {\n imgContent += getTemplate(''); // set the files element without the img\n imgs[index] = fileReader.result;\n j++;\n if (toUploadLength === j) {// if all elements are in place lets load images\n thisS.$element.find('#ssi-fileNumber').removeClass('ssi-hidden');\n $uploadBox.append(imgContent);\n setTimeout(function () {\n setImg();//and load the images\n $uploadBtn.prop(\"disabled\", false);\n $clearBtn.prop(\"disabled\", false);\n }, 10);\n $uploadBtn.prop(\"disabled\", false);\n $clearBtn.prop(\"disabled\", false);\n\n imgContent = '';\n toUploadLength = [];\n } else if (toUploadLength / 2 == Math.round(j)) {\n $uploadBox.append(imgContent);\n setImg();//and load the images\n imgContent = '';\n }\n };\n fileReader.readAsDataURL(file);\n } else {\n imgs[index] = null;\n $uploadBox.append(getTemplate('
'));\n j++;\n }\n } else {\n $clearBtn.prop('disabled', false);\n thisS.$element.find('.ssi-namePreview').html((index === 0 ? cutFileName(filename, ext, 13) : (thisS.currentListLength + 1) + ' ' + thisS.language.files));//set name preview\n $fileList.append('' +//append files element to dom\n '
' +\n '' + cutFileName(filename, ext, 20) + '' +\n '');\n }\n\n var setImg = function () {//load the images\n for (var i = 0; i < imgs.length; i++) {\n if (imgs[i] !== null) {\n $uploadBox.find(\"#ssi-uploadProgress\" + i).parents('table.ssi-imgToUploadTable')\n .find('.ssi-imgToUpload')\n .attr('src', imgs[i]) //set src of the image\n .next().remove();//remove the spinner\n imgs[i] = null;\n }\n }\n imgs = [];\n };\n }\n };\n var clearCompleted = function (thisS) {//clear all completed files\n var $completed = thisS.$element.find('.ssi-completed');\n thisS.successfulUpload = 0;\n thisS.aborted = 0;\n thisS.abortedWithError = 0;\n if (!thisS.options.preview) $completed.prev('tr').remove();\n $completed.remove();\n };\n var clearPending = function (thisS) {//clear all pending files\n var $pending = thisS.$element.find('.ssi-pending');\n var length = thisS.imgNames.length;\n for (var i = 0; i < length; i++) {\n if (thisS.imgNames[i] === null) {\n thisS.toUpload.splice(i, 1);\n thisS.imgNames.splice(i, 1);\n }\n }\n thisS.toUpload.splice(-thisS.pending, thisS.pending);\n thisS.imgNames.splice(-thisS.pending, thisS.pending);\n thisS.pending = 0;\n if (!thisS.options.preview) $pending.prev('tr').remove();\n $pending.remove();\n };\n\n Ssi_upload.prototype.clear = function (action) {//clean the list of all non in progress files\n switch (action) {\n case 'pending':\n clearPending(this);\n break;\n case 'completed':\n clearCompleted(this);\n break;\n default:\n clearPending(this);\n clearCompleted(this);\n }\n var $uploadBtn = this.$element.find('#ssi-uploadBtn'),\n $clearBtn = this.$element.find('#ssi-clearBtn');\n this.currentListLength = getCurrentListLength(this);\n if (this.inProgress === 0) { //if no file are uploading right now\n this.totalProgress = [];\n }\n if ((this.currentListLength === 0)) { // if no items in the list\n $clearBtn.addClass('ssi-hidden');\n $uploadBtn.addClass('ssi-hidden');\n this.$element.find('#ssi-fileNumber').addClass('ssi-hidden');\n this.totalFilesLength = 0;\n if (!this.options.dropZone) {\n this.$element.find('.ssi-uploadBox').removeClass('ssi-uploadNoDropZone')\n }\n }\n $clearBtn.prop('disabled', true);\n $uploadBtn.prop('disabled', true);\n\n if (!this.options.preview) {\n setNamePreview(this);\n }\n };\n\n var setNamePreview = function (thisS) {//set the name preview according to the remaining elements in the list\n if (thisS.currentListLength > 1) {//if more than one element left\n thisS.$element.find('.ssi-namePreview').html(thisS.currentListLength + ' files'); // set the name preview to the length of the remaining items\n } else if (thisS.currentListLength === 1) {//if one left\n setLastElementName(thisS); // set the name of the element\n } else { //if no elements left\n thisS.$element.find('.ssi-uploadDetails').removeClass('ssi-uploadBoxOpened');\n thisS.$element.find('#ssi-fileList').empty();//empty list\n thisS.$element.find('.ssi-namePreview').empty();//empty the name preview\n }\n\n };\n\n Ssi_upload.prototype.appendFileToFormData = function (file) {\n var formData = new FormData();//set the form data\n\n formData.append(this.inputName, file);//append the first file to the form data\n $.each(this.options.data, function (key, value) {// append all extra data\n formData.append(key, value);\n });\n return formData;\n }\n\n\n Ssi_upload.prototype.tryToTransform = function (file, callback) {\n if (typeof this.options.transformFile === 'function') {\n try {\n file = this.options.transformFile(file);// execute the transformFile\n if (file instanceof Promise) {\n file.then(function (newFile) {\n callback(newFile)\n })\n } else {\n callback(file)\n }\n } catch (err) {\n if (!this.options.ignoreCallbackErrors) {\n console.error('There is an error in transformFile');\n return console.error(err);\n }\n }\n } else {\n callback(file)\n }\n }\n Ssi_upload.prototype.uploadFiles = function () {// upload the pending files\n if (this.pending > 0) {\n if (typeof this.options.beforeUpload === 'function') {\n try {\n this.options.beforeUpload();// execute the beforeUpload callback\n } catch (err) {\n if (!this.options.ignoreCallbackErrors) {\n console.log('There is an error in beforeUpload callback');\n return console.log(err);\n }\n }\n }\n this.$element.find('#ssi-abortBtn').removeClass('ssi-hidden');\n this.$element.find('.ssi-removeBtn')\n .addClass('ssi-abortUpload')\n .removeClass('ssi-removeBtn')\n .children('span').removeClass('trash7 trash10 trash')\n .addClass((this.options.preview ? 'ban7w' : 'ban7'));//transform remove button to abort button\n var $uploadBtn = this.$element.find('#ssi-uploadBtn'),\n $clearBtn = this.$element.find('#ssi-clearBtn');\n $uploadBtn.prop(\"disabled\", true);\n var thisS = this,\n i = this.totalFilesLength;\n if (this.totalFilesLength !== 0 && !this.options.preview) {\n setNamePreview(this);\n }\n this.inProgress += this.pending;// add pending to in progress\n this.totalFilesLength += this.pending;// this variable is to prevent id duplication during uploads\n this.pending = 0;\n if (this.inProgress === this.currentListLength) {// disable the clear button if no items in list we can be remove\n $clearBtn.prop(\"disabled\", true);\n }\n\n while (!thisS.toUpload[i]) { // do it until you find a file\n i++;\n }\n var file = thisS.toUpload[i]\n thisS.tryToTransform(file, function (newFile) {\n var formData = thisS.appendFileToFormData(newFile)\n ajaxLoopRequest(formData, i)\n })\n }\n //--------------start of ajax request-----------------------\n function ajaxLoopRequest(formData, ii) {\n var selector = 'table.ssi-imgToUploadTable';\n if (!thisS.options.preview) {\n selector = 'tr.ssi-toUploadTr'\n }\n var uploadBar = thisS.$element.find('#ssi-uploadProgress' + ii);//get the file's progress bar\n uploadBar.removeClass('ssi-hidden') //make it visible\n .parents(selector).removeClass('ssi-pending');\n var ajaxOptions = $.extend({}, {//store the request to the uploadList variable\n xhr: function () {\n var xhr = new window.XMLHttpRequest();\n xhr.upload.addEventListener('progress', function (e) {// add event listener to progress\n if (e.lengthComputable) {\n var percentComplete = (e.loaded / e.total) * 100;// calculate the progress\n if (uploadBar) {\n uploadBar.css({\n width: percentComplete + '%'//update the progress bar width according to the progress\n });\n }\n thisS.totalProgress[ii] = percentComplete;//store the progress to the array\n var sum = arraySum(thisS.totalProgress) / (thisS.inProgress + thisS.successfulUpload);//and calculate the overall progress\n if (!thisS.options.preview) {\n thisS.$element.find('#ssi-uploadProgressNoPreview')\n .removeClass('ssi-hidden')\n .css({\n width: sum + '%'\n });\n }\n $uploadBtn.find('#ssi-up_loading').html(Math.ceil(sum) + '%');// add to upload button the current overall progress percent number\n }\n }, false);\n return xhr;\n },\n async: true,\n beforeSend: function (xhr, settings) {\n thisS.uploadList[ii] = xhr;\n console.log(\"TCL: ajaxLoopRequest -> thisS.toUpload\", thisS.toUpload)\n console.log(\"TCL: ajaxLoopRequest -> ii\", ii)\n $uploadBtn.find('#ssi-up_loading') //add spiner to uploadbutton\n .html('');\n var fileInfo = {\n name: thisS.toUpload[ii].name,//send some info of the file\n type: thisS.toUpload[ii].type,\n size: (thisS.toUpload[ii].size / 1024).toFixed(2)\n };\n if (typeof thisS.options.beforeEachUpload === 'function') {\n try {\n // execute the beforeEachUpload callback and save the returned value\n var msg = thisS.options.beforeEachUpload(fileInfo, xhr, settings);\n } catch (err) {\n if (err.name == 'Error') {\n thisS.abort(ii, undefined, err.message);//call the abort function\n } else {\n if (!thisS.options.ignoreCallbackErrors) {\n console.log('There is an error in beforeEachUpload callback. Filename:' + thisS.toUpload[ii].name);\n console.log(err);\n thisS.abort(ii, undefined, thisS.language.wentWrong);//call the abort function\n }\n }\n return;\n }\n }\n thisS.$element.find('input.ssi-uploadInput').trigger('beforeEachUpload.ssi-uploader', [fileInfo]);\n if (xhr.status === 0) {\n if (xhr.statusText === 'canceled') {//if user used beforeEachUpload to abort the request\n if (typeof msg === 'undefined') {//if no message\n msg = false; //because user have already aborted the request set to false or anything else except undefined to prevent to abort it again\n }\n thisS.abortedWithError++;// we have one error more\n thisS.abort(ii, msg);//call the abort function\n }\n }\n },\n type: 'POST',\n method: 'POST',\n data: formData,\n cache: false,\n contentType: false,\n processData: false,\n url: thisS.options.url,\n error: function (request, error) {\n if (error !== 'abort') {\n uploadBar.addClass('ssi-canceledProgressBar');\n var msg = thisS.language.error;\n thisS.abortedWithError++;//add one more error\n thisS.totalProgress.splice(ii, 1); //remove from progress array\n if (!thisS.options.preview) {\n msg = '';\n }\n setElementMessage(thisS, ii, 'error', msg, thisS.language.serverError);\n thisS.totalProgress[ii] = '';\n thisS.inProgress--;\n $clearBtn.prop(\"disabled\", false);\n if (typeof thisS.options.onEachUpload === 'function') {//execute the onEachUpload callback\n try {\n thisS.options.onEachUpload({//and return some info\n uploadStatus: 'error',\n responseMsg: thisS.language.serverError,\n name: thisS.toUpload[ii].name,\n size: (thisS.toUpload[ii].size / 1024).toFixed(2),\n type: thisS.toUpload[ii].type\n });\n } catch (err) {\n if (!thisS.options.ignoreCallbackErrors) {\n console.log('There is an error in onEachUpload callback. File name:' + thisS.toUpload[ii].name);\n console.log(err);\n }\n }\n }\n if (getCompleteStatus(thisS)) {//if no more elements in progress\n finishUpload(thisS);\n }\n console.log(arguments);//log the error\n console.log(\" Ajax error: \" + error);\n }\n }\n }, thisS.options.ajaxOptions);\n $.ajax(ajaxOptions).done(function (responseData, textStatus, jqXHR) {\n var msg, title = '', dataType = 'error', spanClass = 'exclamation', data;\n try {\n data = $.parseJSON(responseData);\n } catch (err) {\n data = responseData;\n }\n if (thisS.options.responseValidation) {\n var valData = thisS.options.responseValidation;\n if (typeof valData.validationKey === 'object' && valData.resultKey == 'validationKey') {\n if (data.hasOwnProperty(valData.validationKey.success)) {\n cb(true, data[valData.validationKey.success]);\n } else {\n cb(false, data[valData.validationKey.error]);\n }\n } else {\n if (data[valData.validationKey] == valData.success) {\n cb(true, data[valData.resultKey]);\n } else {\n cb(false, data[valData.resultKey]);\n }\n }\n } else {\n if (jqXHR.status == 200) {\n cb(true, data);\n } else {\n cb(false, data);\n }\n }\n function cb(result, data) {\n if (result) {//if response type is success\n dataType = 'success';\n msg = thisS.language.success;\n spanClass = 'check';\n thisS.successfulUpload++;// one more successful upload\n } else {\n uploadBar.addClass('ssi-canceledProgressBar');\n if (thisS.options.preview) {\n msg = thisS.language.error;\n }\n thisS.abortedWithError++;\n }\n title = data;\n }\n\n if (!thisS.options.preview) {\n msg = '';\n }\n setElementMessage(thisS, ii, dataType, msg, title);\n var fileInfo = {//and return some info\n uploadStatus: dataType,\n responseMsg: title,\n name: thisS.toUpload[ii].name,\n size: (thisS.toUpload[ii].size / 1024).toFixed(2),\n type: thisS.toUpload[ii].type\n };\n if (typeof thisS.options.onEachUpload === 'function') {//execute the onEachUpload callback\n try {\n thisS.options.onEachUpload(fileInfo, data);\n } catch (err) {\n console.log('There is an error in onEachUpload callback');\n console.log(err);\n }\n }\n thisS.$element.find('input.ssi-uploadInput').trigger('onEachUpload.ssi-uploader', [fileInfo]);\n thisS.inProgress--;//one less in progress upload\n $clearBtn.prop(\"disabled\", false);\n if (getCompleteStatus(thisS)) {//if no more files in progress\n finishUpload(thisS);\n }\n // thisS.totalProgress[ii]='';\n thisS.uploadList[ii] = '';\n thisS.toUpload[ii] = '';\n thisS.imgNames[ii] = '';\n });\n //--------------end of ajax request-----------------------\n\n i = ii;\n i++;//go to the next element\n while (!thisS.toUpload[i] && typeof thisS.toUpload[i] !== 'undefined') {// do it until you find a file\n i++;\n }\n if (i < thisS.toUpload.length) {// if more files exist start the next request\n const nextFile = thisS.toUpload[i]\n thisS.tryToTransform(nextFile, function (newFile) {\n var formData = thisS.appendFileToFormData(newFile)\n ajaxLoopRequest(formData, i)\n })\n }\n }\n };\n var setElementMessage = function (thisS, index, msgType, msg, title) {\n var className = '', elementSelector = 'table.ssi-imgToUploadTable', element;\n if (!thisS.options.preview) {\n className = 'ssi-noPreviewSubMessage';\n elementSelector = 'tr.ssi-toUploadTr';\n if (thisS.currentListLength === 1) {\n thisS.errors = title;\n }\n }\n\n element = thisS.$element.find(\".ssi-abortUpload[data-delete='\" + index + \"']\");\n element.parents(elementSelector).addClass('ssi-completed');\n element.after(getResultMessage(msgType, msg, title, className))\n .remove();\n };\n\n var getCompleteStatus = function (thisS) {//check if file are in progress\n return (thisS.inProgress === 0);\n };\n\n var getResultMessage = function (type, msg, title, classes) {//return a message label\n return '' + msg + '';\n };\n\n var getCurrentListLength = function (thisS) { //get the list length\n return (thisS.inProgress + thisS.successfulUpload + thisS.aborted + thisS.abortedWithError + thisS.pending);\n };\n var setLastElementName = function (thisS) { //if one file in list get the last file's name and put it to the name preview\n var fileName = thisS.$element.find('#ssi-fileList').find('span').html();//find the only span left\n var ext = fileName.getExtension();//get the extension\n thisS.$element.find('.ssi-uploadDetails').removeClass('ssi-uploadBoxOpened');\n thisS.$element.find('.ssi-namePreview').html(cutFileName(fileName, ext, 15));//short the name and put it to the name preview\n };\n Ssi_upload.prototype.abort = function (index, title, mmsg) {//abort a request\n if (typeof title === 'undefined') {//if no title\n this.uploadList[index].abort();// abort the element\n this.totalProgress[index] = '';\n title = mmsg || 'Aborted';\n this.aborted++;// one more aborted file\n } else if (typeof title !== 'string') {//if not string that means that the request aborted with the beforeEachUpload callback and no message returned\n title = '';\n }\n //nothing of the above happened that means the user aborted the request with the beforeUpload callback and returned a message\n var msg = this.language.aborted;\n if (!this.options.preview) {\n msg = '';\n }\n setElementMessage(this, index, 'error', msg, (title));\n this.$element.find('#ssi-uploadProgress' + index).removeClass('ssi-hidden').addClass('ssi-canceledProgressBar');\n this.toUpload[index] = undefined;\n this.uploadList[index] = undefined;\n this.imgNames[index] = undefined;\n this.$element.find('#ssi-clearBtn').prop(\"disabled\", false);\n this.inProgress--;//one less in progress file\n if (getCompleteStatus(this)) {//if no more file in progress\n finishUpload(this);\n }\n\n };\n\n var finishUpload = function (thisS) {//when every uplaod ends\n thisS.$element.find('#ssi-abortBtn').addClass('ssi-hidden');\n if (!thisS.options.preview) {//display tha main message in the name preview\n var type = 'error', title = '', msg = '';\n if (thisS.abortedWithError > 0) { //if no errors\n if (thisS.totalFilesLength === 1) {// if only one file in the list\n title = thisS.errors; //display the error\n } else {//else display something more general message\n title = thisS.language.someErrorsOccurred\n }\n msg = '';\n } else if (thisS.aborted > 0 && thisS.successfulUpload === 0) {//if all request aborted\n msg = '';\n title = thisS.language.aborted;\n } else if (thisS.successfulUpload > 0) {// all request were successfull\n type = 'success';\n msg = '';\n title = thisS.language.sucUpload;\n }\n thisS.$element.find('.ssi-namePreview').append(getResultMessage(type, msg, title, 'ssi-noPreviewMessage'));//show the message in the name preview\n thisS.$element.find('#ssi-uploadProgressNoPreview') //remove main overall progress bar\n .removeAttr('styles')\n .addClass('ssi-hidden');\n }\n if (typeof thisS.options.onUpload === 'function') {\n try {\n thisS.options.onUpload(type);//execute the on Upload callback\n } catch (err) {\n if (!thisS.options.ignoreCallbackErrors) {\n console.log('There is an error in onUpload callback');\n console.log(err);\n }\n }\n }\n thisS.$element.find('input.ssi-uploadInput').trigger('onUpload.ssi-uploader', [type]);\n var $uploadBtn = thisS.$element.find('#ssi-uploadBtn');\n thisS.$element.find('#ssi-clearBtn').prop(\"disabled\", false);\n $uploadBtn.prop(\"disabled\", false)\n .find('#ssi-up_loading')\n .empty();\n if (thisS.pending === 0) {\n $uploadBtn.addClass('ssi-hidden');\n thisS.toUpload = [];\n thisS.imgNames = [];\n thisS.totalFilesLength = 0;\n }\n thisS.uploadList = [];\n thisS.totalProgress = [];\n thisS.currentListLength = getCurrentListLength(thisS);\n thisS.inProgress = 0;\n };\n\n $.fn.ssi_uploader = function (opts) {\n var defaults = {\n allowDuplicates: false,\n url: '',\n data: {},\n locale: 'en',\n preview: true,\n dropZone: true,\n maxNumberOfFiles: '',\n responseValidation: false,\n ignoreCallbackErrors: false,\n maxFileSize: 2,\n inForm: false,\n ajaxOptions: {},\n onUpload: function () {\n },\n onEachUpload: function () {\n },\n beforeUpload: function () {\n },\n beforeEachUpload: function () {\n },\n allowed: '',\n errorHandler: {\n method: function (msg) {\n alert(msg);\n },\n success: 'success',\n error: 'error'\n }\n };\n var options = $.extend(true, defaults, opts);\n options.allowed = options.allowed || ['jpg', 'jpeg', 'png', 'bmp', 'gif'];\n return this.each(function () {\n var $element = $(this);\n if ($element.is('input[type=\"file\"]')) {\n if ($element.data('ssi_upload')) return;\n var ssi_upload = new Ssi_upload(this, options);\n $element.data('ssi_upload', ssi_upload);\n } else {\n console.log('The targeted element is not file input.')\n }\n });\n };\n //functions\n String.prototype.replaceText = function () {//replace $ with variables\n var args = Array.apply(null, arguments);\n var text = this;\n for (var i = 0; i < args.length; i++) {\n text = text.replace('$' + (i + 1), args[i])\n }\n return text;\n };\n String.prototype.getExtension = function () {//returns the extension of a path or file\n return this.split('.').pop().toLowerCase();\n };\n var cutFileName = function (word, ext, maxLength) {//shorten the name\n if (typeof ext === 'undefined') ext = '';\n if (typeof maxLength === 'undefined') maxLength = 10;\n var min = 4;\n if (maxLength < min) return;\n var extLength = ext.length;\n var wordLength = word.length;\n if ((wordLength - 2) > maxLength) {\n word = word.substring(0, maxLength);\n var wl = word.length - extLength;\n word = word.substring(0, wl);\n return word + '...' + ext;\n } else return word;\n };\n\n var arraySum = function (arr) {//return the sum of an array\n var sum = 0;\n for (var i = 0; i < arr.length; i++) {\n if (typeof arr[i] === 'number')\n sum += arr[i];\n }\n return sum;\n };\n\n var locale = {\n en: {\n success: 'Success',\n sucUpload: 'Successful upload',\n chooseFiles: 'Choose files',\n uploadFailed: 'Upload failed',\n serverError: 'Internal server error',\n error: 'Error',\n abort: 'Abort',\n aborted: 'Aborted',\n files: 'files',\n upload: 'Upload',\n clear: 'Clear',\n drag: 'Drag n Drop',\n sizeError: '$1 exceed the size limit of $2',// $1=file name ,$2=max ie( example.jpg has has exceed the size limit of 2mb)\n extError: '$1 file types are not supported',//$1=file extension ie(exe files are not supported)\n someErrorsOccurred: 'Some errors occurred!',\n wentWrong: 'Something went wrong!',\n pending: 'Pending',\n completed: 'Completed',\n inProgress: 'In progress'\n },\n gr: {\n success: 'Επιτυχία',\n sucUpload: 'Επιτυχής μεταφόρτωση',\n chooseFiles: 'Επιλέξτε αρχεία',\n uploadFailed: 'Η μεταφόρτωση απέτυχε!',\n serverError: 'Εσωτερικό σφάλμα διακομιστή!',\n error: 'Σφάλμα',\n abort: 'Διακοπή',\n aborted: 'Διακόπηκε',\n files: 'αρχεία',\n upload: 'Μεταφόρτωση',\n clear: 'Εκκαθάριση',\n drag: 'Συρετε εδώ...',\n sizeError: '$1 έχει ξεπεράσει το όριο των $2.',// $1=file name ,$2=max file size ie( example.jpg has has exceed the size limit of 2mb)\n extError: '$1 αρχεία δεν υποστηρίζονται.',// $1=file extension ie(exe files are not supported)\n someErrorsOccurred: 'Σημειώθηκαν ορισμένα λάθη!',\n wentWrong: 'Κάτι πήγε στραβά!',\n pending: 'Σε εκκρεμότητα',\n completed: 'Ολοκληρομένα',\n inProgress: 'Σε εξέλιξη'\n },\n fr: { //@author Badulesia\n success: 'Succès',\n sucUpload: 'Envoi réussi',\n chooseFiles: 'Choisissez fichiers',\n uploadFailed: 'Envoi échoué',\n serverError: 'Erreur interne du serveur',\n error: 'Erreur',\n abort: 'Annuler',\n aborted: 'Annulé',\n files: 'Fichiers',\n upload: 'Envoyer',\n clear: 'Effacer',\n drag: 'Glisser déposer',\n sizeError: '$1 excède la taille limite de $2',// $1=file name ,$2=max ie( example.jpg has has exceed the size limit of 2mb)\n extError: 'Types de fichier $1 non autorisé',//$1=file extension ie(exe files are not supported)\n someErrorsOccurred: 'Une erreur a eu lieu !',\n wentWrong: 'Une erreur a eu lieu !',\n pending: 'Εn attendant',\n completed: 'Terminé',\n inProgress: 'En cours'\n },\n zh_CN: {\n success: '上传成功',\n sucUpload: '上传成功',\n chooseFiles: '选择文件',\n uploadFailed: '上传失败',\n serverError: '服务器内部错误',\n error: '错误',\n abort: '中止',\n aborted: '已中止',\n files: '文件',\n upload: '上传',\n clear: '清空',\n drag: '将图片拖拽至此并释放',\n sizeError: '$1 超出了 $2 的大小限制',\n extError: '$1 类型不被支持',\n someErrorsOccurred: '发生了一些错误!',\n wentWrong: '出问题了哦!',\n pending: '等待上传',\n completed: '完成',\n inProgress: '正在上传'\n }\n };\n\n}));"],"file":"ssi-uploader.min.js"} \ No newline at end of file diff --git a/package.json b/package.json index 13eefe3..c740fd4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ssi-uploader", - "version": "1.4.0", + "version": "1.4.1", "main": "dist/ssi-uploader/js/ssi-uploader.js", "description": "An awesome jquery uploader", "scripts": { diff --git a/src/ssi-uploader/js/ssi-uploader.js b/src/ssi-uploader/js/ssi-uploader.js index 70de87a..922e95c 100644 --- a/src/ssi-uploader/js/ssi-uploader.js +++ b/src/ssi-uploader/js/ssi-uploader.js @@ -419,12 +419,37 @@ }; - Ssi_upload.prototype.appendFileToFormData = function (formData, file) { + Ssi_upload.prototype.appendFileToFormData = function (file) { + var formData = new FormData();//set the form data + formData.append(this.inputName, file);//append the first file to the form data $.each(this.options.data, function (key, value) {// append all extra data formData.append(key, value); }); - this.$element.find('input.ssi-uploadInput').trigger('beforeUpload.ssi-uploader'); + return formData; + } + + + Ssi_upload.prototype.tryToTransform = function (file, callback) { + if (typeof this.options.transformFile === 'function') { + try { + file = this.options.transformFile(file);// execute the transformFile + if (file instanceof Promise) { + file.then(function (newFile) { + callback(newFile) + }) + } else { + callback(file) + } + } catch (err) { + if (!this.options.ignoreCallbackErrors) { + console.error('There is an error in transformFile'); + return console.error(err); + } + } + } else { + callback(file) + } } Ssi_upload.prototype.uploadFiles = function () {// upload the pending files if (this.pending > 0) { @@ -448,7 +473,6 @@ $clearBtn = this.$element.find('#ssi-clearBtn'); $uploadBtn.prop("disabled", true); var thisS = this, - formData = new FormData(),//set the form data i = this.totalFilesLength; if (this.totalFilesLength !== 0 && !this.options.preview) { setNamePreview(this); @@ -460,34 +484,15 @@ $clearBtn.prop("disabled", true); } - while (thisS.toUpload[i] === null || thisS.toUpload[i] === '') { // do it until you find a file + while (!thisS.toUpload[i]) { // do it until you find a file i++; } var file = thisS.toUpload[i] - if (typeof this.options.transformFile === 'function') { - try { - file = this.options.transformFile(thisS.toUpload[i]);// execute the transformFile - if (file instanceof Promise) { - file.then(function (file) { - thisS.appendFileToFormData(formData, file) - ajaxLoopRequest(formData, i) - }) - } else { - thisS.appendFileToFormData(formData, file) - ajaxLoopRequest(formData, i) - } - } catch (err) { - if (!this.options.ignoreCallbackErrors) { - console.error('There is an error in transformFile'); - return console.error(err); - } - } - } else { - thisS.appendFileToFormData(formData, file) + thisS.tryToTransform(file, function (newFile) { + var formData = thisS.appendFileToFormData(newFile) ajaxLoopRequest(formData, i) - } + }) } - //--------------start of ajax request----------------------- function ajaxLoopRequest(formData, ii) { var selector = 'table.ssi-imgToUploadTable'; @@ -525,6 +530,8 @@ async: true, beforeSend: function (xhr, settings) { thisS.uploadList[ii] = xhr; + console.log("TCL: ajaxLoopRequest -> thisS.toUpload", thisS.toUpload) + console.log("TCL: ajaxLoopRequest -> ii", ii) $uploadBtn.find('#ssi-up_loading') //add spiner to uploadbutton .html(''); var fileInfo = { @@ -561,6 +568,7 @@ } }, type: 'POST', + method: 'POST', data: formData, cache: false, contentType: false, @@ -682,16 +690,15 @@ i = ii; i++;//go to the next element - while (thisS.toUpload[i] === null || thisS.toUpload[i] === '') {// do it until you find a file + while (!thisS.toUpload[i] && typeof thisS.toUpload[i] !== 'undefined') {// do it until you find a file i++; } if (i < thisS.toUpload.length) {// if more files exist start the next request - formData = new FormData(); - $.each(thisS.options.data, function (key, value) { - formData.append(key, value); - }); - formData.append(thisS.inputName, thisS.toUpload[i]); - ajaxLoopRequest(formData, i); + const nextFile = thisS.toUpload[i] + thisS.tryToTransform(nextFile, function (newFile) { + var formData = thisS.appendFileToFormData(newFile) + ajaxLoopRequest(formData, i) + }) } } };