Bug 954564 - Newly selected contacts don't get scrolled into view. r=aleth
authorNihanth Subramanya <nhnt11@gmail.com>
Sun, 07 Dec 2014 16:31:24 +0530
changeset 21472 da3cf83bf5ddfc1dddd456a9ec95f100a29767c1
parent 21471 7a58936e02a917222d1f62f87178ccb4f73bb9e3
child 21473 ddd5571196485d747d8af8fb2a66b3777af1da44
push id1305
push usermbanner@mozilla.com
push dateMon, 23 Feb 2015 19:48:12 +0000
treeherdercomm-beta@3ae4f13858fd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaleth
bugs954564
Bug 954564 - Newly selected contacts don't get scrolled into view. r=aleth
im/content/blist.js
im/content/blist.xul
--- a/im/content/blist.js
+++ b/im/content/blist.js
@@ -964,12 +964,40 @@ var buddyList = {
   buddylistboxFocus: function() {
     let selectedItem = document.getElementById("buddylistbox").selectedItem;
     if (selectedItem) {
       // Ensure binding changes immediately to avoid the firing of a
       // spurious accessibility focus event referring to the old binding that
       // causes problems for screen readers (BIO bug 1626, BMO bug 786508)
       selectedItem.getBoundingClientRect();
     }
+  },
+
+  // Usually, a scrollable richlistbox will ensure that a newly selected item is
+  // automatically scrolled into view. However, buddylistbox and convlistbox are
+  // both zero-flex children of a flexible notification box, and don't have
+  // scrollboxes themselves - so it's necessary to manually set the scroll of the
+  // notification box when an item is selected to ensure its visibility.
+  listboxSelect: function(event) {
+    if (!event.target.selectedItem)
+      return;
+    let notifbox = document.getElementById('buddyListMsg');
+    let itemBounds = event.target.selectedItem.getBoundingClientRect();
+    let notifboxBounds = notifbox.getBoundingClientRect();
+    // The offset of the top of the notification box from the top of the item.
+    let offsetAboveTop = notifboxBounds.top - itemBounds.top;
+    // The offset of the bottom of the item from the bottom of the notification box.
+    let offsetBelowBottom = itemBounds.top + itemBounds.height -
+                            (notifboxBounds.top + notifboxBounds.height);
+    // If the item is not fully in view, one of the offsets will be positive.
+    if (offsetAboveTop < 0 && offsetBelowBottom < 0)
+      return;
+    if (offsetAboveTop >= 0) {
+      // We need to scroll up to bring the item into view.
+      notifbox.scrollTop -= offsetAboveTop;
+      return;
+    }
+    // We need to scroll down to bring the item into view.
+    notifbox.scrollTop += offsetBelowBottom;
   }
 };
 
 this.addEventListener("load", buddyList.load);
--- a/im/content/blist.xul
+++ b/im/content/blist.xul
@@ -210,20 +210,22 @@
 
   <notificationbox id="buddyListMsg" flex="1" listedConvCount="0"
                    context="buddyListContextMenu">
     <label id="convsHeader" value="&convsHeader.label;"
            control="convlistbox"
            crop="end" class="listboxHeader"/>
     <richlistbox id="convlistbox"
                  onkeypress="buddyList.keyPress(event);"
+                 onselect="buddyList.listboxSelect(event);"
                  tooltip="imTooltip"/>
     <label id="contactsHeader" value="&contactsHeader.label;"
            control="buddylistbox"
            crop="end" class="listboxHeader"/>
     <richlistbox id="buddylistbox"
                  onkeypress="buddyList.keyPress(event);"
                  onfocus="buddyList.buddylistboxFocus();"
+                 onselect="buddyList.listboxSelect(event);"
                  tooltip="imTooltip"/>
     <spacer id="listSpacer" flex="1"
             onclick='document.getElementById("buddylistbox").focus();'/>
   </notificationbox>
 </window>