/** * CodeDropz Uploader v1.3.7.7 * Copyright 2018 Glen Mongaya * CodeDrop Drag&Drop Uploader * @version 1.3.7.7 * @author CodeDropz, Glen Don L. Mongaya * @license The MIT License (MIT) */ // CodeDropz Drag and Drop Plugin (function() { const CodeDropz_Uploader = function( settings ){ // Generate & check nonce const form = document.querySelector('form.wpcf7-form'); if( form ) { const data = new FormData(); data.append('action', '_wpcf7_check_nonce'); data.append('_ajax_nonce', dnd_cf7_uploader.ajax_nonce ); fetch(dnd_cf7_uploader.ajax_url, { method: 'POST', body: data }) .then(res => res.json()) .then(({ data, success }) => success && (dnd_cf7_uploader.ajax_nonce = data)) .catch(console.error) } // Parent input file type var input = this; // Define default options const defaultOptions = { handler: input, color: '#000', background: '', server_max_error: 'Uploaded file exceeds the maximum upload size of your server.', max_file: input.dataset.max ? input.dataset.max : 10, // default 10 max_upload_size: input.dataset.limit ? input.dataset.limit : '10485760', // should be a bytes it's (5MB) supported_type: input.dataset.type ? input.dataset.type : 'jpg|jpeg|JPG|png|gif|pdf|doc|docx|ppt|pptx|odt|avi|ogg|m4a|mov|mp3|mp4|mpg|wav|wmv|xls', text: 'Drag & Drop Files Here', separator: 'or', button_text: 'Browse Files', on_success: '', }; // Merge options with default options const options = Object.assign({}, defaultOptions, settings); // Get storage name var dataStorageName = input.dataset.name + '_count_files'; // File Counter localStorage.setItem( dataStorageName, 1); // Template Container const cdropz_template = `
<${dnd_cf7_uploader.drag_n_drop_upload.tag}>${options.text} ${options.separator}
0 ${dnd_cf7_uploader.dnd_text_counter} ${parseInt(options.max_file)}
`; // Wrap input fields const wrapper = document.createElement('div'); // Begin to wrap upload fields wrapper.classList.add('codedropz-upload-wrapper'); options.handler.parentNode.insertBefore(wrapper, options.handler); wrapper.appendChild(options.handler); // Remove special character options.supported_type = options.supported_type.replace(/[^a-zA-Z0-9| ]/g, ""); // Element Handler const form_handler = options.handler.closest('form'); const options_handler = options.handler.closest('.codedropz-upload-wrapper'); const btnOBJ = form_handler.querySelector('input[type="submit"], button[type="submit"]'); // Append Format options.handler.insertAdjacentHTML('afterend', cdropz_template); // preventing the unwanted behaviours ['drag', 'dragstart', 'dragend', 'dragover', 'dragenter', 'dragleave', 'drop'].forEach(function(eventName) { options_handler.querySelector('.codedropz-upload-handler').addEventListener(eventName, function(e) { e.preventDefault(); e.stopPropagation(); }); }); // dragover and dragenter - add class ['dragover', 'dragenter'].forEach(function(eventName) { options_handler.querySelector('.codedropz-upload-handler').addEventListener(eventName, function(e) { options_handler.querySelector('.codedropz-upload-handler').classList.add('codedropz-dragover'); }); }); // dragleave dragend drop - remove class ['dragleave', 'dragend', 'drop'].forEach(function(eventName){ options_handler.querySelector('.codedropz-upload-handler').addEventListener(eventName, function(e) { options_handler.querySelector('.codedropz-upload-handler').classList.remove('codedropz-dragover'); }); }); // Browse button clicked options_handler.querySelector('.cd-upload-btn').addEventListener('click', function(e){ // stops the default action of an element from happening e.preventDefault(); // Reset value options.handler.value = null; // Click input type[file] element options.handler.click(); }); // when dropping files options_handler.querySelector('.codedropz-upload-handler').addEventListener('drop', function(event) { // Run the uploader DND_Setup_Uploader(event.dataTransfer.files, 'drop'); }); // Trigger when input type[file] is click/changed options.handler.addEventListener('change', function(e) { // Run the uploader DND_Setup_Uploader(this.files, 'click'); }); // Remove accept attribute on mobile devices if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) { input.removeAttribute('accept'); } // Setup Uploader var DND_Setup_Uploader = function( files, action ) { // make sure we have files if (files.length == 0 ) return; // gathering the form data var formData = new FormData(); // Append file //formData.append('supported_type', options.supported_type ); @note : removed due Vulnerability //formData.append('size_limit', options.max_upload_size ); formData.append('action', 'dnd_codedropz_upload' ); formData.append('type', action ); formData.append('security', dnd_cf7_uploader.ajax_nonce ); // CF7 - upload field name & cf7 id formData.append('form_id', input.dataset.id); formData.append('upload_name', input.dataset.name); // black list file types /*if( input.hasAttribute('data-black-list') ){ formData.append('blacklist-types', input.dataset.blackList); }*/ // remove has error const errorHandler = options.handler.querySelector('.has-error'); if (errorHandler) { errorHandler.remove(); } // Loop files for (const file of files) { // Reset upload file type if( typeof formData.delete !== 'undefined' ) { formData.delete('upload-file'); } // Limit file upload if( Number( localStorage.getItem(dataStorageName) ) > options.max_file ) { var hasErrorMsg = options_handler.querySelector('span.has-error-msg'); if (!hasErrorMsg) { var err_msg = dnd_cf7_uploader.drag_n_drop_upload.max_file_limit; var errorMsgEl = document.createElement('span'); errorMsgEl.className = 'has-error-msg'; errorMsgEl.textContent = err_msg.replace('%count%', options.max_file); options_handler.appendChild(errorMsgEl); } return false; } // Create progress bar const progressBarID = CodeDropz_Object.createProgressBar( file ); var has_error = false; // File size limit - validation if (file.size > options.max_upload_size) { const parentProgressBar = document.getElementById(progressBarID); const errorSpan = document.createElement('span'); errorSpan.classList.add('has-error'); errorSpan.textContent = dnd_cf7_uploader.drag_n_drop_upload.large_file; parentProgressBar.querySelector('.dnd-upload-details').appendChild(errorSpan); has_error = true; } // Validate file type regex_type = new RegExp("(.*?)\.("+ options.supported_type +")$"); if ( has_error === false && !( regex_type.test( file.name.toLowerCase() ) ) ) { document.querySelector('#' + progressBarID + ' .dnd-upload-details').insertAdjacentHTML('beforeend', '' + dnd_cf7_uploader.drag_n_drop_upload.inavalid_type + ''); has_error = true; } // Increment count localStorage.setItem( dataStorageName, ( Number( localStorage.getItem( dataStorageName ) ) + 1 ) ); // Make sure there's no error if( has_error === false ) { // Append file formData.append('upload-file', file ); // Process ajax upload var xhr = new XMLHttpRequest(); // Get progress bar element var progressBar = document.getElementById( progressBarID ); var progressElement = progressBar.querySelector('.dnd-progress-bar'); var detailsElement = progressBar.querySelector('.dnd-upload-details'); var submitButton = form_handler.querySelector('input[type="submit"], button[type="submit"]'); xhr.open(form_handler.getAttribute('method'), options.ajax_url); xhr.onreadystatechange = function() { if (this.readyState === 4) { if (this.status === 200) { var response = JSON.parse(this.responseText); if (response.success) { // Complete the progress bar CodeDropz_Object.setProgressBar(progressBarID, 100); // Callback on success if (typeof options.on_success === "function") { options.on_success.call(this, input, progressBarID, response); } } else { progressElement.remove(); detailsElement.insertAdjacentHTML('beforeend', ''+ response.data +''); if( submitButton ){ submitButton.classList.remove('disabled'); submitButton.removeAttribute('disabled'); } progressBar.classList.remove('in-progress'); } } else { progressElement.remove(); detailsElement.insertAdjacentHTML('beforeend', ''+ options.server_max_error +''); if( submitButton ){ submitButton.classList.remove('disabled'); submitButton.removeAttribute('disabled'); } progressBar.classList.remove('in-progress'); } } }; xhr.upload.addEventListener("progress", function(event){ if ( event.lengthComputable ) { var percentComplete = ( event.loaded / event.total ); var percentage = parseInt( percentComplete * 100 ); // Make progress on the loading CodeDropz_Object.setProgressBar( progressBarID, percentage - 1 ); } }, false); xhr.send(formData); } } } // End of Uploader function // CodeDropz object and functions var CodeDropz_Object = { // Create progress bar createProgressBar : function( file ) { // Setup progress bar variable var upload_handler = options_handler.querySelector('.codedropz-upload-handler'); var generated_ID = 'dnd-file-' + Math.random().toString(36).substr(2, 9); // Setup progressbar elements var fileDetails = `
${file.name}(${CodeDropz_Object.bytesToSize(file.size)})
`; // Create new element and insert after upload_handler var statusElement = document.createElement('div'); statusElement.id = generated_ID; statusElement.className = 'dnd-upload-status'; statusElement.innerHTML = fileDetails; upload_handler.parentNode.insertBefore(statusElement, upload_handler.nextSibling); return generated_ID; }, // Process progressbar ( Animate progress ) setProgressBar : function( progressBarID, percent ) { const progressBar = document.getElementById( progressBarID ); const statusBar = progressBar.querySelector('.dnd-progress-bar'); //console.log(statusbar); if (statusBar) { // Disable submit button if( btnOBJ ){ CodeDropz_Object.disableBtn(btnOBJ); } // Compute Progress bar let progress_width = percent * statusBar.offsetWidth / 100; // Set status bar in-progress progressBar.classList.add('in-progress'); if (percent == 100) { statusBar.querySelector('span').style.width = '100%'; statusBar.querySelector('span').textContent = `${percent}% `; } else { statusBar.querySelector('span').style.width = progress_width + 'px'; statusBar.querySelector('span').textContent = `${percent}% `; } if (percent == 100) { progressBar.classList.add('complete'); progressBar.classList.remove('in-progress'); } } return false; }, // Size Conversion bytesToSize : function( bytes ) { if( bytes === 0 ) return '0'; kBytes = (bytes / 1024); fileSize = ( kBytes >= 1024 ? ( kBytes / 1024 ).toFixed(2) + 'MB' : kBytes.toFixed(2) + 'KB' ); return fileSize; }, // Disable button disableBtn : function( BtnOJB ) { if( BtnOJB ) { BtnOJB.classList.add('disable'); BtnOJB.disabled = true; } } }; } // end fn.function // Remove File document.addEventListener("click", function(e) { if( !e.target.classList.contains("dnd-icon-remove") ) return; e.preventDefault(); var _self = e.target, _dnd_status = _self.closest(".dnd-upload-status"), _parent_wrap = _self.closest(".codedropz-upload-wrapper"), removeStorageData = _self.parentElement.getAttribute("data-storage"), storageCount = Number(localStorage.getItem(removeStorageData)); // Direct remove the file if there's any error. if (_dnd_status.classList.contains("in-progress") || _dnd_status.querySelector(".has-error")) { _dnd_status.remove(); localStorage.setItem(removeStorageData, storageCount - 1); return false; } // Change text Status _self.classList.add("deleting"); _self.textContent = dnd_cf7_uploader.drag_n_drop_upload.delete.text + "..."; // Request ajax image delete var xhr = new XMLHttpRequest(); xhr.open("POST", dnd_cf7_uploader.ajax_url); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.onload = function() { if (this.status === 200) { var response = JSON.parse(this.responseText); if (response.success) { // Reduce file count and status bar element. _dnd_status.remove(); localStorage.setItem(removeStorageData, storageCount - 1); // Remove error msg if ( _parent_wrap.querySelectorAll(".dnd-upload-status").length <= 1 ){ if( _parent_wrap.querySelector(".has-error-msg") ){ _parent_wrap.querySelector(".has-error-msg").remove(); } } // Update Counter _parent_wrap.querySelector(".dnd-upload-counter span").textContent = Number(localStorage.getItem(removeStorageData)) - 1; } } }; xhr.send( "path=" + _dnd_status.querySelector('input[type="hidden"]').value + "&action=dnd_codedropz_upload_delete" + "&security=" + dnd_cf7_uploader.ajax_nonce ); document.querySelectorAll(".has-error-msg").forEach(function(el) { el.remove(); }); }); // Attach CodeDropz_Uploader to HTMLElement prototype HTMLElement.prototype.CodeDropz_Uploader = CodeDropz_Uploader; })(); // END: CodeDropz Uploader function // BEGIN: initialize upload document.addEventListener('DOMContentLoaded', function() { // Fires when an Ajax form submission has completed successfully, and mail has been sent. document.addEventListener( 'wpcf7mailsent', function( event ) { // Get form const form = event.target; // Get input type file element var inputFile = form.querySelectorAll('.wpcf7-drag-n-drop-file'); var status = form.querySelectorAll('.dnd-upload-status'); var counter = form.querySelector('.dnd-upload-counter span'); var error = form.querySelectorAll('span.has-error-msg'); // Reset upload list for multiple fields if ( inputFile.length > 0 ) { inputFile.forEach( function(input) { localStorage.setItem( input.getAttribute('data-name') + '_count_files', 1 ); // Reset file counts }); } // Remove status / progress bar if (status) { status.forEach(function(statEl){ statEl.remove(); }); } if (counter) { counter.textContent = '0'; } if (error) { error.forEach(function(errEl){ errEl.remove(); }); } }, false ); window.initDragDrop = function () { // Get text object options/settings from localize script var TextOJB = dnd_cf7_uploader.drag_n_drop_upload; var fileUpload = document.querySelectorAll('.wpcf7-drag-n-drop-file'); fileUpload.forEach(function(Upload) { // Support Multiple Fileds Upload.CodeDropz_Uploader({ 'color': '#fff', 'ajax_url': dnd_cf7_uploader.ajax_url, 'text': TextOJB.text, 'separator': TextOJB.or_separator, 'button_text': TextOJB.browse, 'server_max_error': TextOJB.server_max_error, 'on_success': function(input, progressBar, response) { // Progressbar Object var progressDetails = document.querySelector('.codedropz-upload-wrapper #' + progressBar); var form = input.closest('form'); var span = form.querySelector('.wpcf7-acceptance'); var checkboxInput = ( span ? span.querySelector('input[type="checkbox"]') : '' ); // Remove 'required' error message const requiredMessage = input.closest('.codedropz-upload-wrapper').nextElementSibling; if( requiredMessage && requiredMessage.classList.contains('wpcf7-not-valid-tip') ){ requiredMessage.remove(); } // If it's complete remove disabled attribute in button if ( ( span && span.classList.contains('optional') ) || ! span || checkboxInput.checked || form.classList.contains('wpcf7-acceptance-as-validation')) { setTimeout(function(){ const submitButton = form.querySelector('button[type=submit], input[type=submit]'); if( submitButton ){ submitButton.removeAttribute('disabled'); } }, 1); } // Append hidden input field var detailsElement = progressDetails.querySelector('.dnd-upload-details'); var inputHTML = ''; detailsElement.insertAdjacentHTML('beforeend', inputHTML); // Update counter var filesCounter = ( Number( localStorage.getItem( input.dataset.name + '_count_files' ) ) - 1); var counterElement = input.closest('.codedropz-upload-wrapper').querySelector('.dnd-upload-counter span'); counterElement.textContent = filesCounter; } }); }); } window.initDragDrop(); });