import {Inject, Injectable} from '@angular/core'; import {HttpClient, HttpEvent} from "@angular/common/http"; import {Observable} from "rxjs"; import {DOCUMENT} from "@angular/common"; import {CustomClass} from "./config"; export interface UploadResponse { imageUrl: string; } @Injectable({ providedIn: 'root' }) export class AngularEditorService { savedSelection: Range | null; selectedText: string; uploadUrl: string; constructor(private http: HttpClient, @Inject(DOCUMENT) private _document: any) { } /** * Executed command from editor header buttons exclude toggleEditorMode * @param command string from triggerCommand */ executeCommand(command: string) { if (command === 'h1' || command === 'h2' || command === 'h3' || command === 'h4' || command === 'h5' || command === 'h6' || command === 'p' || command === 'pre') { this._document.execCommand('formatBlock', false, command); } this._document.execCommand(command, false, null); return; } /** * Create URL link * @param url string from UI prompt */ createLink(url: string) { if (!url.includes("http")) { this._document.execCommand('createlink', false, url); } else { const newUrl = '' + this.selectedText + ''; this.insertHtml(newUrl); } } /** * insert color either font or background * * @param color color to be inserted * @param where where the color has to be inserted either text/background */ insertColor(color: string, where: string): void { const restored = this.restoreSelection(); if (restored) { if (where === 'textColor') { this._document.execCommand('foreColor', false, color); } else { this._document.execCommand('hiliteColor', false, color); } } return; } /** * Set font name * @param fontName string */ setFontName(fontName: string) { this._document.execCommand("fontName", false, fontName); } /** * Set font size * @param fontSize string */ setFontSize(fontSize: string) { this._document.execCommand("fontSize", false, fontSize); } /** * Create raw HTML * @param html HTML string */ private insertHtml(html: string): void { const isHTMLInserted = this._document.execCommand('insertHTML', false, html); if (!isHTMLInserted) { throw new Error('Unable to perform the operation'); } return; } /** * save selection when the editor is focussed out */ saveSelection(): any { if (window.getSelection) { const sel = window.getSelection(); if (sel.getRangeAt && sel.rangeCount) { this.savedSelection = sel.getRangeAt(0); this.selectedText = sel.toString(); } } else if (this._document.getSelection && this._document.createRange) { this.savedSelection = document.createRange(); } else { this.savedSelection = null; } } /** * restore selection when the editor is focussed in * * saved selection when the editor is focussed out */ restoreSelection(): boolean { if (this.savedSelection) { if (window.getSelection) { const sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(this.savedSelection); return true; } else if (this._document.getSelection /*&& this.savedSelection.select*/) { // this.savedSelection.select(); return true; } } else { return false; } } /** check any slection is made or not */ private checkSelection(): any { const slectedText = this.savedSelection.toString(); if (slectedText.length === 0) { throw new Error('No Selection Made'); } return true; } /** * Upload file to uploadUrl * @param file */ uploadImage(file: File): Observable> { const uploadData: FormData = new FormData(); uploadData.append('file', file, file.name); return this.http.post(this.uploadUrl, uploadData, { reportProgress: true, observe: 'events', }); } /** * Insert image with Url * @param imageUrl */ insertImage(imageUrl: string) { this._document.execCommand('insertImage', false, imageUrl); } setDefaultParagraphSeparator(separator: string) { this._document.execCommand("defaultParagraphSeparator", false, separator); } createCustomClass(customClass: CustomClass) { const tagName = customClass.tag ? customClass.tag : 'span'; const newTag = '<' + tagName + ' class="' + customClass.class + '">' + this.selectedText + ''; this.insertHtml(newTag); } }