I wrote a UserScript that auto-sorts contacts by offline time using the MutationObserver API. I tried to make it as DRY as I could think, and I also tried to make my code as straight-forward as possible, commenting thoroughly. Please let me know any improvements I can make.// ==UserScript==// @name         Facebook Messenger Chat Sorter// @namespace    http://tampermonkey.net/// @version      0.1// @description  Auto-sort contacts by offline time// @author       Patrick Roberts// @match        https://www.facebook.com/*// @grant        none// ==/UserScript==(function() {  'use strict';  // mutation observer to locate chat sidebar  var exists = new MutationObserver(function(mutations) {    // if chat sidebar found in any mutations    if (mutations.some(function(mutation) {      // check if element with class is added      if (mutation.type === 'childList') {        // return if any added element is the chat sidebar        return Array.from(mutation.addedNodes).some(initFbChatSidebar);      // check if class is changed in existing element      } else {        // return if changed element is the chat sidebar        return initFbChatSidebar(mutation.target);      }    })) {      // then de-initialize this observer      exists.disconnect();      exists.takeRecords();    }  });  // start locating sidebar  exists.observe(document.body, { attributes: true, childList: true, subtree: true, attributeFilter: ['class'] });  // returns if any element is the chat sidebar, and inits it  function initFbChatSidebar(el) {    if (el instanceof HTMLElement && el.classList.contains('fbChatSidebar')) {      initChatSort(el.querySelector('ul'));      return true;    }    return false;  }  // initializes auto-sorting  function initChatSort(ul) {    var li = ul.children;    // observer to sort contacts    var observer = new MutationObserver(sort);    // start sorting whenever list is mutated    observer.observe(ul, { childList: true, characterData: true, subtree: true });    // also sort on initialization since list is already there    sort();    function sort() {      // invoke native sorting algorithm      Array.from(li).sort(function(la, lb) {        // get offline times        var a = getOfflineTime(la);        var b = getOfflineTime(lb);        // compare offline times        return a - b;      }).forEach(function(li) {        // add list items to list in sorted order        ul.appendChild(li);      });      // remove mutations from queue caused by sorting      observer.takeRecords();    }  }  // parse offline time from contact list item  function getOfflineTime(li) {    var str = li.querySelector('[class$=on] [class$=-]').textContent;    var num, unit;    num = +str.slice(0, -1);    unit = str.slice(-1);    // multiply time by 60 if hour    if (unit === 'h') {      num *= 60;    // multiply time by 60 * 24 if day    } else if (unit === 'd') {      num *= 60 * 24;    }    return num;  }})();
Sort Facebook Messenger contacts by idle time
javascript;sorting;dom;userscript;facebook