11import $ from 'jquery' ;
2+
23const { csrfToken} = window . config ;
34
45async function uploadFile ( file , uploadUrl ) {
@@ -21,67 +22,104 @@ function clipboardPastedImages(e) {
2122 if ( ! item . type || ! item . type . startsWith ( 'image/' ) ) continue ;
2223 files . push ( item . getAsFile ( ) ) ;
2324 }
24-
25- if ( files . length ) {
26- e . preventDefault ( ) ;
27- e . stopPropagation ( ) ;
28- }
2925 return files ;
3026}
3127
28+ class TextareaEditor {
29+ constructor ( editor ) {
30+ this . editor = editor ;
31+ }
3232
33- function insertAtCursor ( field , value ) {
34- if ( field . getTextArea ( ) . selectionStart || field . getTextArea ( ) . selectionStart === 0 ) {
35- const startPos = field . getTextArea ( ) . selectionStart ;
36- const endPos = field . getTextArea ( ) . selectionEnd ;
37- field . setValue ( field . getValue ( ) . substring ( 0 , startPos ) + value + field . getValue ( ) . substring ( endPos , field . getValue ( ) . length ) ) ;
38- field . getTextArea ( ) . electionStart = startPos + value . length ;
39- field . getTextArea ( ) . selectionEnd = startPos + value . length ;
40- } else {
41- field . setValue ( field . getValue ( ) + value ) ;
33+ insertPlaceholder ( value ) {
34+ const editor = this . editor ;
35+ const startPos = editor . selectionStart ;
36+ const endPos = editor . selectionEnd ;
37+ editor . value = editor . value . substring ( 0 , startPos ) + value + editor . value . substring ( endPos ) ;
38+ editor . selectionStart = startPos ;
39+ editor . selectionEnd = startPos + value . length ;
40+ editor . focus ( ) ;
4241 }
43- }
4442
45- function replaceAndKeepCursor ( field , oldval , newval ) {
46- if ( field . getTextArea ( ) . selectionStart || field . getTextArea ( ) . selectionStart === 0 ) {
47- const startPos = field . getTextArea ( ) . selectionStart ;
48- const endPos = field . getTextArea ( ) . selectionEnd ;
49- field . setValue ( field . getValue ( ) . replace ( oldval , newval ) ) ;
50- field . getTextArea ( ) . selectionStart = startPos + newval . length - oldval . length ;
51- field . getTextArea ( ) . selectionEnd = endPos + newval . length - oldval . length ;
52- } else {
53- field . setValue ( field . getValue ( ) . replace ( oldval , newval ) ) ;
43+ replacePlaceholder ( oldVal , newVal ) {
44+ const editor = this . editor ;
45+ const startPos = editor . selectionStart ;
46+ const endPos = editor . selectionEnd ;
47+ if ( editor . value . substring ( startPos , endPos ) === oldVal ) {
48+ editor . value = editor . value . substring ( 0 , startPos ) + newVal + editor . value . substring ( endPos ) ;
49+ editor . selectionEnd = startPos + newVal . length ;
50+ } else {
51+ editor . value = editor . value . replace ( oldVal , newVal ) ;
52+ editor . selectionEnd -= oldVal . length ;
53+ editor . selectionEnd += newVal . length ;
54+ }
55+ editor . selectionStart = editor . selectionEnd ;
56+ editor . focus ( ) ;
5457 }
5558}
5659
57- export function initCompImagePaste ( $target ) {
58- const dropzone = $target [ 0 ] . querySelector ( '.dropzone' ) ;
59- if ( ! dropzone ) {
60- return ;
60+ class CodeMirrorEditor {
61+ constructor ( editor ) {
62+ this . editor = editor ;
63+ }
64+
65+ insertPlaceholder ( value ) {
66+ const editor = this . editor ;
67+ const startPoint = editor . getCursor ( 'start' ) ;
68+ const endPoint = editor . getCursor ( 'end' ) ;
69+ editor . replaceSelection ( value ) ;
70+ endPoint . ch = startPoint . ch + value . length ;
71+ editor . setSelection ( startPoint , endPoint ) ;
72+ editor . focus ( ) ;
73+ }
74+
75+ replacePlaceholder ( oldVal , newVal ) {
76+ const editor = this . editor ;
77+ const endPoint = editor . getCursor ( 'end' ) ;
78+ if ( editor . getSelection ( ) === oldVal ) {
79+ editor . replaceSelection ( newVal ) ;
80+ } else {
81+ editor . setValue ( editor . getValue ( ) . replace ( oldVal , newVal ) ) ;
82+ }
83+ endPoint . ch -= oldVal . length ;
84+ endPoint . ch += newVal . length ;
85+ editor . setSelection ( endPoint , endPoint ) ;
86+ editor . focus ( ) ;
6187 }
62- const uploadUrl = dropzone . getAttribute ( 'data-upload-url' ) ;
63- const dropzoneFiles = dropzone . querySelector ( '.files' ) ;
64- $ ( document ) . on ( 'paste' , '.CodeMirror' , async function ( e ) {
65- const img = clipboardPastedImages ( e . originalEvent ) ;
66- const name = img [ 0 ] . name . substring ( 0 , img [ 0 ] . name . lastIndexOf ( '.' ) ) ;
67- insertAtCursor ( this . CodeMirror , `![${ name } ]()` ) ;
68- const data = await uploadFile ( img [ 0 ] , uploadUrl ) ;
69- replaceAndKeepCursor ( this . CodeMirror , `![${ name } ]()` , `` ) ;
70- const input = $ ( `<input id="${ data . uuid } " name="files" type="hidden">` ) . val ( data . uuid ) ;
71- dropzoneFiles . appendChild ( input [ 0 ] ) ;
72- } ) ;
7388}
7489
75- export function initEasyMDEImagePaste ( easyMDE , dropzone , files ) {
76- const uploadUrl = dropzone . getAttribute ( 'data-upload-url' ) ;
77- easyMDE . codemirror . on ( 'paste' , async ( _ , e ) => {
78- for ( const img of clipboardPastedImages ( e ) ) {
90+
91+ export function initEasyMDEImagePaste ( easyMDE , $dropzone ) {
92+ const uploadUrl = $dropzone . attr ( 'data-upload-url' ) ;
93+ const $files = $dropzone . find ( '.files' ) ;
94+
95+ if ( ! uploadUrl || ! $files . length ) return ;
96+
97+ const uploadClipboardImage = async ( editor , e ) => {
98+ const pastedImages = clipboardPastedImages ( e ) ;
99+ if ( ! pastedImages || pastedImages . length === 0 ) {
100+ return ;
101+ }
102+ e . preventDefault ( ) ;
103+ e . stopPropagation ( ) ;
104+
105+ for ( const img of pastedImages ) {
79106 const name = img . name . slice ( 0 , img . name . lastIndexOf ( '.' ) ) ;
107+
108+ const placeholder = `` ;
109+ editor . insertPlaceholder ( placeholder ) ;
80110 const data = await uploadFile ( img , uploadUrl ) ;
81- const pos = easyMDE . codemirror . getCursor ( ) ;
82- easyMDE . codemirror . replaceRange ( `` , pos ) ;
83- const input = $ ( `<input id=" ${ data . uuid } " name="files" type="hidden">` ) . val ( data . uuid ) ;
84- files . append ( input ) ;
111+ editor . replacePlaceholder ( placeholder , `` ) ;
112+
113+ const $ input = $ ( `<input name="files" type="hidden">` ) . attr ( 'id' , data . uuid ) . val ( data . uuid ) ;
114+ $ files. append ( $ input) ;
85115 }
116+ } ;
117+
118+ easyMDE . codemirror . on ( 'paste' , async ( _ , e ) => {
119+ return uploadClipboardImage ( new CodeMirrorEditor ( easyMDE . codemirror ) , e ) ;
120+ } ) ;
121+
122+ $ ( easyMDE . element ) . on ( 'paste' , async ( e ) => {
123+ return uploadClipboardImage ( new TextareaEditor ( easyMDE . element ) , e . originalEvent ) ;
86124 } ) ;
87125}
0 commit comments