793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
|
}else{
e = this.getMessageElemById(id);
}
if(!e || !id) return false;
else if(e.$isToggling) return;
e.$isToggling = true;
const content = e.querySelector('.content-target');
if(!content.$elems){
content.$elems = [
content.firstElementChild, // parsed elem
undefined // plaintext elem
];
}else if(content.$elems[1]){
// We have both content types. Simply toggle them.
const child = (
content.firstElementChild===content.$elems[0]
? content.$elems[1]
: content.$elems[0]
);
delete e.$isToggling;
D.append(D.clearElement(content), child);
return;
}
// We need to fetch the plain-text version...
const self = this;
F.fetch('chat-fetch-one',{
urlParams:{ name: id, raw: true},
responseType: 'json',
onload: function(msg){
content.$elems[1] = D.append(D.pre(),msg.xmsg);
self.toggleTextMode(e);
},
aftersend:function(){
delete e.$isToggling;
Chat.ajaxEnd();
}
});
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
|
}else{
e = this.getMessageElemById(id);
}
if(!e || !id) return false;
else if(e.$isToggling) return;
e.$isToggling = true;
const content = e.querySelector('.content-target');
if(!content){
console.warn("Should not be possible: trying to toggle text",
"mode of a message with no .content-target.", e);
return;
}
if(!content.$elems){
content.$elems = [
content.firstElementChild, // parsed elem
undefined // plaintext elem
];
}else if(content.$elems[1]){
// We have both content types. Simply toggle them.
const child = (
content.firstElementChild===content.$elems[0]
? content.$elems[1]
: content.$elems[0]
);
D.clearElement(content);
if(child===content.$elems[1]){
/* When showing the unformatted version, inject a
copy-to-clipboard button. This is a workaround for
mouse-copying from that field collecting twice as many
newlines as it should (for unknown reasons). */
const cpId = 'copy-to-clipboard-'+id;
/* ^^^ copy button element ID, needed for LABEL element
pairing. Recall that we destroy all child elements of
`content` each time we hit this block, so we can reuse
that element ID on subsequent toggles. */
const btnCp = D.attr(D.addClass(D.span(),'copy-button'), 'id', cpId);
F.copyButton(btnCp, {extractText: ()=>child._xmsgRaw});
const lblCp = D.label(cpId, "Copy unformatted text");
lblCp.addEventListener('click',()=>btnCp.click(), false);
D.append(content, D.append(D.addClass(D.span(), 'nobr'), btnCp, lblCp));
}
delete e.$isToggling;
D.append(content, child);
return;
}
// We need to fetch the plain-text version...
const self = this;
F.fetch('chat-fetch-one',{
urlParams:{ name: id, raw: true},
responseType: 'json',
onload: function(msg){
content.$elems[1] = D.append(D.pre(),msg.xmsg);
content.$elems[1]._xmsgRaw = msg.xmsg/*used for copy-to-clipboard feature*/;
self.toggleTextMode(e);
},
aftersend:function(){
delete e.$isToggling;
Chat.ajaxEnd();
}
});
|
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
|
e = n;
}
eMsg.scrollIntoView();
}
));
const toolbar2 = D.addClass(D.div(), 'toolbar');
D.append(this.e, toolbar2);
D.append(toolbar2, D.button(
"Toggle text mode", function(){
self.hide();
Chat.toggleTextMode(eMsg);
}));
if(eMsg.dataset.xfrom){
/* Add a link to the /timeline filtered on this user. */
const timelineLink = D.attr(
D.a(F.repoUrl('timeline',{
u: eMsg.dataset.xfrom,
y: 'a'
}), "User's Timeline"),
|
>
>
>
|
|
|
|
|
>
|
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
|
e = n;
}
eMsg.scrollIntoView();
}
));
const toolbar2 = D.addClass(D.div(), 'toolbar');
D.append(this.e, toolbar2);
if(eMsg.querySelector('.content-target')){
/* ^^^ messages with only an embedded image have no
.content-target area. */
D.append(toolbar2, D.button(
"Toggle text mode", function(){
self.hide();
Chat.toggleTextMode(eMsg);
}));
}
if(eMsg.dataset.xfrom){
/* Add a link to the /timeline filtered on this user. */
const timelineLink = D.attr(
D.a(F.repoUrl('timeline',{
u: eMsg.dataset.xfrom,
y: 'a'
}), "User's Timeline"),
|
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
|
and/or the file attachment field to the server. If both are
empty, this is a no-op.
*/
Chat.submitMessage = function f(){
if(!f.spaces){
f.spaces = /\s+$/;
f.markdownContinuation = /\\\s+$/;
}
this.setCurrentView(this.e.viewMessages);
const fd = new FormData();
const fallback = {msg: this.inputValue()};
var msg = fallback.msg.trim();
if(msg && (msg.indexOf('\n')>0 || f.spaces.test(msg))){
/* Cosmetic: trim whitespace from the ends of lines to try to
keep copy/paste from terminals, especially wide ones, from
forcing a horizontal scrollbar on all clients. This breaks
markdown's use of blackslash-space-space for paragraph
continuation, but *not* doing this affects all clients every
time someone pastes in console copy/paste from an affected
platform. We seem to have narrowed to the console pasting
problem to users of tmux. Most consoles don't behave
that way. */
const xmsg = msg.split('\n');
xmsg.forEach(function(line,ndx){
if(!f.markdownContinuation.test(line)){
xmsg[ndx] = line.trimRight();
}
});
msg = xmsg.join('\n');
}
if(msg) fd.set('msg',msg);
const file = BlobXferState.blob || this.e.inputFile.files[0];
if(file) fd.set("file", file);
|
>
|
|
>
|
|
>
>
>
>
|
|
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
|
and/or the file attachment field to the server. If both are
empty, this is a no-op.
*/
Chat.submitMessage = function f(){
if(!f.spaces){
f.spaces = /\s+$/;
f.markdownContinuation = /\\\s+$/;
f.spaces2 = /\s{3,}$/;
}
this.setCurrentView(this.e.viewMessages);
const fd = new FormData();
const fallback = {msg: this.inputValue()};
var msg = fallback.msg;
if(msg && (msg.indexOf('\n')>0 || f.spaces.test(msg))){
/* Cosmetic: trim most whitespace from the ends of lines to try to
keep copy/paste from terminals, especially wide ones, from
forcing a horizontal scrollbar on all clients. This breaks
markdown's use of blackslash-space-space for paragraph
continuation, but *not* doing this affects all clients every
time someone pastes in console copy/paste from an affected
platform. We seem to have narrowed to the console pasting
problem to users of tmux together with certain apps (vim, at
a minimum). Most consoles don't behave that way.
We retain two trailing spaces so that markdown conventions
which use end-of-line spacing aren't broken by this
stripping.
*/
const xmsg = msg.split('\n');
xmsg.forEach(function(line,ndx){
if(!f.markdownContinuation.test(line)){
xmsg[ndx] = line.replace(f.spaces2, ' ');
}
});
msg = xmsg.join('\n');
}
if(msg) fd.set('msg',msg);
const file = BlobXferState.blob || this.e.inputFile.files[0];
if(file) fd.set("file", file);
|