Mercurial Hosting > freedit
comparison src/bbcode/bbcode.js @ 48:4e1a01db19ec
add lists
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 17 Nov 2022 00:11:44 -0700 |
parents | 7ef9222474e2 |
children | f225e82b2bf8 |
comparison
equal
deleted
inserted
replaced
47:7ef9222474e2 | 48:4e1a01db19ec |
---|---|
1 // https://fonts.google.com/icons | 1 // https://fonts.google.com/icons |
2 | 2 |
3 function bb_fixTextarea(textarea) { | 3 function upload(input,callback) { |
4 let height = textarea.scrollHeight; | |
5 if( height > textarea.clientHeight ) { | |
6 textarea.style.height = (height+2) + "px"; | |
7 } | |
8 } | |
9 | |
10 function bb_fileButtonClick(button) { | |
11 button.parentNode.querySelector('input[type="file"]').click(); | |
12 } | |
13 | |
14 function bb_upload(input,callback) { | |
15 let file = input.files[0]; | 4 let file = input.files[0]; |
16 input.value = null; | 5 input.value = null; |
17 let request = new XMLHttpRequest(); | 6 let request = new XMLHttpRequest(); |
18 let url = 'https://upload.uploadcare.com/base/'; | 7 let url = 'https://upload.uploadcare.com/base/'; |
19 request.open( 'POST', url ); | 8 request.open( 'POST', url ); |
37 formData.append( 'UPLOADCARE_PUB_KEY', 'fe3d30f3088a50941d45' ); | 26 formData.append( 'UPLOADCARE_PUB_KEY', 'fe3d30f3088a50941d45' ); |
38 formData.append( 'file', file ); | 27 formData.append( 'file', file ); |
39 request.send(formData); | 28 request.send(formData); |
40 } | 29 } |
41 | 30 |
42 function bb_getDivBbcode(node) { | |
43 do { | |
44 //console.log(node); | |
45 if( node.getAttribute('bbcode') !== null ) | |
46 return node; | |
47 } while( node = node.parentNode ); | |
48 } | |
49 | |
50 function bb_getTextarea(node) { | |
51 return bb_getDivBbcode(node).querySelector('textarea'); | |
52 } | |
53 | |
54 function bb_uploaded(input,url,filename) { | |
55 let textarea = bb_getTextarea(input); | |
56 textarea.setRangeText(url,textarea.selectionStart,textarea.selectionEnd,'select'); | |
57 textarea.focus(); | |
58 } | |
59 | |
60 function bb_add(input,openTag,closeTag) { | |
61 let textarea = bb_getTextarea(input); | |
62 let start = textarea.selectionStart; | |
63 let end = textarea.selectionEnd; | |
64 textarea.setRangeText(closeTag,end,end); | |
65 textarea.setRangeText(openTag,start,start); | |
66 let len = openTag.length; | |
67 textarea.setSelectionRange(start+len,end+len); | |
68 textarea.focus(); | |
69 } | |
70 | |
71 function bb_more(button) { | |
72 let checked = button.getAttribute('checked') !== null; | |
73 let buttons = button.parentNode.querySelectorAll('button'); | |
74 if( checked ) { | |
75 button.removeAttribute('checked'); | |
76 for( let b of buttons ) { | |
77 if( b === button ) | |
78 break; | |
79 b.setAttribute('hidden',''); | |
80 } | |
81 } else { | |
82 button.setAttribute('checked',''); | |
83 for( let b of buttons ) { | |
84 if( b === button ) | |
85 break; | |
86 b.removeAttribute('hidden'); | |
87 } | |
88 } | |
89 } | |
90 | |
91 function bbcodeCreate(div,options) { | 31 function bbcodeCreate(div,options) { |
92 if( typeof(div) === 'string' ) { | 32 if( typeof(div) === 'string' ) { |
93 div = document.querySelector(div); | 33 div = document.querySelector(div); |
94 if(!div) throw 'selector not found'; | 34 if(!div) throw 'selector not found'; |
95 } | 35 } |
97 let content = options.content || ''; | 37 let content = options.content || ''; |
98 let save = options.save; | 38 let save = options.save; |
99 let cancel = options.cancel; | 39 let cancel = options.cancel; |
100 let html = `\ | 40 let html = `\ |
101 <div bbcode> | 41 <div bbcode> |
102 <textarea name=bbcode oninput="bb_fixTextarea(this)">${content}</textarea> | 42 <textarea name=bbcode>${content}</textarea> |
103 <div buttons> | 43 <div buttons> |
104 <button type=button onclick="bb_add(this,'[b]','[/b]')" title="Bold"><img src="/bbcode/icons/format_bold.svg"></button> | 44 <button type=button bold title="Bold"><img src="/bbcode/icons/format_bold.svg"></button> |
105 <button type=button onclick="bb_add(this,'[i]','[/i]')" title="Italic"><img src="/bbcode/icons/format_italic.svg"></button> | 45 <button type=button italic title="Italic"><img src="/bbcode/icons/format_italic.svg"></button> |
106 <button type=button onclick="bb_add(this,'[u]','[/u]')" title="Underline"><img src="/bbcode/icons/format_underlined.svg"></button> | 46 <button type=button underline title="Underline"><img src="/bbcode/icons/format_underlined.svg"></button> |
107 <button type=button onclick="bb_add(this,'[s]','[/s]')" title="Strikethrough"><img src="/bbcode/icons/format_strikethrough.svg"></button> | 47 <button type=button strikethrough title="Strikethrough"><img src="/bbcode/icons/format_strikethrough.svg"></button> |
108 <button type=button onclick="bb_add(this,'[sub]','[/sub]')" title="Subscript"><img src="/bbcode/icons/subscript.svg"></button> | 48 <button type=button sub title="Subscript"><img src="/bbcode/icons/subscript.svg"></button> |
109 <button type=button onclick="bb_add(this,'[sup]','[/sup]')" title="Superscript"><img src="/bbcode/icons/superscript.svg"></button> | 49 <button type=button sup title="Superscript"><img src="/bbcode/icons/superscript.svg"></button> |
110 <button more checked type=button onclick="bb_more(this)" title="More..."><img src="/bbcode/icons/more_horiz.svg"></button> | 50 <button type=button ul title="Bullet list"><img src="/bbcode/icons/format_list_bulleted.svg"></button> |
111 <input type=file onchange="bb_upload(this,bb_uploaded)"> | 51 <button type=button ol title="Numbered list"><img src="/bbcode/icons/format_list_numbered.svg"></button> |
112 <button type=button onclick="bb_fileButtonClick(this)" title="Upload File"><img src="/bbcode/icons/file_upload.svg"></button> | 52 <button type=button more checked title="More..."><img src="/bbcode/icons/more_horiz.svg"></button> |
53 <input type=file> | |
54 <button type=button upload title="Upload File"><img src="/bbcode/icons/file_upload.svg"></button> | |
113 ` ; | 55 ` ; |
114 if(save) { | 56 if(save) { |
115 html += `\ | 57 html += `\ |
116 <button type=button save title="Send message"><img src="/bbcode/icons/send.svg"></button> | 58 <button type=button save title="Send message"><img src="/bbcode/icons/send.svg"></button> |
117 ` ; | 59 ` ; |
124 html += `\ | 66 html += `\ |
125 </div> | 67 </div> |
126 </div> | 68 </div> |
127 ` ; | 69 ` ; |
128 div.innerHTML = html; | 70 div.innerHTML = html; |
71 | |
129 if(save) | 72 if(save) |
130 div.querySelector('button[save]').addEventListener('click',save); | 73 div.querySelector('button[save]').onclick = save; |
131 if(cancel) | 74 if(cancel) |
132 div.querySelector('button[cancel]').addEventListener('click',cancel); | 75 div.querySelector('button[cancel]').onclick = cancel; |
133 let textarea = div.querySelector('textarea') | 76 |
134 bb_fixTextarea(textarea); | 77 let textarea = div.querySelector('textarea'); |
135 bb_more( div.querySelector('button[more]') ); | 78 function fixTextarea() { |
79 let height = textarea.scrollHeight; | |
80 if( height > textarea.clientHeight ) { | |
81 textarea.style.height = (height+2) + "px"; | |
82 } | |
83 }; | |
84 textarea.oninput = fixTextarea; | |
85 fixTextarea(); | |
86 | |
87 let moreButton = div.querySelector('button[more]'); | |
88 function more() { | |
89 let button = moreButton; | |
90 let checked = button.getAttribute('checked') !== null; | |
91 let buttons = button.parentNode.querySelectorAll('button'); | |
92 if( checked ) { | |
93 button.removeAttribute('checked'); | |
94 for( let b of buttons ) { | |
95 if( b === button ) | |
96 break; | |
97 b.setAttribute('hidden',''); | |
98 } | |
99 } else { | |
100 button.setAttribute('checked',''); | |
101 for( let b of buttons ) { | |
102 if( b === button ) | |
103 break; | |
104 b.removeAttribute('hidden'); | |
105 } | |
106 } | |
107 }; | |
108 moreButton.onclick = more; | |
109 more(); | |
110 | |
111 function add(tag,openTag,closeTag) { | |
112 let button = div.querySelector('button['+tag+']'); | |
113 button.onclick = function() { | |
114 let start = textarea.selectionStart; | |
115 let end = textarea.selectionEnd; | |
116 textarea.setRangeText(closeTag,end,end); | |
117 textarea.setRangeText(openTag,start,start); | |
118 let len = openTag.length; | |
119 textarea.setSelectionRange(start+len,end+len); | |
120 fixTextarea(); | |
121 textarea.focus(); | |
122 }; | |
123 } | |
124 add('bold','[b]','[/b]'); | |
125 add('italic','[i]','[/i]'); | |
126 add('underline','[u]','[/u]'); | |
127 add('strikethrough','[s]','[/s]'); | |
128 add('sub','[sub]','[/sub]'); | |
129 add('sup','[sup]','[/sup]'); | |
130 add('ul','[list]\n[item]','[/item]\n[/list]'); | |
131 add('ol','[list=1]\n[item]','[/item]\n[/list]'); | |
132 | |
133 let fileInput = div.querySelector('input[type="file"]'); | |
134 div.querySelector('button[upload]').onclick = function(){ fileInput.click(); }; | |
135 function uploaded(input,url,filename) { | |
136 textarea.setRangeText(url,textarea.selectionStart,textarea.selectionEnd,'select'); | |
137 textarea.focus(); | |
138 } | |
139 fileInput.onchange = function() { upload(fileInput,uploaded); }; | |
136 } | 140 } |