10 Commits

Author SHA1 Message Date
c19eec4913 JQuery type install for eslint 2025-03-07 15:28:02 +09:00
d95160cfe1 esbuild/eslint installer, eslint setup
Minor code cleanup
2025-03-07 13:57:19 +09:00
b5d1c9d8c8 Test CSS update with upload error name 2024-09-30 18:55:50 +09:00
e692aef45a Change the error CSS name
from "SubError" to proper afus-upload-error
2024-09-30 18:54:35 +09:00
c53eea0b42 All CSS used are prefixed with afus-, uuid v4 for each upload group
Set uuid v4 for each upload group as ".uploadQueueUid"
Add max upload files as ".uploadQueueMax"
Change to upload files to ".uploadQueueOpen" (from ".uploadQueueMax")

Extract retrun message from two types for messages that could come
from the server
2024-09-17 15:50:39 +09:00
960d396aae Add some missing param declarations in functions 2023-06-30 17:44:42 +09:00
a644b9b207 Remove executable bit 2023-01-06 09:46:29 +09:00
c694815eb3 Ajax file upload make all fuctions "afus" prefixed 2022-12-09 15:20:26 +09:00
22baff8b13 all called functions can have functions options setable during init
function_options is a new object that will be passed on as the last
parameter on all functions
2022-11-30 09:59:24 +09:00
d804a81021 Move round for progress into calculation part 2022-06-16 17:57:28 +09:00
11 changed files with 1804 additions and 56 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
node_modules/

59
eslint.config.mjs Normal file
View File

@@ -0,0 +1,59 @@
import globals from 'globals';
import pluginJs from '@eslint/js';
/*
module.exports = {
// in globals block
'extends': 'eslint:recommended',
'parserOptions': {
'ecmaVersion': 6
},
// rules copied
};
*/
/** @type {import('eslint').Linter.Config[]} */
export default [
{languageOptions: {
globals: {
...globals.browser,
...globals.jquery
}
}},
pluginJs.configs.recommended,
{
'rules': {
'indent': [
'error',
'tab',
{
'SwitchCase': 1
}
],
'linebreak-style': [
'error',
'unix'
],
// 'quotes': [
// 'error',
// 'single'
// ],
'semi': [
'error',
'always'
],
'no-console': 'off',
'no-unused-vars': [
'error', {
'vars': 'all',
'args': 'after-used',
'ignoreRestSiblings': false
}
],
// Requires eslint >= v8.14.0
'no-constant-binary-expression': 'error'
}
}
];
// __END__

15
jsconfig.json Normal file
View File

@@ -0,0 +1,15 @@
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Bundler",
"target": "ES2020",
"jsx": "react",
"allowImportingTsExtensions": true,
"strictNullChecks": true,
"strictFunctionTypes": true
},
"exclude": [
"node_modules",
"**/node_modules/*"
]
}

1572
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

18
package.json Normal file
View File

@@ -0,0 +1,18 @@
{
"name": "ajax-file-upload",
"version": "1.0.0",
"main": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Clemens Schwaighofer",
"license": "",
"description": "Ajax File Upload",
"devDependencies": {
"@eslint/js": "^9.20.0",
"@types/jquery": "^3.5.32",
"esbuild": "^0.25.0",
"eslint": "^9.20.1",
"globals": "^15.15.0"
}
}

122
src/ajaxFileUploadSimple.js Executable file → Normal file
View File

@@ -2,7 +2,7 @@
// 'use strict';
/* jshint esversion: 6 */
/* jshint esversion: 11 */
/**
* CUSTOM SUB CALL FUNCTIONS as passsd on in init call
@@ -49,6 +49,16 @@ if (!String.prototype.format) {
};
}
/**
* A very simple uuidv4 for grouping same uploads together
* @returns uuidv4
*/
function afusUuidv4() {
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
(+c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16)
);
}
/**
* [from edit.js]
* checks if a key exists in a given object
@@ -56,7 +66,7 @@ if (!String.prototype.format) {
* @param {Object} object object to search key in
* @return {Boolean} true/false if key exists in object
*/
function keyInObject(key, object)
function afusKeyInObject(key, object)
{
return (Object.prototype.hasOwnProperty.call(object, key)) ? true : false;
}
@@ -68,7 +78,7 @@ function keyInObject(key, object)
* @param {Number} bytes bytes in int
* @return {String} string in GB/MB/KB
*/
function formatBytes(bytes)
function afusFormatBytes(bytes)
{
var i = -1;
do {
@@ -83,7 +93,7 @@ function formatBytes(bytes)
* prints out error messages based on data available from the browser
* @param {Object} err error from try/catch block
*/
function errorCatch(err)
function afusErrorCatch(err)
{
// for FF & Chrome
if (err.stack) {
@@ -179,9 +189,9 @@ function afusUploadError(target_file, file_pos, error_message, is_error)
document.getElementById(target_file + '-status-progress-bar-span-' + file_pos).style.display = 'none';
// add error style to upload status
if (is_error === true) {
document.getElementById(target_file + '-status-progress-' + file_pos).classList.add('SubError');
document.getElementById(target_file + '-status-progress-' + file_pos).classList.add('afus-upload-error');
} else {
document.getElementById(target_file + '-status-progress-' + file_pos).classList.remove('SubError');
document.getElementById(target_file + '-status-progress-' + file_pos).classList.remove('afus-upload-error');
}
}
@@ -208,7 +218,7 @@ function afusPostUpload(target_file, file_pos, target_router, file_info, data)
document.getElementById(target_file + '-uid-' + file_pos).value = file_info.file_uid;
// append uid, file name, size into uploaded too
if (typeof AFUS_functions[target_file].fileUploaded === 'function') {
AFUS_functions[target_file].fileUploaded(target_file, file_pos, target_router, data);
AFUS_functions[target_file].fileUploaded(target_file, file_pos, target_router, data, AFUS_config[target_file].function_options);
}
}
@@ -261,7 +271,7 @@ function afusUploaderConfigCheck(config)
// if target file is not set, major abort
let empty = false;
for (let ent of ['target_file', 'target_form']) {
if (!keyInObject(ent, config)) {
if (!afusKeyInObject(ent, config)) {
config[ent] = '';
}
if (!(typeof config[ent] === 'string' || config[ent] instanceof String)) {
@@ -280,7 +290,7 @@ function afusUploaderConfigCheck(config)
}
let target_file = config.target_file;
// maximum files allowed to upload at once
if (!keyInObject('max_files', config)) {
if (!afusKeyInObject('max_files', config)) {
config.max_files = 1;
} else {
config.max_files = parseInt(config.max_files);
@@ -291,7 +301,7 @@ function afusUploaderConfigCheck(config)
}
}
// maximum file size allowed (in bytes)
if (!keyInObject('max_file_size', config)) {
if (!afusKeyInObject('max_file_size', config)) {
config.max_file_size = 0;
} else {
// TODO: if has M/G/etc multiply by 1024 to bytes
@@ -300,7 +310,7 @@ function afusUploaderConfigCheck(config)
}
config.file_accept = [];
// allowed file extensions (eg jpg, gif)
if (!keyInObject('allowed_extensions', config)) {
if (!afusKeyInObject('allowed_extensions', config)) {
config.allowed_extensions = [];
} else {
// must be array and always lower case
@@ -318,7 +328,7 @@ function afusUploaderConfigCheck(config)
}
}
// allowed file types in mime format, image/jpeg, etc
if (!keyInObject('allowed_file_types', config)) {
if (!afusKeyInObject('allowed_file_types', config)) {
config.allowed_file_types = [];
} else {
// copy to new
@@ -335,19 +345,19 @@ function afusUploaderConfigCheck(config)
}
}
// target router for ajax submit
if (!keyInObject('target_router', config)) {
if (!afusKeyInObject('target_router', config)) {
config.target_router = '';
} else {
// must be string
}
// ajax form action target name
if (!keyInObject('target_action', config)) {
if (!afusKeyInObject('target_action', config)) {
config.target_action = '';
} else {
// must be string
}
// any additional parameters to be sent to the server
if (!keyInObject('form_parameters', config)) {
if (!afusKeyInObject('form_parameters', config)) {
config.form_parameters = {};
} else if (!(
typeof config.form_parameters === 'object' &&
@@ -357,7 +367,7 @@ function afusUploaderConfigCheck(config)
config.form_parameters = {};
}
// upload without confirmation step
if (!keyInObject('auto_submit', config)) {
if (!afusKeyInObject('auto_submit', config)) {
config.auto_submit = false;
} else if (!(
config.auto_submit === false ||
@@ -366,6 +376,15 @@ function afusUploaderConfigCheck(config)
// must be boolean
config.auto_submit = false;
}
if (!afusKeyInObject('function_options', config)) {
config.function_options = {};
} else if (!(
typeof config.function_options === 'object' &&
config.function_options !== null
)) {
// must be object
config.function_options = {};
}
// set path name
config.path = window.location.pathname;
// do we end in .php, we need to remove the name then, we just want the path
@@ -379,7 +398,7 @@ function afusUploaderConfigCheck(config)
// write general config things into config
AFUS_config[target_file] = {};
for (var ent of [
'target_file', 'target_form', 'path',
'target_file', 'target_form', 'path', 'function_options',
'max_files', 'max_file_size', 'allowed_extensions', 'allowed_file_types',
'target_router', 'target_action', 'form_parameters', 'auto_submit'
]) {
@@ -401,7 +420,7 @@ function afusUploaderConfigCheck(config)
'fileChange', 'fileChangeAll', 'fileRemove', 'fileClear', 'fileBeforeUploadAll',
'fileBeforeUpload', 'fileUploaded', 'fileUploadedAll', 'fileUploadError'
]) {
if (!keyInObject(fkt, config)) {
if (!afusKeyInObject(fkt, config)) {
config[fkt] = '';
}
AFUS_functions[target_file][fkt] = config[fkt];
@@ -409,14 +428,14 @@ function afusUploaderConfigCheck(config)
// init strings for this groups
AFUS_strings[target_file] = {};
// if set translation strings, set them to the AFUS string
if (keyInObject('translation', config)) {
if (afusKeyInObject('translation', config)) {
// upload_start, upload_finished, too_many_files only
for (var k of [
'invalid_type', 'invalid_size', 'cancel', 'remove',
'upload_start', 'upload_finished', 'upload_cancled',
'too_many_files'
]) {
if (keyInObject(k, config.translation)) {
if (afusKeyInObject(k, config.translation)) {
AFUS_strings[target_file][k] = config.translation[k];
}
}
@@ -478,6 +497,7 @@ function afusSupportAjaxUploadWithProgress()
* Added BEFORE fileBeforeUpload parameters
* {Object} [translation={}] Translated strings pushed into the AFUS_strings object
* {Boolean} [auto_submit=false] if we override the submit button and directly upload
* {Object} [function_options={}] Additional data to pass to functions
* {Function} [fileChange=''] Function run on change of -file element entry
* Parameters are target_file, file_pos, target_router
* {Function} [fileChangeAll=''] Function run on change of -file element entry
@@ -495,7 +515,8 @@ function afusSupportAjaxUploadWithProgress()
* {Function} [fileUploaded=''] Function called after upload has successfully finished
* Parameters are target_file, file_pos, target_router, data
* (object returned from upload function call)
* {Function} [fileUploadedAll=''] After all uploads have been done, this one will be called
* {Function} [fileUploadedAll=''] After all uploads have been done,
* this one will be called
* Parameters are target_file, target_router
* {Function} [fileUploadError=''] Function called after upload has failed
* Parameters are target_file, file_pos, target_router, data
@@ -546,7 +567,7 @@ function initAjaxUploader(config) // eslint-disable-line
document.getElementById(target_file + '-abort-all-div').style.display = 'none';
// call clear post
if (typeof AFUS_functions[target_file].fileClear === 'function') {
AFUS_functions[target_file].fileClear(target_file, config.target_router);
AFUS_functions[target_file].fileClear(target_file, config.target_router, AFUS_config[target_file].function_options);
}
});
}
@@ -619,6 +640,7 @@ function afusPassThroughEvent(target_file, max_files, target_router, auto_submit
document.getElementById(target_file + '-abort-all-div').style.display = 'none';
// init wipe upload status
document.getElementById(target_file + '-upload-status').innerHTML = '';
document.getElementById(target_file + '-upload-status').style.display = 'none';
// write file name to upload status
// show submit button
document.getElementById(target_file + '-file').addEventListener('change', function() {
@@ -635,13 +657,13 @@ function afusPassThroughEvent(target_file, max_files, target_router, auto_submit
document.getElementById(target_file + '-submit-div').style.display = 'none';
document.getElementById(target_file + '-clear-div').style.display = 'none';
document.getElementById(target_file + '-abort-all-div').style.display = 'none';
document.getElementById(target_file + '-upload-status').classList.add('SubError');
document.getElementById(target_file + '-upload-status').classList.add('afus-upload-error');
document.getElementById(target_file + '-upload-status').innerHTML = (AFUS_strings[target_file].too_many_files || '{0} files selected, but maximum allowed is {1}').format(input_files.files.length, max_files);
document.getElementById(target_file + '-upload-status').style.display = '';
// abort
return false;
} else {
document.getElementById(target_file + '-upload-status').classList.remove('SubError');
document.getElementById(target_file + '-upload-status').classList.remove('afus-upload-error');
}
var el, el_sub, el_sub_sub;
var valid_type = false, valid_size = false;
@@ -680,16 +702,19 @@ function afusPassThroughEvent(target_file, max_files, target_router, auto_submit
// add to upload status list
el = document.createElement('div');
el.id = target_file + '-status-' + i;
el.classList.add('afus-status-row');
// file pos in queue? would need pos update on delete
// file name
el_sub = document.createElement('span');
el_sub.id = target_file + '-status-name-' + i;
el_sub.classList.add('afus-status-name');
el_sub.innerHTML = input_files.files[i].name;
el.appendChild(el_sub);
// progress info (just text)
el_sub = document.createElement('span');
el_sub.id = target_file + '-status-progress-' + i;
el_sub.setAttribute('style', 'display:none;margin-left:5px;');
el_sub.classList.add('afus-status-progress');
el.appendChild(el_sub);
// Toptional progress info as visual bar
el_sub = document.createElement('span');
@@ -698,6 +723,7 @@ function afusPassThroughEvent(target_file, max_files, target_router, auto_submit
// attach progress element into it
el_sub_sub = document.createElement('progress');
el_sub_sub.id = target_file + '-status-progress-bar-' + i;
el_sub_sub.classList.add('afus-status-progress-bar');
el_sub_sub.max = 100;
el_sub_sub.value = 0;
el_sub.appendChild(el_sub_sub);
@@ -708,18 +734,19 @@ function afusPassThroughEvent(target_file, max_files, target_router, auto_submit
// if invalid types, show error
if (valid_type === false || valid_size === false) {
el_sub.setAttribute('style', 'margin-left:5px;');
el_sub.classList.add('SubError');
el_sub.classList.add('afus-status-error');
let error_list = [];
if (valid_type === false) {
error_list.push(AFUS_strings[target_file].invalid_type || 'Invalid file type');
}
if (valid_size === false) {
error_list.push((AFUS_strings[target_file].invalid_size || 'Maximum file size is {0}').format(formatBytes(AFUS_config[target_file].max_file_size)));
error_list.push((AFUS_strings[target_file].invalid_size || 'Maximum file size is {0}').format(afusFormatBytes(AFUS_config[target_file].max_file_size)));
}
el_sub.innerHTML = error_list.join(', ');
} else {
// else show remove
el_sub.setAttribute('style', 'margin-left:5px;');
el_sub.classList.add('afus-status-delete');
// -W083
el_sub.addEventListener('click', function() { // jshint ignore:line
AFUS_file_list[target_file].splice(i, 1);
@@ -733,7 +760,7 @@ function afusPassThroughEvent(target_file, max_files, target_router, auto_submit
}
// delete
if (typeof AFUS_functions[target_file].fileRemove === 'function') {
AFUS_functions[target_file].fileRemove(target_file, i, target_router);
AFUS_functions[target_file].fileRemove(target_file, i, target_router, AFUS_config[target_file].function_options);
}
});
el_sub.innerHTML = AFUS_strings[target_file].remove || 'Remove';
@@ -743,6 +770,7 @@ function afusPassThroughEvent(target_file, max_files, target_router, auto_submit
el_sub = document.createElement('span');
el_sub.id = target_file + '-status-abort-' + i;
el_sub.setAttribute('style', 'margin-left:5px;display:none;');
el_sub.classList.add('afus-status-abort');
el_sub.innerHTML = AFUS_strings[target_file].cancel || 'Cancel';
el.appendChild(el_sub);
// hidden info
@@ -755,12 +783,12 @@ function afusPassThroughEvent(target_file, max_files, target_router, auto_submit
document.getElementById(target_file + '-upload-status').appendChild(el);
// file change update per file
if (typeof AFUS_functions[target_file].fileChange === 'function') {
AFUS_functions[target_file].fileChange(target_file, i, target_router);
AFUS_functions[target_file].fileChange(target_file, i, target_router, AFUS_config[target_file].function_options);
}
}
// file change update after all files processed
if (typeof AFUS_functions[target_file].fileChangeAll === 'function') {
AFUS_functions[target_file].fileChangeAll(target_file, target_router);
AFUS_functions[target_file].fileChangeAll(target_file, target_router, AFUS_config[target_file].function_options);
}
// updated file list render
document.getElementById(target_file + '-upload-status').style.display = '';
@@ -855,7 +883,7 @@ function afusInitFullFormAjaxUpload(target_file, target_form, config)
target_file = _target_file;
}
// remove previous highlight if set
document.getElementById(target_file + '-upload-status').classList.remove('SubError');
document.getElementById(target_file + '-upload-status').classList.remove('afus-upload-error');
document.getElementById(target_file + '-upload-status').style.display = '';
// hide the upload button itself so we don't press twice
document.getElementById(target_file + '-file-div').style.display = 'none';
@@ -888,7 +916,7 @@ function afusInitFullFormAjaxUpload(target_file, target_form, config)
afusFinalPostUpload(target_file);
// if there is a final function, call it
if (typeof AFUS_functions[target_file].fileUploadedAll === 'function') {
AFUS_functions[target_file].fileUploadedAll(target_file, config.target_router, AFUS_config[target_file].all_success);
AFUS_functions[target_file].fileUploadedAll(target_file, config.target_router, AFUS_config[target_file].all_success, AFUS_config[target_file].function_options);
}
});
// Avoid normal form submission
@@ -914,10 +942,12 @@ class afusAsyncUploader
// additional data to append to the form submit (global)
this.form_append = {};
if (typeof AFUS_functions[this.target_file].fileBeforeUploadAll === 'function') {
for (const [key, value] of Object.entries(AFUS_functions[this.target_file].fileBeforeUploadAll(this.target_file, AFUS_config[this.target_file].target_router))) {
for (const [key, value] of Object.entries(AFUS_functions[this.target_file].fileBeforeUploadAll(this.target_file, AFUS_config[this.target_file].target_router, AFUS_config[target_file].function_options))) {
this.form_append[key] = value;
}
}
this.form_append.uploadQueueUid = afusUuidv4();
this.form_append.uploadQueueMax = AFUS_file_list[target_file].length;
// the function call (afusSendFile) with promise
this.functionCall = function_call;
// error flag for upload error
@@ -1013,7 +1043,7 @@ function afusSendFile(target_file, file, form_append)
}
formData.append('action', AFUS_config[target_file].target_router);
formData.append('uploadQueuePos', file_pos);
formData.append('uploadQueueMax', AFUS_file_list[target_file].length);
formData.append('uploadQueueOpen', AFUS_file_list[target_file].length);
formData.append('uploadName', target_file + '-file');
// add file only (first file found) with target file name
formData.append(target_file + '-file', file);
@@ -1030,7 +1060,7 @@ function afusSendFile(target_file, file, form_append)
}
// external data gets added
if (typeof AFUS_functions[target_file].fileBeforeUpload === 'function') {
for (const [key, value] of Object.entries(AFUS_functions[target_file].fileBeforeUpload(target_file, file_pos, AFUS_config[target_file].target_router))) {
for (const [key, value] of Object.entries(AFUS_functions[target_file].fileBeforeUpload(target_file, file_pos, AFUS_config[target_file].target_router, AFUS_config[target_file].function_options))) {
formData.append(key, value);
}
}
@@ -1160,11 +1190,11 @@ function afusOnLoadHandler(target_file, file_pos)
function afusOnProgressHandler(target_file, file_pos, evt)
{
// must set dynamic
var percent = evt.loaded / evt.total * 100;
// console.log('[AJAX Uploader: %s] Uploading: %s', target_file, Math.round(percent));
document.getElementById(target_file + '-status-progress-' + file_pos).innerHTML = Math.round(percent) + '%';
var percent = Math.round(evt.loaded / evt.total * 100);
// console.log('[AJAX Uploader: %s] Uploading: %s', target_file, percent);
document.getElementById(target_file + '-status-progress-' + file_pos).innerHTML = percent + '%';
// write progress bar too
document.getElementById(target_file + '-status-progress-bar-' + file_pos).value = Math.round(percent);
document.getElementById(target_file + '-status-progress-bar-' + file_pos).value = percent;
}
/**
@@ -1185,7 +1215,7 @@ function afusOnReadyStateChangeHandler(target_file, file_pos, target_router, evt
responseText = evt.target.responseText;
status = evt.target.status;
} catch(e) {
errorCatch(e);
afusErrorCatch(e);
return;
}
// XMLHttpRequest.DONE == 4
@@ -1195,8 +1225,18 @@ function afusOnReadyStateChangeHandler(target_file, file_pos, target_router, evt
afusRunningStop(target_file);
// must set dynamic
console.log('[AJAX Uploader ORSC: %s/%s] Running: %s, Uploader response: %s -> %o', target_file, file_pos, afusRunningGet(target_file), responseData.status, responseData);
// the return msg is normally on base level, but it can be in content too
let msg = [];
if (afusKeyInObject('msg', responseData.content)) {
msg = responseData.content.msg;
} else if (afusKeyInObject('msg', responseData)) {
// we need to prep this one, these are default error mssages objects
for (let __message in responseData.msg) {
msg.append(__message.str);
}
}
// then run status output
afusUploadError(target_file, file_pos, responseData.content.msg, responseData.status == 'success' ? false : true);
afusUploadError(target_file, file_pos, msg, responseData.status == 'success' ? false : true);
// run post uploader
if (responseData.status == 'success') {
afusPostUpload(target_file, file_pos, target_router, {
@@ -1210,7 +1250,7 @@ function afusOnReadyStateChangeHandler(target_file, file_pos, target_router, evt
AFUS_config[target_file].all_success = false;
// call per file upload error function if exsts
if (typeof AFUS_functions[target_file].fileUploadError === 'function') {
AFUS_functions[target_file].fileUploadError(target_file, file_pos, target_router, responseData.content);
AFUS_functions[target_file].fileUploadError(target_file, file_pos, target_router, responseData.content, AFUS_config[target_file].function_options);
}
}
} else {

View File

@@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore PSR1.Files.SideEffects
header("Content-Type: application/json; charset=UTF-8");
session_start();
@@ -8,7 +8,7 @@ define('LOG', 'log' . DS);
// run id
DEFINE('RUNUID', session_id());
function logWrite($message)
function logWrite(string $message): void
{
global $fh;
if (!$fh) {
@@ -17,7 +17,7 @@ function logWrite($message)
fwrite($fh, '{' . RUNUID . '} [' . printTime() . '] ' . $message . "\n");
}
function logHandleClose()
function logHandleClose(): void
{
global $fh;
if ($fh) {
@@ -25,7 +25,7 @@ function logHandleClose()
}
}
function printTime()
function printTime(): string
{
$set_microtime = 4;
list($microtime, $timestamp) = explode(' ', microtime());
@@ -243,6 +243,7 @@ if (isset($_POST['action'])) {
$ajax_data = [
'msg' => [],
'file_uid' => null,
'file_crc' => null,
'file_url' => null,
'file_name' => null,
'file_size' => null,
@@ -263,6 +264,7 @@ if (isset($_POST['action'])) {
if ($status == 'success') {
// basic file id data
$file_uid = null;
$file_crc = null;
$file_url = null;
$file_name = null;
$file_size = null;
@@ -279,6 +281,7 @@ if (isset($_POST['action'])) {
$file_name = $_FILES[$upload_name]['name'];
$file_size = humanReadableByteFormat($_FILES[$upload_name]['size']);
$file_size_raw = $_FILES[$upload_name]['size'];
$file_crc = hash('sha256', file_get_contents($folder . $file_uid) ?: '');
// correct the image rotation
// $this->correctImageOrientation(BASE.TMP.$file_uid);
// make a copy to layout/cache/images for file url
@@ -289,6 +292,7 @@ if (isset($_POST['action'])) {
$ajax_data = [
'msg' => $file_upload_message,
'file_uid' => $file_uid,
'file_crc' => $file_crc,
'file_url' => $file_url,
'file_name' => $file_name,
'file_size' => $file_size,

0
test/multiple_files_test.html Executable file → Normal file
View File

View File

@@ -45,6 +45,28 @@ CSS Other
.uploaded { margin-top: 20px; }
.title { font-size: 1.5em; font-weight: bold; margin-bottom: 10px; }
.afus-status-delete {
color: orange;
font-weight: bold;
}
.afus-status-progress {
color: rgb(37, 140, 191);
}
.afus-status-progress-bar {
height: 10px;
}
.afus-status-progress-bar::slider-fill {
background-color: orange;
}
.afus-status-abort {
color: red;
}
.afus-status-error {
color: red;
font-weight: bold;
font-size: 1.2em;
}
.file-upload label div {
text-align: center;
color: #e60012;
@@ -82,7 +104,8 @@ CSS Other
cursor: pointer;
}
.SubError {
.SubError,
.afus-upload-error {
color: red;
}

View File

@@ -4,7 +4,7 @@
/* jshint esversion: 6 */
/* global initAjaxUploader, keyInObject, errorCatch, showActionIndicator, hideActionIndicator, exists, phfo, aelx, cel */
/* global initAjaxUploader, afusKeyInObject, afusErrorCatch, showActionIndicator, hideActionIndicator, exists, phfo, aelx, cel */
/**
* clear the alert div and hide it
@@ -30,7 +30,7 @@ function printMsg(msg) {
var content = [];
for (const t of msg) {
// console.log('v: %s, t: %o', v, t);
if (keyInObject('code', t) && t.code != null && t.code.length > 0) {
if (afusKeyInObject('code', t) && t.code != null && t.code.length > 0) {
t.str = '[' + t.code + '] ' + t.str;
}
content.push(phfo(cel('div', '', t.str, ['error-' + t.level])));
@@ -57,7 +57,7 @@ function printMsg(msg) {
*/
function ajaxWrapper(call_id, queryString = {}, control = {}, url = 'backend.php') {
var no_action_indicator = false;
if (keyInObject('no_action_indicator', control)) {
if (afusKeyInObject('no_action_indicator', control)) {
no_action_indicator = control.no_action_indicator ? true : false;
}
// if inidicator not visible, show before
@@ -93,15 +93,27 @@ function ajaxWrapper(call_id, queryString = {}, control = {}, url = 'backend.php
});
}
/**
* uuid4 creator
* @returns {String} uuid4
*/
function uuidv4() {
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
(+c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16)
);
}
/**
* FILE CHANGE:
* helper call for ajax file upload on file selected
* @param {Number} file_pos Position in upload queue
* @param {String} target_file The file upload target prefix id
* @param {Number} file_pos Position in upload queue
* @param {String} target_router [description]
* @param {Object} options additional functions options
*/
function fileChangeFunction(target_file, file_pos, target_router)
function fileChangeFunction(target_file, file_pos, target_router, options={})
{
console.log('{FILE} CHANGE [%s/%s] FUNCTION CALL [%s]', target_file, file_pos, target_router);
console.log('{FILE} CHANGE [%s/%s] FUNCTION CALL [%s]: [%o]', target_file, file_pos, target_router, options);
clearAlerts();
// console.log('Upload Status: %s', $('#' + target_file + '-upload-status').outerHeight());
}
@@ -224,7 +236,7 @@ function fileUploadedFunction(target_file, file_pos, target_router, control_data
}
}
} catch(err) {
errorCatch(err);
afusErrorCatch(err);
}
// chain action test
var call_id = 'chainAction';
@@ -248,7 +260,7 @@ function fileUploadedFunction(target_file, file_pos, target_router, control_data
// top message
printMsg(data.msg);
} catch (err) {
errorCatch(err);
afusErrorCatch(err);
}
});
}
@@ -314,7 +326,7 @@ $(document).ready(function () {
// top message
printMsg(data.msg);
} catch (err) {
errorCatch(err);
afusErrorCatch(err);
}
});
@@ -328,6 +340,10 @@ $(document).ready(function () {
target_action: '',
form_parameters: {'parameter_a': 'Value 123'},
auto_submit: false,
function_options: {action_box_id: 'actionBox-alt', 'other': 'free'},
translation: {
remove: "REMOVE"
},
fileChange: fileChangeFunction,
fileChangeAll: fileChangeFunctionAll,
fileRemove: fileRemoveFunction,