PageRenderTime 57ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/root/tpl/zaak_v1/nl_NL/js/jquery.fileUploader.js

https://bitbucket.org/dgieselaar/zaaksysteem
JavaScript | 716 lines | 462 code | 134 blank | 120 comment | 63 complexity | 9dd7814beaa7ecce610cb9e022ff7878 MD5 | raw file
  1. /*
  2. * Class: fileUploader
  3. * Use: Upload multiple files using jquery
  4. * Author: John Laniba (http://pixelcone.com)
  5. * Version: 1.3
  6. */
  7. (function($) {
  8. $.fileUploader = {version: '1.3', count: 0};
  9. $.fn.fileUploader = function(config){
  10. config = $.extend({}, {
  11. autoUpload: false,
  12. limit: false,
  13. buttonUpload: '#px-submit',
  14. buttonClear: '#px-clear',
  15. selectFileLabel: 'Select files',
  16. allowedExtension: 'jpg|jpeg|gif|png',
  17. timeInterval: [1, 2, 4, 2, 1, 5], //Mock percentage for iframe upload
  18. percentageInterval: [10, 20, 30, 40, 60, 80],
  19. //Callbacks
  20. onValidationError: null, //trigger if file is invalid
  21. onFileChange: function(){},
  22. onFileRemove: function(){},
  23. beforeUpload: function(){}, //trigger after the submit button is click: before upload
  24. beforeEachUpload: function(){}, //callback before each file has been uploaded ::: returns each Form
  25. afterUpload: function(){},
  26. afterEachUpload: function(){} //callback after each file has been uploaded
  27. }, config);
  28. $.fileUploader.count++;
  29. //Multiple instance of a FOrm Container
  30. var pxUploadForm = 'px-form-' + $.fileUploader.count,
  31. pxWidget = 'px-widget-' + $.fileUploader.count,
  32. pxButton = 'px-button-' + $.fileUploader.count,
  33. wrapper = ' \
  34. <div id="'+ pxWidget +'" class="px-widget ui-widget"> \
  35. <div class="ui-helper-clearfix"> \
  36. <div id="'+ pxUploadForm +'-input" class="px-form-input"></div> \
  37. <div id="'+ pxButton +'" class="px-buttons"></div> \
  38. </div> \
  39. <div id="'+ pxUploadForm +'"></div> \
  40. </div> \
  41. ',
  42. pxUploadForm = '#' + pxUploadForm,
  43. pxUploadFormInput = pxUploadForm + '-input',
  44. pxButton = '#' + pxButton,
  45. pxWidget = '#' + pxWidget,
  46. buttonClearId = null,
  47. itr = 1, //index/itr of file
  48. isLimit = (config.limit)? true : false,
  49. limit = parseInt(config.limit),
  50. e = this, //set e as this
  51. selector = $(this).selector,
  52. buttonM = pxButton + ' input, '+ pxButton +' button'; //Accept button as input and as button
  53. isFile = false, //this is use to hide other inputs in a form
  54. progress = 0, //percentage of the upload,
  55. totalForm = 0,
  56. jqxhr = null, //return object from jquery.ajax,
  57. timeInterval = config.timeInterval,
  58. percentageInterval = config.percentageInterval,
  59. pcount = 0, //progress count to set interval,
  60. progressTime = null,
  61. stopUpload = false; //Stop all upload
  62. if (window.FormData) {
  63. var isHtml5 = true;
  64. } else {
  65. var isHtml5 = false;
  66. }
  67. //Wrap all function that is accessable within the plugin
  68. var px = {
  69. //Initialize and format data
  70. init: function(){
  71. px.form = $(e).parents('form');
  72. //prepend wrapper markup
  73. px.form.before(wrapper);
  74. //Wrap input button
  75. $(e).wrap('<div class="px-input-button" />');
  76. px.form.children('.px-input-button').prepend('<span>'+ config.selectFileLabel +'</span>');
  77. //move upload and clear button into id px_button
  78. px.form.find(config.buttonUpload + ',' + config.buttonClear).appendTo(pxButton);
  79. //Transform file input into ui button
  80. px.form.find('.px-input-button').button({
  81. icons: {
  82. primary: "ui-icon-circle-plus"
  83. }
  84. });
  85. $(config.buttonUpload, pxButton).button({
  86. icons: {
  87. primary: "ui-icon-arrowthickstop-1-n"
  88. }
  89. });
  90. $(config.buttonClear, pxButton).button({
  91. icons: {
  92. primary: "ui-icon-circle-close"
  93. }
  94. });
  95. //clear all form data
  96. px.clearFormData(px.form);
  97. px.form.hide();
  98. this.printForm();
  99. //Disable button
  100. $(buttonM).attr('disabled','disabled');
  101. },
  102. //Clone, format and append form
  103. printForm: function(){
  104. var formId = 'pxupload' + itr,
  105. iframeId = formId + '_frame';
  106. $('<iframe name="'+ iframeId +'"></iframe>').attr({
  107. id: iframeId,
  108. src: 'about:blank',
  109. style: 'display:none'
  110. }).prependTo(pxUploadFormInput);
  111. px.form.clone().attr({
  112. id: formId,
  113. target: iframeId
  114. }).prependTo(pxUploadFormInput).show();
  115. //Show only the file input
  116. px.showInputFile( '#'+formId );
  117. //This is not good but i left no choice because live function is not working on IE
  118. $(selector).change(function() {
  119. if (isHtml5) {
  120. html5Change(this);
  121. } else {
  122. uploadChange($(this));
  123. }
  124. });
  125. },
  126. //Show only the file input
  127. showInputFile: function(form) {
  128. $(pxUploadFormInput).find(form).children().each(function(){
  129. isFile = $(this).is(':file');
  130. if (!isFile && $(this).find(':file').length == 0) {
  131. $(this).hide();
  132. }
  133. });
  134. },
  135. //Hide file input and show other data
  136. hideInputFile: function($form) {
  137. $form.children().each(function(){
  138. isFile = $(this).is(':file');
  139. if (isFile || $(this).find(':file').length > 0) {
  140. $(this).hide();
  141. } else {
  142. $(this).show();
  143. }
  144. });
  145. },
  146. //Validate file
  147. getFileName: function(file) {
  148. if (file.indexOf('/') > -1){
  149. file = file.substring(file.lastIndexOf('/') + 1);
  150. } else if (file.indexOf('\\') > -1){
  151. file = file.substring(file.lastIndexOf('\\') + 1);
  152. }
  153. return file;
  154. },
  155. validateFileName: function(filename) {
  156. var extensions = new RegExp(config.allowedExtension + '$', 'i');
  157. if (extensions.test(filename)){
  158. return filename;
  159. } else {
  160. return -1;
  161. }
  162. },
  163. getFileSize: function(file) {
  164. var fileSize = 0;
  165. if (file.size > 1024 * 1024) {
  166. fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
  167. } else {
  168. fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';
  169. }
  170. return fileSize;
  171. },
  172. //clear form data
  173. clearFormData: function(form) {
  174. $(form).find(':input').each(function() {
  175. if (this.type == 'file') {
  176. $(this).val('');
  177. }
  178. });
  179. }
  180. }
  181. //initialize
  182. px.init();
  183. /*
  184. * Plugin Events/Method
  185. */
  186. /*
  187. * Html5 file change
  188. */
  189. function html5Change($this) {
  190. $.each( $this.files, function(index, file){
  191. uploadChange(file);
  192. });
  193. afterUploadChange();
  194. }
  195. /*
  196. * Html5 Drag and Drop
  197. */
  198. $.event.props.push('dataTransfer');
  199. $(pxWidget).bind( 'dragenter dragover', false)
  200. .bind( 'drop', function( e ) {
  201. e.stopPropagation();
  202. e.preventDefault();
  203. html5Change(e.dataTransfer);
  204. });
  205. /*
  206. * On Change of upload file
  207. */
  208. function uploadChange($this) {
  209. var $form = $(pxUploadFormInput + ' #pxupload'+ itr);
  210. //validate file
  211. var filename = (isHtml5)? $this.name : px.getFileName( $this.val() );
  212. if ( px.validateFileName(filename) == -1 ){
  213. if ($.isFunction(config.onValidationError)) {
  214. config.onValidationError($this);
  215. } else {
  216. alert ('Invalid file!');
  217. }
  218. $form.find(':file').val('');
  219. return false;
  220. }
  221. //Limit
  222. if (limit <= 0) {
  223. //Your message about exceeding limit
  224. return false;
  225. }
  226. limit = limit - 1;
  227. //remove disabled attr
  228. $(buttonM).removeAttr('disabled');
  229. //remove upload text after uploaded
  230. $('.upload-data', pxUploadForm).each(function() {
  231. if ( $(this).find('form').length <= 0 ) {
  232. $(this).remove();
  233. }
  234. });
  235. //append size of the file after filename
  236. if (isHtml5) {
  237. filename += ' (' + px.getFileSize($this) + ')';
  238. }
  239. //DIsplay syled markup
  240. $(pxUploadForm).append(
  241. $('<div>').attr({
  242. 'class': 'upload-data pending ui-widget-content ui-corner-all',
  243. id: 'pxupload'+ itr +'_text'
  244. })
  245. .data('formId', 'pxupload'+ itr)
  246. .append(' \
  247. <ul class="actions ui-helper-clearfix"> \
  248. <li title="Upload" class="upload ui-state-default ui-corner-all"> \
  249. <span class="ui-icon ui-icon-circle-triangle-e"></span> \
  250. </li> \
  251. <li title="Delete" class="delete ui-state-default ui-corner-all"> \
  252. <span class="ui-icon ui-icon-circle-minus"></span> \
  253. </li> \
  254. </ul> \
  255. <span class="filename">'+ filename +'</span> \
  256. <div class="progress ui-helper-clearfix"> \
  257. <div class="progressBar" id="progressBar_'+ itr +'"></div> \
  258. <div class="percentage">0%</div> \
  259. </div> \
  260. <div class="status">Pending...</div> \
  261. ')
  262. );
  263. //Store input in form
  264. $form.data('input', $this);
  265. $form.appendTo(pxUploadForm + ' #pxupload'+ itr +'_text');
  266. //hide the input file
  267. px.hideInputFile( $form );
  268. //increment for printing form
  269. itr++;
  270. //print form
  271. px.printForm();
  272. //Callback on file Changed
  273. config.onFileChange($this, $form);
  274. if (!isHtml5) {
  275. afterUploadChange();
  276. }
  277. }
  278. /*
  279. * After upload change triggers autoupload
  280. */
  281. function afterUploadChange() {
  282. if (config.autoUpload) {
  283. //Display Cancel Button
  284. toogleCancel(true)
  285. stopUpload = false;
  286. //Queue and process upload
  287. uploadQueue();
  288. }
  289. }
  290. /*
  291. * Queue Upload and send each form to process upload
  292. */
  293. function uploadQueue() {
  294. //stop all upload
  295. if (stopUpload) {
  296. return;
  297. }
  298. totalForm = $(pxUploadForm + ' form').parent('.upload-data').get().length;
  299. if (totalForm > 0) {
  300. pendingUpload = $(pxUploadForm + ' form').parent('.upload-data').get(0);
  301. $form = $(pendingUpload).children('form');
  302. //before upload
  303. beforeEachUpload( $form );
  304. if (isHtml5) {
  305. //Upload Using Html5 api
  306. html5Upload( $form );
  307. } else {
  308. //upload using iframe
  309. iframeUpload( $form );
  310. }
  311. } else {
  312. config.afterUpload(pxUploadForm);
  313. //Revert Button to clear
  314. toogleCancel(false);
  315. }
  316. }
  317. /*
  318. * Process form Upload
  319. */
  320. function html5Upload($form) {
  321. file = $form.data('input');
  322. if (file) {
  323. var fd = new FormData();
  324. fd.append($form.find(selector).attr('name'), file);
  325. //get other form input and append to formData
  326. $form.find(':input').each(function() {
  327. if (this.type != 'file') {
  328. fd.append($(this).attr('name'), $(this).val());
  329. }
  330. });
  331. //show progress bar
  332. $uploadData = $form.parent();
  333. $uploadData.find('.progress').show();
  334. $progressBar = $uploadData.find('.progressBar');
  335. $percentage = $uploadData.find('.percentage');
  336. //Upload using jQuery AJAX
  337. jqxhr = $.ajax({
  338. url: $form.attr('action'),
  339. data: fd,
  340. cache: false,
  341. contentType: false,
  342. processData: false,
  343. type: 'POST',
  344. xhr: function() {
  345. var req = $.ajaxSettings.xhr();
  346. if (req) {
  347. req.upload.addEventListener('progress',function(ev){
  348. //Display progress Percentage
  349. progress = Math.round(ev.loaded * 100 / ev.total);
  350. $percentage.text(progress.toString() + '%');
  351. $progressBar.progressbar({
  352. value: progress
  353. });
  354. }, false);
  355. }
  356. return req;
  357. }
  358. })
  359. .success(function(data) {
  360. afterEachUpload($form.attr('id'), data );
  361. })
  362. .error(function(jqXHR, textStatus, errorThrown) {
  363. afterEachUpload($form.attr('id'), null, textStatus, errorThrown );
  364. })
  365. .complete(function(jqXHR, textStatus) {
  366. $progressBar.progressbar({
  367. value: 100
  368. });
  369. $percentage.text('100%');
  370. uploadQueue();
  371. });
  372. }
  373. $form.remove();
  374. }
  375. /*
  376. * Iframe Upload Process
  377. */
  378. function iframeUpload($form) {
  379. //show progress bar
  380. $uploadData = $form.parent();
  381. $uploadData.find('.progress').show();
  382. $percentage = $uploadData.find('.percentage');
  383. $progressBar = $uploadData.find('.progressBar');
  384. pcount = 0;
  385. dummyProgress($progressBar, $percentage);
  386. $form.submit();
  387. var id = pxWidget + ' #' + $form.attr('id');
  388. $(id +'_frame').load(function(){
  389. data = $(this).contents().find('body').html();
  390. afterEachUpload($form.attr('id'), data);
  391. clearTimeout ( progressTime );
  392. progress = 100;
  393. $percentage.text(progress.toString() + '%');
  394. $progressBar.progressbar({
  395. value: progress
  396. });
  397. uploadQueue();
  398. });
  399. }
  400. /*
  401. * Show the progress bar to the user
  402. */
  403. function dummyProgress($progressBar, $percentage) {
  404. if (percentageInterval[pcount]) {
  405. progress = percentageInterval[pcount] + Math.floor( Math.random() * 5 + 1 );
  406. $percentage.text(progress.toString() + '%');
  407. $progressBar.progressbar({
  408. value: progress
  409. });
  410. }
  411. if (timeInterval[pcount]) {
  412. progressTime = setTimeout(function(){
  413. dummyProgress($progressBar, $percentage)
  414. }, timeInterval[pcount] * 1000);
  415. }
  416. pcount++;
  417. }
  418. /*
  419. * before Upload
  420. */
  421. function beforeAllUpload() {
  422. //trigger before upload callback
  423. $continue = config.beforeUpload(e, pxButton);
  424. if ($continue === false) {
  425. return false;
  426. }
  427. //Show Cancle Button
  428. toogleCancel(true);
  429. //process and queue upload
  430. uploadQueue();
  431. }
  432. /*
  433. * Before Each file is uploaded
  434. */
  435. function beforeEachUpload($form) {
  436. //trigger before upload callback
  437. config.beforeEachUpload($form);
  438. $uploadData = $form.parent();
  439. $uploadData.find('.status').text('Uploading...');
  440. $uploadData.removeClass('pending').addClass('uploading');
  441. $uploadData.find('.delete').removeClass('delete').addClass('cancel').attr('title', 'Cancel');
  442. }
  443. /*
  444. * After Each file is uploaded
  445. */
  446. function afterEachUpload(formId, data, status, errorThrown) {
  447. if (data) {
  448. data = $('<div>').append(data);
  449. status = $(data).find('#status').text();
  450. }
  451. formId = pxWidget + ' #' + formId;
  452. $uploadData = $(formId + '_text');
  453. if (status == 'success'){
  454. $uploadData.removeClass('uploading').addClass('success');
  455. $uploadData.children('.status').html( $(data).find('#message').text() );
  456. } else if (status == 'error'){
  457. $uploadData.removeClass('uploading').addClass('error');
  458. //if client side error other display error from backend
  459. if (errorThrown) {
  460. $uploadData.children('.status').html( errorThrown );
  461. } else {
  462. $uploadData.children('.status').html( $(data).find('#message').text() );
  463. }
  464. } else if (status == 'abort') {
  465. $uploadData.removeClass('uploading').addClass('cancel');
  466. $uploadData.children('.status').html( 'Cancelled' );
  467. }
  468. $uploadData.find('.cancel').removeClass('cancel').addClass('delete').attr('title', 'Delete');
  469. //hide progress bar
  470. $uploadData.find('.progress').hide();
  471. //trigger after each upload
  472. config.afterEachUpload(data, status, $uploadData);
  473. $(formId).remove();
  474. $(formId + '_frame').remove();
  475. }
  476. /*
  477. * Toggle Cancel/Delete button
  478. */
  479. function toogleCancel(cancel) {
  480. if (cancel) {
  481. //store button clear id
  482. buttonClearId = $(config.buttonClear, pxButton).attr('id');
  483. //Cancel Button
  484. $(config.buttonClear, pxButton).attr({ id: 'px-cancel', title: 'Cancel' });
  485. } else {
  486. //Clear button
  487. $('#px-cancel', pxButton).attr({ id: buttonClearId, title: 'Clear' });
  488. }
  489. }
  490. /*
  491. * Onlick submit button: start upload
  492. */
  493. $(config.buttonUpload, pxButton).click(function(){
  494. stopUpload = false;
  495. beforeAllUpload();
  496. });
  497. /*
  498. * Individual Upload
  499. */
  500. $('.upload', pxUploadForm).live('click', function(){
  501. $form = $(this).parents('.upload-data').children('form');
  502. if ($form.length > 0) {
  503. //Show Cancle Button
  504. toogleCancel(true);
  505. //before upload
  506. beforeEachUpload( $form );
  507. if (isHtml5) {
  508. //Upload Using Html5 api
  509. html5Upload( $form );
  510. } else {
  511. //upload using iframe
  512. iframeUpload( $form );
  513. }
  514. stopUpload = true;
  515. }
  516. });
  517. //Button Clear Event
  518. $(config.buttonClear, pxButton).live('click', function(){
  519. $(pxUploadForm).fadeOut('slow',function(){
  520. $(this).empty();
  521. $(this).show();
  522. $(pxUploadFormInput).empty();
  523. itr = 1; //reset iteration
  524. limit = parseInt(config.limit);
  525. //print the First form
  526. px.printForm();
  527. //disable button
  528. $(buttonM).attr('disabled','disabled');
  529. });
  530. });
  531. $('.delete', pxUploadForm).live('click', function(){
  532. limit++;
  533. var id = pxWidget + ' #' + $(this).parents('.upload-data').data('formId');
  534. $(id+'_text').fadeOut('slow',function(){
  535. $(id+'_frame').remove();
  536. $(this).remove();
  537. //disable button
  538. if ($(pxUploadForm).find('form').length <= 1) {
  539. $(buttonM).attr('disabled','disabled');
  540. }
  541. });
  542. //on file remove callback
  543. config.onFileRemove(this);
  544. });
  545. /*
  546. * Cancel individual upload
  547. */
  548. $('.cancel', pxUploadForm).live('click', function() {
  549. if (jqxhr) {
  550. jqxhr.abort();
  551. }
  552. if (!isHtml5) {
  553. $form = $(this).parents('.upload-data').children('form');
  554. $form.remove();
  555. afterEachUpload($form.attr('id'), null, 'abort', 'Cancelled');
  556. }
  557. });
  558. /*
  559. * Cancel all uploads
  560. */
  561. $('#px-cancel', pxButton).live('click', function(){
  562. stopUpload = true;
  563. if (jqxhr) {
  564. jqxhr.abort();
  565. }
  566. $('form', pxUploadForm).each(function(){
  567. afterEachUpload($(this).attr('id'), null, 'abort', 'Cancelled');
  568. });
  569. //Show Clear Button
  570. toogleCancel(false);
  571. });
  572. /* Icons hover */
  573. $(".px-widget .actions li").live("mouseover mouseout", function(event) {
  574. if ( event.type == "mouseover" ) {
  575. $(this).addClass('ui-state-hover');
  576. } else {
  577. $(this).removeClass("ui-state-hover");
  578. }
  579. });
  580. return this;
  581. }
  582. })(jQuery);