Alt text functionality for accessibility compliance with form-based editing and validation.
Main alt text plugin that combines editing and UI functionality.
/**
* Main alt text plugin that combines editing and UI functionality
*/
class ImageTextAlternative {
static pluginName: 'ImageTextAlternative';
static requires: [ImageTextAlternativeEditing, ImageTextAlternativeUI];
static isOfficialPlugin: true;
}Usage:
import { ImageTextAlternative } from '@ckeditor/ckeditor5-image';
import { ClassicEditor } from '@ckeditor/ckeditor5-editor-classic';
ClassicEditor
.create(document.querySelector('#editor'), {
plugins: [ImageTextAlternative],
image: {
toolbar: ['imageTextAlternative']
}
});Core editing functionality for image alt text with schema and command registration.
/**
* Core editing functionality for image alt text with schema and command registration
*/
class ImageTextAlternativeEditing {
static pluginName: 'ImageTextAlternativeEditing';
static requires: [ImageUtils];
static isOfficialPlugin: true;
}User interface for image alt text with form-based editing.
/**
* User interface for image alt text with form-based editing
*/
class ImageTextAlternativeUI {
static pluginName: 'ImageTextAlternativeUI';
static requires: [ImageTextAlternativeEditing, ContextualBalloon];
static isOfficialPlugin: true;
}Command for setting alt text on selected images.
/**
* Command for setting alt text on selected images
*/
class ImageTextAlternativeCommand {
constructor(editor: Editor);
/**
* Execute alt text update
* @param options - Alt text options
*/
execute(options: { newValue: string }): void;
/** Current alt text value or empty string */
readonly value: string;
/** True if command can be executed (image is selected) */
readonly isEnabled: boolean;
}Usage:
// Set alt text for selected image
editor.execute('imageTextAlternative', {
newValue: 'A beautiful sunset over the mountains'
});
// Get current alt text
const command = editor.commands.get('imageTextAlternative');
console.log('Current alt text:', command.value);
console.log('Can edit alt text:', command.isEnabled);
// Clear alt text
editor.execute('imageTextAlternative', { newValue: '' });
// Listen for alt text changes
command.on('change:value', (evt, name, value, oldValue) => {
console.log('Alt text changed from:', oldValue, 'to:', value);
});The alt text functionality provides a contextual form for editing:
/**
* Form view for editing image alternative text
*/
class _ImageTextAlternativeFormView {
constructor(locale: any);
/** Text input for alt text */
labeledInput: any;
/** Save button */
saveButtonView: any;
/** Cancel button */
cancelButtonView: any;
/** Form validation state */
isValid: boolean;
/**
* Render the form
*/
render(): void;
/**
* Focus the input field
*/
focus(): void;
/**
* Destroy the form
*/
destroy(): void;
}The plugin ensures proper ARIA attributes for accessibility:
alt attribute on <img> elements// Good alt text examples
editor.execute('imageTextAlternative', {
newValue: 'Line graph showing sales increase from 2020 to 2023'
});
editor.execute('imageTextAlternative', {
newValue: 'Portrait of Jane Smith, company CEO'
});
// Decorative images - empty alt text
editor.execute('imageTextAlternative', {
newValue: ''
});
// Bad examples (avoid these)
// editor.execute('imageTextAlternative', { newValue: 'image' });
// editor.execute('imageTextAlternative', { newValue: 'photo.jpg' });
// editor.execute('imageTextAlternative', { newValue: 'click here' });Alt text is stored as the alt attribute on image elements:
// Model structure
interface ImageElement {
name: 'imageBlock' | 'imageInline';
attributes: {
src: string;
alt?: string; // Alt text attribute
width?: string;
height?: string;
};
}// View output
interface ImageView {
name: 'img';
attributes: {
src: string;
alt?: string; // Converted from model alt attribute
width?: string;
height?: string;
};
}Usage with Model:
// Access alt text through model
editor.model.change(writer => {
const imageElement = /* get image element */;
// Set alt text
writer.setAttribute('alt', 'Description of the image', imageElement);
// Get alt text
const altText = imageElement.getAttribute('alt');
console.log('Alt text:', altText);
// Remove alt text
writer.removeAttribute('alt', imageElement);
});
// Listen for alt text changes in model
editor.model.document.on('change:data', () => {
const changes = editor.model.document.differ.getChanges();
for (const change of changes) {
if (change.type === 'attribute' && change.attributeKey === 'alt') {
console.log('Alt text changed on:', change.range);
}
}
});The alt text form includes validation:
// Form validation rules
const validation = {
maxLength: 255, // Typical alt text length limit
required: false, // Alt text is optional but recommended
// Custom validation can be added
validate(value) {
if (value.length > 255) {
return 'Alt text should be shorter than 255 characters';
}
if (value.toLowerCase().startsWith('image of')) {
return 'Avoid starting with "image of" - describe the content directly';
}
return null; // Valid
}
};While the plugin doesn't have specific configuration options, it integrates with image toolbar configuration:
ClassicEditor
.create(document.querySelector('#editor'), {
image: {
toolbar: [
'imageTextAlternative', // Alt text button
'toggleImageCaption',
'|',
'imageStyle:inline',
'imageStyle:block'
]
}
});/**
* Check if element is an image with alt text capability
* @param element - Model element to check
* @returns True if element supports alt text
*/
function isImageWithAltTextSupport(element: any): boolean;
/**
* Get image balloon positioning data for alt text form
* @param editor - Editor instance
* @returns Positioning configuration
*/
function _getImageBalloonPositionData(editor: any): any;
/**
* Reposition image contextual balloon
* @param editor - Editor instance
*/
function _repositionImageContextualBalloon(editor: any): void;// Events fired during alt text operations
interface ImageTextAlternativeEvents {
/** Fired when alt text form is opened */
'imageTextAlternative:open': {
imageElement: any;
formView: any;
};
/** Fired when alt text form is closed */
'imageTextAlternative:close': {
imageElement: any;
wasCancelled: boolean;
};
/** Fired when alt text is saved */
'imageTextAlternative:save': {
imageElement: any;
oldValue: string;
newValue: string;
};
}Usage:
// Listen for alt text events
editor.on('imageTextAlternative:save', (evt, data) => {
console.log('Alt text updated:', {
old: data.oldValue,
new: data.newValue,
element: data.imageElement
});
});
editor.on('imageTextAlternative:open', (evt, data) => {
console.log('Alt text form opened for image');
// Could add custom validation or hints
data.formView.on('ready', () => {
// Form is ready for interaction
});
});