11<template >
22 <div >
3- <div >
3+ <div class = " border-2 border-b-0 rounded-t p-2 bg-gray-200 " >
44 <ul >
55 <li >
6- <button type =" button" @click =" handleClick('bold')" >
7- <i class =" fa fa-bold" ></i >
8- </button >
9- <button type =" button" @click =" handleClick('emphasis')" >
10- <i class =" fa fa-italic" ></i >
11- </button >
12- <button type =" button" @click =" handleClick" >
13- <i class =" fa fa-header" ></i >
14- </button >
15- <button type =" button" @click =" handleClick('code')" >
16- <i class =" fa fa-code" ></i >
6+ <button
7+ v-for =" [key, value] of Object.entries(styles)"
8+ :key =" key"
9+ type =" button"
10+ class =" text-gray-600 mr-4 cursor-pointer"
11+ @click =" handleClick(key)"
12+ >
13+ <i class =" fa" :class =" value.class" ></i >
1714 </button >
1815 </li >
1916 </ul >
2017 </div >
21- <textarea
22- :name =" name"
18+ <textarea
19+ :name =" name"
2320 :id =" id"
2421 :value =" content"
25- class =" editor"
26- >
27- </textarea >
22+ class =" editor rounded-t-none resize-none h-40"
23+ ></textarea >
2824 </div >
2925</template >
3026
3127<script >
32- export default {
33- props: [' name' , ' id' , ' content' ],
34- data : () => {
35- return {
36- styles: {
37- ' headings' : {
38- ' h1' : ' # ' ,
39- ' h2' : ' ## ' ,
40- ' h3' : ' ### ' ,
41- ' h4' : ' #### ' ,
42- ' h5' : ' ##### ' ,
43- ' h6' : ' ###### ' ,
44- },
45- ' bold' : ' **' ,
46- ' emphasis' : ' _' ,
47- ' code' : ' ```'
28+ export default {
29+ props: [" name" , " id" , " content" ],
30+ data : () => {
31+ return {
32+ // Style configuration.
33+ styles: {
34+ header: {
35+ before: " ### " ,
36+ class: {
37+ " fa-header" : true
38+ }
39+ },
40+ bold: {
41+ before: " **" ,
42+ after: " **" ,
43+ class: {
44+ " fa-bold" : true
45+ }
46+ },
47+ italic: {
48+ before: " _" ,
49+ after: " _" ,
50+ class: {
51+ " fa-italic" : true
52+ }
53+ },
54+ quote: {
55+ before: " > " ,
56+ class: {
57+ " fa-quote-left" : true
58+ }
59+ },
60+ code: {
61+ before: " `" ,
62+ after: " `" ,
63+ class: {
64+ " fa-code" : true
65+ }
66+ },
67+ link: {
68+ before: " [](" ,
69+ after: " )" ,
70+ class: {
71+ " fa-link" : true
72+ }
73+ },
74+ image: {
75+ before: " " ,
77+ class: {
78+ " fa-file-image-o" : true
79+ }
4880 }
4981 }
50- },
51- methods : {
52- handleClick ( style ) {
53- const input = document . getElementById ( this . id );
54- let value = input . value ;
55- const selectionStart = input . selectionStart ;
56- const selectionEnd = input . selectionEnd ;
57- const styleCharacter = this .styles [style ];
82+ };
83+ },
84+ methods : {
85+ /**
86+ * Handle the click event of one a style button.
87+ */
88+ handleClick ( style ) {
89+ const input = this .$el . querySelectorAll ( " textarea " )[ 0 ];
5890
59- value = this .insertCharacterAtPosition (value, styleCharacter, selectionStart);
60- value = this .insertCharacterAtPosition (value, styleCharacter, selectionEnd + styleCharacter .length );
91+ // Get the start and end positions of the current selection.
92+ const selectionStart = input .selectionStart ;
93+ const selectionEnd = input .selectionEnd ;
6194
62- input .value = value;
63- input .setSelectionRange (selectionStart + styleCharacter .length , selectionEnd + styleCharacter .length );
64- input .focus ();
65- },
95+ // Find the style in the configuration.
96+ const styleFormat = this .styles [style];
6697
67- insertCharacterAtPosition (string , character , position ) {
68- return [string .slice (0 , position), character, string .slice (position)].join (' ' );
69- }
98+ // Get any prefix and/or suffix characters from the selected style.
99+ const prefix = styleFormat .before ? styleFormat .before : " " ;
100+ const suffix = styleFormat .after ? styleFormat .after : " " ;
101+
102+ // Insert the prefix at the relevant position.
103+ input .value = this .insertCharactersAtPosition (
104+ input .value ,
105+ prefix,
106+ selectionStart
107+ );
108+
109+ // Insert the suffix at the relevant position.
110+ input .value = this .insertCharactersAtPosition (
111+ input .value ,
112+ suffix,
113+ selectionEnd + prefix .length
114+ );
115+
116+ // Reselect the selection and focus the input.
117+ input .setSelectionRange (
118+ selectionStart + prefix .length ,
119+ selectionEnd + prefix .length
120+ );
121+ input .focus ();
122+ },
123+
124+ /**
125+ * Insert one or more characters at a certain position in a string.
126+ */
127+ insertCharactersAtPosition (string , character , position ) {
128+ return [
129+ string .slice (0 , position),
130+ character,
131+ string .slice (position)
132+ ].join (" " );
70133 }
71134 }
135+ };
72136 </script >
0 commit comments