Mercurial Hosting > freedit
comparison src/bbcode/bbcode.js @ 60:8b5b1bce7d6b
bcode menus
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 30 Nov 2022 23:50:52 -0700 |
parents | cac477dd1f82 |
children |
comparison
equal
deleted
inserted
replaced
59:02d8876dc41d | 60:8b5b1bce7d6b |
---|---|
50 if( typeof(div) === 'string' ) { | 50 if( typeof(div) === 'string' ) { |
51 div = document.querySelector(div); | 51 div = document.querySelector(div); |
52 if(!div) throw 'selector not found'; | 52 if(!div) throw 'selector not found'; |
53 } | 53 } |
54 options = options || {}; | 54 options = options || {}; |
55 options.buttons = options.buttons || {}; | |
55 let content = options.content || ''; | 56 let content = options.content || ''; |
56 let save = options.save; | |
57 let cancel = options.cancel; | |
58 let html = `\ | 57 let html = `\ |
59 <div bbcode_editor> | 58 <div bbcode_editor> |
60 <textarea name=bbcode>${content}</textarea> | 59 <div buttons=top> |
61 <div preview from_bbcode></div> | |
62 <div buttons> | |
63 <button type=button bold title="Bold"><img src="/bbcode/icons/format_bold.svg"></button> | 60 <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> | 61 <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> | 62 <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> | 63 <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> | 64 <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> | 65 <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> | 66 <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> | 67 <button type=button ol title="Numbered list"><img src="/bbcode/icons/format_list_numbered.svg"></button> |
71 <button type=button code_block title="Code block"><img src="/bbcode/icons/code_blocks.svg"></button> | 68 <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> | 69 <button type=button code_inline title="Inline code"><img src="/bbcode/icons/code.svg"></button> |
73 <button type=button convert_urls checked title="Convert URLs"><img src="/bbcode/icons/media_link.svg"></button> | 70 <button type=button convert_urls><input type=checkbox name=convert_urls checked> Convert URLs</button> |
74 <input type=hidden name=convert_urls value=true> | 71 </div> |
75 <button type=button more checked title="More..."><img src="/bbcode/icons/more_horiz.svg"></button> | 72 <textarea name=bbcode>${content}</textarea> |
73 <div preview from_bbcode></div> | |
74 <div buttons=bottom> | |
75 <button type=button more><input type=checkbox> BBCode menu</button> | |
76 <input type=file> | 76 <input type=file> |
77 <button type=button upload title="Upload File"><img src="/bbcode/icons/file_upload.svg"></button> | 77 <button type=button upload>Upload file</button> |
78 <button type=button preview title="Preview"><img src="/bbcode/icons/preview.svg"></button> | 78 <button type=button preview><input type=checkbox> Preview</button> |
79 ` ; | 79 ` ; |
80 if(save) { | 80 for( let key of Object.keys(options.buttons) ) { |
81 html += `\ | 81 html += `\ |
82 <button type=button save title="Send message"><img src="/bbcode/icons/send.svg"></button> | 82 <button type=button key="${key}">${key}</button> |
83 ` ; | |
84 } | |
85 if(cancel) { | |
86 html += `\ | |
87 <button type=button cancel title="Cancel"><img src="/bbcode/icons/cancel.svg"></button> | |
88 ` ; | 83 ` ; |
89 } | 84 } |
90 html += `\ | 85 html += `\ |
91 </div> | 86 </div> |
92 </div> | 87 </div> |
94 div.innerHTML = html; | 89 div.innerHTML = html; |
95 | 90 |
96 let enabledInPreview = []; | 91 let enabledInPreview = []; |
97 let convertUrls = true; | 92 let convertUrls = true; |
98 | 93 |
99 if(save) { | 94 for( let entry of Object.entries(options.buttons) ) { |
100 let button = div.querySelector('button[save]'); | 95 console.log(entry); |
96 let button = div.querySelector('button[key="'+entry[0]+'"]'); | |
97 let fn = entry[1]; | |
101 button.onclick = function(event) { | 98 button.onclick = function(event) { |
102 event.convertUrls = convertUrls; | 99 event.convertUrls = convertUrls; |
103 save(event); | 100 fn(event); |
104 }; | 101 }; |
105 enabledInPreview.push(button); | |
106 } | |
107 if(cancel) { | |
108 let button = div.querySelector('button[cancel]'); | |
109 button.onclick = cancel; | |
110 enabledInPreview.push(button); | 102 enabledInPreview.push(button); |
111 } | 103 } |
112 | 104 |
113 let textarea = div.querySelector('textarea'); | 105 let textarea = div.querySelector('textarea'); |
114 function fixTextarea() { | 106 function fixTextarea() { |
118 } | 110 } |
119 }; | 111 }; |
120 textarea.oninput = fixTextarea; | 112 textarea.oninput = fixTextarea; |
121 fixTextarea(); | 113 fixTextarea(); |
122 | 114 |
123 function toggle(button) { | 115 function checkboxButtonClick(event) { |
124 let checked = button.getAttribute('checked') !== null; | 116 event.target.querySelector('input').click(); |
125 checked = !checked; // toggle | 117 }; |
126 if( checked ) { | 118 |
127 button.setAttribute('checked',''); | 119 let topButtons = div.querySelector('[buttons="top"]'); |
120 topButtons.style.display = 'none'; | |
121 let moreButton = div.querySelector('button[more]'); | |
122 moreButton.onclick = checkboxButtonClick; | |
123 let moreCheckbox = moreButton.querySelector('input'); | |
124 moreCheckbox.onclick = function() { | |
125 if( moreCheckbox.checked ) { | |
126 topButtons.style.display = 'flex'; | |
128 } else { | 127 } else { |
129 button.removeAttribute('checked'); | 128 topButtons.style.display = 'none'; |
130 } | 129 } |
131 return checked; | 130 event.stopPropagation(); |
132 } | 131 }; |
133 | |
134 let moreButton = div.querySelector('button[more]'); | |
135 function more() { | |
136 let checked = toggle(moreButton); | |
137 let buttons = moreButton.parentNode.querySelectorAll('button'); | |
138 if( checked ) { | |
139 for( let b of buttons ) { | |
140 if( b === moreButton ) | |
141 break; | |
142 b.removeAttribute('hidden'); | |
143 } | |
144 } else { | |
145 for( let b of buttons ) { | |
146 if( b === moreButton ) | |
147 break; | |
148 b.setAttribute('hidden',''); | |
149 } | |
150 } | |
151 }; | |
152 moreButton.onclick = more; | |
153 more(); | |
154 enabledInPreview.push(moreButton); | |
155 | 132 |
156 let divPreview = div.querySelector('div[preview]'); | 133 let divPreview = div.querySelector('div[preview]'); |
157 function contextPreview(bbcode,html) { | 134 function contextPreview(bbcode,html) { |
158 textarea.value = bbcode; | 135 textarea.value = bbcode; |
159 divPreview.innerHTML = html; | 136 divPreview.innerHTML = html; |
160 } | 137 } |
161 let previewButton = div.querySelector('button[preview]'); | 138 let previewButton = div.querySelector('button[preview]'); |
162 function preview() { | 139 previewButton.onclick = checkboxButtonClick; |
163 let checked = toggle(previewButton); | 140 let previewCheckbox = previewButton.querySelector('input'); |
141 previewCheckbox.onclick = function() { | |
164 let buttons = previewButton.parentNode.querySelectorAll('button'); | 142 let buttons = previewButton.parentNode.querySelectorAll('button'); |
165 if( checked ) { | 143 if( previewCheckbox.checked ) { |
166 for( let b of buttons ) { | 144 for( let b of buttons ) { |
167 if( !enabledInPreview.includes(b) ) | 145 if( !enabledInPreview.includes(b) ) |
168 b.disabled = true; | 146 b.disabled = true; |
169 } | 147 } |
170 textarea.style.display = 'none'; | 148 textarea.style.display = 'none'; |
171 divPreview.style.display = 'block'; | 149 divPreview.style.display = 'block'; |
150 topButtons.style.display = 'none'; | |
172 let postData = 'text=' + encodeURIComponent(textarea.value) + '&convert_urls=' + convertUrls; | 151 let postData = 'text=' + encodeURIComponent(textarea.value) + '&convert_urls=' + convertUrls; |
173 ajax( '/bbcode/preview.js', postData, {preview: contextPreview} ); | 152 ajax( '/bbcode/preview.js', postData, {preview: contextPreview} ); |
174 } else { | 153 } else { |
175 for( let b of buttons ) { | 154 for( let b of buttons ) { |
176 b.disabled = false; | 155 b.disabled = false; |
177 } | 156 } |
178 textarea.style.display = 'initial'; | 157 textarea.style.display = 'initial'; |
179 divPreview.style.display = 'none'; | 158 divPreview.style.display = 'none'; |
159 if( moreCheckbox.checked ) | |
160 topButtons.style.display = 'flex'; | |
180 textarea.focus(); | 161 textarea.focus(); |
181 } | 162 } |
182 } | 163 event.stopPropagation(); |
183 previewButton.onclick = preview; | 164 } |
184 enabledInPreview.push(previewButton); | 165 enabledInPreview.push(previewButton); |
185 | 166 |
186 let convertUrlsButton = div.querySelector('button[convert_urls]'); | 167 let convertUrlsButton = div.querySelector('button[convert_urls]'); |
187 let convertUrlsInput = div.querySelector('input[name="convert_urls"]'); | 168 convertUrlsButton.onclick = checkboxButtonClick; |
188 function toggleConvertUrls() { | 169 let convertUrlsCheckbox = convertUrlsButton.querySelector('input'); |
189 convertUrls = toggle(convertUrlsButton); | 170 convertUrlsCheckbox.onclick = function(event) { |
190 convertUrlsInput.value = convertUrls; | 171 convertUrls = convertUrlsCheckbox.checked; |
191 } | 172 event.stopPropagation(); |
192 convertUrlsButton.onclick = toggleConvertUrls; | 173 }; |
193 | 174 |
194 function add(tag,openTag,closeTag) { | 175 function add(tag,openTag,closeTag) { |
195 let button = div.querySelector('button['+tag+']'); | 176 let button = div.querySelector('button['+tag+']'); |
196 button.onclick = function() { | 177 button.onclick = function() { |
197 let start = textarea.selectionStart; | 178 let start = textarea.selectionStart; |