Skip to content

Commit f67274d

Browse files
author
lon
committed
add upload input
1 parent d2b6661 commit f67274d

8 files changed

+146
-13
lines changed

demo/src/app/app.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<div style="margin: 20px">
22
<form novalidate #form="ngForm">
3-
<md-editor #md="ngModel" name="Content" [(ngModel)]="content" [mode]="mode" [options]="options" required maxlength="500"></md-editor>
3+
<md-editor #md="ngModel" name="Content" [upload]="doUpload" [(ngModel)]="content" [mode]="mode" [options]="options" required maxlength="500"></md-editor>
44
</form>
55
<div class="well well-sm">
66
<button class="btn btn-default" (click)="changeMode()">Change Mode (Current: {{ mode }})</button>
@@ -18,4 +18,4 @@
1818
<p>Required: {{ md?.errors?.required }}</p>
1919
<p>Maxlength: {{ md?.errors?.maxlength | json }}</p>
2020
</div>
21-
</div>
21+
</div>

demo/src/app/app.component.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Component } from '@angular/core';
2+
import { UploadResult } from './../../../src/public_api';
23

34
@Component({
45
selector: 'app-root',
@@ -45,4 +46,20 @@ export class AppComponent {
4546
this.options.enablePreviewContentClick = !this.options.enablePreviewContentClick;
4647
this.options = Object.assign({}, this.options);
4748
}
49+
50+
doUpload(files: Array<File>): Promise<Array<UploadResult>> {
51+
return new Promise((resolve, reject) => {
52+
setTimeout(() => {
53+
let result: Array<UploadResult> = [];
54+
for (let file of files) {
55+
result.push({
56+
name: file.name,
57+
url: `https://avatars3.githubusercontent.com/${file.name}`,
58+
isImg: file.type.indexOf('image') !== -1
59+
})
60+
}
61+
resolve(result);
62+
}, 3000);
63+
});
64+
}
4865
}

demo/src/app/app.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { NgModule } from '@angular/core';
55
import { AppRoutingModule } from './app-routing.module';
66
import { AppComponent } from './app.component';
77

8-
import { LMarkdownEditorModule } from './../../../dist';
8+
import { LMarkdownEditorModule } from './../../../src/public_api';
99

1010
@NgModule({
1111
declarations: [

src/lib/md-editor.component.ts

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export class MarkdownEditorComponent implements ControlValueAccessor, Validator
3131
@Input() public hideToolbar: boolean = false;
3232
@Input() public height: string = "300px";
3333
@Input() public preRender: Function;
34+
@Input() public upload: Function;
3435

3536
@Input()
3637
public get mode(): string {
@@ -61,6 +62,8 @@ export class MarkdownEditorComponent implements ControlValueAccessor, Validator
6162
public showPreviewPanel: boolean = true;
6263
public isFullScreen: boolean = false;
6364
public previewHtml: any;
65+
public dragover: boolean = false;
66+
public isUploading: boolean = false;
6467

6568
public get markdownValue(): any {
6669
return this._markdownValue || '';
@@ -91,6 +94,10 @@ export class MarkdownEditorComponent implements ControlValueAccessor, Validator
9194
scrollPastEnd: 0,
9295
enablePreviewContentClick: false
9396
};
97+
private get _hasUploadFunction(): boolean {
98+
return this.upload && this.upload instanceof Function;
99+
}
100+
94101
private _onChange = (_: any) => { };
95102
private _onTouched = () => { };
96103

@@ -112,7 +119,6 @@ export class MarkdownEditorComponent implements ControlValueAccessor, Validator
112119
markedRender.table = (header: string, body: string) => {
113120
return `<table class="table table-bordered">\n<thead>\n${header}</thead>\n<tbody>\n${body}</tbody>\n</table>\n`;
114121
};
115-
116122
markedRender.listitem = (text: any) => {
117123
if (/^\s*\[[x ]\]\s*/.test(text)) {
118124
text = text
@@ -123,7 +129,6 @@ export class MarkdownEditorComponent implements ControlValueAccessor, Validator
123129
return `<li>${text}</li>`;
124130
}
125131
};
126-
127132
this._markedOpt = {
128133
renderer: markedRender,
129134
highlight: (code: any) => hljs.highlightAuto(code).value
@@ -153,7 +158,7 @@ export class MarkdownEditorComponent implements ControlValueAccessor, Validator
153158
setTimeout(() => {
154159
this.markdownValue = value;
155160
if (typeof value !== 'undefined' && this._editor) {
156-
this._editor.setValue(value || '', 1);
161+
this._editor.setValue(value || '', 1);
157162
}
158163
}, 1);
159164
}
@@ -177,7 +182,7 @@ export class MarkdownEditorComponent implements ControlValueAccessor, Validator
177182
return result;
178183
}
179184

180-
insertContent(type: string) {
185+
insertContent(type: string, customContent?: string) {
181186
if (!this._editor) return;
182187
let selectedText = this._editor.getSelectedText();
183188
let isSelected = !!selectedText;
@@ -221,6 +226,10 @@ export class MarkdownEditorComponent implements ControlValueAccessor, Validator
221226
selectedText = "```language\r\n" + (selectedText || initText) + "\r\n```";
222227
startSize = 3;
223228
break;
229+
case 'Custom':
230+
selectedText = customContent;
231+
startSize = 0;
232+
break;
224233
}
225234
this._editor.session.replace(range, selectedText);
226235
if (!isSelected) {
@@ -257,4 +266,57 @@ export class MarkdownEditorComponent implements ControlValueAccessor, Validator
257266
}, timeOut);
258267
}
259268
}
269+
270+
onDragover(evt: DragEvent) {
271+
evt.stopImmediatePropagation();
272+
evt.preventDefault();
273+
if (!this._hasUploadFunction) return;
274+
this.dragover = true;
275+
}
276+
277+
onDrop(evt: DragEvent) {
278+
evt.stopImmediatePropagation();
279+
evt.preventDefault();
280+
if (!this._hasUploadFunction || this.isUploading) return;
281+
282+
if (!evt.dataTransfer.files || evt.dataTransfer.files.length === 0) {
283+
this.dragover = false;
284+
return;
285+
}
286+
287+
this.isUploading = true;
288+
Promise.resolve()
289+
.then(() => {
290+
return this.upload(evt.dataTransfer.files);
291+
})
292+
.then(data => {
293+
if (Array.isArray(data)) {
294+
let msg = [];
295+
for (let item of data) {
296+
let tempMsg = `[${item.name}](${item.url})`;
297+
if (item.isImg) {
298+
tempMsg = `!${tempMsg}`;
299+
}
300+
msg.push(tempMsg);
301+
}
302+
this.insertContent('Custom', msg.join('\r\n'));
303+
} else {
304+
console.warn('Invalid upload result. Please using follow this type `UploadResult`.')
305+
}
306+
this.isUploading = false;
307+
this.dragover = false;
308+
})
309+
.catch(err => {
310+
console.error(err);
311+
this.isUploading = false;
312+
this.dragover = false;
313+
});
314+
}
315+
316+
onDragleave(evt: DragEvent) {
317+
evt.stopImmediatePropagation();
318+
evt.preventDefault();
319+
if (!this._hasUploadFunction) return;
320+
this.dragover = false;
321+
}
260322
}

src/lib/md-editor.css

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,46 @@
6161
display: flex;
6262
}
6363

64+
.md-editor-container .editor-container>div .drag-container {
65+
display: none;
66+
}
67+
68+
.md-editor-container .editor-container>div.dragover {
69+
position: relative;
70+
}
71+
72+
.md-editor-container .editor-container>div.dragover .drag-container {
73+
display: block;
74+
position: absolute;
75+
left: 0;
76+
top: 0;
77+
right: 0;
78+
bottom: 0;
79+
z-index: 10;
80+
background-color: rgba(0, 0, 0, 0.4);
81+
display: flex;
82+
align-items: center;
83+
justify-content: center;
84+
font-size: 50px;
85+
color: white;
86+
}
87+
88+
.md-editor-container .editor-container>div.dragover .drag-container.drag-container-mask {
89+
background-color: transparent;
90+
z-index: 11;
91+
}
92+
93+
.md-editor-container .editor-container>div.dragover .drag-container .upload-loading {
94+
display: flex;
95+
flex-direction: column;
96+
align-items: center;
97+
}
98+
99+
.md-editor-container .editor-container>div.dragover .drag-container .upload-loading .text {
100+
font-size: 20px;
101+
margin-top: 10px;
102+
}
103+
64104
.md-editor-container .editor-container>div {
65105
flex: 1;
66106
}

src/lib/md-editor.html

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
</button>
3535
</div>
3636
<div class="btn-group">
37-
<button class="btn btn-sm btn-default" type="button" [attr.title]="showPreviewPanel ? 'Hide Preview' : 'Show Preview'" (click)="togglePreview()"
38-
*ngIf="!hideIcons.TogglePreview">
37+
<button class="btn btn-sm btn-default" type="button" [attr.title]="showPreviewPanel ? 'Hide Preview' : 'Show Preview'"
38+
(click)="togglePreview()" *ngIf="!hideIcons.TogglePreview">
3939
<i class="fa" [class.fa-eye]="!showPreviewPanel" [class.fa-eye-slash]="showPreviewPanel"></i>
4040
</button>
4141
</div>
@@ -46,7 +46,15 @@
4646
</div>
4747
</div>
4848
<div class="editor-container">
49-
<div [style.display]="mode == 'preview' ? 'none' : null">
49+
<div [class.dragover]="dragover" [style.display]="mode == 'preview' ? 'none' : null" (dragover)="onDragover($event)">
50+
<div class="drag-container">
51+
<div class="upload-loading">
52+
<i class="fa fa-upload" *ngIf="!isUploading"></i>
53+
<i class="fa fa-spinner fa-pulse fa-fw" *ngIf="isUploading"></i>
54+
<div class="text">{{ isUploading ? 'Uploading' : 'Drag it here' }}</div>
55+
</div>
56+
</div>
57+
<div class="drag-container drag-container-mask" (drop)="onDrop($event)" (dragleave)="onDragleave($event)"></div>
5058
<div class="editor-panel" [style.height]="height">
5159
<div class="ace-editor" #aceEditor></div>
5260
</div>

src/lib/md-editor.types.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
export interface MdEditorOption {
1+
export interface MdEditorOption {
22
showBorder: boolean // Show editor component's border
33
hideIcons: Array<string> // ['Bold', 'Italic', 'Heading', 'Refrence', 'Link', 'Image', 'Ul', 'Ol', 'Code', 'TogglePreview', 'FullScreen'], Default is empty
44
scrollPastEnd: number // The option for ace editor
55
enablePreviewContentClick: boolean // Allow user fire the click event on the preview panel, like href etc.
6-
}
6+
}
7+
8+
export interface UploadResult {
9+
isImg: boolean
10+
name: string
11+
url: string
12+
}

src/public_api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { FormsModule } from '@angular/forms';
55
import { MarkdownEditorComponent } from './lib/md-editor.component';
66

77
export { MarkdownEditorComponent } from './lib/md-editor.component';
8-
export { MdEditorOption } from './lib/md-editor.types';
8+
export { MdEditorOption, UploadResult } from './lib/md-editor.types';
99

1010
@NgModule({
1111
declarations: [

0 commit comments

Comments
 (0)