diff --git a/.github/assets/bytescale-upload-widget-jquery.svg b/.github/assets/bytescale-upload-widget-jquery.svg new file mode 100644 index 0000000..665c4c3 --- /dev/null +++ b/.github/assets/bytescale-upload-widget-jquery.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e2f20a..26fb9b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: env: SLACK_CHANNEL: deployments SLACK_COLOR: "#17BB5E" - SLACK_TITLE: "Built: jquery-uploader :rocket:" + SLACK_TITLE: "Built: @bytescale/upload-widget-jquery :rocket:" SLACK_FOOTER: "This package was successfully built." MSG_MINIMAL: true SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} @@ -67,7 +67,7 @@ jobs: env: SLACK_CHANNEL: deployments SLACK_COLOR: "#BB1717" - SLACK_TITLE: "Failed: jquery-uploader :boom:" + SLACK_TITLE: "Failed: @bytescale/upload-widget-jquery :boom:" SLACK_FOOTER: "No packages published." MSG_MINIMAL: true SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} diff --git a/BUILD.md b/BUILD.md index e7663cb..d608c29 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,6 +1,6 @@ # Building From Source -This repository contains a hot-reloading sandbox for developing the `@upload-io/jquery-uploader` NPM package. +This repository contains a hot-reloading sandbox for developing the `@bytescale/upload-widget-jquery` NPM package. ## Prerequisites @@ -16,8 +16,8 @@ This repository contains a hot-reloading sandbox for developing the `@upload-io/ ### 1. Clone ```shell -git clone git@github.com:bytescale/jquery-uploader.git -cd jquery-uploader +git clone git@github.com:bytescale/bytescale-upload-widget-jquery.git +cd bytescale-upload-widget-jquery ``` ### 2. Setup Environment @@ -38,6 +38,6 @@ npm install npm start ``` -The above launches a **hot-reloading** server on `http://127.0.0.1:3050` that uses `@upload-io/jquery-uploader` from source. +The above launches a **hot-reloading** server on `http://127.0.0.1:3050` that uses `@bytescale/upload-widget-jquery` from source. _Please ensure nothing else is running on TCP port `3050`_. diff --git a/MIGRATE.md b/MIGRATE.md new file mode 100644 index 0000000..8f866c3 --- /dev/null +++ b/MIGRATE.md @@ -0,0 +1,110 @@ +# Migration Guide + +## From jQuery Uploader (`@upload-io/jquery-uploader`) + +Steps: + +1. Install `@bytescale/upload-widget-jquery` +2. Uninstall `@upload-io/jquery-uploader` and `uploader` +3. Replace `"@upload-io/jquery-uploader"` with `"@bytescale/upload-widget-jquery"` in your `import` statements. +4. Replace `uploader` with `upload-widget` in all CSS class name overrides (if you have any). +5. Remove `uploader` (from imports and props) +6. Remove `$.uploader.init(...)` +7. Replace `.uploader({...})` with `.bytescaleUploadWidget({...})` +8. Add `apiKey` as a field to the object passed to the `bytescaleUploadWidget` method (add it if you don't have one). + +### Before + +```html + + + +``` + +### After + +```html + + + +``` + +## See also + +Bytescale migration guides listed below: + +- [Migrating from `upload-js` to `@bytescale/sdk`](https://github.com/bytescale/bytescale-javascript-sdk/blob/main/MIGRATE.md) +- [Migrating from `uploader` to `@bytescale/upload-widget`](https://github.com/bytescale/bytescale-upload-widget/blob/main/MIGRATE.md) +- [Migrating from `jquery-uploader` to `@bytescale/upload-widget-jquery`](https://github.com/bytescale/bytescale-upload-widget-jquery/blob/main/MIGRATE.md) +- [Migrating from `angular-uploader` to `@bytescale/upload-widget-angular`](https://github.com/bytescale/bytescale-upload-widget-angular/blob/main/MIGRATE.md) +- [Migrating from `@upload-io/vue-uploader` to `@bytescale/upload-widget-vue`](https://github.com/bytescale/bytescale-upload-widget-vue/blob/main/MIGRATE.md) +- [Migrating from `@upload-io/jquery-uploader` to `@bytescale/upload-widget-jquery`](https://github.com/bytescale/bytescale-upload-widget-jquery/blob/main/MIGRATE.md) diff --git a/README.md b/README.md index c0ca20e..1163f19 100644 --- a/README.md +++ b/README.md @@ -1,105 +1,100 @@

- - jQuery Uploader + + Bytescale Upload Widget for jQuery

-

jQuery File Upload Widget
(With Integrated Cloud Storage)

+

Beautiful File Upload Widget for jQuery
(With Built-in Cloud Storage)


- - + + - - + + - - + + - - + +
- + - - + + - - Twitter URL + + Twitter URL

Get Started — - + Try on CodePen

-

Upload Widget Demo

+

Upload Widget Demo

100% Serverless File Upload Widget
Powered by Bytescale

+
-

DMCA CompliantGDPR Compliant99.9% Uptime SLA -
- Supports: Rate Limiting, Volume Limiting, File Size & Type Limiting, JWT Auth, and more... +

+ Supports: Image Cropping, Video Previews, Document Previews, Drag & Drop, Multiple Files & More... +

+ Full DocumentationHeadless SDKMedia Processing APIsStorageCDN


+

-# Installation +## Installation Install via NPM: ```shell -npm install jquery @upload-io/jquery-uploader +npm install jquery@^3.6.0 @bytescale/upload-widget-jquery ``` Or via YARN: ```shell -yarn add jquery @upload-io/jquery-uploader +yarn add jquery@^3.6.0 @bytescale/upload-widget-jquery ``` Or via a ` - + ``` ## Usage -### Step 1) Initialize the `uploader` plugin - -Call this once only — at the start of your app — before calling `$(x).uploader()`. - -```javascript -// Get production-ready API keys from Bytescale -$.uploader.init({ - apiKey: "free" -}); -``` - -### Step 2) Display the Upload Widget +### Option 1) Create an Upload Button To display a **file upload dialog** on click — [Try on CodePen](https://codepen.io/bytescale/pen/ZEvoJaG?editors=1000) ```javascript $(() => { - $("button").uploader({ + $("button").bytescaleUploadWidget({ + // Full Configuration: + // https://www.bytescale.com/docs/upload-widget#configuration + apiKey: "free", // Get API keys from: www.bytescale.com onComplete: files => { if (files.length === 0) { console.log('No files selected.') @@ -112,11 +107,16 @@ $(() => { }); ``` +### Option 2) Create a Dropzone Area + To display a **file upload dropzone** inline on the page — [Try on CodePen](https://codepen.io/bytescale/pen/ExRrgRx?editors=1000) ```javascript $(() => { - $("div").uploader({ + $("div").bytescaleUploadWidget({ + // Full Configuration: + // https://www.bytescale.com/docs/upload-widget#configuration + apiKey: "free", // Get API keys from: www.bytescale.com dropzone: { width: "600px", height: "375px" @@ -133,9 +133,9 @@ $(() => { }); ``` -## The Result +## Result -All callbacks receive an `Array`: +The callbacks receive a `Array`: ```javascript { @@ -165,44 +165,136 @@ All callbacks receive an `Array`: } ``` -# 🌐 API Support +## ⚙️ Configuration -## 🌐 File Management API +All configuration is optional (except for the `apiKey` field, which is required). -Bytescale provides an [Upload API](https://www.bytescale.com/docs/upload-api), which supports the following: +```javascript +const options = { + apiKey: "free", // Get API keys from: www.bytescale.com + locale: myCustomLocale, // EN_US by default. (See "Localization" section below.) + maxFileCount: 5, // Unlimited by default (or 1 if multi: false). + maxFileSizeBytes: 1024 ** 2, // Unlimited by default. + mimeTypes: ["image/*"], // Unrestricted by default. Supports * wildcard suffix. + multi: false, // False by default. + onInit: ({ // Exposes lifecycle methods for the component. + close, // Closes the widget when called. + reset, // Resets the widget when called. + updateConfig // Updates the widget's config by passing a new config + }) => {}, // object to the method's first parameter. + onUpdate: files => {}, // Called each time the list of uploaded files change. + onPreUpload: async file => ({ + errorMessage: "Uh oh!", // Displays this validation error to the user (if set). + transformedFile: file // Uploads 'transformedFile' instead of 'file' (if set). + }), + showFinishButton: true, // Show/hide the "finish" button in the widget. + showRemoveButton: true, // Show/hide the "remove" button next to each file. + styles: { + colors: { + primary: "#377dff", // Primary buttons & links + active: "#528fff", // Primary buttons & links (hover). Inferred if undefined. + error: "#d23f4d", // Error messages + shade100: "#333", // Standard text + shade200: "#7a7a7a", // Secondary button text + shade300: "#999", // Secondary button text (hover) + shade400: "#a5a6a8", // Welcome text + shade500: "#d3d3d3", // Modal close button + shade600: "#dddddd", // Border + shade700: "#f0f0f0", // Progress indicator background + shade800: "#f8f8f8", // File item background + shade900: "#fff" // Various (draggable crop buttons, etc.) + }, + fontFamilies: { + base: "arial, sans-serif" // Base font family (comma-delimited). + }, + fontSizes: { + base: 16 // Base font size (px). + } + }, + path: { // Optional: a string (full file path) or object like so: + fileName: "Example.jpg", // Supports path variables (e.g. {ORIGINAL_FILE_EXT}). + folderPath: "/uploads" // Please refer to docs for all path variables. + }, + metadata: { + hello: "world" // Arbitrary JSON metadata (saved against the file). + }, + tags: ["profile_picture"], // Requires a Bytescale account. + editor: { + images: { + preview: true, // True by default if cropping is enabled. Previews PDFs and videos too. + crop: true, // True by default. + cropFilePath: image => { // Choose the file path used for JSON image crop files. + const {filePath} = image // In: https://www.bytescale.com/docs/upload-api/types/FileDetails + return `${filePath}.crop` // Out: https://www.bytescale.com/docs/upload-api/types/FilePathDefinition + }, + cropRatio: 4 / 3, // Width / Height. Undefined enables freeform (default). + cropShape: "rect" // "rect" (default) or "circ". + } + }, +} +``` -- File uploading. -- File listing. -- File deleting. -- And more... +### 🏳️ Localization -Uploading a `"Hello World"` text file is as simple as: +Default is [EN_US](https://github.com/bytescale/bytescale-upload-widget-jquery/blob/main/lib/src/modules/locales/EN_US.ts): -```shell -curl --data "Hello World" \ - -u apikey:free \ - -X POST "https://api.bytescale.com/v1/files/basic" +```javascript +const myCustomLocale = { + "error!": "Error!", + "done": "Done", + "addAnotherFile": "Add another file...", + "addAnotherImage": "Add another image...", + "cancel": "cancel", + "cancelInPreviewWindow": "Cancel", + "cancelled!": "cancelled", + "continue": "Continue", + "customValidationFailed": "Failed to validate file.", + "crop": "Crop", + "finish": "Finished", + "finishIcon": true, + "image": "Image", + "maxFilesReached": "Maximum number of files:", + "maxImagesReached": "Maximum number of images:", + "maxSize": "File size limit:", + "next": "Next", + "of": "of", + "orDragDropFile": "...or drag and drop a file.", + "orDragDropFiles": "...or drag and drop files.", + "orDragDropImage": "...or drag and drop an image.", + "orDragDropImages": "...or drag and drop images.", + "pleaseWait": "Please wait...", + "removed!": "removed", + "remove": "remove", + "skip": "Skip", + "unsupportedFileType": "File type not supported.", + "uploadFile": "Upload a File", + "uploadFiles": "Upload Files", + "uploadImage": "Upload an Image", + "uploadImages": "Upload Images", + "validatingFile": "Validating file..." +} ``` -_Note: Remember to set `-H "Content-Type: mime/type"` when uploading other file types!_ +# 🌐 API Support -[Read the Upload API docs »](https://www.bytescale.com/docs/upload-api) +## 🌐 File Management APIs -## 🌐 Image Processing API (Resize, Crop, etc.) +Bytescale provides a wide range of [File Management APIs](https://www.bytescale.com/docs/apis): -Bytescale also provides an [Image Processing API](https://www.bytescale.com/docs/image-processing-api), which supports the following: +- **[File Listing](https://www.bytescale.com/docs/folder-api/ListFolder)** +- **[File Deleting](https://www.bytescale.com/docs/file-api/DeleteFile)** +- **[File Copying](https://www.bytescale.com/docs/file-api/CopyFile)** +- [And more...](https://www.bytescale.com/docs/apis) -- [Image Resizing](https://www.bytescale.com/docs/image-processing-api#image-resizing-api) -- [Image Cropping](https://www.bytescale.com/docs/image-processing-api#image-cropping-api) -- [Image Compression](https://www.bytescale.com/docs/image-processing-api#image-compression-api) -- [Image Conversion](https://www.bytescale.com/docs/image-processing-api#f) -- [Image Manipulation (blur, sharpen, brightness, etc.)](https://www.bytescale.com/docs/image-processing-api#image-manipulation-api) -- [Layering (e.g for text & image watermarks)](https://www.bytescale.com/docs/image-processing-api#image) -- and more... +## 🌐 Media Processing APIs (Image/Video/Audio) -[Read the Image Processing API docs »](https://www.bytescale.com/docs/image-processing-api) +Bytescale also provides real-time [Media Processing APIs](https://www.bytescale.com/docs/media-processing-apis): -### Original Image +- **[Image Processing APIs](https://www.bytescale.com/docs/image-processing-api)** ([resize](https://www.bytescale.com/docs/image-processing-api#image-resizing-api), [crop](https://www.bytescale.com/docs/image-processing-api#image-cropping-api), [convert](https://www.bytescale.com/docs/image-processing-api#f), [compress](https://www.bytescale.com/docs/image-processing-api#image-compression-api) & [watermark](https://www.bytescale.com/docs/image-processing-api#Text-layering-api)) +- **[Video Processing APIs](https://www.bytescale.com/docs/video-processing-api)** ([transcode](https://www.bytescale.com/docs/video-processing-api#video-transcoding-api), [optimize](https://www.bytescale.com/docs/video-processing-api#video-compression-api), [resize](https://www.bytescale.com/docs/video-processing-api#video-resizing-api) & [extract metadata](https://www.bytescale.com/docs/video-processing-api#video-metadata-api)) +- **[Audio Processing APIs](https://www.bytescale.com/docs/audio-processing-api)** ([transcode](https://www.bytescale.com/docs/audio-processing-api#audio-transcoding-api), [optimize](https://www.bytescale.com/docs/audio-processing-api#audio-compression-api), [trim](https://www.bytescale.com/docs/audio-processing-api#audio-trimming-api) & [extract metadata](https://www.bytescale.com/docs/audio-processing-api#audio-metadata-api)) + +### Image Processing API (Original Image) Here's an example using [a photo of Chicago](https://upcdn.io/W142hJk/raw/example/city-landscape.jpg): @@ -212,7 +304,7 @@ Here's an example using [a photo of Chicago](https://upcdn.io/W142hJk/raw/exampl https://upcdn.io/W142hJk/raw/example/city-landscape.jpg ``` -### Processed Image +### Image Processing API (Transformed Image) Using the [Image Processing API](https://www.bytescale.com/docs/image-processing-api), you can produce [this image](https://upcdn.io/W142hJk/image/example/city-landscape.jpg?w=900&h=600&fit=crop&f=webp&q=80&blur=4&text=WATERMARK&layer-opacity=80&blend=overlay&layer-rotate=315&font-size=100&padding=10&font-weight=900&color=ffffff&repeat=true&text=Chicago&gravity=bottom&padding-x=50&padding-bottom=20&font=/example/fonts/Lobster.ttf&color=ffe400): @@ -243,31 +335,161 @@ https://upcdn.io/W142hJk/image/example/city-landscape.jpg &color=ffe400 ``` -## Full Documentation +## Authorization + +Bytescale supports two types of authorization: + +### API Keys + +The Bytescale Upload Widget uses the `apiKey` parameter to authenticate with the [Bytescale API](https://www.bytescale.com/docs/apis). + +With API key auth, the requester has access to the resources available to the API key: -[Uploader Documentation »](https://www.bytescale.com/docs/upload-widget) +- Secret API keys (`secret_***`) have access to all API endpoints (see the [Bytescale JavaScript SDK](https://www.bytescale.com/docs/sdks/javascript)). -## Need a Headless (no UI) File Upload Library? +- Public API keys (`public_***`) have access to file upload, file download, and file listing API endpoints. File overwrites, file deletes, and all other destructive operations cannot be performed using public API keys. File listing is also disabled by default (but can be changed in the API key's settings). -[Try Upload.js »](https://www.bytescale.com/upload-js) +You must always use **public API keys** (e.g. `public_***`) in your client-side code. + +Each API key can have its read/write access limited to a subset of files/folders. + +### JWT Cookies + +JWT cookies are optional. + +With JWT cookies, the user can download private files directly via the URL, as authorization is performed implicitly via a session cookie. This allows the browser to display private files in `` and `