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 }