User:Tiny plastic Grey Knight/scripts/suldropdown.js

Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/*
 * Example of your monobook.js with this script imported, with a customised menu:
 *
 *
 *
 * importScript("User:tiny_plastic_Grey_Knight/scripts/suldropdown.js");
 *
 *  function setupSULDropDownMenu() {
 *    addSULDropDownOption("wikiversity", "en");
 *    addSULDropDownOption("wikibooks",   "en");
 *    addSULDropDownOption("wikipedia",   "en");
 *    addSULDropDownOption("wikipedia",   "la");
 *    addSULDropDownOption("meta");
 *  }
 *
 *
 */




/**
 * Write a function setupSULDropDownMenu() after importing this script, defining the
 * projects you want in order.  By default the below will be used.
 */
function defaultSULDropDownMenu() {
  addSULDropDownOption("wikipedia",   "en");
  addSULDropDownOption("wikibooks",   "en");
  addSULDropDownOption("wiktionary",  "en");
  addSULDropDownOption("wikinews",    "en");
  addSULDropDownOption("wikisource",  "en");
  addSULDropDownOption("wikiquote",   "en");
  addSULDropDownOption("wikiversity", "en");
  addSULDropDownOption("meta");
  addSULDropDownOption("species");
  addSULDropDownOption("commons");
}

var SULDropDownItems = [];
var SULDropDownSubmenuNodes = {};

/**
 * Sets up the base of the menu
 */
function addSULDropDown() {
  var upnode_id   = "p-personal";
  var nextnode_id = "pt-mytalk";
  var node_id = "pt-suldropdown";
  
  mw.util.addPortletLink(upnode_id, "#", "<SUL>", node_id, "SUL account drop-down menu", "", document.getElementById(nextnode_id));
  var node = document.getElementById(node_id);
  if(!node) return false;
  node.firstChild.innerHTML = "";
  var downIcon = document.createElement("img");
  downIcon.src = "http://upload.wikimedia.org/wikipedia/commons/thumb/3/30/Gtk-go-down.svg/16px-Gtk-go-down.svg.png";
  downIcon.width  = 16;
  downIcon.height = 16;
  downIcon.alt = "(v)";
  
  node.firstChild.appendChild(downIcon);
  node.firstChild.appendChild(document.createTextNode("SUL"));
  node.firstChild.style.textTransform = "none";
  
  var menunode = document.createElement("div");
  var menulist = document.createElement("ul");
  var menuhead = document.createElement("li");
  menunode.style.textAlign = "left";
  menuhead.style.textAlign = "left";
  menulist.style.textAlign = "left";
  menunode.style.display = "none";
  menunode.style.position = "absolute";
  menunode.style.left= "0px";
  menunode.style.top = "0px";
  menunode.style.border="1px solid #000000";
  menunode.style.background="#ffffff";
  menuhead.style.display = "block";
  menuhead.style.background = "#ddddff";
  menuhead.style.text       = "#000000";
  menuhead.style.textTransform = "none";
  menunode.style.zIndex = 3;
  menulist.style.zIndex = 3;
  menuhead.style.zIndex = 3;
  menulist.style.paddingLeft  = "0px";
  menulist.style.marginLeft   = "0px";
  menulist.style.paddingRight = "0px";
  menulist.style.marginRight  = "0px";
  menulist.style.listStyleType = "none";
  menunode.style.textTransform = "none";
  
  /* ??? Why won't the menunode stack properly in Firefox without this...  It should normally be 2, which should work. */
  document.getElementById("content").style.zIndex = 0;
  
  menunode.id = "pt-suldropdown-menu";
  menulist.id = "pt-suldropdown-menulist";
  
  var exitIcon = document.createElement("img");
  exitIcon.src = "http://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Gtk-stop.svg/16px-Gtk-stop.svg.png";
  exitIcon.width  = 16;
  exitIcon.height = 16;
  var headText = document.createElement("span");
  headText.appendChild(document.createTextNode("SUL"));
  var headwrap = document.createElement("div");
  headwrap.style.width = "10em";
  headwrap.style.clear = "both";
  exitIcon.style.cssFloat = "right";
  headText.style.cssFloat = "left";
  headText.style.paddingLeft = "1em";
  var CLEAR = document.createElement("div");
  CLEAR.style.clear = "both";
  CLEAR.appendChild(document.createTextNode(""));
  headwrap.appendChild(headText);
  headwrap.appendChild(exitIcon);
  headwrap.appendChild(CLEAR);
  menuhead.appendChild(headwrap);
  menulist.appendChild(menuhead);
  menunode.appendChild(menulist);
  
  menuhead.onclick = hideSULDropDown;
  
  var nextnode = document.getElementById(nextnode_id);
  var upnode = node.parentNode;
  upnode.insertBefore(menunode, nextnode);

  if((typeof setupSULDropDownMenu) == "function") {
    setupSULDropDownMenu();
  } else {
    defaultSULDropDownMenu();
  }
  updateSULDropDown();
  
  node.onclick = showSULDropDown;
}

var tprojects = [];

/**
 * Update the HTML of the menu to match what is in SULDropDownItems[].
 */
function updateSULDropDown() {
  var menulist = document.getElementById("pt-suldropdown-menulist");
  var submenu_icon_src = "http://upload.wikimedia.org/wikipedia/commons/thumb/b/b9/Gtk-go-forward-ltr.svg/16px-Gtk-go-forward-ltr.svg.png";
  var max_icon_width  = 20;
  var max_icon_height = 26;
  var submenu_icon_w = 16;
  var submenu_icon_h = 16;
  var submenu_icon_alt = ">>";
  var cells = [];
  var item;
  var project_data;
  var img, link, imgwrap, submenu, subIcon, sublist, subcell, sublink;
  var i, deltaX, deltaY;
  var addlinkonclick = function(link, project, cell) {
    link.onclick = function(e) { return clickSULDropDownSubmenu(e, project, cell); }
  }
  for(i in allowedSULDropDownProjects) {
    allowedSULDropDownProjects[i].inuse = false;
  }
  for(i in SULDropDownItems) {
    item = SULDropDownItems[i];
    project_data = item.data;
    if(!project_data.inuse) {
      if(project_data.unlanguaged) {
        cell = document.createElement("li");
        img  = document.createElement("img");
        link = document.createElement("a");
        link.href = project_data.userpage;
        img.src   = project_data.icon;
        img.width  = project_data.icon_w;
        img.height = project_data.icon_h;
        deltaY = (max_icon_height - img.height);
        deltaX = (max_icon_width  - img.width);
        link.appendChild(document.createTextNode(project_data.name));
        link.style.textTransform = "none";
        imgwrap = document.createElement("span");
        imgwrap.style.paddingBottom = Math.ceil(deltaY/2)  + "px";
        imgwrap.style.paddingTop    = Math.floor(deltaY/2) + "px";
        imgwrap.style.paddingRight  = deltaX + "px";
        imgwrap.appendChild(img);
        cell.appendChild(imgwrap);
        cell.appendChild(link);
      } else {
        cell = document.createElement("li");
        img  = document.createElement("img");
        link = document.createElement("a");
        submenu = document.createElement("ul");
        link.href = "#";
        img.src   = project_data.icon;
        img.width  = project_data.icon_w;
        img.height = project_data.icon_h;
        deltaY = (max_icon_height - img.height);
        deltaX = (max_icon_width  - img.width);
        link.appendChild(document.createTextNode(project_data.name));
        link.style.textTransform = "none";
        subIcon = document.createElement("img");
        subIcon.src = submenu_icon_src;
        subIcon.width  = submenu_icon_w;
        subIcon.height = submenu_icon_h;
        subIcon.alt = submenu_icon_alt;
        subIcon.style.marginLeft = "1em";
        link.appendChild(subIcon);
        submenu.id = "pt-suldropdown-menulist-" + project_data.domain;
        submenu.style.display = "none";
        submenu.style.border="0px solid #000000";
        submenu.style.background="#ffffff";
        submenu.style.marginLeft = "4em";
        submenu.style.padding = "1px";
        submenu.style.listStyleType = "none";
        imgwrap = document.createElement("span");
        imgwrap.style.paddingBottom = Math.ceil(deltaY/2)  + "px";
        imgwrap.style.paddingTop    = Math.floor(deltaY/2) + "px";
        imgwrap.style.paddingRight  = deltaX + "px";
        imgwrap.appendChild(img);
        addlinkonclick(link, item.project, cell);
        cell.appendChild(imgwrap);
        cell.appendChild(link);
        cell.appendChild(submenu);
        SULDropDownSubmenuNodes[project_data.domain] = submenu;
      }
      cell.style.display = "block";
      cell.style.padding = "1px";
      cell.style.zIndex = 4;
      cells.push(cell);
      project_data.inuse = true;
    }
    if(!project_data.unlanguaged) {
      /* add subelement for language */
      sublist = SULDropDownSubmenuNodes[project_data.domain];
      subcell = document.createElement("li");
      sublink = document.createElement("a");
      sublink.href = project_data.userpage;
      subcell.style.display = "block";
      subcell.style.textAlign = "left";
      sublink.appendChild(document.createTextNode(item.lang));
      subcell.appendChild(sublink);
      if(sublist) {
        sublist.appendChild(subcell);
      } else {
        alert("No submenu for '" +project_data.domain+ "'!");
      }
    }
  }
  while(menulist.childNodes.length > 1) menulist.removeChild(menulist.lastChild);
  for(i in cells) {
    menulist.appendChild(cells[i]);
  }
}

/**
 * Hide the menu.
 */
function hideSULDropDown(e) {
  var node = document.getElementById("pt-suldropdown");
  var menunode = document.getElementById("pt-suldropdown-menu");
  menunode.style.display = 'none';
  node.onclick = showSULDropDown;
}

/**
 * Show the menu based on a given click.
 */
function showSULDropDown(e) {
  var event = e ? e : window.event;
  var x = 0;
  var y = 0;
  var menunode = document.getElementById("pt-suldropdown-menu");
  if(!menunode) return false;
  
  if(isNaN(window.scrollX)) {
    x = event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
    y = event.clientY + document.documentElement.scrollTop  + document.body.scrollTop;
  } else {
    x = event.clientX + window.scrollX;
    y = event.clientY + window.scrollY;
  }
  x -= 5;
  y -= 5;
  menunode.style.left = x + 'px';
  menunode.style.top  = y + 'px';
  menunode.style.display = 'block';
  var node = document.getElementById("pt-suldropdown");
  node.onclick = hideSULDropDown;
  //menunode.onmouseout = hideSULDropDown;
  //menunode.ondragout  = hideSULDropDown;
}


/**
 * Properties list for the various Wikimedia projects
 */
allowedSULDropDownProjects = [
  {domain:"wikipedia",   unlanguaged:false, inuse:false, name:"Wikipedia",   icon_h:16, icon_w:16, icon:"http://upload.wikimedia.org/wikipedia/commons/thumb/6/63/Wikipedia-logo.png/16px-Wikipedia-logo.png"},
  {domain:"wiktionary",  unlanguaged:false, inuse:false, name:"Wiktionary",  icon_h:11, icon_w:16, icon:"http://upload.wikimedia.org/wikipedia/en/thumb/b/bd/Wiktionary-logo-51px.gif/16px-Wiktionary-logo-51px.gif"},
  {domain:"wikibooks",   unlanguaged:false, inuse:false, name:"Wikibooks",   icon_h:16, icon_w:16, icon:"http://upload.wikimedia.org/wikipedia/en/thumb/7/7f/Wikibooks-logo-35px.png/16px-Wikibooks-logo-35px.png"},
  {domain:"wikinews",    unlanguaged:false, inuse:false, name:"Wikinews",    icon_h: 9, icon_w:16, icon:"http://upload.wikimedia.org/wikipedia/en/thumb/6/60/Wikinews-logo-51px.png/16px-Wikinews-logo-51px.png"},
  {domain:"wikisource",  unlanguaged:false, inuse:false, name:"Wikisource",  icon_h:17, icon_w:16, icon:"http://upload.wikimedia.org/wikipedia/en/thumb/b/b6/Wikisource-logo-35px.png/16px-Wikisource-logo-35px.png"},
  {domain:"wikiquote",   unlanguaged:false, inuse:false, name:"Wikiquote",   icon_h:13, icon_w:16, icon:"http://upload.wikimedia.org/wikipedia/en/thumb/4/46/Wikiquote-logo-51px.png/16px-Wikiquote-logo-51px.png"},
  {domain:"wikiversity", unlanguaged:false, inuse:false, name:"Wikiversity", icon_h:12, icon_w:16, icon:"http://upload.wikimedia.org/wikipedia/en/thumb/e/e3/Wikiversity-logo-41px.png/16px-Wikiversity-logo-41px.png"},
  {domain:"commons",     unlanguaged:true,  inuse:false, name:"Commons",     icon_h:21, icon_w:16, icon:"http://upload.wikimedia.org/wikipedia/en/thumb/9/9d/Commons-logo-31px.png/16px-Commons-logo-31px.png"},
  {domain:"meta",        unlanguaged:true,  inuse:false, name:"Meta-Wiki",   icon_h:16, icon_w:16, icon:"http://upload.wikimedia.org/wikipedia/en/thumb/d/d3/Wikimedia-logo-35px.png/16px-Wikimedia-logo-35px.png"},
  {domain:"species",     unlanguaged:true,  inuse:false, name:"Wikispecies", icon_h:19, icon_w:16, icon:"http://upload.wikimedia.org/wikipedia/en/thumb/b/bf/Wikispecies-logo-35px.png/16px-Wikispecies-logo-35px.png"}
];  

/**
 * Adds the specified project (including language) to the menu.
 * @param project Should match the "domain" field of an entry in allowedSULDropDownProjects[].
 * @param lang    If the project has language-specific versions, you should specify the language code you want here.  Otherwise, leave undefined.
 */
function addSULDropDownOption(project, lang) {
  var project = project.toLowerCase();
  var index = -1;
  for(var i in allowedSULDropDownProjects) {
    if(allowedSULDropDownProjects[i].domain==project) {
      index = i;
      break;
    }
  }
  if(index<0) return false;
  var project_data = allowedSULDropDownProjects[index];
  
  var username = document.getElementById('pt-userpage').firstChild.firstChild.data;
  
  var domain = "wikimedia";
  var subdomain = "meta";
  if(project_data.unlanguaged) {
    domain = "wikimedia";
    subdomain = project_data.domain;
  } else {
    domain = project_data.domain;
    subdomain = lang;
  }
  project_data.userpage = "http://" + subdomain + "." + domain + ".org/wiki/User:" + username;
  var item = {};
  item.project = project;
  item.lang = lang;
  item.domain = domain;
  item.subdomain = subdomain;
  item.data = project_data;
  SULDropDownItems.push(item);
}

/**
 * Show/hide submenus by click.
 * @param e           The click event.
 * @param project     The project we are looking at (probably defined from the caller_node).
 * @param caller_node The cell whose click called this function (probably an LI in the main list).
 */
function clickSULDropDownSubmenu(e, project, caller_node) {
  var submenu = document.getElementById("pt-suldropdown-menulist-" + project);
  if(!submenu) {
    alert("SULDropDown panic -- can't find 'pt-suldropdown-menulist-" + project + "'");
    return false;
  }
  var currentlyVisible = (submenu.style.display != "none" ? true : false);
  if(currentlyVisible) {
    submenu.style.display = "none";
  } else {
    submenu.style.display = "block";
  }
}


/* Finally, add the hook to kick everything off. */
$(addSULDropDown);