Lightweight web-based rich text editor (WYSIWYG editor) built with JavaScript and CSS for modern browsers
—
Image upload functionality with support for local uploads, network images, and various cloud storage services.
Upload image files to the editor.
/**
* Upload image files to the editor
* @param files - FileList or Array of File objects to upload
*/
uploadImg(files: FileList | File[]): void;Usage Examples:
// Upload from file input
const fileInput = document.getElementById('imageInput');
fileInput.addEventListener('change', function(e) {
if (e.target.files.length > 0) {
editor.uploadImg.uploadImg(e.target.files);
}
});
// Upload programmatically
function uploadImages(files) {
editor.uploadImg.uploadImg(files);
}
// Drag and drop upload
const dropZone = document.getElementById('editor-container');
dropZone.addEventListener('drop', function(e) {
e.preventDefault();
const files = Array.from(e.dataTransfer.files).filter(file =>
file.type.startsWith('image/')
);
if (files.length > 0) {
editor.uploadImg.uploadImg(files);
}
});Configure server endpoint and upload parameters.
interface ServerConfig {
/** Server endpoint for image upload */
uploadImgServer?: string;
/** Custom filename for uploads */
uploadFileName?: string;
/** Additional parameters for image upload */
uploadImgParams?: {[key: string]: any};
/** Custom headers for image upload requests */
uploadImgHeaders?: {[key: string]: string};
/** Send cookies with upload requests */
withCredentials?: boolean;
/** Upload timeout in milliseconds */
uploadImgTimeout?: number;
}Usage Examples:
// Basic server configuration
editor.customConfig.uploadImgServer = '/api/upload/image';
// Advanced server configuration
editor.customConfig.uploadImgServer = 'https://api.example.com/upload';
editor.customConfig.uploadFileName = 'custom_file_name';
editor.customConfig.uploadImgParams = {
token: 'user-auth-token',
folder: 'editor-uploads'
};
editor.customConfig.uploadImgHeaders = {
'Authorization': 'Bearer ' + authToken,
'X-Upload-Source': 'wangEditor'
};
editor.customConfig.withCredentials = true;
editor.customConfig.uploadImgTimeout = 30000; // 30 secondsConfigure upload size and quantity limits.
interface UploadLimits {
/** Maximum image file size in bytes */
uploadImgMaxSize?: number;
/** Maximum number of images to upload at once */
uploadImgMaxLength?: number;
/** Show base64 format for uploaded images */
uploadImgShowBase64?: boolean;
}Usage Examples:
// Size and quantity limits
editor.customConfig.uploadImgMaxSize = 5 * 1024 * 1024; // 5MB limit
editor.customConfig.uploadImgMaxLength = 10; // Max 10 images at once
// Base64 image support
editor.customConfig.uploadImgShowBase64 = true; // Allow base64 images
// Strict limits for comments/forums
editor.customConfig.uploadImgMaxSize = 1 * 1024 * 1024; // 1MB
editor.customConfig.uploadImgMaxLength = 3; // Max 3 images
// Generous limits for content creation
editor.customConfig.uploadImgMaxSize = 20 * 1024 * 1024; // 20MB
editor.customConfig.uploadImgMaxLength = 50; // Max 50 imagesConfigure upload lifecycle callbacks.
interface UploadHooks {
/** Called before upload starts */
before?: (xhr: XMLHttpRequest, editor: any, files: File[]) => void | false;
/** Called after successful upload */
success?: (xhr: XMLHttpRequest, editor: any, result: any) => void;
/** Called after failed upload */
fail?: (xhr: XMLHttpRequest, editor: any, result: any) => void;
/** Called on upload error */
error?: (xhr: XMLHttpRequest, editor: any, error: any) => void;
/** Called on upload timeout */
timeout?: (xhr: XMLHttpRequest, editor: any) => void;
/** Custom image insertion function */
customInsert?: (insertImg: Function, result: any, editor: any) => void;
}Usage Examples:
editor.customConfig.uploadImgHooks = {
before: function(xhr, editor, files) {
console.log('Upload starting...', files.length, 'files');
// Validate files
for (let file of files) {
if (!file.type.startsWith('image/')) {
alert('Only image files are allowed');
return false; // Cancel upload
}
}
// Show loading indicator
showLoadingIndicator();
},
success: function(xhr, editor, result) {
console.log('Upload successful:', result);
hideLoadingIndicator();
// Process server response
if (result.code === 0) {
console.log('Images uploaded:', result.data);
}
},
fail: function(xhr, editor, result) {
console.log('Upload failed:', result);
hideLoadingIndicator();
alert('Upload failed: ' + (result.message || 'Unknown error'));
},
error: function(xhr, editor, error) {
console.error('Upload error:', error);
hideLoadingIndicator();
alert('Upload error occurred');
},
timeout: function(xhr, editor) {
console.log('Upload timeout');
hideLoadingIndicator();
alert('Upload timed out. Please try again.');
},
customInsert: function(insertImg, result, editor) {
// Custom logic for inserting images
if (result.code === 0 && result.data) {
result.data.forEach(url => {
insertImg(url);
});
}
}
};Completely custom upload handling.
interface CustomUpload {
/** Custom image upload implementation */
customUploadImg?: (files: FileList, insert: (url: string) => void) => void;
}Usage Examples:
// Complete custom upload
editor.customConfig.customUploadImg = function(files, insert) {
console.log('Custom upload:', files.length, 'files');
// Convert to array for easier handling
const fileArray = Array.from(files);
// Upload each file
fileArray.forEach(file => {
const formData = new FormData();
formData.append('image', file);
formData.append('timestamp', Date.now().toString());
fetch('/api/custom-upload', {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(result => {
if (result.success) {
// Insert image into editor
insert(result.imageUrl);
} else {
console.error('Upload failed:', result.error);
alert('Upload failed: ' + result.error);
}
})
.catch(error => {
console.error('Upload error:', error);
alert('Upload error occurred');
});
});
};
// AWS S3 upload example
editor.customConfig.customUploadImg = function(files, insert) {
Array.from(files).forEach(file => {
// Get presigned URL from your backend
fetch('/api/s3-presigned-url', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
fileName: file.name,
fileType: file.type
})
})
.then(response => response.json())
.then(data => {
// Upload directly to S3
return fetch(data.presignedUrl, {
method: 'PUT',
body: file,
headers: {
'Content-Type': file.type
}
});
})
.then(() => {
// Insert the S3 URL
const s3Url = `https://your-bucket.s3.amazonaws.com/${file.name}`;
insert(s3Url);
})
.catch(error => {
console.error('S3 upload error:', error);
alert('Upload to cloud storage failed');
});
});
};Integration with popular cloud storage services.
interface CloudConfig {
/** Enable Qiniu cloud upload */
qiniu?: boolean;
}Usage Examples:
// Qiniu cloud storage
editor.customConfig.qiniu = true;
editor.customConfig.uploadImgServer = 'https://your-qiniu-endpoint.com/upload';
// Custom cloud integration
editor.customConfig.customUploadImg = function(files, insert) {
// Cloudinary upload example
const cloudinaryUrl = 'https://api.cloudinary.com/v1_1/your-cloud-name/image/upload';
Array.from(files).forEach(file => {
const formData = new FormData();
formData.append('file', file);
formData.append('upload_preset', 'your-upload-preset');
fetch(cloudinaryUrl, {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(result => {
if (result.secure_url) {
insert(result.secure_url);
}
})
.catch(error => {
console.error('Cloudinary upload error:', error);
});
});
};interface UploadImgAPI {
/** Upload image files */
uploadImg(files: FileList | File[]): void;
}
interface UploadConfig {
// Server configuration
uploadImgServer?: string;
uploadFileName?: string;
uploadImgParams?: {[key: string]: any};
uploadImgHeaders?: {[key: string]: string};
withCredentials?: boolean;
uploadImgTimeout?: number;
// Upload limits
uploadImgMaxSize?: number;
uploadImgMaxLength?: number;
uploadImgShowBase64?: boolean;
// Upload hooks
uploadImgHooks?: {
before?: (xhr: XMLHttpRequest, editor: any, files: File[]) => void | false;
success?: (xhr: XMLHttpRequest, editor: any, result: any) => void;
fail?: (xhr: XMLHttpRequest, editor: any, result: any) => void;
error?: (xhr: XMLHttpRequest, editor: any, error: any) => void;
timeout?: (xhr: XMLHttpRequest, editor: any) => void;
customInsert?: (insertImg: Function, result: any, editor: any) => void;
};
// Cloud storage
qiniu?: boolean;
// Custom upload
customUploadImg?: (files: FileList, insert: (url: string) => void) => void;
// UI
customAlert?: (info: string) => void;
}// Upload with progress tracking
editor.customConfig.uploadImgHooks = {
before: function(xhr, editor, files) {
// Setup progress tracking
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
const percentComplete = (e.loaded / e.total) * 100;
updateProgressBar(percentComplete);
}
};
},
success: function(xhr, editor, result) {
hideProgressBar();
},
error: function(xhr, editor, error) {
hideProgressBar();
}
};// Handle multiple file uploads with coordination
let uploadCounter = 0;
let totalUploads = 0;
editor.customConfig.customUploadImg = function(files, insert) {
totalUploads = files.length;
uploadCounter = 0;
showUploadStatus(`Uploading ${totalUploads} images...`);
Array.from(files).forEach((file, index) => {
uploadSingleFile(file, insert, index);
});
};
function uploadSingleFile(file, insert, index) {
const formData = new FormData();
formData.append('image', file);
fetch('/api/upload', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(result => {
uploadCounter++;
updateUploadStatus(`Uploaded ${uploadCounter}/${totalUploads} images`);
if (result.success) {
insert(result.url);
}
if (uploadCounter === totalUploads) {
hideUploadStatus();
}
})
.catch(error => {
console.error(`Upload ${index + 1} failed:`, error);
uploadCounter++;
});
}// Client-side image optimization before upload
editor.customConfig.customUploadImg = function(files, insert) {
Array.from(files).forEach(file => {
// Optimize image before upload
optimizeImage(file, {
maxWidth: 1200,
maxHeight: 800,
quality: 0.8
})
.then(optimizedFile => {
return uploadToServer(optimizedFile);
})
.then(result => {
insert(result.url);
})
.catch(error => {
console.error('Image optimization/upload failed:', error);
});
});
};
function optimizeImage(file, options) {
return new Promise((resolve, reject) => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.onload = function() {
// Calculate new dimensions
let { width, height } = img;
const maxWidth = options.maxWidth || width;
const maxHeight = options.maxHeight || height;
if (width > maxWidth || height > maxHeight) {
const ratio = Math.min(maxWidth / width, maxHeight / height);
width *= ratio;
height *= ratio;
}
// Draw and compress
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
canvas.toBlob(resolve, file.type, options.quality || 0.9);
};
img.onerror = reject;
img.src = URL.createObjectURL(file);
});
}Install with Tessl CLI
npx tessl i tessl/npm-wangeditor