PageSourceSearch

https://richardtaittinger.com/wp-content/plugins/drag-and-drop-mul…/js/codedropz-uploader-min.js?ver=1.3.7.4

js richardtaittinger.com collected 2026-09-24 23:21:35 UTC 22,689 bytes, 536 lines download raw bytes

1/**
2 * CodeDropz Uploader v1.3.7.2
3 * Copyright 2018 Glen Mongaya
4 * CodeDrop Drag&Drop Uploader
5 * @version 1.3.7.2
6 * @author CodeDropz, Glen Don L. Mongaya
7 * @license The MIT License (MIT)
8 */
9
10// CodeDropz Drag and Drop Plugin
11(function() {
12
13    const CodeDropz_Uploader = function( settings ){
14
15        // Generate & check nonce
16        const form = document.querySelector('form.wpcf7-form');
17        if( form ) {
18            const data = new FormData();
19            data.append('action', '_wpcf7_check_nonce');
20            data.append('_ajax_nonce', dnd_cf7_uploader.ajax_nonce );
21            fetch(dnd_cf7_uploader.ajax_url, { method: 'POST', body: data })
22            .then(res => res.json())
23            .then(({ data, success }) => success && (dnd_cf7_uploader.ajax_nonce = data))
24            .catch(console.error)
25        }
26
27        // Parent input file type
28        var input = this;
29
30        // Define default options
31        const defaultOptions = {
32            handler: input,
33            color: '#000',
34            background: '',
35            server_max_error: 'Uploaded file exceeds the maximum upload size of your server.',
36            max_file: input.dataset.max ? input.dataset.max : 10, // default 10
37            max_upload_size: input.dataset.limit ? input.dataset.limit : '10485760', // should be a bytes it's (5MB)
38            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',
39            text: 'Drag & Drop Files Here',
40            separator: 'or',
41            button_text: 'Browse Files',
42            on_success: '',
43        };
44
45        // Merge options with default options
46        const options = Object.assign({}, defaultOptions, settings);
47
48        // Get storage name
49        var dataStorageName = input.dataset.name + '_count_files';
50
51        // File Counter
52        localStorage.setItem( dataStorageName, 1);
53
54        // Template Container
55        const cdropz_template = `
56            <div class="codedropz-upload-handler">
57                <div class="codedropz-upload-container">
58                <div class="codedropz-upload-inner">
59                    <${dnd_cf7_uploader.drag_n_drop_upload.tag}>${options.text}</${dnd_cf7_uploader.drag_n_drop_upload.tag}>
60                    <span>${options.separator}</span>
61                    <div class="codedropz-btn-wrap"><a class="cd-upload-btn" href="javascript:void(0)">${options.button_text}</a></div>
62                </div>
63                </div>
64                <span class="dnd-upload-counter"><span>0</span> ${dnd_cf7_uploader.dnd_text_counter} ${parseInt(options.max_file)}</span>
65            </div>
66        `;
67
68        // Wrap input fields
69        const wrapper = document.createElement('div');
70
71        // Begin to wrap upload fields
72        wrapper.classList.add('codedropz-upload-wrapper');
73        options.handler.parentNode.insertBefore(wrapper, options.handler);
74        wrapper.appendChild(options.handler);
75
76        // Remove special character
77        options.supported_type = options.supported_type.replace(/[^a-zA-Z0-9| ]/g, "");
78
79        // Element Handler
80        const form_handler = options.handler.closest('form');
81        const options_handler = options.handler.closest('.codedropz-upload-wrapper');
82        const btnOBJ = form_handler.querySelector('input[type="submit"]');
83
84        // Append Format
85        options.handler.insertAdjacentHTML('afterend', cdropz_template);
86
87        // preventing the unwanted behaviours
88        ['drag', 'dragstart', 'dragend', 'dragover', 'dragenter', 'dragleave', 'drop'].forEach(function(eventName) {
89            options_handler.querySelector('.codedropz-upload-handler').addEventListener(eventName, function(e) {
90                e.preventDefault();
91                e.stopPropagation();
92            });
93        });
94
95        // dragover and dragenter - add class
96        ['dragover', 'dragenter'].forEach(function(eventName) {
97            options_handler.querySelector('.codedropz-upload-handler').addEventListener(eventName, function(e) {
98                options_handler.querySelector('.codedropz-upload-handler').classList.add('codedropz-dragover');
99            });
100        });
101
102        // dragleave dragend drop - remove class
103        ['dragleave', 'dragend', 'drop'].forEach(function(eventName){
104            options_handler.querySelector('.codedropz-upload-handler').addEventListener(eventName, function(e) {
105                options_handler.querySelector('.codedropz-upload-handler').classList.remove('codedropz-dragover');
106            });
107        });
108
109        // Browse button clicked
110        options_handler.querySelector('.cd-upload-btn').addEventListener('click', function(e){
111            // stops the default action of an element from happening
112            e.preventDefault();
113
114            // Reset value
115            options.handler.value = null;
116
117            // Click input type[file] element
118            options.handler.click();
119        });
120
121        // when dropping files
122        options_handler.querySelector('.codedropz-upload-handler').addEventListener('drop', function(event) {
123            // Run the uploader
124            DND_Setup_Uploader(event.dataTransfer.files, 'drop');
125        });
126
127        // Trigger when input type[file] is click/changed
128        options.handler.addEventListener('change', function(e) {
129            // Run the uploader
130            DND_Setup_Uploader(this.files, 'click');
131        });
132        
133        // Remove accept attribute on mobile devices
134        if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
135            input.removeAttribute('accept');
136        }
137
138        // Setup Uploader
139        var DND_Setup_Uploader = function( files, action ) {
140
141            // make sure we have files
142            if (files.length == 0 ) return;
143
144            // gathering the form data
145            var formData = new FormData();
146
147            // Append file
148            //formData.append('supported_type', options.supported_type ); @note : removed due Vulnerability
149            //formData.append('size_limit', options.max_upload_size );
150            formData.append('action', 'dnd_codedropz_upload' );
151            formData.append('type', action );
152            formData.append('security', dnd_cf7_uploader.ajax_nonce );
153
154            // CF7 - upload field name & cf7 id
155            formData.append('form_id', input.dataset.id);
156            formData.append('upload_name', input.dataset.name);
157
158            // black list file types
159            /*if( input.hasAttribute('data-black-list') ){
160                formData.append('blacklist-types', input.dataset.blackList);
161            }*/
162
163            // remove has error
164            const errorHandler = options.handler.querySelector('.has-error');
165            if (errorHandler) {
166                errorHandler.remove();
167            }
168
169            // Loop files
170            for (const file of files) {
171
172                // Reset upload file type
173                if( typeof formData.delete !== 'undefined' ) {
174                    formData.delete('upload-file');
175                }
176
177                // Limit file upload
178                if( Number( localStorage.getItem(dataStorageName) ) > options.max_file ) {
179                    var hasErrorMsg = options_handler.querySelector('span.has-error-msg');
180                    if (!hasErrorMsg) {
181                        var err_msg = dnd_cf7_uploader.drag_n_drop_upload.max_file_limit;
182                        var errorMsgEl = document.createElement('span');
183                        errorMsgEl.className = 'has-error-msg';
184                        errorMsgEl.textContent = err_msg.replace('%count%', options.max_file);
185                        options_handler.appendChild(errorMsgEl);
186                    }
187                    return false;
188                }
189
190
191                // Create progress bar
192                const progressBarID = CodeDropz_Object.createProgressBar( file );
193                var has_error = false;
194
195                // File size limit - validation
196                if (file.size > options.max_upload_size) {
197                    const parentProgressBar = document.getElementById(progressBarID);
198                    const errorSpan = document.createElement('span');
199                    errorSpan.classList.add('has-error');
200                    errorSpan.textContent = dnd_cf7_uploader.drag_n_drop_upload.large_file;
201                    parentProgressBar.querySelector('.dnd-upload-details').appendChild(errorSpan);
202                    has_error = true;
203                }
204
205                // Validate file type
206                regex_type = new RegExp("(.*?)\.("+ options.supported_type +")$");
207                if ( has_error === false && !( regex_type.test( file.name.toLowerCase() ) ) ) {
208                    document.querySelector('#' + progressBarID + ' .dnd-upload-details').insertAdjacentHTML('beforeend', '<span class="has-error">' + dnd_cf7_uploader.drag_n_drop_upload.inavalid_type + '</span>');
209                    has_error = true;
210                }
211
212                // Increment count
213                localStorage.setItem( dataStorageName, ( Number( localStorage.getItem( dataStorageName ) ) + 1 ) );
214            
215                // Make sure there's no error
216                if( has_error === false ) {
217
218                    // Append file
219                    formData.append('upload-file', file );
220
221                    // Process ajax upload
222                    var xhr = new XMLHttpRequest();
223
224                    // Get progress bar element
225                    var progressBar = document.getElementById( progressBarID );
226                    var progressElement = progressBar.querySelector('.dnd-progress-bar');
227                    var detailsElement = progressBar.querySelector('.dnd-upload-details');
228                    var submitButton = form_handler.querySelector('input[type="submit"]');
229
230                    xhr.open(form_handler.getAttribute('method'), options.ajax_url);
231                    xhr.onreadystatechange = function() {
232                        if (this.readyState === 4) {
233                            if (this.status === 200) {
234                                var response = JSON.parse(this.responseText);
235                                if (response.success) {
236
237                                    // Complete the progress bar
238                                    CodeDropz_Object.setProgressBar(progressBarID, 100);
239
240                                    // Callback on success
241                                    if (typeof options.on_success === "function") {
242                                        options.on_success.call(this, input, progressBarID, response);
243                                    }
244
245                                } else {
246                                    progressElement.remove();
247                                    detailsElement.insertAdjacentHTML('beforeend', '<span class="has-error">'+ response.data +'</span>');
248                                    submitButton.classList.remove('disabled');
249                                    submitButton.removeAttribute('disabled');
250                                    progressBar.classList.remove('in-progress');
251                                }
252                            } else {
253                                progressElement.remove();
254                                detailsElement.insertAdjacentHTML('beforeend', '<span class="has-error">'+ options.server_max_error +'</span>');
255                                submitButton.classList.remove('disabled');
256                                submitButton.removeAttribute('disabled');
257                                progressBar.classList.remove('in-progress');
258                            }
259                        }
260                    };
261                    xhr.upload.addEventListener("progress", function(event){
262                        if ( event.lengthComputable ) {
263
264                            var percentComplete = ( event.loaded / event.total );
265                            var percentage = parseInt( percentComplete * 100 );
266
267                            // Make progress on the loading
268                            CodeDropz_Object.setProgressBar( progressBarID, percentage - 1 );
269                        }
270                    }, false);
271
272                    xhr.send(formData);
273
274                }
275            }
276
277        }
278        // End of Uploader function
279
280        // CodeDropz object and functions
281        var CodeDropz_Object = {
282
283            // Create progress bar
284            createProgressBar : function( file ) {
285
286                // Setup progress bar variable
287                var upload_handler = options_handler.querySelector('.codedropz-upload-handler');
288                var generated_ID = 'dnd-file-' + Math.random().toString(36).substr(2, 9);
289
290                // Setup progressbar elements
291                var fileDetails = `
292                    <div class="dnd-upload-image">
293                        <span class="file"></span>
294                    </div>
295                    <div class="dnd-upload-details">
296                        <span class="name"><span>${file.name}</span><em>(${CodeDropz_Object.bytesToSize(file.size)})</em></span>
297                        <a href="javascript:void(0)" title="${dnd_cf7_uploader.drag_n_drop_upload.delete.title}" class="remove-file" data-storage="${dataStorageName}">
298                        <span class="dnd-icon-remove"></span>
299                        </a>
300                        <span class="dnd-progress-bar"><span></span></span>
301                    </div>
302                `;
303
304                // Create new element and insert after upload_handler
305                var statusElement = document.createElement('div');
306                statusElement.id = generated_ID;
307                statusElement.className = 'dnd-upload-status';
308                statusElement.innerHTML = fileDetails;
309                upload_handler.parentNode.insertBefore(statusElement, upload_handler.nextSibling);
310
311                return generated_ID;
312
313            },
314
315            // Process progressbar ( Animate progress )
316            setProgressBar : function( progressBarID, percent ) {
317
318                const progressBar = document.getElementById( progressBarID );
319                const statusBar = progressBar.querySelector('.dnd-progress-bar');
320
321                //console.log(statusbar);
322                if (statusBar) {
323
324                    // Disable submit button
325                    CodeDropz_Object.disableBtn(btnOBJ);
326
327                    // Compute Progress bar
328                    let progress_width = percent * statusBar.offsetWidth / 100;
329
330                    // Set status bar in-progress
331                    progressBar.classList.add('in-progress');
332
333                    if (percent == 100) {
334                        statusBar.querySelector('span').style.width = '100%';
335                        statusBar.querySelector('span').textContent = `${percent}% `;
336                    } else {
337                        statusBar.querySelector('span').style.width = progress_width + 'px';
338                        statusBar.querySelector('span').textContent = `${percent}% `;
339                    }
340
341                    if (percent == 100) {
342                        progressBar.classList.add('complete');
343                        progressBar.classList.remove('in-progress');
344                    }
345                }
346                return false;
347
348            },
349
350            // Size Conversion
351            bytesToSize : function( bytes ) {
352
353                if( bytes === 0 )
354                    return '0';
355
356                kBytes = (bytes / 1024);
357                fileSize = ( kBytes >= 1024 ? ( kBytes / 1024 ).toFixed(2) + 'MB' : kBytes.toFixed(2) + 'KB' );
358
359                return fileSize;
360            },
361
362            // Disable button
363            disableBtn : function( BtnOJB ) {
364                if( BtnOJB  ) {
365                    BtnOJB.classList.add('disable');
366                    BtnOJB.disabled = true;
367                }
368            }
369        };
370
371	} // end fn.function
372
373    // Remove File
374    document.addEventListener("click", function(e) {
375        if( !e.target.classList.contains("dnd-icon-remove") ) return;
376
377        var _self = e.target,
378            _dnd_status = _self.closest(".dnd-upload-status"),
379            _parent_wrap = _self.closest(".codedropz-upload-wrapper"),
380            removeStorageData = _self.parentElement.getAttribute("data-storage"),
381            storageCount = Number(localStorage.getItem(removeStorageData));
382        
383        // Direct remove the file if there's any error.
384        if (_dnd_status.classList.contains("in-progress") || _dnd_status.querySelector(".has-error")) {
385            _dnd_status.remove();
386            localStorage.setItem(removeStorageData, storageCount - 1);
387            return false;
388        }
389        
390        // Change text Status
391        _self.classList.add("deleting");
392        _self.textContent = dnd_cf7_uploader.drag_n_drop_upload.delete.text + "...";
393
394        // Request ajax image delete
395        var xhr = new XMLHttpRequest();
396        xhr.open("POST", dnd_cf7_uploader.ajax_url);
397        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
398        xhr.onload = function() {
399            if (this.status === 200) {
400                var response = JSON.parse(this.responseText);
401                if (response.success) {
402
403                    // Reduce file count and status bar element.
404                    _dnd_status.remove();   
405                    localStorage.setItem(removeStorageData, storageCount - 1);
406                    
407                    // Remove error msg
408                    if ( _parent_wrap.querySelectorAll(".dnd-upload-status").length <= 1 ){
409                        if( _parent_wrap.querySelector(".has-error-msg") ){
410                            _parent_wrap.querySelector(".has-error-msg").remove();
411                        }
412                    }
413
414                    // Update Counter
415                    _parent_wrap.querySelector(".dnd-upload-counter span").textContent = Number(localStorage.getItem(removeStorageData)) - 1;
416                }
417            }
418        };
419
420        xhr.send(
421            "path=" + _dnd_status.querySelector('input[type="hidden"]').value +
422            "&action=dnd_codedropz_upload_delete" +
423            "&security=" + dnd_cf7_uploader.ajax_nonce
424        );
425
426        document.querySelectorAll(".has-error-msg").forEach(function(el) {
427            el.remove();
428        });
429
430    });
431
432    // Attach CodeDropz_Uploader to HTMLElement prototype
433    HTMLElement.prototype.CodeDropz_Uploader = CodeDropz_Uploader;
434
435})();
436// END: CodeDropz Uploader function
437
438// BEGIN: initialize upload
439document.addEventListener('DOMContentLoaded', function() {
440
441	// Fires when an Ajax form submission has completed successfully, and mail has been sent.
442    document.addEventListener( 'wpcf7mailsent', function( event ) {
443
444        // Get form
445        const form = event.target;
446
447        // Get input type file element
448        var inputFile = form.querySelectorAll('.wpcf7-drag-n-drop-file');
449        var status = form.querySelectorAll('.dnd-upload-status');
450        var counter = form.querySelector('.dnd-upload-counter span');
451        var error = form.querySelectorAll('span.has-error-msg');
452
453        // Reset upload list for multiple fields
454        if ( inputFile.length > 0 ) {
455            inputFile.forEach( function(input) {
456                localStorage.setItem( input.getAttribute('data-name') + '_count_files', 1 ); // Reset file counts
457            });
458        }
459
460        // Remove status / progress bar
461        if (status) {
462            status.forEach(function(statEl){
463                statEl.remove();
464            });
465        }
466        
467        if (counter) {
468            counter.textContent = '0';
469        }
470
471        if (error) {
472            error.forEach(function(errEl){
473                errEl.remove();
474            });
475        }
476
477    }, false );
478
479	window.initDragDrop = function () {
480
481		// Get text object options/settings from localize script
482		var TextOJB = dnd_cf7_uploader.drag_n_drop_upload;
483        var fileUpload = document.querySelectorAll('.wpcf7-drag-n-drop-file');
484
485        fileUpload.forEach(function(Upload) {
486
487            // Support Multiple Fileds
488            Upload.CodeDropz_Uploader({
489                'color': '#fff',
490                'ajax_url': dnd_cf7_uploader.ajax_url,
491                'text': TextOJB.text,
492                'separator': TextOJB.or_separator,
493                'button_text': TextOJB.browse,
494                'server_max_error': TextOJB.server_max_error,
495                'on_success': function(input, progressBar, response) {
496
497                    // Progressbar Object
498                    var progressDetails = document.querySelector('.codedropz-upload-wrapper #' + progressBar);
499                    var form = input.closest('form');
500                    var span = form.querySelector('.wpcf7-acceptance');
501                    var checkboxInput = ( span ? span.querySelector('input[type="checkbox"]') : '' );
502
503                    // Remove 'required' error message
504                    const requiredMessage = input.closest('.codedropz-upload-wrapper').nextElementSibling;
505                    if( requiredMessage && requiredMessage.classList.contains('wpcf7-not-valid-tip') ){
506                        requiredMessage.remove();
507                    }
508
509                    // If it's complete remove disabled attribute in button
510                    if ( ( span && span.classList.contains('optional') ) || ! span || checkboxInput.checked || form.classList.contains('wpcf7-acceptance-as-validation')) {
511                        setTimeout(function(){ 
512                            form.querySelector('input[type="submit"]').removeAttribute('disabled'); 
513                        }, 1);
514                    }
515
516                    // Append hidden input field
517                    var detailsElement = progressDetails.querySelector('.dnd-upload-details');
518                    var inputHTML = '<span><input type="hidden" name="' + input.dataset.name + '[]" value="' + response.data.path + '/' + response.data.file + '"></span>';
519                    detailsElement.insertAdjacentHTML('beforeend', inputHTML);
520
521                    // Update counter
522                    var filesCounter = ( Number( localStorage.getItem( input.dataset.name + '_count_files' ) ) - 1);
523                    var counterElement = input.closest('.codedropz-upload-wrapper').querySelector('.dnd-upload-counter span');
524                    counterElement.textContent = filesCounter;
525                }
526            });
527
528        });
529
530		
531
532	}
533
534	window.initDragDrop();
535
536});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.