Fossil SCM
When chat is in chat-only mode, the input area is now sticky at the top of the window. This required a bit of hackery involving its background color to keep it from being transparent (which causes the chat messages to be visible through it).
Commit
429e5a9bdece22026c007b61a552c5d63b4ad234675fb7cde549e5756be10591
Parent
08533f90953886e…
2 files changed
+23
-7
+13
-3
+23
-7
| --- src/chat.js | ||
| +++ src/chat.js | ||
| @@ -14,10 +14,11 @@ | ||
| 14 | 14 | const cs = { |
| 15 | 15 | e:{/*map of certain DOM elements.*/ |
| 16 | 16 | messageInjectPoint: E1('#message-inject-point'), |
| 17 | 17 | pageTitle: E1('head title'), |
| 18 | 18 | loadToolbar: undefined /* the load-posts toolbar (dynamically created) */, |
| 19 | + inputWrapper: E1("#chat-input-area"), | |
| 19 | 20 | messagesWrapper: E1('#chat-messages-wrapper') |
| 20 | 21 | }, |
| 21 | 22 | me: F.user.name, |
| 22 | 23 | mxMsg: F.config.chatInitSize ? -F.config.chatInitSize : -50, |
| 23 | 24 | mnMsg: undefined/*lowest message ID we've seen so far (for history loading)*/, |
| @@ -323,19 +324,17 @@ | ||
| 323 | 324 | D.append(this.e, toolbar); |
| 324 | 325 | const btnDeleteLocal = D.button("Delete locally"); |
| 325 | 326 | D.append(toolbar, btnDeleteLocal); |
| 326 | 327 | const self = this; |
| 327 | 328 | btnDeleteLocal.addEventListener('click', function(){ |
| 328 | - console.debug("local-only delete"); | |
| 329 | 329 | self.hide(); |
| 330 | 330 | Chat.deleteMessageElem(eMsg); |
| 331 | 331 | }); |
| 332 | 332 | if(Chat.userMayDelete(eMsg)){ |
| 333 | 333 | const btnDeleteGlobal = D.button("Delete globally"); |
| 334 | 334 | D.append(toolbar, btnDeleteGlobal); |
| 335 | 335 | btnDeleteGlobal.addEventListener('click', function(){ |
| 336 | - console.debug("global delete"); | |
| 337 | 336 | self.hide(); |
| 338 | 337 | Chat.deleteMessage(eMsg); |
| 339 | 338 | }); |
| 340 | 339 | } |
| 341 | 340 | }/*refresh()*/ |
| @@ -384,19 +383,36 @@ | ||
| 384 | 383 | if(!e.classList) return/*TEXT nodes and such*/; |
| 385 | 384 | else if(!e.classList.contains('content')){ |
| 386 | 385 | f.elemsToToggle.push(e); |
| 387 | 386 | } |
| 388 | 387 | }); |
| 388 | + /* In order to make the input area opaque, such that the | |
| 389 | + message list scrolls under it without being visible, we | |
| 390 | + have to ensure that the input area has a non-inherited | |
| 391 | + background color. Ideally we'd select the color of | |
| 392 | + div.content, but that is not necessarily set, so we fall | |
| 393 | + back to using the body's background color. If we rely on | |
| 394 | + the input area having its own color specified in CSS then | |
| 395 | + all skins would have to define an appropriate color. | |
| 396 | + Thus our selection of the body color, while slightly unfortunate, | |
| 397 | + is in the interest of keeping skins from being forced to | |
| 398 | + define an opaque bg color. | |
| 399 | + */ | |
| 400 | + f.initialBg = Chat.e.messagesWrapper.style.backgroundColor; | |
| 401 | + const cs = window.getComputedStyle(document.body); | |
| 402 | + f.inheritedBg = cs.backgroundColor; | |
| 389 | 403 | } |
| 390 | - if(f.isHidden){ | |
| 391 | - D.removeClass(f.elemsToToggle, 'hidden'); | |
| 392 | - D.removeClass(document.body, 'chat-only-mode'); | |
| 393 | - }else{ | |
| 404 | + const cs = Chat.e.inputWrapper.style; | |
| 405 | + if((f.isHidden = !f.isHidden)){ | |
| 394 | 406 | D.addClass(f.elemsToToggle, 'hidden'); |
| 395 | 407 | D.addClass(document.body, 'chat-only-mode'); |
| 408 | + cs.backgroundColor = f.inheritedBg; | |
| 409 | + }else{ | |
| 410 | + D.removeClass(f.elemsToToggle, 'hidden'); | |
| 411 | + D.removeClass(document.body, 'chat-only-mode'); | |
| 412 | + cs.backgroundColor = f.initialBg; | |
| 396 | 413 | } |
| 397 | - f.isHidden = !f.isHidden; | |
| 398 | 414 | } |
| 399 | 415 | },{ |
| 400 | 416 | label: "Toggle left/right layout", |
| 401 | 417 | callback: function f(){ |
| 402 | 418 | if('right'===Chat.msgMyAlign) Chat.msgMyAlign = 'left'; |
| 403 | 419 |
| --- src/chat.js | |
| +++ src/chat.js | |
| @@ -14,10 +14,11 @@ | |
| 14 | const cs = { |
| 15 | e:{/*map of certain DOM elements.*/ |
| 16 | messageInjectPoint: E1('#message-inject-point'), |
| 17 | pageTitle: E1('head title'), |
| 18 | loadToolbar: undefined /* the load-posts toolbar (dynamically created) */, |
| 19 | messagesWrapper: E1('#chat-messages-wrapper') |
| 20 | }, |
| 21 | me: F.user.name, |
| 22 | mxMsg: F.config.chatInitSize ? -F.config.chatInitSize : -50, |
| 23 | mnMsg: undefined/*lowest message ID we've seen so far (for history loading)*/, |
| @@ -323,19 +324,17 @@ | |
| 323 | D.append(this.e, toolbar); |
| 324 | const btnDeleteLocal = D.button("Delete locally"); |
| 325 | D.append(toolbar, btnDeleteLocal); |
| 326 | const self = this; |
| 327 | btnDeleteLocal.addEventListener('click', function(){ |
| 328 | console.debug("local-only delete"); |
| 329 | self.hide(); |
| 330 | Chat.deleteMessageElem(eMsg); |
| 331 | }); |
| 332 | if(Chat.userMayDelete(eMsg)){ |
| 333 | const btnDeleteGlobal = D.button("Delete globally"); |
| 334 | D.append(toolbar, btnDeleteGlobal); |
| 335 | btnDeleteGlobal.addEventListener('click', function(){ |
| 336 | console.debug("global delete"); |
| 337 | self.hide(); |
| 338 | Chat.deleteMessage(eMsg); |
| 339 | }); |
| 340 | } |
| 341 | }/*refresh()*/ |
| @@ -384,19 +383,36 @@ | |
| 384 | if(!e.classList) return/*TEXT nodes and such*/; |
| 385 | else if(!e.classList.contains('content')){ |
| 386 | f.elemsToToggle.push(e); |
| 387 | } |
| 388 | }); |
| 389 | } |
| 390 | if(f.isHidden){ |
| 391 | D.removeClass(f.elemsToToggle, 'hidden'); |
| 392 | D.removeClass(document.body, 'chat-only-mode'); |
| 393 | }else{ |
| 394 | D.addClass(f.elemsToToggle, 'hidden'); |
| 395 | D.addClass(document.body, 'chat-only-mode'); |
| 396 | } |
| 397 | f.isHidden = !f.isHidden; |
| 398 | } |
| 399 | },{ |
| 400 | label: "Toggle left/right layout", |
| 401 | callback: function f(){ |
| 402 | if('right'===Chat.msgMyAlign) Chat.msgMyAlign = 'left'; |
| 403 |
| --- src/chat.js | |
| +++ src/chat.js | |
| @@ -14,10 +14,11 @@ | |
| 14 | const cs = { |
| 15 | e:{/*map of certain DOM elements.*/ |
| 16 | messageInjectPoint: E1('#message-inject-point'), |
| 17 | pageTitle: E1('head title'), |
| 18 | loadToolbar: undefined /* the load-posts toolbar (dynamically created) */, |
| 19 | inputWrapper: E1("#chat-input-area"), |
| 20 | messagesWrapper: E1('#chat-messages-wrapper') |
| 21 | }, |
| 22 | me: F.user.name, |
| 23 | mxMsg: F.config.chatInitSize ? -F.config.chatInitSize : -50, |
| 24 | mnMsg: undefined/*lowest message ID we've seen so far (for history loading)*/, |
| @@ -323,19 +324,17 @@ | |
| 324 | D.append(this.e, toolbar); |
| 325 | const btnDeleteLocal = D.button("Delete locally"); |
| 326 | D.append(toolbar, btnDeleteLocal); |
| 327 | const self = this; |
| 328 | btnDeleteLocal.addEventListener('click', function(){ |
| 329 | self.hide(); |
| 330 | Chat.deleteMessageElem(eMsg); |
| 331 | }); |
| 332 | if(Chat.userMayDelete(eMsg)){ |
| 333 | const btnDeleteGlobal = D.button("Delete globally"); |
| 334 | D.append(toolbar, btnDeleteGlobal); |
| 335 | btnDeleteGlobal.addEventListener('click', function(){ |
| 336 | self.hide(); |
| 337 | Chat.deleteMessage(eMsg); |
| 338 | }); |
| 339 | } |
| 340 | }/*refresh()*/ |
| @@ -384,19 +383,36 @@ | |
| 383 | if(!e.classList) return/*TEXT nodes and such*/; |
| 384 | else if(!e.classList.contains('content')){ |
| 385 | f.elemsToToggle.push(e); |
| 386 | } |
| 387 | }); |
| 388 | /* In order to make the input area opaque, such that the |
| 389 | message list scrolls under it without being visible, we |
| 390 | have to ensure that the input area has a non-inherited |
| 391 | background color. Ideally we'd select the color of |
| 392 | div.content, but that is not necessarily set, so we fall |
| 393 | back to using the body's background color. If we rely on |
| 394 | the input area having its own color specified in CSS then |
| 395 | all skins would have to define an appropriate color. |
| 396 | Thus our selection of the body color, while slightly unfortunate, |
| 397 | is in the interest of keeping skins from being forced to |
| 398 | define an opaque bg color. |
| 399 | */ |
| 400 | f.initialBg = Chat.e.messagesWrapper.style.backgroundColor; |
| 401 | const cs = window.getComputedStyle(document.body); |
| 402 | f.inheritedBg = cs.backgroundColor; |
| 403 | } |
| 404 | const cs = Chat.e.inputWrapper.style; |
| 405 | if((f.isHidden = !f.isHidden)){ |
| 406 | D.addClass(f.elemsToToggle, 'hidden'); |
| 407 | D.addClass(document.body, 'chat-only-mode'); |
| 408 | cs.backgroundColor = f.inheritedBg; |
| 409 | }else{ |
| 410 | D.removeClass(f.elemsToToggle, 'hidden'); |
| 411 | D.removeClass(document.body, 'chat-only-mode'); |
| 412 | cs.backgroundColor = f.initialBg; |
| 413 | } |
| 414 | } |
| 415 | },{ |
| 416 | label: "Toggle left/right layout", |
| 417 | callback: function f(){ |
| 418 | if('right'===Chat.msgMyAlign) Chat.msgMyAlign = 'left'; |
| 419 |
+13
-3
| --- src/default.css | ||
| +++ src/default.css | ||
| @@ -1267,11 +1267,11 @@ | ||
| 1267 | 1267 | .fossil-toast-message { |
| 1268 | 1268 | /* "toast"-style popup message. |
| 1269 | 1269 | See fossil.popupwidget:toast() */ |
| 1270 | 1270 | position: absolute; |
| 1271 | 1271 | display: block; |
| 1272 | - z-index: 101; | |
| 1272 | + z-index: 1001; | |
| 1273 | 1273 | text-align: left; |
| 1274 | 1274 | padding: 0.15em 0.5em; |
| 1275 | 1275 | margin: 0; |
| 1276 | 1276 | font-size: 1em; |
| 1277 | 1277 | border-width: 1px; |
| @@ -1513,10 +1513,11 @@ | ||
| 1513 | 1513 | opacity: 0.8; |
| 1514 | 1514 | display: flex; |
| 1515 | 1515 | flex-direction: column; |
| 1516 | 1516 | align-items: stretch; |
| 1517 | 1517 | padding: 0.25em; |
| 1518 | + z-index: 200; | |
| 1518 | 1519 | } |
| 1519 | 1520 | body.chat .chat-message-popup > span { white-space: nowrap; } |
| 1520 | 1521 | body.chat .chat-message-popup > .toolbar { |
| 1521 | 1522 | padding: 0.2em; |
| 1522 | 1523 | margin: 0; |
| @@ -1573,10 +1574,11 @@ | ||
| 1573 | 1574 | text-align: left; |
| 1574 | 1575 | display: flex; |
| 1575 | 1576 | flex-direction: column; |
| 1576 | 1577 | align-items: stretch; |
| 1577 | 1578 | padding: 0.25em; |
| 1579 | + z-index: 200; | |
| 1578 | 1580 | } |
| 1579 | 1581 | body.chat .chat-settings-popup > span { |
| 1580 | 1582 | margin: 0.25em 0.2em; |
| 1581 | 1583 | padding: 0.5em; |
| 1582 | 1584 | white-space: nowrap; |
| @@ -1601,16 +1603,24 @@ | ||
| 1601 | 1603 | /* would like to pin this to the top so that it stays in place when |
| 1602 | 1604 | scrolling, but doing so causes #chat-messages-wrapper to scroll |
| 1603 | 1605 | behind it visibly, which is really ugly. Only current workaround is |
| 1604 | 1606 | to force an opaque background color on this element, but that's not |
| 1605 | 1607 | skin-friendly. */ |
| 1606 | - /*position: fixed; | |
| 1608 | + position: sticky; | |
| 1607 | 1609 | top: 0; |
| 1608 | - left: 0;*/ | |
| 1610 | + left: 0; | |
| 1609 | 1611 | padding: 0.5em 1em; |
| 1612 | + z-index: 100 | |
| 1613 | + /* see notes in #chat-messages-wrapper. The various popups require a | |
| 1614 | + z-index higher than this one. */ | |
| 1610 | 1615 | } |
| 1611 | 1616 | body.chat.chat-only-mode #chat-messages-wrapper { |
| 1617 | + position: relative; | |
| 1618 | + top: 0; | |
| 1619 | + z-index: 99 /* so that it scrolls under input area. If it's | |
| 1620 | + lower than div.content then mouse events to it | |
| 1621 | + are blocked!*/; | |
| 1612 | 1622 | } |
| 1613 | 1623 | |
| 1614 | 1624 | body.chat #chat-input-area { |
| 1615 | 1625 | display: flex; |
| 1616 | 1626 | flex-direction: column; |
| 1617 | 1627 |
| --- src/default.css | |
| +++ src/default.css | |
| @@ -1267,11 +1267,11 @@ | |
| 1267 | .fossil-toast-message { |
| 1268 | /* "toast"-style popup message. |
| 1269 | See fossil.popupwidget:toast() */ |
| 1270 | position: absolute; |
| 1271 | display: block; |
| 1272 | z-index: 101; |
| 1273 | text-align: left; |
| 1274 | padding: 0.15em 0.5em; |
| 1275 | margin: 0; |
| 1276 | font-size: 1em; |
| 1277 | border-width: 1px; |
| @@ -1513,10 +1513,11 @@ | |
| 1513 | opacity: 0.8; |
| 1514 | display: flex; |
| 1515 | flex-direction: column; |
| 1516 | align-items: stretch; |
| 1517 | padding: 0.25em; |
| 1518 | } |
| 1519 | body.chat .chat-message-popup > span { white-space: nowrap; } |
| 1520 | body.chat .chat-message-popup > .toolbar { |
| 1521 | padding: 0.2em; |
| 1522 | margin: 0; |
| @@ -1573,10 +1574,11 @@ | |
| 1573 | text-align: left; |
| 1574 | display: flex; |
| 1575 | flex-direction: column; |
| 1576 | align-items: stretch; |
| 1577 | padding: 0.25em; |
| 1578 | } |
| 1579 | body.chat .chat-settings-popup > span { |
| 1580 | margin: 0.25em 0.2em; |
| 1581 | padding: 0.5em; |
| 1582 | white-space: nowrap; |
| @@ -1601,16 +1603,24 @@ | |
| 1601 | /* would like to pin this to the top so that it stays in place when |
| 1602 | scrolling, but doing so causes #chat-messages-wrapper to scroll |
| 1603 | behind it visibly, which is really ugly. Only current workaround is |
| 1604 | to force an opaque background color on this element, but that's not |
| 1605 | skin-friendly. */ |
| 1606 | /*position: fixed; |
| 1607 | top: 0; |
| 1608 | left: 0;*/ |
| 1609 | padding: 0.5em 1em; |
| 1610 | } |
| 1611 | body.chat.chat-only-mode #chat-messages-wrapper { |
| 1612 | } |
| 1613 | |
| 1614 | body.chat #chat-input-area { |
| 1615 | display: flex; |
| 1616 | flex-direction: column; |
| 1617 |
| --- src/default.css | |
| +++ src/default.css | |
| @@ -1267,11 +1267,11 @@ | |
| 1267 | .fossil-toast-message { |
| 1268 | /* "toast"-style popup message. |
| 1269 | See fossil.popupwidget:toast() */ |
| 1270 | position: absolute; |
| 1271 | display: block; |
| 1272 | z-index: 1001; |
| 1273 | text-align: left; |
| 1274 | padding: 0.15em 0.5em; |
| 1275 | margin: 0; |
| 1276 | font-size: 1em; |
| 1277 | border-width: 1px; |
| @@ -1513,10 +1513,11 @@ | |
| 1513 | opacity: 0.8; |
| 1514 | display: flex; |
| 1515 | flex-direction: column; |
| 1516 | align-items: stretch; |
| 1517 | padding: 0.25em; |
| 1518 | z-index: 200; |
| 1519 | } |
| 1520 | body.chat .chat-message-popup > span { white-space: nowrap; } |
| 1521 | body.chat .chat-message-popup > .toolbar { |
| 1522 | padding: 0.2em; |
| 1523 | margin: 0; |
| @@ -1573,10 +1574,11 @@ | |
| 1574 | text-align: left; |
| 1575 | display: flex; |
| 1576 | flex-direction: column; |
| 1577 | align-items: stretch; |
| 1578 | padding: 0.25em; |
| 1579 | z-index: 200; |
| 1580 | } |
| 1581 | body.chat .chat-settings-popup > span { |
| 1582 | margin: 0.25em 0.2em; |
| 1583 | padding: 0.5em; |
| 1584 | white-space: nowrap; |
| @@ -1601,16 +1603,24 @@ | |
| 1603 | /* would like to pin this to the top so that it stays in place when |
| 1604 | scrolling, but doing so causes #chat-messages-wrapper to scroll |
| 1605 | behind it visibly, which is really ugly. Only current workaround is |
| 1606 | to force an opaque background color on this element, but that's not |
| 1607 | skin-friendly. */ |
| 1608 | position: sticky; |
| 1609 | top: 0; |
| 1610 | left: 0; |
| 1611 | padding: 0.5em 1em; |
| 1612 | z-index: 100 |
| 1613 | /* see notes in #chat-messages-wrapper. The various popups require a |
| 1614 | z-index higher than this one. */ |
| 1615 | } |
| 1616 | body.chat.chat-only-mode #chat-messages-wrapper { |
| 1617 | position: relative; |
| 1618 | top: 0; |
| 1619 | z-index: 99 /* so that it scrolls under input area. If it's |
| 1620 | lower than div.content then mouse events to it |
| 1621 | are blocked!*/; |
| 1622 | } |
| 1623 | |
| 1624 | body.chat #chat-input-area { |
| 1625 | display: flex; |
| 1626 | flex-direction: column; |
| 1627 |