45
|
1 // https://fonts.google.com/icons
|
|
2
|
51
|
3 function ajax(url,postData,context) {
|
|
4 let request = new XMLHttpRequest();
|
|
5 let method = postData ? 'POST' : 'GET';
|
|
6 request.open( method, url );
|
|
7 if( postData )
|
|
8 request.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
|
|
9 request.onload = function() {
|
|
10 if( request.status !== 200 ) {
|
|
11 window.console && console.log( 'ajax failed: ' + request.status );
|
|
12 if( request.responseText )
|
|
13 document.write('<pre>'+request.responseText+'</pre>');
|
|
14 return;
|
|
15 }
|
|
16 eval( request.responseText );
|
|
17 };
|
|
18 request.send(postData);
|
|
19 }
|
|
20
|
48
|
21 function upload(input,callback) {
|
44
|
22 let file = input.files[0];
|
|
23 input.value = null;
|
|
24 let request = new XMLHttpRequest();
|
|
25 let url = 'https://upload.uploadcare.com/base/';
|
|
26 request.open( 'POST', url );
|
|
27 request.onload = function() {
|
|
28 if( request.status !== 200 ) {
|
|
29 let err = 'ajax failed: ' + request.status;
|
|
30 if( request.responseText ) {
|
|
31 err += '\n' + request.responseText;
|
|
32 document.write('<pre>'+request.responseText+'</pre>');
|
|
33 }
|
|
34 console.log(err);
|
|
35 ajax( '/error_log.js', 'err='+encodeURIComponent(err) );
|
|
36 return;
|
|
37 }
|
|
38 let response = JSON.parse(request.responseText);
|
|
39 let filename = file.name;
|
|
40 let url = 'https://ucarecdn.com/' + response.file + '/' + filename;
|
|
41 callback(input,url,filename);
|
|
42 };
|
|
43 let formData = new FormData();
|
|
44 formData.append( 'UPLOADCARE_PUB_KEY', 'fe3d30f3088a50941d45' );
|
|
45 formData.append( 'file', file );
|
|
46 request.send(formData);
|
|
47 }
|
|
48
|
|
49 function bbcodeCreate(div,options) {
|
46
|
50 if( typeof(div) === 'string' ) {
|
44
|
51 div = document.querySelector(div);
|
46
|
52 if(!div) throw 'selector not found';
|
|
53 }
|
|
54 options = options || {};
|
44
|
55 let content = options.content || '';
|
|
56 let save = options.save;
|
|
57 let cancel = options.cancel;
|
|
58 let html = `\
|
50
|
59 <div bbcode_editor>
|
48
|
60 <textarea name=bbcode>${content}</textarea>
|
51
|
61 <div preview from_bbcode></div>
|
45
|
62 <div buttons>
|
48
|
63 <button type=button bold title="Bold"><img src="/bbcode/icons/format_bold.svg"></button>
|
|
64 <button type=button italic title="Italic"><img src="/bbcode/icons/format_italic.svg"></button>
|
|
65 <button type=button underline title="Underline"><img src="/bbcode/icons/format_underlined.svg"></button>
|
|
66 <button type=button strikethrough title="Strikethrough"><img src="/bbcode/icons/format_strikethrough.svg"></button>
|
|
67 <button type=button sub title="Subscript"><img src="/bbcode/icons/subscript.svg"></button>
|
|
68 <button type=button sup title="Superscript"><img src="/bbcode/icons/superscript.svg"></button>
|
|
69 <button type=button ul title="Bullet list"><img src="/bbcode/icons/format_list_bulleted.svg"></button>
|
|
70 <button type=button ol title="Numbered list"><img src="/bbcode/icons/format_list_numbered.svg"></button>
|
49
|
71 <button type=button code_block title="Code block"><img src="/bbcode/icons/code_blocks.svg"></button>
|
|
72 <button type=button code_inline title="Inline code"><img src="/bbcode/icons/code.svg"></button>
|
48
|
73 <button type=button more checked title="More..."><img src="/bbcode/icons/more_horiz.svg"></button>
|
|
74 <input type=file>
|
|
75 <button type=button upload title="Upload File"><img src="/bbcode/icons/file_upload.svg"></button>
|
51
|
76 <button type=button preview title="Preview"><img src="/bbcode/icons/preview.svg"></button>
|
44
|
77 ` ;
|
|
78 if(save) {
|
|
79 html += `\
|
45
|
80 <button type=button save title="Send message"><img src="/bbcode/icons/send.svg"></button>
|
44
|
81 ` ;
|
|
82 }
|
|
83 if(cancel) {
|
|
84 html += `\
|
45
|
85 <button type=button cancel title="Cancel"><img src="/bbcode/icons/cancel.svg"></button>
|
44
|
86 ` ;
|
|
87 }
|
|
88 html += `\
|
45
|
89 </div>
|
44
|
90 </div>
|
|
91 ` ;
|
|
92 div.innerHTML = html;
|
48
|
93
|
51
|
94 let enabledInPreview = [];
|
|
95
|
|
96 if(save) {
|
|
97 let button = div.querySelector('button[save]');
|
|
98 button.onclick = save;
|
|
99 enabledInPreview.push(button);
|
|
100 }
|
|
101 if(cancel) {
|
|
102 let button = div.querySelector('button[cancel]');
|
|
103 button.onclick = cancel;
|
|
104 enabledInPreview.push(button);
|
|
105 }
|
48
|
106
|
|
107 let textarea = div.querySelector('textarea');
|
|
108 function fixTextarea() {
|
|
109 let height = textarea.scrollHeight;
|
|
110 if( height > textarea.clientHeight ) {
|
|
111 textarea.style.height = (height+2) + "px";
|
|
112 }
|
|
113 };
|
|
114 textarea.oninput = fixTextarea;
|
|
115 fixTextarea();
|
|
116
|
|
117 let moreButton = div.querySelector('button[more]');
|
|
118 function more() {
|
|
119 let button = moreButton;
|
|
120 let checked = button.getAttribute('checked') !== null;
|
|
121 let buttons = button.parentNode.querySelectorAll('button');
|
|
122 if( checked ) {
|
|
123 button.removeAttribute('checked');
|
|
124 for( let b of buttons ) {
|
|
125 if( b === button )
|
|
126 break;
|
|
127 b.setAttribute('hidden','');
|
|
128 }
|
|
129 } else {
|
|
130 button.setAttribute('checked','');
|
|
131 for( let b of buttons ) {
|
|
132 if( b === button )
|
|
133 break;
|
|
134 b.removeAttribute('hidden');
|
|
135 }
|
|
136 }
|
|
137 };
|
|
138 moreButton.onclick = more;
|
|
139 more();
|
51
|
140 enabledInPreview.push(moreButton);
|
|
141
|
|
142 let divPreview = div.querySelector('div[preview]');
|
|
143 function contextPreview(html) {
|
|
144 divPreview.innerHTML = html;
|
|
145 }
|
|
146 let previewButton = div.querySelector('button[preview]');
|
|
147 function preview() {
|
|
148 let button = previewButton;
|
|
149 let checked = button.getAttribute('checked') !== null;
|
|
150 let buttons = button.parentNode.querySelectorAll('button');
|
|
151 if( checked ) {
|
|
152 button.removeAttribute('checked');
|
|
153 for( let b of buttons ) {
|
|
154 b.disabled = false;
|
|
155 }
|
|
156 textarea.style.display = 'initial';
|
|
157 divPreview.style.display = 'none';
|
|
158 textarea.focus();
|
|
159 } else {
|
|
160 window.enabledInPreview = enabledInPreview;
|
|
161 button.setAttribute('checked','');
|
|
162 for( let b of buttons ) {
|
|
163 if( !enabledInPreview.includes(b) )
|
|
164 b.disabled = true;
|
|
165 }
|
|
166 textarea.style.display = 'none';
|
|
167 divPreview.style.display = 'block';
|
|
168 let url = '/bbcode/preview.js?text=' + encodeURIComponent(textarea.value);
|
|
169 ajax( url, null, {preview: contextPreview} );
|
|
170 }
|
|
171 }
|
|
172 previewButton.onclick = preview;
|
|
173 enabledInPreview.push(previewButton);
|
48
|
174
|
|
175 function add(tag,openTag,closeTag) {
|
|
176 let button = div.querySelector('button['+tag+']');
|
|
177 button.onclick = function() {
|
|
178 let start = textarea.selectionStart;
|
|
179 let end = textarea.selectionEnd;
|
|
180 textarea.setRangeText(closeTag,end,end);
|
|
181 textarea.setRangeText(openTag,start,start);
|
|
182 let len = openTag.length;
|
|
183 textarea.setSelectionRange(start+len,end+len);
|
|
184 fixTextarea();
|
|
185 textarea.focus();
|
|
186 };
|
|
187 }
|
|
188 add('bold','[b]','[/b]');
|
|
189 add('italic','[i]','[/i]');
|
|
190 add('underline','[u]','[/u]');
|
|
191 add('strikethrough','[s]','[/s]');
|
|
192 add('sub','[sub]','[/sub]');
|
|
193 add('sup','[sup]','[/sup]');
|
|
194 add('ul','[list]\n[item]','[/item]\n[/list]');
|
|
195 add('ol','[list=1]\n[item]','[/item]\n[/list]');
|
49
|
196 add('code_block','[code]','[/code]');
|
|
197 add('code_inline','[code=inline]','[/code]');
|
48
|
198
|
|
199 let fileInput = div.querySelector('input[type="file"]');
|
|
200 div.querySelector('button[upload]').onclick = function(){ fileInput.click(); };
|
|
201 function uploaded(input,url,filename) {
|
|
202 textarea.setRangeText(url,textarea.selectionStart,textarea.selectionEnd,'select');
|
|
203 textarea.focus();
|
|
204 }
|
|
205 fileInput.onchange = function() { upload(fileInput,uploaded); };
|
44
|
206 }
|