Fossil SCM

chat.js restructuring/cleanup - no functional changes.

stephan 2020-12-25 09:39 trunk
Commit 12682568f0c60b58ac36a9af395bd015b0fdfd08db749bdd1c05a0f962b6ac51
1 file changed +93 -88
+93 -88
--- src/chat.js
+++ src/chat.js
@@ -155,43 +155,102 @@
155155
cs.e.pageTitle.innerText = cs.pageTitleOrig;
156156
}
157157
}, true);
158158
return cs;
159159
})()/*Chat initialization*/;
160
- /* State for paste and drag/drop */
161
- const BlobXferState = {
162
- dropDetails: document.querySelector('#chat-drop-details'),
163
- blob: undefined
164
- };
165
- /** Updates the paste/drop zone with details of the pasted/dropped
166
- data. The argument must be a Blob or Blob-like object (File) or
167
- it can be falsy to reset/clear that state.*/
168
- const updateDropZoneContent = function(blob){
169
- const bx = BlobXferState, dd = bx.dropDetails;
170
- bx.blob = blob;
171
- D.clearElement(dd);
172
- if(!blob){
173
- form.file.value = '';
174
- return;
175
- }
176
- D.append(dd, "Name: ", blob.name,
177
- D.br(), "Size: ",blob.size);
178
- if(blob.type && blob.type.startsWith("image/")){
179
- const img = D.img();
180
- D.append(dd, D.br(), img);
181
- const reader = new FileReader();
182
- reader.onload = (e)=>img.setAttribute('src', e.target.result);
183
- reader.readAsDataURL(blob);
184
- }
185
- const btn = D.button("Cancel");
186
- D.append(dd, D.br(), btn);
187
- btn.addEventListener('click', ()=>updateDropZoneContent(), false);
188
- };
189
- form.file.addEventListener('change', function(ev){
190
- //console.debug("this =",this);
191
- updateDropZoneContent(this.files && this.files[0] ? this.files[0] : undefined)
192
- });
160
+
161
+ const BlobXferState = (function(){/*drag/drop bits...*/
162
+ /* State for paste and drag/drop */
163
+ const bxs = {
164
+ dropDetails: document.querySelector('#chat-drop-details'),
165
+ blob: undefined,
166
+ clear: function(){
167
+ this.blob = undefined;
168
+ D.clearElement(this.dropDetails);
169
+ form.file.value = "";
170
+ }
171
+ };
172
+ /** Updates the paste/drop zone with details of the pasted/dropped
173
+ data. The argument must be a Blob or Blob-like object (File) or
174
+ it can be falsy to reset/clear that state.*/
175
+ const updateDropZoneContent = function(blob){
176
+ const dd = bxs.dropDetails;
177
+ bxs.blob = blob;
178
+ D.clearElement(dd);
179
+ if(!blob){
180
+ form.file.value = '';
181
+ return;
182
+ }
183
+ D.append(dd, "Name: ", blob.name,
184
+ D.br(), "Size: ",blob.size);
185
+ if(blob.type && blob.type.startsWith("image/")){
186
+ const img = D.img();
187
+ D.append(dd, D.br(), img);
188
+ const reader = new FileReader();
189
+ reader.onload = (e)=>img.setAttribute('src', e.target.result);
190
+ reader.readAsDataURL(blob);
191
+ }
192
+ const btn = D.button("Cancel");
193
+ D.append(dd, D.br(), btn);
194
+ btn.addEventListener('click', ()=>updateDropZoneContent(), false);
195
+ };
196
+ form.file.addEventListener('change', function(ev){
197
+ updateDropZoneContent(this.files && this.files[0] ? this.files[0] : undefined)
198
+ });
199
+ /* Handle image paste from clipboard. TODO: figure out how we can
200
+ paste non-image binary data as if it had been selected via the
201
+ file selection element. */
202
+ document.addEventListener('paste', function(event){
203
+ const items = event.clipboardData.items,
204
+ item = items[0];
205
+ if(!item || !item.type) return;
206
+ else if('file'===item.kind){
207
+ updateDropZoneContent(false/*clear prev state*/);
208
+ updateDropZoneContent(items[0].getAsFile());
209
+ }else if(false && 'string'===item.kind){
210
+ /* ----^^^^^ disabled for now: the intent here is that if
211
+ form.msg is not active, populate it with this text, but
212
+ whether populating it from ctrl-v when it does not have focus
213
+ is a feature or a bug is debatable. It seems useful but may
214
+ violate the Principle of Least Surprise. */
215
+ if(document.activeElement !== form.msg){
216
+ /* Overwrite input field if it DOES NOT have focus,
217
+ otherwise let it do its own paste handling. */
218
+ item.getAsString((v)=>form.msg.value = v);
219
+ }
220
+ }
221
+ }, false);
222
+ /* Add help button for drag/drop/paste zone */
223
+ form.file.parentNode.insertBefore(
224
+ F.helpButtonlets.create(
225
+ document.querySelector('#chat-input-file-area .help-buttonlet')
226
+ ), form.file
227
+ );
228
+ ////////////////////////////////////////////////////////////
229
+ // File drag/drop visual notification.
230
+ const dropHighlight = form.file /* target zone */;
231
+ const dropEvents = {
232
+ drop: function(ev){
233
+ D.removeClass(dropHighlight, 'dragover');
234
+ },
235
+ dragenter: function(ev){
236
+ ev.preventDefault();
237
+ ev.dataTransfer.dropEffect = "copy";
238
+ D.addClass(dropHighlight, 'dragover');
239
+ },
240
+ dragleave: function(ev){
241
+ D.removeClass(dropHighlight, 'dragover');
242
+ },
243
+ dragend: function(ev){
244
+ D.removeClass(dropHighlight, 'dragover');
245
+ }
246
+ };
247
+ Object.keys(dropEvents).forEach(
248
+ (k)=>form.file.addEventListener(k, dropEvents[k], true)
249
+ );
250
+ return bxs;
251
+ })()/*drag/drop*/;
193252
194253
form.addEventListener('submit',(e)=>{
195254
e.preventDefault();
196255
const fd = new FormData(form);
197256
if(BlobXferState.blob/*replace file content with this*/){
@@ -201,68 +260,14 @@
201260
fetch("chat-send",{
202261
method: 'POST',
203262
body: fd
204263
});
205264
}
206
- BlobXferState.blob = undefined;
207
- D.clearElement(BlobXferState.dropDetails);
265
+ BlobXferState.clear();
208266
form.msg.value = "";
209
- form.file.value = "";
210267
form.msg.focus();
211268
});
212
- /* Handle image paste from clipboard. TODO: figure out how we can
213
- paste non-image binary data as if it had been selected via the
214
- file selection element. */
215
- document.onpaste = function(event){
216
- const items = event.clipboardData.items,
217
- item = items[0];
218
- if(!item || !item.type) return;
219
- else if('file'===item.kind){
220
- updateDropZoneContent(false/*clear prev state*/);
221
- updateDropZoneContent(items[0].getAsFile());
222
- }else if(false && 'string'===item.kind){
223
- /* ----^^^^^ disabled for now: the intent here is that if
224
- form.msg is not active, populate it with this text, but
225
- whether populating it from ctrl-v when it does not have focus
226
- is a feature or a bug is debatable. It seems useful but may
227
- violate the Principle of Least Surprise. */
228
- if(document.activeElement !== form.msg){
229
- /* Overwrite input field if it DOES NOT have focus,
230
- otherwise let it do its own paste handling. */
231
- item.getAsString((v)=>form.msg.value = v);
232
- }
233
- }
234
- };
235
- if(true){/* Add help button for drag/drop/paste zone */
236
- form.file.parentNode.insertBefore(
237
- F.helpButtonlets.create(
238
- document.querySelector('#chat-input-file-area .help-buttonlet')
239
- ), form.file
240
- );
241
- }
242
- ////////////////////////////////////////////////////////////
243
- // File drag/drop visual notification.
244
- const dropHighlight = form.file /* target zone */;
245
- const dropEvents = {
246
- drop: function(ev){
247
- D.removeClass(dropHighlight, 'dragover');
248
- },
249
- dragenter: function(ev){
250
- ev.preventDefault();
251
- ev.dataTransfer.dropEffect = "copy";
252
- D.addClass(dropHighlight, 'dragover');
253
- },
254
- dragleave: function(ev){
255
- D.removeClass(dropHighlight, 'dragover');
256
- },
257
- dragend: function(ev){
258
- D.removeClass(dropHighlight, 'dragover');
259
- }
260
- };
261
- Object.keys(dropEvents).forEach(
262
- (k)=>form.file.addEventListener(k, dropEvents[k], true)
263
- );
264269
265270
/* Returns a new TEXT node with the given text content. */
266271
/** Returns the local time string of Date object d, defaulting
267272
to the current time. */
268273
const localTimeString = function ff(d){
269274
--- src/chat.js
+++ src/chat.js
@@ -155,43 +155,102 @@
155 cs.e.pageTitle.innerText = cs.pageTitleOrig;
156 }
157 }, true);
158 return cs;
159 })()/*Chat initialization*/;
160 /* State for paste and drag/drop */
161 const BlobXferState = {
162 dropDetails: document.querySelector('#chat-drop-details'),
163 blob: undefined
164 };
165 /** Updates the paste/drop zone with details of the pasted/dropped
166 data. The argument must be a Blob or Blob-like object (File) or
167 it can be falsy to reset/clear that state.*/
168 const updateDropZoneContent = function(blob){
169 const bx = BlobXferState, dd = bx.dropDetails;
170 bx.blob = blob;
171 D.clearElement(dd);
172 if(!blob){
173 form.file.value = '';
174 return;
175 }
176 D.append(dd, "Name: ", blob.name,
177 D.br(), "Size: ",blob.size);
178 if(blob.type && blob.type.startsWith("image/")){
179 const img = D.img();
180 D.append(dd, D.br(), img);
181 const reader = new FileReader();
182 reader.onload = (e)=>img.setAttribute('src', e.target.result);
183 reader.readAsDataURL(blob);
184 }
185 const btn = D.button("Cancel");
186 D.append(dd, D.br(), btn);
187 btn.addEventListener('click', ()=>updateDropZoneContent(), false);
188 };
189 form.file.addEventListener('change', function(ev){
190 //console.debug("this =",this);
191 updateDropZoneContent(this.files && this.files[0] ? this.files[0] : undefined)
192 });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
194 form.addEventListener('submit',(e)=>{
195 e.preventDefault();
196 const fd = new FormData(form);
197 if(BlobXferState.blob/*replace file content with this*/){
@@ -201,68 +260,14 @@
201 fetch("chat-send",{
202 method: 'POST',
203 body: fd
204 });
205 }
206 BlobXferState.blob = undefined;
207 D.clearElement(BlobXferState.dropDetails);
208 form.msg.value = "";
209 form.file.value = "";
210 form.msg.focus();
211 });
212 /* Handle image paste from clipboard. TODO: figure out how we can
213 paste non-image binary data as if it had been selected via the
214 file selection element. */
215 document.onpaste = function(event){
216 const items = event.clipboardData.items,
217 item = items[0];
218 if(!item || !item.type) return;
219 else if('file'===item.kind){
220 updateDropZoneContent(false/*clear prev state*/);
221 updateDropZoneContent(items[0].getAsFile());
222 }else if(false && 'string'===item.kind){
223 /* ----^^^^^ disabled for now: the intent here is that if
224 form.msg is not active, populate it with this text, but
225 whether populating it from ctrl-v when it does not have focus
226 is a feature or a bug is debatable. It seems useful but may
227 violate the Principle of Least Surprise. */
228 if(document.activeElement !== form.msg){
229 /* Overwrite input field if it DOES NOT have focus,
230 otherwise let it do its own paste handling. */
231 item.getAsString((v)=>form.msg.value = v);
232 }
233 }
234 };
235 if(true){/* Add help button for drag/drop/paste zone */
236 form.file.parentNode.insertBefore(
237 F.helpButtonlets.create(
238 document.querySelector('#chat-input-file-area .help-buttonlet')
239 ), form.file
240 );
241 }
242 ////////////////////////////////////////////////////////////
243 // File drag/drop visual notification.
244 const dropHighlight = form.file /* target zone */;
245 const dropEvents = {
246 drop: function(ev){
247 D.removeClass(dropHighlight, 'dragover');
248 },
249 dragenter: function(ev){
250 ev.preventDefault();
251 ev.dataTransfer.dropEffect = "copy";
252 D.addClass(dropHighlight, 'dragover');
253 },
254 dragleave: function(ev){
255 D.removeClass(dropHighlight, 'dragover');
256 },
257 dragend: function(ev){
258 D.removeClass(dropHighlight, 'dragover');
259 }
260 };
261 Object.keys(dropEvents).forEach(
262 (k)=>form.file.addEventListener(k, dropEvents[k], true)
263 );
264
265 /* Returns a new TEXT node with the given text content. */
266 /** Returns the local time string of Date object d, defaulting
267 to the current time. */
268 const localTimeString = function ff(d){
269
--- src/chat.js
+++ src/chat.js
@@ -155,43 +155,102 @@
155 cs.e.pageTitle.innerText = cs.pageTitleOrig;
156 }
157 }, true);
158 return cs;
159 })()/*Chat initialization*/;
160
161 const BlobXferState = (function(){/*drag/drop bits...*/
162 /* State for paste and drag/drop */
163 const bxs = {
164 dropDetails: document.querySelector('#chat-drop-details'),
165 blob: undefined,
166 clear: function(){
167 this.blob = undefined;
168 D.clearElement(this.dropDetails);
169 form.file.value = "";
170 }
171 };
172 /** Updates the paste/drop zone with details of the pasted/dropped
173 data. The argument must be a Blob or Blob-like object (File) or
174 it can be falsy to reset/clear that state.*/
175 const updateDropZoneContent = function(blob){
176 const dd = bxs.dropDetails;
177 bxs.blob = blob;
178 D.clearElement(dd);
179 if(!blob){
180 form.file.value = '';
181 return;
182 }
183 D.append(dd, "Name: ", blob.name,
184 D.br(), "Size: ",blob.size);
185 if(blob.type && blob.type.startsWith("image/")){
186 const img = D.img();
187 D.append(dd, D.br(), img);
188 const reader = new FileReader();
189 reader.onload = (e)=>img.setAttribute('src', e.target.result);
190 reader.readAsDataURL(blob);
191 }
192 const btn = D.button("Cancel");
193 D.append(dd, D.br(), btn);
194 btn.addEventListener('click', ()=>updateDropZoneContent(), false);
195 };
196 form.file.addEventListener('change', function(ev){
197 updateDropZoneContent(this.files && this.files[0] ? this.files[0] : undefined)
198 });
199 /* Handle image paste from clipboard. TODO: figure out how we can
200 paste non-image binary data as if it had been selected via the
201 file selection element. */
202 document.addEventListener('paste', function(event){
203 const items = event.clipboardData.items,
204 item = items[0];
205 if(!item || !item.type) return;
206 else if('file'===item.kind){
207 updateDropZoneContent(false/*clear prev state*/);
208 updateDropZoneContent(items[0].getAsFile());
209 }else if(false && 'string'===item.kind){
210 /* ----^^^^^ disabled for now: the intent here is that if
211 form.msg is not active, populate it with this text, but
212 whether populating it from ctrl-v when it does not have focus
213 is a feature or a bug is debatable. It seems useful but may
214 violate the Principle of Least Surprise. */
215 if(document.activeElement !== form.msg){
216 /* Overwrite input field if it DOES NOT have focus,
217 otherwise let it do its own paste handling. */
218 item.getAsString((v)=>form.msg.value = v);
219 }
220 }
221 }, false);
222 /* Add help button for drag/drop/paste zone */
223 form.file.parentNode.insertBefore(
224 F.helpButtonlets.create(
225 document.querySelector('#chat-input-file-area .help-buttonlet')
226 ), form.file
227 );
228 ////////////////////////////////////////////////////////////
229 // File drag/drop visual notification.
230 const dropHighlight = form.file /* target zone */;
231 const dropEvents = {
232 drop: function(ev){
233 D.removeClass(dropHighlight, 'dragover');
234 },
235 dragenter: function(ev){
236 ev.preventDefault();
237 ev.dataTransfer.dropEffect = "copy";
238 D.addClass(dropHighlight, 'dragover');
239 },
240 dragleave: function(ev){
241 D.removeClass(dropHighlight, 'dragover');
242 },
243 dragend: function(ev){
244 D.removeClass(dropHighlight, 'dragover');
245 }
246 };
247 Object.keys(dropEvents).forEach(
248 (k)=>form.file.addEventListener(k, dropEvents[k], true)
249 );
250 return bxs;
251 })()/*drag/drop*/;
252
253 form.addEventListener('submit',(e)=>{
254 e.preventDefault();
255 const fd = new FormData(form);
256 if(BlobXferState.blob/*replace file content with this*/){
@@ -201,68 +260,14 @@
260 fetch("chat-send",{
261 method: 'POST',
262 body: fd
263 });
264 }
265 BlobXferState.clear();
 
266 form.msg.value = "";
 
267 form.msg.focus();
268 });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
270 /* Returns a new TEXT node with the given text content. */
271 /** Returns the local time string of Date object d, defaulting
272 to the current time. */
273 const localTimeString = function ff(d){
274

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button