@asoftwareworld/form-builder-pro
Version:
ASW Form Builder Pro helps you with rapid development and designed web forms which includes several controls. The key feature of Form Builder is to make your content attractive and effective. We can customize our control at run time and preview the same b
903 lines (899 loc) • 97.5 kB
JavaScript
import * as i3$1 from '@angular/common';
import { DOCUMENT, CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { Inject, Injectable, Component, EventEmitter, forwardRef, HostListener, ViewChild, Output, HostBinding, Input, ViewEncapsulation, SecurityContext, ContentChild, Attribute, NgModule } from '@angular/core';
import * as i2 from '@angular/forms';
import { NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { aswEditorConfig } from '@asoftwareworld/form-builder-pro/api';
import { isDefined } from '@asoftwareworld/form-builder-pro/utils';
import * as i1 from '@angular/common/http';
import * as i2$1 from '@angular/platform-browser';
import * as i8 from '@asoftwareworld/form-builder-pro/common';
import { Icons, Constants, AswPipeModule } from '@asoftwareworld/form-builder-pro/common';
import * as i1$1 from '@angular/material/dialog';
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
import * as i3 from '@angular/material/form-field';
import { MatFormFieldModule } from '@angular/material/form-field';
import * as i4 from '@angular/material/button';
import { MatButtonModule } from '@angular/material/button';
import * as i5 from '@angular/material/input';
import { MatInputModule } from '@angular/material/input';
import * as i6 from '@angular/material/tooltip';
import { MatTooltipModule } from '@angular/material/tooltip';
import * as i7 from '@angular/material/divider';
import { MatDividerModule } from '@angular/material/divider';
import * as i6$1 from '@asoftwareworld/form-builder-pro/color-picker';
import { AswColorPickerModule } from '@asoftwareworld/form-builder-pro/color-picker';
import { AswTranslateModule } from '@asoftwareworld/form-builder-pro/core';
class AswEditorService {
http;
doc;
savedSelection;
selectedText;
uploadUrl;
uploadWithCredentials;
constructor(http, doc) {
this.http = http;
this.doc = doc;
}
/**
* Executed command from editor header buttons exclude toggleEditorMode
* @param command string from triggerCommand
*/
executeCommand(command, value) {
const commands = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'pre'];
if (commands.includes(command)) {
this.doc.execCommand('formatBlock', false, command);
return;
}
this.doc.execCommand(command, false, value);
}
/**
* Create URL link
* @param url string from UI prompt
*/
createLink(url) {
if (!url.includes('http')) {
this.doc.execCommand('createlink', false, url);
}
else {
const newUrl = `<a href='${url}' target='_blank'> ${this.selectedText} </a>`;
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, where) {
const restored = this.restoreSelection();
if (restored) {
if (where === 'textColor') {
this.doc.execCommand('foreColor', false, color);
}
else {
this.doc.execCommand('hiliteColor', false, color);
}
}
}
/**
* Set font name
* @param fontName string
*/
setFontName(fontName) {
this.doc.execCommand('fontName', false, fontName);
}
/**
* Set font size
* @param fontSize string
*/
setFontSize(fontSize) {
this.doc.execCommand('fontSize', false, fontSize);
}
/**
* Create raw HTML
* @param html HTML string
*/
insertHtml(html) {
const isHTMLInserted = this.doc.execCommand('insertHTML', false, html);
if (!isHTMLInserted) {
throw new Error('Unable to perform the operation');
}
}
/**
* save selection when the editor is focussed out
*/
saveSelection = () => {
if (this.doc.getSelection) {
const sel = this.doc.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
this.savedSelection = sel.getRangeAt(0);
this.selectedText = sel.toString();
}
}
else if (this.doc.getSelection && this.doc.createRange) {
this.savedSelection = document.createRange();
}
else {
this.savedSelection = null;
}
};
/**
* restore selection when the editor is focused in
*
* saved selection when the editor is focused out
*/
restoreSelection() {
if (this.savedSelection) {
if (this.doc.getSelection) {
const sel = this.doc.getSelection();
sel.removeAllRanges();
sel.addRange(this.savedSelection);
return true;
}
else if (this.doc.getSelection /*&& this.savedSelection.select*/) {
// this.savedSelection.select();
return true;
}
else {
return false;
}
}
else {
return false;
}
}
/**
* setTimeout used for execute 'saveSelection' method in next event loop iteration
*/
executeInNextQueueIteration(callbackFn, timeout = 1e2) {
setTimeout(callbackFn, timeout);
}
/** check any selection is made or not */
checkSelection() {
const selectedText = this.savedSelection?.toString();
if (selectedText?.length === 0) {
throw new Error('No Selection Made');
}
return true;
}
/**
* Upload file to uploadUrl
* @param file The file
*/
uploadImage(file) {
const uploadData = new FormData();
uploadData.append('file', file, file.name);
return this.http.post(this.uploadUrl, uploadData, {
reportProgress: true,
observe: 'events',
withCredentials: this.uploadWithCredentials
});
}
/**
* Insert image with Url
* @param imageUrl The imageUrl.
*/
insertImage(imageUrl) {
this.doc.execCommand('insertImage', false, imageUrl);
}
setDefaultParagraphSeparator(separator) {
this.doc.execCommand('defaultParagraphSeparator', false, separator);
}
createCustomClass(customClass) {
let newTag = this.selectedText;
if (customClass) {
const tagName = customClass.tag ? customClass.tag : 'span';
newTag = '<' + tagName + ' class="' + customClass.class + '">' + this.selectedText + '</' + tagName + '>';
}
this.insertHtml(newTag);
}
insertVideo(videoUrl) {
if (videoUrl.match('www.youtube.com')) {
this.insertYouTubeVideoTag(videoUrl);
}
if (videoUrl.match('vimeo.com')) {
this.insertVimeoVideoTag(videoUrl);
}
}
insertYouTubeVideoTag(videoUrl) {
const id = videoUrl.split('v=')[1];
const imageUrl = `https://img.youtube.com/vi/${id}/0.jpg`;
const thumbnail = `
<div style='position: relative'>
<a href='${videoUrl}' target='_blank'>
<img src="${imageUrl}" alt="click to watch"/>
<img style='position: absolute; left:200px; top:140px'
src="https://img.icons8.com/color/96/000000/youtube-play.png"/>
</a>
</div>`;
this.insertHtml(thumbnail);
}
insertVimeoVideoTag(videoUrl) {
const sub = this.http.get(`https://vimeo.com/api/oembed.json?url=${videoUrl}`).subscribe((data) => {
const imageUrl = data.thumbnail_url_with_play_button;
const thumbnail = `<div>
<a href='${videoUrl}' target='_blank'>
<img src="${imageUrl}" alt="${data.title}"/>
</a>
</div>`;
this.insertHtml(thumbnail);
sub.unsubscribe();
});
}
nextNode(node) {
if (node.hasChildNodes()) {
return node.firstChild;
}
else {
while (node && !node.nextSibling) {
node = node.parentNode;
}
if (!node) {
return null;
}
return node.nextSibling;
}
}
getRangeSelectedNodes(range, includePartiallySelectedContainers) {
let node = range.startContainer;
const endNode = range.endContainer;
let rangeNodes = [];
// Special case for a range that is contained within a single node
if (node === endNode) {
rangeNodes = [node];
}
else {
// Iterate nodes until we hit the end container
while (node && node !== endNode) {
rangeNodes.push((node = this.nextNode(node)));
}
// Add partially selected nodes at the start of the range
node = range.startContainer;
while (node && node !== range.commonAncestorContainer) {
rangeNodes.unshift(node);
node = node.parentNode;
}
}
// Add ancestors of the range container, if required
if (includePartiallySelectedContainers) {
node = range.commonAncestorContainer;
while (node) {
rangeNodes.push(node);
node = node.parentNode;
}
}
return rangeNodes;
}
getSelectedNodes() {
const nodes = [];
if (this.doc.getSelection) {
const sel = this.doc.getSelection();
for (let i = 0, len = sel.rangeCount; i < len; ++i) {
nodes.push.apply(nodes, this.getRangeSelectedNodes(sel.getRangeAt(i), true));
}
}
return nodes;
}
replaceWithOwnChildren(el) {
const parent = el.parentNode;
while (el.hasChildNodes()) {
parent.insertBefore(el.firstChild, el);
}
parent.removeChild(el);
}
removeSelectedElements(tagNames) {
const tagNamesArray = tagNames.toLowerCase().split(',');
this.getSelectedNodes().forEach((node) => {
if (node.nodeType === 1 && tagNamesArray.indexOf(node.tagName.toLowerCase()) > -1) {
// Remove the node and replace it with its children
this.replaceWithOwnChildren(node);
}
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswEditorService, deps: [{ token: i1.HttpClient }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswEditorService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswEditorService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }] });
/**
* @license
* Copyright ASW (A Software World) All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file
*/
class AswEditorDialog {
dialogRef;
data;
icons = Icons;
linkTo;
constructor(dialogRef, data) {
this.dialogRef = dialogRef;
this.data = data;
}
ngOnInit() {
this.linkTo = this.data.linkTo;
}
onNoClick() {
this.dialogRef.close();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswEditorDialog, deps: [{ token: i1$1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.8", type: AswEditorDialog, selector: "asw-editor-dialog", ngImport: i0, template: "<div class=\"asw-dialog-header\">\r\n <div class=\"asw-edit-row-dialog\">\r\n <div class=\"asw-dialog-header clearfix\">\r\n <div class=\"asw-dialog-about\">\r\n <h1 mat-dialog-title class=\"asw-m-0\">Add Link</h1>\r\n </div>\r\n </div>\r\n </div>\r\n <button mat-icon-button (click)=\"onNoClick()\" aria-label=\"Close dialog\" class=\"asw-mt-2 asw-me-2\">\r\n <div [innerHTML]=\"icons.close | aswSafeHtml\">add</div>\r\n </button>\r\n</div>\r\n<mat-divider></mat-divider>\r\n<div mat-dialog-content class=\"mat-typography\">\r\n <mat-form-field appearance=\"outline\" class=\"asw-width-100\">\r\n <mat-label>Link to</mat-label>\r\n <input matInput \r\n type=\"text\"\r\n placeholder=\"Link to\"\r\n matTooltip=\"Link to\"\r\n #input=\"ngModel\"\r\n [(ngModel)]=\"linkTo\">\r\n </mat-form-field>\r\n</div>\r\n<mat-divider></mat-divider>\r\n<div mat-dialog-actions align=\"end\">\r\n <button id=\"no\"\r\n type=\"button\"\r\n class=\"asw-button asw-button-danger asw-mb-1 asw-me-2\"\r\n (click)=\"onNoClick()\">\r\n Cancel\r\n </button>\r\n <button type=\"button\"\r\n id=\"yes\"\r\n class=\"asw-button asw-button-primary asw-mb-1\"\r\n [mat-dialog-close]=\"linkTo\"\r\n cdkFocusInitial>\r\n Ok\r\n </button>\r\n</div>", dependencies: [{ kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1$1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i6.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: i7.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "pipe", type: i8.AswSafeHtmlPipe, name: "aswSafeHtml" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswEditorDialog, decorators: [{
type: Component,
args: [{ selector: 'asw-editor-dialog', template: "<div class=\"asw-dialog-header\">\r\n <div class=\"asw-edit-row-dialog\">\r\n <div class=\"asw-dialog-header clearfix\">\r\n <div class=\"asw-dialog-about\">\r\n <h1 mat-dialog-title class=\"asw-m-0\">Add Link</h1>\r\n </div>\r\n </div>\r\n </div>\r\n <button mat-icon-button (click)=\"onNoClick()\" aria-label=\"Close dialog\" class=\"asw-mt-2 asw-me-2\">\r\n <div [innerHTML]=\"icons.close | aswSafeHtml\">add</div>\r\n </button>\r\n</div>\r\n<mat-divider></mat-divider>\r\n<div mat-dialog-content class=\"mat-typography\">\r\n <mat-form-field appearance=\"outline\" class=\"asw-width-100\">\r\n <mat-label>Link to</mat-label>\r\n <input matInput \r\n type=\"text\"\r\n placeholder=\"Link to\"\r\n matTooltip=\"Link to\"\r\n #input=\"ngModel\"\r\n [(ngModel)]=\"linkTo\">\r\n </mat-form-field>\r\n</div>\r\n<mat-divider></mat-divider>\r\n<div mat-dialog-actions align=\"end\">\r\n <button id=\"no\"\r\n type=\"button\"\r\n class=\"asw-button asw-button-danger asw-mb-1 asw-me-2\"\r\n (click)=\"onNoClick()\">\r\n Cancel\r\n </button>\r\n <button type=\"button\"\r\n id=\"yes\"\r\n class=\"asw-button asw-button-primary asw-mb-1\"\r\n [mat-dialog-close]=\"linkTo\"\r\n cdkFocusInitial>\r\n Ok\r\n </button>\r\n</div>" }]
}], ctorParameters: () => [{ type: i1$1.MatDialogRef }, { type: undefined, decorators: [{
type: Inject,
args: [MAT_DIALOG_DATA]
}] }] });
class AswEditorSelect {
elRef;
r;
options = [];
// tslint:disable-next-line:no-input-rename
isHidden;
selectedOption;
disabled = false;
optionId = 0;
get label() {
return this.selectedOption && this.selectedOption.hasOwnProperty('label') ? this.selectedOption.label : 'Select';
}
opened = false;
get value() {
return this.selectedOption.value;
}
hidden = 'inline-block';
changeEvent = new EventEmitter();
labelButton;
constructor(elRef, r) {
this.elRef = elRef;
this.r = r;
}
ngOnInit() {
this.selectedOption = this.options[0];
if (isDefined(this.isHidden) && this.isHidden) {
this.hide();
}
}
hide() {
this.hidden = 'none';
}
optionSelect(option, event) {
event.stopPropagation();
this.setValue(option.value);
this.onChange(this.selectedOption.value);
this.changeEvent.emit(this.selectedOption.value);
this.onTouched();
this.opened = false;
}
toggleOpen(event) {
// event.stopPropagation();
if (this.disabled) {
return;
}
this.opened = !this.opened;
}
onClick($event) {
if (!this.elRef.nativeElement.contains($event.target)) {
this.close();
}
}
close() {
this.opened = false;
}
get isOpen() {
return this.opened;
}
writeValue(value) {
if (!value || typeof value !== 'string') {
return;
}
this.setValue(value);
}
setValue(value) {
let index = 0;
const selectedEl = this.options.find((el, i) => {
index = i;
return el.value === value;
});
if (selectedEl) {
this.selectedOption = selectedEl;
this.optionId = index;
}
}
onChange = () => { };
onTouched = () => { };
registerOnChange(fn) {
this.onChange = fn;
}
registerOnTouched(fn) {
this.onTouched = fn;
}
setDisabledState(isDisabled) {
this.labelButton.nativeElement.disabled = isDisabled;
const div = this.labelButton.nativeElement;
const action = isDisabled ? 'addClass' : 'removeClass';
this.r[action](div, 'disabled');
this.disabled = isDisabled;
}
handleKeyDown($event) {
if (!this.opened) {
return;
}
// console.log($event.key);
// if (KeyCode[$event.key]) {
switch ($event.key) {
case 'ArrowDown':
this._handleArrowDown();
break;
case 'ArrowUp':
this._handleArrowUp();
break;
case 'Space':
this._handleSpace();
break;
case 'Enter':
this._handleEnter($event);
break;
case 'Tab':
this._handleTab();
break;
case 'Escape':
this.close();
$event.preventDefault();
break;
case 'Backspace':
this._handleBackspace();
break;
}
// } else if ($event.key && $event.key.length === 1) {
// this._keyPress$.next($event.key.toLocaleLowerCase());
// }
}
_handleArrowDown() {
if (this.optionId < this.options.length - 1) {
this.optionId++;
}
}
_handleArrowUp() {
if (this.optionId >= 1) {
this.optionId--;
}
}
_handleSpace() { }
_handleEnter($event) {
this.optionSelect(this.options[this.optionId], $event);
}
_handleTab() { }
_handleBackspace() { }
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswEditorSelect, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.8", type: AswEditorSelect, selector: "asw-editor-select", inputs: { options: "options", isHidden: ["hidden", "isHidden"] }, outputs: { changeEvent: "change" }, host: { listeners: { "document:click": "onClick($event)", "keydown": "handleKeyDown($event)" }, properties: { "style.display": "this.hidden" } }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AswEditorSelect),
multi: true
}
], viewQueries: [{ propertyName: "labelButton", first: true, predicate: ["labelButton"], descendants: true, static: true }], ngImport: i0, template: "<span class=\"asw-font asw-picker\" [ngClass]=\"{'asw-expanded':isOpen}\">\r\n <button [tabIndex]=\"-1\" #labelButton tabindex=\"0\" type=\"button\" role=\"button\" class=\"asw-picker-label\" matTooltip=\"{{label}}\"\r\n (click)=\"toggleOpen($event);\">{{label}}\r\n <svg viewBox=\"0 0 18 18\">\r\n <polygon class=\"asw-stroke\" points=\"7 11 9 13 11 11 7 11\"></polygon>\r\n <polygon class=\"asw-stroke\" points=\"7 7 9 5 11 7 7 7\"></polygon>\r\n </svg>\r\n </button>\r\n <span class=\"asw-picker-options\">\r\n <button tabindex=\"-1\" type=\"button\" role=\"button\" class=\"asw-picker-item\"\r\n *ngFor=\"let item of options; let i = index\"\r\n [ngClass]=\"{'selected': item.value === value, 'focused': i === optionId}\"\r\n (click)=\"optionSelect(item, $event)\">\r\n {{item.label}}\r\n </button>\r\n <span class=\"dropdown-item\" *ngIf=\"!options.length\">No items for select</span>\r\n </span>\r\n</span>", styles: [".asw-font.asw-picker{color:#1a73e8;display:inline-block;width:100%;position:relative;vertical-align:middle}.asw-font .asw-picker-label{cursor:pointer;display:inline-block;height:100%;padding-left:8px;padding-right:10px;position:relative;width:100%;line-height:26px;vertical-align:middle;font-size:100%;text-align:left;background-color:#fff;min-width:2rem;float:left;border:1px solid #ddd;text-overflow:clip;overflow:hidden;white-space:nowrap;min-height:2.4rem;color:#1a73e8;background-color:#e8f0fe}.asw-font .asw-picker-label:before{content:\"\";position:absolute;right:0;top:0;width:20px;height:100%}.asw-font .asw-picker-label:focus{outline:none}.asw-font .asw-picker-label:hover{cursor:pointer;background-color:#e8f0fe;transition:.2s ease}.asw-font .asw-picker-label:disabled{background-color:#f5f5f5;pointer-events:none;cursor:not-allowed}.asw-font .asw-picker-label:disabled:before{background:linear-gradient(to right,#f5f5f5 100%,#fff)}.asw-font .asw-picker-label svg{position:absolute;margin-top:-9px;right:0;top:50%;width:18px}.asw-font .asw-picker-label svg:not(:root){overflow:hidden}.asw-font .asw-picker-label svg .asw-stroke{fill:none;stroke:#1a73e8;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.asw-font .asw-picker-options{background-color:#fff;display:none;min-width:100%;position:absolute;white-space:nowrap;z-index:3;border:1px solid transparent;box-shadow:#0003 0 2px 8px}.asw-font .asw-picker-options .asw-picker-item{cursor:pointer;display:block;padding-bottom:5px;padding-top:5px;padding-left:5px;z-index:3;text-align:left;background-color:transparent;min-width:2rem;width:100%;border:0 solid #ddd}.asw-font .asw-picker-options .asw-picker-item.selected{color:#1a73e8;background-color:#e8f0fe}.asw-font.asw-expanded{display:block;margin-top:-1px;z-index:1}.asw-font.asw-expanded .asw-picker-label{color:#1a73e8;z-index:2}.asw-font.asw-expanded .asw-picker-label svg{color:#1a73e8;z-index:2}.asw-font.asw-expanded .asw-picker-label svg .asw-stroke{stroke:#1a73e8}.asw-font.asw-expanded .asw-picker-options{display:block;margin-top:-1px;top:100%;z-index:3;border-color:#ccc}\n"], dependencies: [{ kind: "directive", type: i3$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswEditorSelect, decorators: [{
type: Component,
args: [{ selector: 'asw-editor-select', encapsulation: ViewEncapsulation.None, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AswEditorSelect),
multi: true
}
], template: "<span class=\"asw-font asw-picker\" [ngClass]=\"{'asw-expanded':isOpen}\">\r\n <button [tabIndex]=\"-1\" #labelButton tabindex=\"0\" type=\"button\" role=\"button\" class=\"asw-picker-label\" matTooltip=\"{{label}}\"\r\n (click)=\"toggleOpen($event);\">{{label}}\r\n <svg viewBox=\"0 0 18 18\">\r\n <polygon class=\"asw-stroke\" points=\"7 11 9 13 11 11 7 11\"></polygon>\r\n <polygon class=\"asw-stroke\" points=\"7 7 9 5 11 7 7 7\"></polygon>\r\n </svg>\r\n </button>\r\n <span class=\"asw-picker-options\">\r\n <button tabindex=\"-1\" type=\"button\" role=\"button\" class=\"asw-picker-item\"\r\n *ngFor=\"let item of options; let i = index\"\r\n [ngClass]=\"{'selected': item.value === value, 'focused': i === optionId}\"\r\n (click)=\"optionSelect(item, $event)\">\r\n {{item.label}}\r\n </button>\r\n <span class=\"dropdown-item\" *ngIf=\"!options.length\">No items for select</span>\r\n </span>\r\n</span>", styles: [".asw-font.asw-picker{color:#1a73e8;display:inline-block;width:100%;position:relative;vertical-align:middle}.asw-font .asw-picker-label{cursor:pointer;display:inline-block;height:100%;padding-left:8px;padding-right:10px;position:relative;width:100%;line-height:26px;vertical-align:middle;font-size:100%;text-align:left;background-color:#fff;min-width:2rem;float:left;border:1px solid #ddd;text-overflow:clip;overflow:hidden;white-space:nowrap;min-height:2.4rem;color:#1a73e8;background-color:#e8f0fe}.asw-font .asw-picker-label:before{content:\"\";position:absolute;right:0;top:0;width:20px;height:100%}.asw-font .asw-picker-label:focus{outline:none}.asw-font .asw-picker-label:hover{cursor:pointer;background-color:#e8f0fe;transition:.2s ease}.asw-font .asw-picker-label:disabled{background-color:#f5f5f5;pointer-events:none;cursor:not-allowed}.asw-font .asw-picker-label:disabled:before{background:linear-gradient(to right,#f5f5f5 100%,#fff)}.asw-font .asw-picker-label svg{position:absolute;margin-top:-9px;right:0;top:50%;width:18px}.asw-font .asw-picker-label svg:not(:root){overflow:hidden}.asw-font .asw-picker-label svg .asw-stroke{fill:none;stroke:#1a73e8;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.asw-font .asw-picker-options{background-color:#fff;display:none;min-width:100%;position:absolute;white-space:nowrap;z-index:3;border:1px solid transparent;box-shadow:#0003 0 2px 8px}.asw-font .asw-picker-options .asw-picker-item{cursor:pointer;display:block;padding-bottom:5px;padding-top:5px;padding-left:5px;z-index:3;text-align:left;background-color:transparent;min-width:2rem;width:100%;border:0 solid #ddd}.asw-font .asw-picker-options .asw-picker-item.selected{color:#1a73e8;background-color:#e8f0fe}.asw-font.asw-expanded{display:block;margin-top:-1px;z-index:1}.asw-font.asw-expanded .asw-picker-label{color:#1a73e8;z-index:2}.asw-font.asw-expanded .asw-picker-label svg{color:#1a73e8;z-index:2}.asw-font.asw-expanded .asw-picker-label svg .asw-stroke{stroke:#1a73e8}.asw-font.asw-expanded .asw-picker-options{display:block;margin-top:-1px;top:100%;z-index:3;border-color:#ccc}\n"] }]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { options: [{
type: Input
}], isHidden: [{
type: Input,
args: ['hidden']
}], hidden: [{
type: HostBinding,
args: ['style.display']
}], changeEvent: [{
type: Output,
args: ['change']
}], labelButton: [{
type: ViewChild,
args: ['labelButton', { static: true }]
}], onClick: [{
type: HostListener,
args: ['document:click', ['$event']]
}], handleKeyDown: [{
type: HostListener,
args: ['keydown', ['$event']]
}] } });
class AswEditorToolbar {
renderer;
aswEditorService;
doc;
dialog;
elementDOM;
htmlMode = false;
linkSelected = false;
block = 'default';
fontSize = '3';
foreColour;
backColor;
icons = Icons;
colorsName = [];
constant = Constants;
textColor = '#000105';
backgroundColor = '#ffffff';
selectedColor;
show = false;
headings = [
{
label: 'Heading 1',
value: 'h1'
},
{
label: 'Heading 2',
value: 'h2'
},
{
label: 'Heading 3',
value: 'h3'
},
{
label: 'Heading 4',
value: 'h4'
},
{
label: 'Heading 5',
value: 'h5'
},
{
label: 'Heading 6',
value: 'h6'
},
{
label: 'Heading 7',
value: 'h7'
},
{
label: 'Paragraph',
value: 'p'
},
{
label: 'Predefined',
value: 'pre'
},
{
label: 'Standard',
value: 'div'
},
{
label: 'default',
value: 'default'
}
];
fontSizes = [
{
label: '1',
value: '1'
},
{
label: '2',
value: '2'
},
{
label: '3',
value: '3'
},
{
label: '4',
value: '4'
},
{
label: '5',
value: '5'
},
{
label: '6',
value: '6'
},
{
label: '7',
value: '7'
}
];
customClassId = '-1';
customClasses$ = [];
customClassList = [{ label: '', value: '' }];
// uploadUrl: string;
tagMap = {
BLOCKQUOTE: 'indent',
A: 'link'
};
select = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'P', 'PRE', 'DIV'];
buttons = ['bold', 'italic', 'underline', 'strikeThrough', 'subscript', 'superscript', 'justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull', 'indent', 'outdent', 'insertUnorderedList', 'insertOrderedList', 'link'];
id;
uploadUrl;
upload;
showToolbar;
fonts = [{ label: '', value: '' }];
set customClasses(classes) {
if (classes) {
this.customClasses$ = classes;
this.customClassList = this.customClasses$.map((x, i) => ({ label: x.name, value: i.toString() }));
this.customClassList.unshift({ label: 'Clear Class', value: '-1' });
}
}
set defaultFontSize(value) {
if (value) {
this.fontSize = value;
}
}
hiddenButtons;
execute = new EventEmitter();
myInputFile;
get isLinkButtonDisabled() {
return this.htmlMode || !Boolean(this.aswEditorService.selectedText);
}
constructor(renderer, aswEditorService, doc, dialog, elementDOM) {
this.renderer = renderer;
this.aswEditorService = aswEditorService;
this.doc = doc;
this.dialog = dialog;
this.elementDOM = elementDOM;
}
ngOnInit() {
this.colorsName = Object.keys(this.constant.colors);
}
/**
* Trigger command from editor header buttons
* @param command string from toolbar buttons
*/
triggerCommand(command) {
this.execute.emit(command);
}
/**
* highlight editor buttons when cursor moved or positioning
*/
triggerButtons() {
if (!this.showToolbar) {
return;
}
this.buttons.forEach((e) => {
const result = this.doc.queryCommandState(e);
const elementById = this.getChildById(e + '-' + this.id);
if (result) {
this.renderer.addClass(elementById, 'active');
}
else {
this.renderer.removeClass(elementById, 'active');
}
});
}
getChildById(id) {
return this.elementDOM.nativeElement.querySelector(`#${id}`);
}
/**
* trigger highlight editor buttons when cursor moved or positioning in block
*/
triggerBlocks(nodes) {
if (!this.showToolbar) {
return;
}
this.linkSelected = nodes.findIndex((x) => x.nodeName === 'A') > -1;
let found = false;
this.select.forEach((y) => {
const node = nodes.find((x) => x.nodeName === y);
if (node !== undefined && y === node.nodeName) {
if (found === false) {
this.block = node.nodeName.toLowerCase();
found = true;
}
}
else if (found === false) {
this.block = 'default';
}
});
found = false;
if (this.customClasses$) {
this.customClasses$.forEach((y, index) => {
const node = nodes.find((x) => {
if (x instanceof Element) {
return x.className === y.class;
}
});
if (node !== undefined) {
if (found === false) {
this.customClassId = index.toString();
found = true;
}
}
else if (found === false) {
this.customClassId = '-1';
}
});
}
Object.keys(this.tagMap).map((e) => {
const elementById = this.getChildById(this.tagMap[e] + '-' + this.id);
const node = nodes.find((x) => x.nodeName === e);
if (node !== undefined && e === node.nodeName) {
this.renderer.addClass(elementById, 'active');
}
else {
this.renderer.removeClass(elementById, 'active');
}
});
this.foreColour = this.doc.queryCommandValue('ForeColor');
this.fontSize = this.doc.queryCommandValue('FontSize');
// this.fontName = this.doc.queryCommandValue('FontName').replace(/"/g, '');
this.backColor = this.doc.queryCommandValue('backColor');
}
/**
* insert URL link
*/
insertUrl() {
let url = 'https://';
const selection = this.aswEditorService.savedSelection;
if (selection && selection.commonAncestorContainer.parentElement?.nodeName === 'A') {
const parent = selection.commonAncestorContainer.parentElement;
if (parent.href !== '') {
url = parent.href;
}
}
// const dialogRef = this.dialog.open(AswEditorDialog, {
// width: '450px',
// data: { linkTo: url }
// });
// dialogRef.afterClosed().subscribe((result) => {
// if (result !== undefined) {
// url = result;
// this.aswEditorService.createLink(url);
// }
// });
url = prompt('Insert URL link', url);
if (url && url !== '' && url !== 'https://') {
this.aswEditorService.createLink(url);
}
}
/**
* insert Video link
*/
insertVideo() {
this.execute.emit('');
const dialogRef = this.dialog.open(AswEditorDialog, {
width: '450px',
data: { linkTo: `https://` }
});
dialogRef.afterClosed().subscribe((result) => {
if (result !== undefined) {
const url = result;
if (url && url !== '' && url !== `https://`) {
this.aswEditorService.insertVideo(url);
}
}
});
}
/** insert color */
insertColor(color, where) {
if (where === 'textColor') {
this.textColor = color;
}
else {
this.backgroundColor = color;
}
this.aswEditorService.insertColor(color, where);
this.execute.emit('');
this.show = false;
}
/**
* Change status of visibility to color picker
*/
toggleColors(where) {
this.show = !this.show;
this.selectedColor = where;
}
/**
* Change color from input
*/
setColor(data) {
this.insertColor(data.colorCode, data.where);
}
/**
* set font Name/family
* @param foreColor string
*/
setFontName(foreColor) {
this.aswEditorService.setFontName(foreColor);
this.execute.emit('');
}
/**
* set font Size
* @param fontSize string
*/
setFontSize(fontSize) {
this.aswEditorService.setFontSize(fontSize);
this.execute.emit('');
}
/**
* toggle editor mode (WYSIWYG or SOURCE)
* @param m boolean
*/
setEditorMode(m) {
const toggleEditorModeButton = this.getChildById('toggleEditorMode' + '-' + this.id);
if (m) {
this.renderer.addClass(toggleEditorModeButton, 'active');
}
else {
this.renderer.removeClass(toggleEditorModeButton, 'active');
}
this.htmlMode = m;
}
/**
* Upload image when file is selected.
*/
onFileChanged(event) {
const file = event.target.files[0];
if (file.type.includes('image/')) {
if (this.upload) {
this.upload(file).subscribe((response) => this.watchUploadImage(response, event));
}
else if (this.uploadUrl) {
this.aswEditorService.uploadImage(file).subscribe((response) => this.watchUploadImage(response, event));
}
else {
const reader = new FileReader();
reader.onload = (e) => {
const fr = e.currentTarget;
if (fr.result) {
this.aswEditorService.insertImage(fr.result.toString());
}
};
reader.readAsDataURL(file);
}
}
}
watchUploadImage(response, event) {
const { imageUrl } = response.body;
this.aswEditorService.insertImage(imageUrl);
event.srcElement.value = null;
}
/**
* Set custom class
*/
setCustomClass(classId) {
if (classId === '-1') {
this.execute.emit('clear');
}
else {
this.aswEditorService.createCustomClass(this.customClasses$[+classId]);
}
}
isButtonHidden(name) {
if (!name) {
return false;
}
if (!(this.hiddenButtons instanceof Array)) {
return false;
}
let result;
for (const arr of this.hiddenButtons) {
if (arr instanceof Array) {
result = arr.find((item) => item === name);
}
if (result) {
break;
}
}
return result !== undefined;
}
focus() {
this.execute.emit('focus');
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswEditorToolbar, deps: [{ token: i0.Renderer2 }, { token: AswEditorService }, { token: DOCUMENT }, { token: i1$1.MatDialog }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.8", type: AswEditorToolbar, selector: "asw-editor-toolbar", inputs: { id: "id", uploadUrl: "uploadUrl", upload: "upload", showToolbar: "showToolbar", fonts: "fonts", customClasses: "customClasses", defaultFontSize: "defaultFontSize", hiddenButtons: "hiddenButtons" }, outputs: { execute: "execute" }, viewQueries: [{ propertyName: "myInputFile", first: true, predicate: ["fileInput"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"asw-editor-toolbar\" *ngIf=\"showToolbar\">\r\n <div class=\"asw-editor-toolbar-set\">\r\n <button type=\"button\" matTooltip=\"Undo (Ctrl+Z)\" class=\"asw-editor-button\" (click)=\"triggerCommand('undo')\"\r\n [hidden]=\"isButtonHidden('undo')\" tabindex=\"-1\">\r\n <div [innerHTML]=\"icons.undo | aswSafeHtml\"></div>\r\n </button>\r\n <button type=\"button\" matTooltip=\"Redo (Ctrl+Y)\" class=\"asw-editor-button\" (click)=\"triggerCommand('redo')\"\r\n [hidden]=\"isButtonHidden('redo')\" tabindex=\"-1\">\r\n <div [innerHTML]=\"icons.redo | aswSafeHtml\"></div>\r\n </button>\r\n </div>\r\n <div class=\"asw-editor-toolbar-set\">\r\n <button [id]=\"'bold-'+id\" type=\"button\" matTooltip=\"Bold (Ctrl+B)\" class=\"asw-editor-button\" (click)=\"triggerCommand('bold')\"\r\n [disabled]=\"htmlMode\" [hidden]=\"isButtonHidden('bold')\" tabindex=\"-1\">\r\n <div [ngClass]=\"{'asw-icon-disabled': htmlMode }\" [innerHTML]=\"icons.bold | aswSafeHtml\"></div>\r\n </button>\r\n <button [id]=\"'italic-'+id\" type=\"button\" matTooltip=\"Italic (Ctrl+I)\" class=\"asw-editor-button\"\r\n (click)=\"triggerCommand('italic')\" [disabled]=\"htmlMode\" [hidden]=\"isButtonHidden('italic')\"\r\n tabindex=\"-1\">\r\n <div [ngClass]=\"{'asw-icon-disabled': htmlMode }\" [innerHTML]=\"icons.italic | aswSafeHtml\"></div>\r\n </button>\r\n <button [id]=\"'underline-'+id\" type=\"button\" matTooltip=\"Underline (Ctrl+U)\" class=\"asw-editor-button\"\r\n (click)=\"triggerCommand('underline')\" [disabled]=\"htmlMode\" [hidden]=\"isButtonHidden('underline')\"\r\n tabindex=\"-1\">\r\n <div [ngClass]=\"{'asw-icon-disabled': htmlMode }\" [innerHTML]=\"icons.underline | aswSafeHtml\"></div>\r\n </button>\r\n <button [id]=\"'strikeThrough-'+id\" type=\"button\" matTooltip=\"Strikethrough\" class=\"asw-editor-button\"\r\n (click)=\"triggerCommand('strikeThrough')\" [disabled]=\"htmlMode\" [hidden]=\"isButtonHidden('strikeThrough')\"\r\n tabindex=\"-1\">\r\n <div [ngClass]=\"{'asw-icon-disabled': htmlMode }\" [innerHTML]=\"icons.strikeThrough | aswSafeHtml\"></div>\r\n </button>\r\n <!-- <button [id]=\"'subscript-'+id\" type=\"button\" matTooltip=\"Subscript\" class=\"asw-editor-button\"\r\n (click)=\"triggerCommand('subscript')\" [disabled]=\"htmlMode\" [hidden]=\"isButtonHidden('subscript')\"\r\n tabindex=\"-1\">\r\n <mat-icon [ngClass]=\"{'asw-icon-disabled': htmlMode }\">subscript</mat-icon>\r\n </button>\r\n <button [id]=\"'superscript-'+id\" type=\"button\" matTooltip=\"Superscript\" class=\"asw-editor-button\"\r\n (click)=\"triggerCommand('superscript')\" [disabled]=\"htmlMode\" [hidden]=\"isButtonHidden('superscript')\"\r\n tabindex=\"-1\">\r\n <mat-icon [ngClass]=\"{'asw-icon-disabled': htmlMode }\">superscript</mat-icon>\r\n </button> -->\r\n </div>\r\n <div class=\"asw-editor-toolbar-set\">\r\n <button [id]=\"'foregroundColorPicker-'+id\" type=\"button\" class=\"asw-editor-button\"\r\n (click)=\"toggleColors('textColor')\" matTooltip=\"Text color\" [disabled]=\"htmlMode\"\r\n [hidden]=\"isButtonHidden('textColor')\" tabindex=\"-1\">\r\n <div [ngClass]=\"{'asw-icon-disabled': htmlMode }\" [innerHTML]=\"icons.formatColorText | aswSafeHtml\"></div>\r\n </button>\r\n <ng-container *ngIf=\"show\">\r\n <asw-color-picker [textColor]=\"textColor\"\r\n [isEditor]=\"true\"\r\n [backgroundColor]=\"backgroundColor\"\r\n (colorChange)=\"setColor($event)\"></asw-color-picker>\r\n </ng-container>\r\n </div>\r\n <div class=\"asw-editor-toolbar-set\">\r\n <button [id]=\"'alignLeft-'+id\" type=\"button\" matTooltip=\"Align left\" class=\"asw-editor-button\"\r\n (click)=\"triggerCommand('justifyLeft')\" [disabled]=\"htmlMode\" [hidden]=\"isButtonHidden('justifyLeft')\"\r\n tabindex=\"-1\">\r\n <div [ngClass]=\"{'asw-icon-disabled': htmlMode }\" [innerHTML]=\"icons.justifyLeft | aswSafeHtml\"></div>\r\n </button>\r\n <button [id]=\"'alignCenter-'+id\" type=\"button\" matTooltip=\"Align center\" class=\"asw-editor-button\"\r\n (click)=\"triggerCommand('justifyCenter')\" [disabled]=\"htmlMode\" [hidden]=\"isButtonHidden('justifyCenter')\"\r\n tabindex=\"-1\">\r\n <div [ngClass]=\"{'asw-icon-disabled': htmlMode }\" [innerHTML]=\"icons.justifyCenter | aswSafeHtml\"></div>\r\n </button>\r\n <button [id]=\"'alignRight-'+id\" type=\"button\" matTooltip=\"Align right\" class=\"asw-editor-button\"\r\n (click)=\"triggerCommand('justifyRight')\" [disabled]=\"htmlMode\" [hidden]=\"isButtonHidden('justifyRight')\"\r\n tabindex=\"-1\">\r\n <div [ngClass]=\"{'asw-icon-disabled': htmlMode }\" [innerHTML]=\"icons.justifyRight | aswSafeHtml\"></div>\r\n </button>\r\n <button [id]=\"'justifyFull-'+id\" type=\"button\" matTooltip=\"Justify Full\" class=\"asw-editor-button\"\r\n (click)=\"triggerCommand('justifyFull')\" [disabled]=\"htmlMode\" [hidden]=\"isButtonHidden('justifyFull')\"\r\n tabindex=\"-1\">\r\n <div [ngClass]=\"{'asw-icon-disabled': htmlMode }\" [innerHTML]=\"icons.justifyFull | aswSafeHtml\"></div>\r\n </button>\r\n </div>\r\n <div class=\"asw-editor-toolbar-set\">\r\n <button [id]=\"'indent-'+id\" type=\"button\" matTooltip=\"Indent\" class=\"asw-editor-button\"\r\n (click)=\"triggerCommand('indent')\" [disabled]=\"htmlMode\" [hidden]=\"isButtonHidden('indent')\"\r\n tabindex=\"-1\">\r\n <div [ngClass]=\"{'asw-icon-disabled': htmlMode }\" [innerHTML]=\"icons.indent | aswSafeHtml\"></div>\r\n </button>\r\n <button [id]=\"'outdent-'+id\" type=\"button\" matTooltip=\"Outdent\" class=\"asw-editor-button\"\r\n (click)=\"triggerCommand('outdent')\" [disabled]=\"htmlMode\" [hidden]=\"isButtonHidden('outdent')\"\r\n tabindex=\"-1\">\r\n <div [ngClass]=\"{'asw-icon-disabled': htmlMode }\" [innerHTML]=\"icons.outdent | aswSafeHtml\"></div>\r\n </button>\r\n </div>\r\n <div class=\"asw-editor-toolbar-set\">\r\n <button [id]=\"'insertUnorderedList-'+id\" type=\"button\" matTooltip=\"Unordered List\" class=\"asw-editor-button\"\r\n (click)=\"triggerCommand('insertUnorderedList')\" [disabled]=\"htmlMode\"\r\n [hidden]=\"isButtonHidden('insertUnorderedList')\" tabindex=\"-1\">\r\n <div [ngClass]=\"{'asw-icon-disabled': htmlMode }\" [innerHTML]=\"icons.formatListBulleted | aswSafeHtml\"></div>\r\n </button>\r\n <button [id]=\"'insertOrderedList-'+id\" type=\"button\" matTooltip=\"Ordered List\" class=\"asw-editor-button\"\r\n (click)=\"triggerCommand('insertOrderedList')\" [disabled]=\"htmlMode\"\r\n [hidden]=\"isButtonHidden('insertOrderedList')\" tabindex=\"-1\">\r\n <div [ngClass]=\"{'asw-icon-disabled': htmlMode }\" [innerHTML]=\