WY Image Plugin for Redactor
Status: Production Ready
Version: 1.0.0
Last Updated: January 2025
Overview
Section titled “Overview”The WY Image plugin enables rich image insertion in the Redactor editor with full ImageKit transformation support. Users can select images from the library, customize cropping/sizing/effects, and insert optimized images with proper srcset attributes for responsive delivery.
Architecture
Section titled “Architecture”┌──────────────┐ Select ┌──────────────────┐ Configure ┌─────────────────┐│ WY Image │─────────────►│ Image Picker │──────────────►│ Image Options ││ Toolbar Btn │ │ Modal │ │ Editor Modal │└──────────────┘ └──────────────────┘ └────────┬────────┘ │ ┌──────────────────┐ │ Insert │ oEmbed API │◄───────────────────────┘ │ /api/v1/oembed │ │ /image │ └────────┬─────────┘ │ ┌────────▼─────────┐ │ ImageKit URL │ │ with transforms │ └──────────────────┘Features
Section titled “Features”Image Picker Modal
Section titled “Image Picker Modal”- Search modes: Keyword, AI semantic, Hybrid
- Filters: Tags, source, colorspace, dimensions, product line
- Tom Select: Searchable multi-select dropdowns
- Infinite scroll: Loads more results on scroll
- Filter badge: Shows count of active filters
Image Options Editor
Section titled “Image Options Editor”| Tab | Options |
|---|---|
| Basic | Caption, alt text, size presets, custom dimensions |
| Crop | Visual cropping with Cropper.js |
| Advanced | Format, quality, blur, border, background color, lazy loading, srcset |
Live Preview
Section titled “Live Preview”- Preview updates in real-time as options change
- ImageKit URL displayed and copy-able
- Lightbox for full-size preview
oEmbed Integration
Section titled “oEmbed Integration”Images are inserted via an internal oEmbed endpoint that generates the full HTML:
<figure class="wy-image-embed" data-wy-image-id="12345" data-wy-image-options='{"width":800}'> <img src="https://ik.warmlyyours.com/img/..." srcset="..." sizes="..." alt="..." class="img-fluid" loading="lazy"> <figcaption class="figure-caption">Optional caption</figcaption></figure>Inserting a New Image
Section titled “Inserting a New Image”- Click WY Image button in toolbar
- Search/filter to find the image
- Click image thumbnail to select
- Configure options in the editor modal
- Click Insert Image
Editing an Existing Image
Section titled “Editing an Existing Image”- Click on an embedded image in the editor
- Select WY Image from context menu
- Modify options in the editor modal
- Click Update Image
Image Options
Section titled “Image Options”Size Presets
Section titled “Size Presets”| Preset | Dimensions | Use Case |
|---|---|---|
| Small | 400px | Thumbnails, inline |
| Medium | 800px | Standard content |
| Large | 1200px | Hero images |
| Full Width | 2000px | Full-bleed layouts |
| Custom | User-defined | Specific requirements |
Cropping
Section titled “Cropping”The visual cropper uses Cropper.js with coordinate scaling:
// Coordinates are scaled from displayed size to original dimensionsconst scaleX = originalWidth / displayedWidthconst scaleY = originalHeight / displayedHeight
cropParams = { x: Math.round(cropData.x * scaleX), y: Math.round(cropData.y * scaleY), w: Math.round(cropData.width * scaleX), h: Math.round(cropData.height * scaleY)}Advanced Options
Section titled “Advanced Options”| Option | Description | Values |
|---|---|---|
| Format | Output format | Auto, JPEG, PNG, WebP, AVIF |
| Quality | Compression | 1-100 (default: 80) |
| Blur | Gaussian blur | 0-100 |
| Border | Border width | 0-20px |
| Border Color | Border color | Hex color |
| Background | Pad color | Hex color |
| Lazy Load | Native lazy loading | On/Off |
| Include srcset | Responsive images | On/Off |
API Endpoints
Section titled “API Endpoints”Image Picker Modal
Section titled “Image Picker Modal”GET /redactor/image_picker_modalParameters: - callback: JavaScript callback function nameImage Options Modal
Section titled “Image Options Modal”GET /redactor/image_options_modalParameters: - image_id: Selected image ID - callback: JavaScript callback function name - caption: Pre-fill caption (for editing) - alt: Pre-fill alt text (for editing)oEmbed Image
Section titled “oEmbed Image”GET /api/v1/oembed/imageParameters: - image_id: Image record ID - caption: Figure caption - alt: Alt text - width: Max width - height: Max height - crop_x, crop_y, crop_w, crop_h: Crop region - format: Output format - quality: Compression quality - blur: Blur amount - border: Border width - border_color: Border color - background: Background color - lazy: Enable lazy loading - srcset: Include srcset attribute| File | Purpose |
|---|---|
client/js/common/wyimage4.js | Redactor plugin |
app/javascript/controllers/image_picker_controller.js | Picker modal logic |
app/javascript/controllers/image_editor_controller.js | Options editor logic |
app/views/crm/redactor_image_picker/_modal.html.erb | Picker modal view |
app/views/crm/redactor_image_picker/_options_modal.html.erb | Options modal view |
app/controllers/crm/redactor_image_picker_controller.rb | Modal endpoints |
app/controllers/api/v1/oembed_controller.rb | oEmbed endpoint |
app/services/oembed/image_provider.rb | Image HTML generation |
Stimulus Controllers
Section titled “Stimulus Controllers”image_picker_controller
Section titled “image_picker_controller”Targets:
searchInput,results,loadingmodeButton,modeIcon,searchButtonfilterBadge,tagsFilter,excludeTagsFiltersourceFilter,colorspaceFilter,productLineFilterminWidthFilter,minHeightFilter
Values:
callback: Callback function namesearchUrl: Image search endpointsearchMode: keyword | ai | hybridplaceholders: Mode-specific placeholder texticons: Mode-specific icons
image_editor_controller
Section titled “image_editor_controller”Targets:
preview,urlDisplay,urlCopied,copyBtncaption,alt,sizePreset,customDimensionswidth,height,lockAspect,link,linkTargetcropperContainer,cropperImage,cropInfoformat,quality,qualityValue,blur,blurValueborder,borderColor,bgColor,lazyload,includeSrcset
Values:
imageId: Selected image IDimageUrl: Full image URLbaseUrl: Raw ImageKit URLimageWidth,imageHeight: Original dimensionsimageAlt: Default alt textcallback: Insert callback function name
Troubleshooting
Section titled “Troubleshooting”Image Not Inserting
Section titled “Image Not Inserting”Cause: oEmbed endpoint error
Fix: Check browser console for API errors, verify image_id is valid
Cropping Ignored
Section titled “Cropping Ignored”Cause: Coordinate scaling mismatch
Fix: Ensure original dimensions are passed via data attributes
Preview Not Updating
Section titled “Preview Not Updating”Cause: Debounce delay or missing target
Fix: Check updatePreview() is called and targets exist
Tom Select Not Initializing
Section titled “Tom Select Not Initializing”Cause: DOM not ready when controller connects
Fix: Ensure Tom Select controller is on the select element
Related Documentation
Section titled “Related Documentation”- Blog Editor UX - Editor layout and configuration
- Redactor Configuration - All editor modes
- Imageable Concern - ImageKit URL building