src/app/ngx-editor/ngx-editor-toolbar/ngx-editor-toolbar.component.ts
providers |
PopoverConfig
|
selector | app-ngx-editor-toolbar |
styleUrls | ngx-editor-toolbar.component.scss |
templateUrl | ./ngx-editor-toolbar.component.html |
Properties |
Methods |
Inputs |
Outputs |
constructor(_popOverConfig: PopoverConfig, _formBuilder: FormBuilder, _messageService: MessageService, _commandExecutorService: CommandExecutorService)
|
|||||||||||||||
Parameters :
|
config
|
Editor configuration
Type: |
execute
|
Emits an event when a toolbar button is clicked $event type: EventEmitter<string>
|
buildImageForm |
buildImageForm()
|
create insert image form
Returns :
void
|
buildUrlForm |
buildUrlForm()
|
create URL insert form
Returns :
void
|
buildVideoForm |
buildVideoForm()
|
create insert image form
Returns :
void
|
canEnableToolbarOptions | ||||||
canEnableToolbarOptions(value: )
|
||||||
enable or diable toolbar based on configuration
Parameters :
Returns :
boolean
|
insertColor |
insertColor(color: string, where: string)
|
inser text/background color
Returns :
void
|
insertImage |
insertImage()
|
insert image in the editor
Returns :
void
|
insertLink |
insertLink()
|
inserts link in the editor
Returns :
void
|
insertVideo |
insertVideo()
|
insert image in the editor
Returns :
void
|
onFileChange | ||||||
onFileChange(e: )
|
||||||
Executed when file is selected
Parameters :
Returns :
void
|
onlyNumbers | ||||||||
onlyNumbers(event: KeyboardEvent)
|
||||||||
allow only numbers
Parameters :
Returns :
boolean
|
setFontName | ||||||
setFontName(fontName: string)
|
||||||
set font Name/family
Parameters :
Returns :
void
|
setFontSize | ||||||
setFontSize(fontSize: string)
|
||||||
set font size
Parameters :
Returns :
void
|
triggerCommand | ||||||||
triggerCommand(command: string)
|
||||||||
triggers command from the toolbar to be executed and emits an event
Parameters :
Returns :
void
|
colorPopover |
colorPopover:
|
Decorators : ViewChild
|
fontName |
fontName:
|
Type : string
|
Default value : ''
|
font family name |
fontSize |
fontSize:
|
Type : string
|
Default value : ''
|
font size |
fontSizePopover |
fontSizePopover:
|
Decorators : ViewChild
|
hexColor |
hexColor:
|
Type : string
|
Default value : ''
|
hex color code |
imageForm |
imageForm:
|
Type : FormGroup
|
holds values of the insert image form |
imagePopover |
imagePopover:
|
Decorators : ViewChild
|
isImageUploader |
isImageUploader:
|
Default value : false
|
show/hide image uploader |
isUploading |
isUploading:
|
Default value : false
|
set to true when the image is being uploaded |
selectedColorTab |
selectedColorTab:
|
Type : string
|
Default value : 'textColor'
|
which tab to active for color insetion |
updloadPercentage |
updloadPercentage:
|
Type : number
|
Default value : 0
|
upload percentage |
uploadComplete |
uploadComplete:
|
Default value : true
|
set to false when image is being uploaded |
urlForm |
urlForm:
|
Type : FormGroup
|
holds values of the insert link form |
urlPopover |
urlPopover:
|
Decorators : ViewChild
|
videoForm |
videoForm:
|
Type : FormGroup
|
holds values of the insert video form |
videoPopover |
videoPopover:
|
Decorators : ViewChild
|
import { Component, Input, Output, EventEmitter, OnInit, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { HttpResponse } from '@angular/common/http';
import { PopoverConfig } from 'ngx-bootstrap';
import { CommandExecutorService } from '../common/services/command-executor.service';
import { MessageService } from '../common/services/message.service';
import * as Utils from '../common/utils/ngx-editor.utils';
@Component({
selector: 'app-ngx-editor-toolbar',
templateUrl: './ngx-editor-toolbar.component.html',
styleUrls: ['./ngx-editor-toolbar.component.scss'],
providers: [PopoverConfig]
})
export class NgxEditorToolbarComponent implements OnInit {
/** holds values of the insert link form */
urlForm: FormGroup;
/** holds values of the insert image form */
imageForm: FormGroup;
/** holds values of the insert video form */
videoForm: FormGroup;
/** set to false when image is being uploaded */
uploadComplete = true;
/** upload percentage */
updloadPercentage = 0;
/** set to true when the image is being uploaded */
isUploading = false;
/** which tab to active for color insetion */
selectedColorTab = 'textColor';
/** font family name */
fontName = '';
/** font size */
fontSize = '';
/** hex color code */
hexColor = '';
/** show/hide image uploader */
isImageUploader = false;
/**
* Editor configuration
*/
@Input() config: any;
@ViewChild('urlPopover') urlPopover;
@ViewChild('imagePopover') imagePopover;
@ViewChild('videoPopover') videoPopover;
@ViewChild('fontSizePopover') fontSizePopover;
@ViewChild('colorPopover') colorPopover;
/**
* Emits an event when a toolbar button is clicked
*/
@Output() execute: EventEmitter<string> = new EventEmitter<string>();
constructor(private _popOverConfig: PopoverConfig,
private _formBuilder: FormBuilder,
private _messageService: MessageService,
private _commandExecutorService: CommandExecutorService) {
this._popOverConfig.outsideClick = true;
this._popOverConfig.placement = 'bottom';
this._popOverConfig.container = 'body';
}
/**
* enable or diable toolbar based on configuration
*
* @param value name of the toolbar buttons
*/
canEnableToolbarOptions(value): boolean {
return Utils.canEnableToolbarOptions(value, this.config['toolbar']);
}
/**
* triggers command from the toolbar to be executed and emits an event
*
* @param command name of the command to be executed
*/
triggerCommand(command: string): void {
this.execute.emit(command);
}
/**
* create URL insert form
*/
buildUrlForm(): void {
this.urlForm = this._formBuilder.group({
urlLink: ['', [Validators.required]],
urlText: ['', [Validators.required]],
urlNewTab: [true]
});
return;
}
/**
* inserts link in the editor
*/
insertLink(): void {
try {
this._commandExecutorService.createLink(this.urlForm.value);
} catch (error) {
this._messageService.sendMessage(error.message);
}
/** reset form to default */
this.buildUrlForm();
/** close inset URL pop up */
this.urlPopover.hide();
return;
}
/**
* create insert image form
*/
buildImageForm(): void {
this.imageForm = this._formBuilder.group({
imageUrl: ['', [Validators.required]]
});
return;
}
/**
* create insert image form
*/
buildVideoForm(): void {
this.videoForm = this._formBuilder.group({
videoUrl: ['', [Validators.required]],
height: [''],
width: ['']
});
return;
}
/**
* Executed when file is selected
*
* @param e onChange event
*/
onFileChange(e): void {
this.uploadComplete = false;
this.isUploading = true;
if (e.target.files.length > 0) {
const file = e.target.files[0];
try {
this._commandExecutorService.uploadImage(file, this.config.imageEndPoint).subscribe(event => {
if (event.type) {
this.updloadPercentage = Math.round(100 * event.loaded / event.total);
}
if (event instanceof HttpResponse) {
try {
this._commandExecutorService.insertImage(event.body.url);
} catch (error) {
this._messageService.sendMessage(error.message);
}
this.uploadComplete = true;
this.isUploading = false;
}
});
} catch (error) {
this._messageService.sendMessage(error.message);
this.uploadComplete = true;
this.isUploading = false;
}
}
return;
}
/** insert image in the editor */
insertImage(): void {
try {
this._commandExecutorService.insertImage(this.imageForm.value.imageUrl);
} catch (error) {
this._messageService.sendMessage(error.message);
}
/** reset form to default */
this.buildImageForm();
/** close inset URL pop up */
this.imagePopover.hide();
return;
}
/** insert image in the editor */
insertVideo(): void {
try {
this._commandExecutorService.insertVideo(this.videoForm.value);
} catch (error) {
this._messageService.sendMessage(error.message);
}
/** reset form to default */
this.buildVideoForm();
/** close inset URL pop up */
this.videoPopover.hide();
return;
}
/** inser text/background color */
insertColor(color: string, where: string): void {
try {
this._commandExecutorService.insertColor(color, where);
} catch (error) {
this._messageService.sendMessage(error.message);
}
this.colorPopover.hide();
return;
}
/** set font size */
setFontSize(fontSize: string): void {
try {
this._commandExecutorService.setFontSize(fontSize);
} catch (error) {
this._messageService.sendMessage(error.message);
}
this.fontSizePopover.hide();
return;
}
/** set font Name/family */
setFontName(fontName: string): void {
try {
this._commandExecutorService.setFontName(fontName);
} catch (error) {
this._messageService.sendMessage(error.message);
}
this.fontSizePopover.hide();
return;
}
/**
* allow only numbers
*
* @param event keypress event
*/
onlyNumbers(event: KeyboardEvent): boolean {
return event.charCode >= 48 && event.charCode <= 57;
}
ngOnInit() {
this.buildUrlForm();
this.buildImageForm();
this.buildVideoForm();
}
}
<div class="ngx-toolbar" *ngIf="config['showToolbar']">
<div class="ngx-toolbar-set">
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('bold')" (click)="triggerCommand('bold')"
title="Bold" [disabled]="!config['enableToolbar']">
<i class="fa fa-bold" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('italic')" (click)="triggerCommand('italic')"
title="Italic" [disabled]="!config['enableToolbar']">
<i class="fa fa-italic" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('underline')" (click)="triggerCommand('underline')"
title="Underline" [disabled]="!config['enableToolbar']">
<i class="fa fa-underline" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('strikeThrough')" (click)="triggerCommand('strikeThrough')"
title="Strikethrough" [disabled]="!config['enableToolbar']">
<i class="fa fa-strikethrough" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('superscript')" (click)="triggerCommand('superscript')"
title="Superscript" [disabled]="!config['enableToolbar']">
<i class="fa fa-superscript" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('subscript')" (click)="triggerCommand('subscript')"
title="Subscript" [disabled]="!config['enableToolbar']">
<i class="fa fa-subscript" aria-hidden="true"></i>
</button>
</div>
<div class="ngx-toolbar-set">
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('fontName')" (click)="fontName = ''" title="Font Family"
[popover]="fontNameTemplate" #fontNamePopover="bs-popover" containerClass="ngxePopover" [disabled]="!config['enableToolbar']">
<i class="fa fa-font" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('fontSize')" (click)="fontSize = ''" title="Font Size"
[popover]="fontSizeTemplate" #fontSizePopover="bs-popover" containerClass="ngxePopover" [disabled]="!config['enableToolbar']">
<i class="fa fa-text-height" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('color')" (click)="hexColor = ''" title="Color Picker"
[popover]="insertColorTemplate" #colorPopover="bs-popover" containerClass="ngxePopover" [disabled]="!config['enableToolbar']">
<i class="fa fa-tint" aria-hidden="true"></i>
</button>
</div>
<div class="ngx-toolbar-set">
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('justifyLeft')" (click)="triggerCommand('justifyLeft')"
title="Justify Left" [disabled]="!config['enableToolbar']">
<i class="fa fa-align-left" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('justifyCenter')" (click)="triggerCommand('justifyCenter')"
title="Justify Center" [disabled]="!config['enableToolbar']">
<i class="fa fa-align-center" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('justifyRight')" (click)="triggerCommand('justifyRight')"
title="Justify Right" [disabled]="!config['enableToolbar']">
<i class="fa fa-align-right" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('justifyFull')" (click)="triggerCommand('justifyFull')"
title="Justify" [disabled]="!config['enableToolbar']">
<i class="fa fa-align-justify" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('indent')" (click)="triggerCommand('indent')"
title="Indent" [disabled]="!config['enableToolbar']">
<i class="fa fa-indent" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('outdent')" (click)="triggerCommand('outdent')"
title="Outdent" [disabled]="!config['enableToolbar']">
<i class="fa fa-outdent" aria-hidden="true"></i>
</button>
</div>
<div class="ngx-toolbar-set">
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('cut')" (click)="triggerCommand('cut')" title="Cut"
[disabled]="!config['enableToolbar']">
<i class="fa fa-scissors" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('copy')" (click)="triggerCommand('copy')"
title="Copy" [disabled]="!config['enableToolbar']">
<i class="fa fa-files-o" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('delete')" (click)="triggerCommand('delete')"
title="Delete" [disabled]="!config['enableToolbar']">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('removeFormat')" (click)="triggerCommand('removeFormat')"
title="Clear Formatting" [disabled]="!config['enableToolbar']">
<i class="fa fa-eraser" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('undo')" (click)="triggerCommand('undo')"
title="Undo" [disabled]="!config['enableToolbar']">
<i class="fa fa-undo" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('redo')" (click)="triggerCommand('redo')"
title="Redo" [disabled]="!config['enableToolbar']">
<i class="fa fa-repeat" aria-hidden="true"></i>
</button>
</div>
<div class="ngx-toolbar-set">
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('paragraph')" (click)="triggerCommand('insertParagraph')"
title="Paragraph" [disabled]="!config['enableToolbar']">
<i class="fa fa-paragraph" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('blockquote')" (click)="triggerCommand('blockquote')"
title="Blockquote" [disabled]="!config['enableToolbar']">
<i class="fa fa-quote-left" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('removeBlockquote')" (click)="triggerCommand('removeBlockquote')"
title="Remove Blockquote" [disabled]="!config['enableToolbar']">
<i class="fa fa-quote-right" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('horizontalLine')" (click)="triggerCommand('insertHorizontalRule')"
title="Horizontal Line" [disabled]="!config['enableToolbar']">
<i class="fa fa-minus" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('unorderedList')" (click)="triggerCommand('insertUnorderedList')"
title="Unordered List" [disabled]="!config['enableToolbar']">
<i class="fa fa-list-ul" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('orderedList')" (click)="triggerCommand('insertOrderedList')"
title="Ordered List" [disabled]="!config['enableToolbar']">
<i class="fa fa-list-ol" aria-hidden="true"></i>
</button>
</div>
<div class="ngx-toolbar-set">
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('link')" (click)="buildUrlForm()" [popover]="insertLinkTemplate"
title="Insert Link" #urlPopover="bs-popover" containerClass="ngxePopover" [disabled]="!config['enableToolbar']">
<i class="fa fa-link" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('unlink')" (click)="triggerCommand('unlink')"
title="Unlink" [disabled]="!config['enableToolbar']">
<i class="fa fa-chain-broken" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('image')" (click)="buildImageForm()" title="Insert Image"
[popover]="insertImageTemplate" #imagePopover="bs-popover" containerClass="ngxePopover" [disabled]="!config['enableToolbar']">
<i class="fa fa-picture-o" aria-hidden="true"></i>
</button>
<button type="button" class="ngx-editor-button" *ngIf="canEnableToolbarOptions('video')" (click)="buildVideoForm()" title="Insert Video"
[popover]="insertVideoTemplate" #videoPopover="bs-popover" containerClass="ngxePopover" [disabled]="!config['enableToolbar']">
<i class="fa fa-youtube-play" aria-hidden="true"></i>
</button>
</div>
</div>
<!-- URL Popover template -->
<ng-template #insertLinkTemplate>
<div class="ngxe-popover extra-gt">
<form [formGroup]="urlForm" (ngSubmit)="urlForm.valid && insertLink()" autocomplete="off">
<div class="form-group">
<label for="urlInput" class="small">URL</label>
<input type="text" class="form-control-sm" id="URLInput" placeholder="URL" formControlName="urlLink" required>
</div>
<div class="form-group">
<label for="urlTextInput" class="small">Text</label>
<input type="text" class="form-control-sm" id="urlTextInput" placeholder="Text" formControlName="urlText" required>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="urlNewTab" formControlName="urlNewTab">
<label class="form-check-label" for="urlNewTab">Open in new tab</label>
</div>
<button type="submit" class="btn-primary btn-sm btn">Submit</button>
</form>
</div>
</ng-template>
<!-- Image Uploader Popover template -->
<ng-template #insertImageTemplate>
<div class="ngxe-popover imgc-ctnr">
<div class="imgc-topbar btn-ctnr">
<button type="button" class="btn" [ngClass]="{active: isImageUploader}" (click)="isImageUploader = true">
<i class="fa fa-upload"></i>
</button>
<button type="button" class="btn" [ngClass]="{active: !isImageUploader}" (click)="isImageUploader = false">
<i class="fa fa-link"></i>
</button>
</div>
<div class="imgc-ctnt is-image">
<div *ngIf="isImageUploader; else insertImageLink"> </div>
<div *ngIf="!isImageUploader; else imageUploder"> </div>
<ng-template #imageUploder>
<div class="ngx-insert-img-ph">
<p *ngIf="uploadComplete">Choose Image</p>
<p *ngIf="!uploadComplete">
<span>Uploading Image</span>
<br>
<span>{{ updloadPercentage }} %</span>
</p>
<div class="ngxe-img-upl-frm">
<input type="file" (change)="onFileChange($event)" accept="image/*" [disabled]="isUploading" [style.cursor]="isUploading ? 'not-allowed': 'allowed'">
</div>
</div>
</ng-template>
<ng-template #insertImageLink>
<form class="extra-gt" [formGroup]="imageForm" (ngSubmit)="imageForm.valid && insertImage()" autocomplete="off">
<div class="form-group">
<label for="imageURLInput" class="small">URL</label>
<input type="text" class="form-control-sm" id="imageURLInput" placeholder="URL" formControlName="imageUrl" required>
</div>
<button type="submit" class="btn-primary btn-sm btn">Submit</button>
</form>
</ng-template>
<div class="progress" *ngIf="!uploadComplete">
<div class="progress-bar progress-bar-striped progress-bar-animated bg-success" [ngClass]="{'bg-danger': updloadPercentage<20, 'bg-warning': updloadPercentage<50, 'bg-success': updloadPercentage>=100}"
[style.width.%]="updloadPercentage"></div>
</div>
</div>
</div>
</ng-template>
<!-- Insert Video Popover template -->
<ng-template #insertVideoTemplate>
<div class="ngxe-popover imgc-ctnr">
<div class="imgc-topbar btn-ctnr">
<button type="button" class="btn active">
<i class="fa fa-link"></i>
</button>
</div>
<div class="imgc-ctnt is-image">
<form class="extra-gt" [formGroup]="videoForm" (ngSubmit)="videoForm.valid && insertVideo()" autocomplete="off">
<div class="form-group">
<label for="videoURLInput" class="small">URL</label>
<input type="text" class="form-control-sm" id="videoURLInput" placeholder="URL" formControlName="videoUrl" required>
</div>
<div class="row form-group">
<div class="col">
<input type="text" class="form-control-sm" formControlName="height" placeholder="height (px)" (keypress)="onlyNumbers($event)">
</div>
<div class="col">
<input type="text" class="form-control-sm" formControlName="width" placeholder="width (px)" (keypress)="onlyNumbers($event)">
</div>
<label class="small">Height/Width</label>
</div>
<button type="submit" class="btn-primary btn-sm btn">Submit</button>
</form>
</div>
</div>
</ng-template>
<!-- Insert color template -->
<ng-template #insertColorTemplate>
<div class="ngxe-popover imgc-ctnr">
<div class="imgc-topbar two-tabs">
<span (click)="selectedColorTab ='textColor'" [ngClass]="{active: selectedColorTab ==='textColor'}">Text</span>
<span (click)="selectedColorTab ='backgroundColor'" [ngClass]="{active: selectedColorTab ==='backgroundColor'}">Background</span>
</div>
<div class="imgc-ctnt is-color extra-gt1">
<form autocomplete="off">
<div class="form-group">
<label for="hexInput" class="small">Hex Color</label>
<input type="text" class="form-control-sm" id="hexInput" name="hexInput" maxlength="7" placeholder="HEX Color" [(ngModel)]="hexColor"
required>
</div>
<button type="button" class="btn-primary btn-sm btn" (click)="insertColor(hexColor, selectedColorTab)">Submit</button>
</form>
</div>
</div>
</ng-template>
<!-- font size template -->
<ng-template #fontSizeTemplate>
<div class="ngxe-popover extra-gt1">
<form autocomplete="off">
<div class="form-group">
<label for="fontSize" class="small">Font Size</label>
<input type="text" class="form-control-sm" id="fontSize" name="fontSize" placeholder="Font size in px/rem" [(ngModel)]="fontSize"
required>
</div>
<button type="button" class="btn-primary btn-sm btn" (click)="setFontSize(fontSize)">Submit</button>
</form>
</div>
</ng-template>
<!-- font family/name template -->
<ng-template #fontNameTemplate>
<div class="ngxe-popover extra-gt1">
<form autocomplete="off">
<div class="form-group">
<label for="fontSize" class="small">Font Size</label>
<input type="text" class="form-control-sm" id="fontSize" name="fontName" placeholder="Ex: 'Times New Roman', Times, serif"
[(ngModel)]="fontName" required>
</div>
<button type="button" class="btn-primary btn-sm btn" (click)="setFontName(fontName)">Submit</button>
</form>
</div>
</ng-template>