Skip to content

Commit

Permalink
feat(editor): create [content] for input content by binding.
Browse files Browse the repository at this point in the history
  • Loading branch information
WilliamAguera committed May 10, 2018
1 parent bf7f923 commit c3c2d38
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 63 deletions.
34 changes: 14 additions & 20 deletions src/app/components/editor/editor.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,36 @@
[(ngModel)]="font">
</tl-dropdown-list>
</li>
<li><tl-dropdown-list [data]="dataFontSize" [(ngModel)]="fontSize"></tl-dropdown-list></li>
<li><tl-dropdown-list [data]="dataFontSize" (ngModelChange)="onChangeFontSize($event)" [(ngModel)]="fontSize"></tl-dropdown-list></li>
<li><span class="ui-separator"></span></li>
<li><button class="ui-command fa fa-bold" (click)="setBold()"></button></li>
<li><button class="ui-command fa fa-italic" (click)="setItalic()"></button></li>
<li><button class="ui-command fa fa-underline" (click)="setUnderline()"></button></li>
<li><button class="ui-command fa fa-bold" [ngClass]="{'ui-active-tool': activeTools.bold}" (click)="setBold()"></button></li>
<li><button class="ui-command fa fa-italic" [ngClass]="{'ui-active-tool': activeTools.italic}" (click)="setItalic()"></button></li>
<li><button class="ui-command fa fa-underline" [ngClass]="{'ui-active-tool': activeTools.underline}" (click)="setUnderline()"></button></li>
<li>
<i class="ion-paintbucket"></i>
<button class="ui-command fa fa-font"></button>
<input class="ui-command ui-color-component" [(ngModel)]="colorSelected" (ngModelChange)="onChangeColor($event)" type="color">
</li>
<li><button class="ui-command fa fa-pencil" (click)="setHighlight()"></button></li>
<li><button class="ui-command fa fa-pencil" [ngClass]="{'ui-active-tool': cursorHighlight}" (click)="setHighlight()"></button></li>
<li><span class="ui-separator"></span></li>
<li><button class="ui-command fa fa-align-left" (click)="alignContent('justifyLeft')"></button></li>
<li><button class="ui-command fa fa-align-center" (click)="alignContent('justifyCenter')"></button></li>
<li><button class="ui-command fa fa-align-right" (click)="alignContent('justifyRight')"></button></li>
<li><button class="ui-command fa fa-align-justify" (click)="alignContent('justifyFull')"></button></li>
<li><button class="ui-command fa fa-align-left" [ngClass]="{'ui-active-tool': activeTools.alignLeft}" (click)="alignContent('justifyLeft')"></button></li>
<li><button class="ui-command fa fa-align-center" [ngClass]="{'ui-active-tool': activeTools.alignCenter}" (click)="alignContent('justifyCenter')"></button></li>
<li><button class="ui-command fa fa-align-right" [ngClass]="{'ui-active-tool': activeTools.alignRight}" (click)="alignContent('justifyRight')"></button></li>
<li><button class="ui-command fa fa-align-justify" [ngClass]="{'ui-active-tool': activeTools.alignJustify}" (click)="alignContent('justifyFull')"></button></li>
<li><span class="ui-separator"></span></li>
<li><button class="ui-command fa fa-list-ul" (click)="setUnorderedList()"></button></li>
<li><button class="ui-command fa fa-list-ol" (click)="setOrderedList()"></button></li>
<li><button class="ui-command fa fa-list-ul" [ngClass]="{'ui-active-tool': activeTools.listUnordered}" (click)="setUnorderedList()"></button></li>
<li><button class="ui-command fa fa-list-ol" [ngClass]="{'ui-active-tool': activeTools.listOrdered}" (click)="setOrderedList()"></button></li>
<li><span class="ui-separator"></span></li>
<li><button class="ui-command fa fa-link" (click)="toggleLinkBox(); setDescriptionLink();"></button></li>
<li><button class="ui-command fa ion-image" (click)="toggleImageBox()"></button></li>
<li><button class="ui-command fa ion-quote" [ngClass]="{'ui-active-tool': activeTools.blockQuote}" (click)="setQuote()"></button></li>
</ul>
</div>
<div #contentEditor
tabindex="-1"
class="ui-editor-content"
(mouseup)="onMouseUp()"
(click)="setCursorSelection()"
[ngStyle]="{
'text-align': alignment,
'font-size': fontSize + 'px'
}"
[attr.contenteditable]="contentEditable">
Lorem Ipsum é simplesmente uma simulação de texto da indústria tipográfica e de impressos, e vem sendo utilizado desde o século XVI,
quando um impressor desconhecido pegou uma bandeja de tipos e os embaralhou para fazer um livro de modelos de tipos. Lorem Ipsum sobreviveu não só a cinco séculos, como também ao salto para a editoração eletrônica, permanecendo essencialmente inalterado. Se popularizou na década de 60, quando a Letraset lançou decalques contendo passagens de
Lorem Ipsum, e mais recentemente quando passou a ser integrado a softwares de editoração eletrônica como Aldus PageMaker.
[attr.contenteditable]="contentEditable" [innerHTML]="content">
</div>
<tl-editor-link-box [descriptionLink]="descriptionLink"
*ngIf="toggleLink && !toggleImage"
Expand Down
4 changes: 4 additions & 0 deletions src/app/components/editor/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
}
}

.ui-active-tool {
color: #66CC99;
}

.ui-separator {
height: 100%;
background: #e8e8e8;
Expand Down
192 changes: 160 additions & 32 deletions src/app/components/editor/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*/
import {
AfterContentInit,
Component, ElementRef, OnChanges, Renderer2, SimpleChanges, ViewChild,
Component, ElementRef, Input, OnChanges, Renderer2, SimpleChanges, ViewChild,
} from '@angular/core';

@Component( {
Expand All @@ -32,6 +32,8 @@ import {

export class TlEditor implements AfterContentInit, OnChanges {

@Input() content;

@ViewChild( 'contentEditor' ) contentEditor;

@ViewChild( 'linkBox' ) linkBox;
Expand All @@ -42,11 +44,9 @@ export class TlEditor implements AfterContentInit, OnChanges {

public dataFontSize = [];

public font = 'Segoe UI';

public fontSize = '16';
public font = 'Arial';

public alignment = '';
public fontSize = '3pt';

public toggleLink = false;

Expand All @@ -60,15 +60,28 @@ export class TlEditor implements AfterContentInit, OnChanges {

public anchorNodeCursor;

public cursor = false;
public cursorHighlight = false;

public selectedContent = false;

public cursorSelection;

public contentEditable = true;

public image = { imageUrl: '', width: 0, height: 0};
public activeTools = {
bold: false,
italic: false,
underline: false,
listUnordered: false,
listOrdered: false,
alignLeft: false,
alignCenter: false,
alignRight: false,
alignJustify: false,
blockQuote: false
};

public image = { imageUrl: '' };

public selection = { start: 0, end: 0, baseNode: null };

Expand All @@ -81,7 +94,7 @@ export class TlEditor implements AfterContentInit, OnChanges {
{ textItem: 'Comic Sans MS', value: 'Comic Sans MS' },
{ textItem: 'Segoe UI', value: 'Segoe UI' },
];
this.dataFontSize = [ '3', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20' ];
this.dataFontSize = [ '1pt', '2pt', '3pt', '4pt', '5pt', '6pt', '7pt' ];
}

ngAfterContentInit() {
Expand All @@ -91,6 +104,7 @@ export class TlEditor implements AfterContentInit, OnChanges {
alignContent( align ) {
this.setContentFocus();
document.execCommand( align, false, null );
this.setCursorSelection();
}

setAnchorNode() {
Expand All @@ -112,37 +126,154 @@ export class TlEditor implements AfterContentInit, OnChanges {
setBold() {
this.setContentFocus();
document.execCommand( 'bold', false, null );
this.setCursorSelection();
}

setQuote() {
this.setContentFocus();
this.activeTools.blockQuote = !this.activeTools.blockQuote;
document.execCommand( 'formatBlock', false, this.activeTools.blockQuote ? 'blockquote' : 'div' );
this.setCursorSelection();
}

setItalic() {
this.setContentFocus();
document.execCommand( 'italic', false, null );
this.setCursorSelection();
}

setUnorderedList() {
this.setContentFocus();
document.execCommand( 'insertUnorderedList', false, null );
this.setCursorSelection();
}

setOrderedList() {
this.setContentFocus();
document.execCommand( 'insertOrderedList', false, null );
this.setCursorSelection();
}

setCursorSelection() {
this.cursorSelection = window.getSelection();
this.handleActiveTools();
}

handleActiveTools() {
this.handleClosestBold();
this.handleClosestItalic();
this.handleClosestUnderline();
this.handleColorParent();
this.handleListUnordered();
this.handleListOrdered();
this.handleAlignLeft();
this.handleAlignCenter();
this.handleAlignRight();
this.handleAlignJustify();
this.handleFontSize();
this.handleFontName();
this.handleBlockQuote();
}

handleFontName() {
this.isClosestParentElement( 'font' ) && this.hasFontFace()
? this.setFontNodeSelected() : this.setDefaultFont();
}

hasFontFace() {
return this.cursorSelection.baseNode.parentNode.closest( 'font' ).getAttribute( 'face' );
}

hasFontSize() {
return this.cursorSelection.baseNode.parentNode.closest( 'font' ).getAttribute( 'size' );
}

setFontNodeSelected() {
this.font = this.cursorSelection.baseNode.parentNode.closest( 'font' ).getAttribute( 'face' );
}

setDefaultFont() {
this.font = 'Arial';
}

setFontSizeNodeSelected() {
this.fontSize = this.cursorSelection.baseNode.parentNode.closest( 'font' ).getAttribute( 'size' ) + 'pt';
}

setDefaultFontSize() {
this.fontSize = '3pt';
}

handleFontSize() {
this.isClosestParentElement( 'font' ) && this.hasFontSize()
? this.setFontSizeNodeSelected() : this.setDefaultFontSize();
}

handleAlignLeft() {
this.activeTools.alignLeft = this.hasStyleParentElement( 'left' );
}

handleAlignCenter() {
this.activeTools.alignCenter = this.hasStyleParentElement( 'center' );
}

handleAlignRight() {
this.activeTools.alignRight = this.hasStyleParentElement( 'right' );
}

handleAlignJustify() {
this.activeTools.alignJustify = this.hasStyleParentElement( 'justify' );
}

handleListOrdered() {
this.activeTools.listOrdered = this.isClosestParentElement( 'ol' );
}

handleListUnordered() {
this.activeTools.listUnordered = this.isClosestParentElement( 'ul' );
}

onChangeColor($event) {
document.execCommand('foreColor', false, $event);
}

handleColorParent() {
const getElementFont = this.cursorSelection.baseNode.parentNode.closest( 'font' );
getElementFont ? this.colorSelected = getElementFont.getAttribute( 'color' ) : this.colorSelected = '#00000';
}

handleClosestBold() {
this.activeTools.bold = this.isClosestParentElement( 'b' );
}

handleClosestUnderline() {
this.activeTools.underline = this.isClosestParentElement( 'u' );
}

handleClosestItalic() {
this.activeTools.italic = this.isClosestParentElement( 'i' );
}

handleBlockQuote() {
this.activeTools.blockQuote = this.isClosestParentElement( 'blockquote' );
}

hasStyleParentElement( alignment: string ) {
const childElement = this.cursorSelection.baseNode.parentNode;
if ( childElement.attributes.length > 0 ) {
return childElement.attributes[ 0 ].value.includes( alignment );
}
return false;
}

onChangeColor( $event ) {
console.log( 'change value', $event );
isClosestParentElement( element ) {
return !!this.cursorSelection.baseNode.parentNode.closest( element );
}

setImage( $event ) {
this.setContentFocus();
this.image.imageUrl = $event.imageUrl;
this.image.width = $event.width;
this.image.height = $event.height;
this.cursorSelection.getRangeAt( 0 ).insertNode(this.createImageElement());
this.cursorSelection.getRangeAt( 0 ).insertNode( this.createImageElement() );
this.toggleImageBox();
}

Expand Down Expand Up @@ -173,14 +304,8 @@ export class TlEditor implements AfterContentInit, OnChanges {

createImageElement() {
const imageHTML = new ElementRef( this.renderer.createElement( 'img' ) );
this.renderer.addClass(imageHTML.nativeElement, 'ui-image-editor');
this.renderer.addClass( imageHTML.nativeElement, 'ui-image-editor' );
imageHTML.nativeElement.src = this.image.imageUrl;
if (this.image.width > 0) {
imageHTML.nativeElement.width = this.image.width;
}
if (this.image.height > 0) {
imageHTML.nativeElement.height = this.image.height;
}
return imageHTML.nativeElement;
}

Expand All @@ -193,13 +318,9 @@ export class TlEditor implements AfterContentInit, OnChanges {
this.handleAddElementRange( link );
}


handleAddElementRange( link ) {
if ( this.selectedContent ) {
window.getSelection().getRangeAt( 0 ).surroundContents( link.nativeElement );
} else {
this.selectedContent ? window.getSelection().getRangeAt( 0 ).surroundContents( link.nativeElement ) :
window.getSelection().getRangeAt( 0 ).insertNode( link.nativeElement );
}
}

recoverSelection() {
Expand All @@ -211,9 +332,16 @@ export class TlEditor implements AfterContentInit, OnChanges {
selection.addRange( range );
}

onChangeFontSize( $event ) {
this.recoverSelection();
this.setContentFocus();
this.fontSize = $event;
document.execCommand( 'fontSize', null, parseInt( this.fontSize, 10 ) );
}

setHighlight() {
this.wrapper.nativeElement.style.cursor = 'grabbing';
this.cursor = true;
this.cursorHighlight = true;
}

resetCursor() {
Expand All @@ -223,30 +351,30 @@ export class TlEditor implements AfterContentInit, OnChanges {
setUnderline() {
this.setContentFocus();
document.execCommand( 'underline', false, null );
this.setCursorSelection();
}

setContentFocus() {
this.contentEditor.nativeElement.focus();
}

onChangeFont( $event ) {
this.font = $event;
this.setContentFocus();
this.recoverSelection();
this.setContentFocus();
this.font = $event;
document.execCommand( 'fontName', false, this.font );
}

onMouseUp() {
this.toggleLink = false;
this.setAnchorNode();
if ( this.cursor ) {
if ( this.cursorHighlight ) {
document.execCommand( 'hiliteColor', false, '#f0ef99' );
this.cursor = false;
this.cursorHighlight = false;
this.resetCursor();
}
}

ngOnChanges( data: SimpleChanges ) {
}
ngOnChanges( data: SimpleChanges ) {}

}
Loading

0 comments on commit c3c2d38

Please sign in to comment.