Цвет перо и проблему курсораJavascript

Форум по Javascript
Ответить
Anonymous
 Цвет перо и проблему курсора

Сообщение Anonymous »

Я внедряю пользовательский цветовой сборщик для Quill.js, чтобы пользователи выбирали цвета за пределами палитры по умолчанию. Мое решение включает в себя использование нативного элемента браузера, запускаемого пользовательским опцией «Picker» на панели инструментов. Выбранный текст в редакторе Quill должен обновить в режиме реального времени. При прослушивании входного события на элементе сборщика цвета, применение формата к редактору Quill заставляет курсор прыгать в начало редактора с каждым изменением цвета. Это делает живой предварительный просмотр непригодным.

Код: Выделить всё

import { Injectable } from '@angular/core';
import { Quill } from 'quill';

export interface QuillColorPickerConfig {
defaultColors?: string[];
colorPickerOption?: string;
onColorChange?: (content: string, quillInstance: Quill) => void;
}

@Injectable({
providedIn: 'root'
})
export class QuillCustomColorPickerService {

private readonly QUILL_DEFAULT_COLORS = [
"#000000", "#e60000", "#ff9900", "#ffff00", "#008a00", "#0066cc", "#9933ff",
"#ffffff", "#facccc", "#ffebcc", "#ffffcc", "#cce8cc", "#cce0f5", "#ebd6ff",
"#bbbbbb", "#f06666", "#ffc266", "#ffff66", "#66b966", "#66a3e0", "#c285ff",
"#888888", "#a10000", "#b26b00", "#b2b200", "#006100", "#0047b2", "#6b24b2",
"#444444", "#5c0000", "#663d00", "#666600", "#003700", "#002966", "#3d1466"
];

private currentQuillInstance: Quill | null = null;
private currentSelection: any = null;

/**
* Get default toolbar options with custom color picker
*/
getToolbarOptions(config?: QuillColorPickerConfig): any[] {
const colors = config?.defaultColors || this.QUILL_DEFAULT_COLORS;
const colorPickerOption = config?.colorPickerOption || 'color-picker';

const allCustomColors = [...colors, colorPickerOption];

return [
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'script': 'sub' }, { 'script': 'super' }],
[{ 'indent': '-1' }, { 'indent': '+1' }],
[{ 'direction': 'rtl' }],
[{ 'size': ['small', false, 'large', 'huge'] }],
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': allCustomColors }, { 'background': allCustomColors }],
[{ 'font': [] }],
[{ 'align': [] }],
['clean'],
['link']
];
}

/**
* Setup custom color picker for a Quill editor instance
*/
setupCustomColorPicker(quillEditor: Quill, config?: QuillColorPickerConfig): void {
if (!quillEditor) {
console.warn('QuillCustomColorPickerService: Quill editor instance is required');
return;
}

this.currentQuillInstance = quillEditor;
const toolbar = quillEditor.getModule('toolbar');
const colorPickerOption = config?.colorPickerOption || 'color-picker';

// Setup color handler
toolbar.addHandler('color', (value: string) => {
this.handleColorChange(quillEditor, value, 'color', colorPickerOption, config);
});

// Setup background color handler
toolbar.addHandler('background', (value: string) => {
this.handleColorChange(quillEditor, value, 'background', colorPickerOption, config);
});
}

private handleColorChange(
quillEditor: Quill,
value: string,
type: 'color' | 'background',
colorPickerOption: string,
config?: QuillColorPickerConfig
): void {
// Store current selection
this.currentSelection = quillEditor.getSelection(true);

if (value === colorPickerOption) {
// Show custom color picker
this.showColorPicker(quillEditor, type, config);
} else {
// Apply predefined color
this.applyColor(quillEditor, value, type, config);
}
}

private showColorPicker(
quillEditor: Quill,
type: 'color' | 'background',
config?: QuillColorPickerConfig
): void {
// Remove existing color picker if any
this.removeExistingColorPicker();

// Create color input element
const colorInput = document.createElement('input');
colorInput.type = 'color';
colorInput.id = `quill-${type}-picker`;
colorInput.style.position = 'absolute';
colorInput.style.visibility = 'hidden';
colorInput.style.width = '0';
colorInput.style.height = '0';

// Get current color value if text is selected
const currentColor = this.getCurrentColor(quillEditor, type);
if (currentColor) {
colorInput.value = currentColor;
}

// Add event listeners
colorInput.addEventListener('input', (event) => {
const target = event.target as HTMLInputElement;
this.applyColorWithPreview(quillEditor, target.value, type, config);
});

colorInput.addEventListener('change', (event) =>  {
const target = event.target as HTMLInputElement;
this.applyColor(quillEditor, target.value, type, config);
this.removeExistingColorPicker();
});

colorInput.addEventListener('blur', () => {
setTimeout(() => this.removeExistingColorPicker(), 100);
});

// Add to DOM and trigger click
document.body.appendChild(colorInput);
colorInput.click();
}

private applyColorWithPreview(
quillEditor: Quill,
color: string,
type: 'color' | 'background',
config?: QuillColorPickerConfig
): void {
if (!this.currentSelection) return;

// Apply color to current selection
if (this.currentSelection.length > 0) {
quillEditor.setSelection(this.currentSelection.index, this.currentSelection.length);
quillEditor.format(type, color);
} else {
// Set formatting for next input
quillEditor.format(type, color);
}

// Notify color change
this.notifyColorChange(quillEditor, config);
}

private applyColor(
quillEditor: Quill,
color: string,
type: 'color' | 'background',
config?: QuillColorPickerConfig
): void {
if (!this.currentSelection) return;

// Restore selection
quillEditor.setSelection(this.currentSelection.index, this.currentSelection.length);

if (this.currentSelection.length > 0) {
// Apply to selected text
quillEditor.formatText(this.currentSelection.index, this.currentSelection.length, type, color);
} else {
// Set formatting for next input
quillEditor.format(type, color);
}

// Focus back to editor
quillEditor.focus();

// Notify color change
this.notifyColorChange(quillEditor, config);
}

private getCurrentColor(quillEditor: Quill, type: 'color' | 'background'): string | null {
if (!this.currentSelection || this.currentSelection.length === 0) {
return null;
}

const format = quillEditor.getFormat(this.currentSelection.index, this.currentSelection.length);
return format[type] || null;
}

private removeExistingColorPicker(): void {
const existingPickers = document.querySelectorAll('[id^="quill-"][id$="-picker"]');
existingPickers.forEach(picker => picker.remove());
}

private notifyColorChange(quillEditor: Quill, config?: QuillColorPickerConfig): void {
if (config?.onColorChange) {
const htmlContent = quillEditor.root.innerHTML;
config.onColorChange(htmlContent, quillEditor);
}
}

/**
* Clean up method to remove any remaining color pickers
*/
cleanup(): void {
this.removeExistingColorPicker();
this.currentQuillInstance = null;
this.currentSelection = null;
}
}



Подробнее здесь: https://stackoverflow.com/questions/797 ... rsor-issue
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»