Hi, I want to collaborate with your component, but I don't know exactly how.
I have done a few of changes:
One to get a new button for the font size
and the other one to translate to Spanish.
If you like my solution, or you want to improve I wold be proud of it.
I send the modifieds files.
Thanks
`import {
Component,
ElementRef,
EventEmitter,
Input,
OnChanges,
OnInit,
Output,
SimpleChanges,
ViewChild,
ViewEncapsulation,
forwardRef,
} from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { NgxWigToolbarService, TButton } from './ngx-wig-toolbar.service';
@component({
selector: 'ngx-wig',
templateUrl: './ngx-wig.html',
styleUrls: ['./ngx-wig.css'],
providers: [
NgxWigToolbarService,
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NgxWigComponent),
multi: true
}
],
encapsulation: ViewEncapsulation.None
})
export class NgxWigComponent implements OnInit, OnChanges, ControlValueAccessor {
@input()
public content: string;
@input()
public placeholder: string;
@input()
public buttons: string;
@input()
public disabled: boolean;
@input()
public language: string = 'en';
@input()
public isSourceModeAllowed = false;
@output()
public contentChange = new EventEmitter();
@ViewChild('ngWigEditable')
public ngxWigEditable: ElementRef;
public editMode = false;
public container: HTMLElement;
public toolbarButtons: TButton[] = [];
public hasFocus = false;
public iconsTheme: string;
public constructor(
private _ngWigToolbarService: NgxWigToolbarService
) {
// hardcoded icons theme for now
this.iconsTheme = nw-button-mdi
;
}
public toggleEditMode(): void {
this.editMode = !this.editMode;
}
public execCommand(command: string, options: string): boolean {
if (this.editMode) {
return false;
}
if (document.queryCommandSupported && !document.queryCommandSupported(command)) {
throw 'The command "' + command + '" is not supported';
}
if (command === 'createlink' || command === 'insertImage' || command === 'fontSize') {
if (command === 'fontSize') {
options = window.prompt(this._ngWigToolbarService.resource().enterURL, '3');
if (options != '1' && options != '2' && options != '3' && options != '4' &&
options != '5' && options != '6' && options != '7')
return;
}
else {
options = window.prompt(this._ngWigToolbarService.resource().enterURL, 'http://');
if (!options) {
return;
}
}
}
this.container.focus();
// use insertHtml for `createlink` command to account for IE/Edge purposes, in case there is no selection
let selection = document.getSelection().toString();
if (command === 'createlink' && selection === '') {
document.execCommand('insertHtml', false, '<a href="' + options + '">' + options + '</a>');
} else {
document.execCommand(command, false, options);
}
this._onContentChange(this.container.innerHTML);
}
public ngOnInit(): void {
this._ngWigToolbarService.language(this.language);
this.toolbarButtons = this._ngWigToolbarService.getToolbarButtons(this.buttons);
this.container = this.ngxWigEditable.nativeElement;
if (this.content) {
this.container.innerHTML = this.content;
}
}
private _onContentChange(newContent: string): void {
this.content = newContent;
this.contentChange.emit(this.content);
this.propagateChange(this.content);
}
public ngOnChanges(changes: SimpleChanges): void {
if (this.container && changes['content']) {
// clear the previous content
this.container.innerHTML = '';
// add the new content
this.pasteHtmlAtCaret(changes['content'].currentValue);
}
}
public onTextareaChange(newContent: string): void {
// model -> view
this.container.innerHTML = newContent;
this._onContentChange(newContent);
}
public writeValue(value: any): void {
if (!value) { value = ''; }
this.container.innerHTML = value;
this._onContentChange(value);
}
public shouldShowPlaceholder(): boolean {
return this.placeholder
&& !this.container.innerText;
}
private pasteHtmlAtCaret(html) {
let sel, range;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
// append the content in a temporary div
let el = document.createElement('div');
el.innerHTML = html;
let frag = document.createDocumentFragment(), node, lastNode;
while ( (node = el.firstChild) ) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
}
}
public registerOnChange(fn: any): void {
this.propagateChange = fn;
}
public registerOnTouched(fn: () => void): void {
this.propagateTouched = fn;
}
private propagateChange: any = (_: any) => { };
public propagateTouched = () => {};
onBlur() {
this.hasFocus = false;
this.propagateTouched();
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
}
}
export type TButton = {
title?: string,
command?: string,
styleClass?: string,
pluginName?: string,
isComplex?: boolean
};
export type TResource = {
language: string,
unorderedList: string,
orderedList: string,
bold: string,
italic: string,
link: string,
underline: string,
fontSize: string,
enterURL: string,
insertFontSize:string
}
export type TButtonLibrary = {
[name: string]: TButton
};
export class NgxWigToolbarService {
private _resources: TResource[];
private getResources(): TResource[] {
return this._resources ||
(this._resources = [{
language: 'en',
unorderedList: 'Unordered List',
orderedList: 'Ordered List',
bold: 'Bold',
italic: 'Italic',
link: 'Link',
underline: 'Underline',
fontSize: 'Font Size',
enterURL: 'Please enter the URL',
insertFontSize: 'Insert font size from 1 to 7'
},
{
language: 'es',
unorderedList: 'Lista de puntos',
orderedList: 'Lista ordenada',
bold: 'Negrita',
italic: 'Cursiva',
link: 'Link',
underline: 'Subrayado',
fontSize: 'Tamaño fuente',
enterURL: 'Introduzca la dirección URL',
insertFontSize: 'Introduzca el tamaño de la fuente del 1 al 7'
}
]);
}
private _resource: TResource;
public resource(): TResource {
return this._resource || (this._resource = this.getResources().find(c => c.language == (this._language || 'en')) ||
this.getResources().find(c => c.language == 'en'));
}
private _language
public language(l: string) {
this._language = l;
this._resource = undefined;
}
private __buttonLibrary: TButtonLibrary;
private _buttonLibrary(): TButtonLibrary {
return this.__buttonLibrary || (this.__buttonLibrary = {
list1: { title: this.resource().unorderedList, command: 'insertunorderedlist', styleClass: 'list-ul' },
list2: { title: this.resource().orderedList, command: 'insertorderedlist', styleClass: 'list-ol' },
bold: { title: this.resource().bold, command: 'bold', styleClass: 'bold' },
italic: { title: this.resource().italic, command: 'italic', styleClass: 'italic' },
link: { title: this.resource().link, command: 'createlink', styleClass: 'link' },
underline: { title: this.resource().underline, command: 'underline', styleClass: 'format-underlined' },
fontsize: { title: this.resource().fontSize, command: 'fontSize', styleClass: 'font-size' }
});
}
private _defaultButtonsList = ['list1', 'list2', 'bold', 'italic', 'link', 'underline', 'fontsize'];
public setButtons(buttons: string[]): void {
// if(!angular.isArray(buttons)) {
// throw 'Argument "buttons" should be an array';
// }
this._defaultButtonsList = buttons;
};
public addStandardButton(
name: string,
title: string,
command: string,
styleClass: string
) {
if (!name || !title || !command) {
throw 'Arguments "name", "title" and "command" are required';
}
styleClass = styleClass || '';
this._buttonLibrary()[name] = {title: title, command: command, styleClass: styleClass};
this._defaultButtonsList.push(name);
}
public addCustomButton(name: string, pluginName: string): void {
if (!name || !pluginName) {
throw 'Arguments "name" and "pluginName" are required';
}
this._buttonLibrary()[name] = {pluginName: pluginName, isComplex: true};
this._defaultButtonsList.push(name);
}
public getToolbarButtons(buttonsList?: string): {}[] {
let buttons = this._defaultButtonsList;
const toolbarButtons: TButton[] = [];
if (typeof buttonsList !== 'undefined') {
buttons = string2array(buttonsList);
}
buttons.forEach(buttonKey => {
if (!buttonKey) {
return;
}
if (!this._buttonLibrary()[buttonKey]) {
throw 'There is no "' + buttonKey + '" in your library. Possible variants: ' + Object.keys(this._buttonLibrary);
}
let button = Object.assign({}, this._buttonLibrary()[buttonKey]);
// button.isActive = () => {return !!this.command && document.queryCommandState(this.command);}
toolbarButtons.push(button);
});
return toolbarButtons;
}
}
function string2array(keysString: string) {
return keysString.split(',').map(Function.prototype.call, String.prototype.trim);
}
.nw-button-fa.font-size:before {
content: '\f27f';
}
.nw-button-mdi.font-size:before {
content: '\f27f';
}`