/* * Based on NiceTitle, by Stuart Langridge * http://www.kryogenix.org/code/browser/nicetitle/ */ // Start configuration var SHOW_LINKS = false; // Set to false to disable showing link URLs var FOLLOW_MOUSE = true; // Set to false to disable title follows mouse var MIN_WIDTH = 100; // Min/Max width/height of title var MAX_WIDTH = 600; var MIN_HEIGHT = 25; var SNAP_LENGTH = 25; // Define the length from the edge of the window to snap to var MOUSE_OFFSET = 15; // Define the distance to place the title from the mouse // End configuration // Let the magic begin... addEvent(window, "load", makeNiceTitles); // Get script self directory var src = document.getElementById("nicetitle").src.split("/"); src.pop(); src = src.join("/"); // Pre-load background PNG (new Image()).src = src + "/ntbg.png"; var XHTMLNS = "http://www.w3.org/1999/xhtml"; var CURRENT_NICE_TITLE; function makeNiceTitles() { if (!document.createElement || !document.getElementsByTagName) return; // add namespace methods to HTML DOM; this makes the script work in both // HTML and XML contexts. if (!document.createElementNS) { document.createElementNS = function(ns,elt) { return document.createElement(elt); } } if (!document.links) { document.links = document.getElementsByTagName("a"); } for (var ti = 0; ti < document.links.length; ti++) { var lnk = document.links[ti]; if (lnk.title) { lnk.setAttribute("nicetitle", lnk.title); lnk.removeAttribute("title"); addEvent(lnk, "mouseover", showNiceTitle); addEvent(lnk, "mouseover", moveNiceTitle); addEvent(lnk, "mouseout", hideNiceTitle); addEvent(lnk, "mousemove", moveNiceTitle); addEvent(lnk, "mousedown", hideNiceTitle); /* * Focus and blur events are not quite right. In Mozilla, titles do not show on keyboard focus. * This may present an accessibility issue, but it doesn't currently play nice * with FOLLOW_MOUSE=true, or mousedown events. */ // addEvent(lnk, "focus", showNiceTitle); // addEvent(lnk, "blur", hideNiceTitle); } } var instags = document.getElementsByTagName("ins"); if (instags) { for (var ti = 0; ti < instags.length; ti++) { var instag = instags[ti]; if (instag.dateTime) { var strDate = instag.dateTime; var dtIns = new Date( strDate.substring(0, 4), parseInt(strDate.substring(4, 6) - 1), strDate.substring(6, 8), strDate.substring(9, 11), strDate.substring(11, 13), strDate.substring(13, 15) ); instag.setAttribute("nicetitle", "Added on " + dtIns.toString()); addEvent(instag, "mouseover", showNiceTitle); addEvent(instag, "mouseover", moveNiceTitle); addEvent(instag, "mouseout", hideNiceTitle); addEvent(instag, "mousemove", moveNiceTitle); addEvent(instag, "mousedown", hideNiceTitle); // addEvent(instag, "focus", showNiceTitle); // addEvent(instag, "blur", hideNiceTitle); } } } } function findPosition(oLink) { if (oLink.offsetParent) { for (var posX = 0, posY = 0; oLink.offsetParent; oLink = oLink.offsetParent) { posX += oLink.offsetLeft; posY += oLink.offsetTop; } return [posX, posY]; } else { return [oLink.x, oLink.y]; } } function get_longest(ary) { var l = 0; ary.forEach(function(el) { if (el.length > l) l = el.length; }); return l; } function moveNiceTitle(e) { if (!CURRENT_NICE_TITLE) return; var d = CURRENT_NICE_TITLE; if (e && e.currentTarget && (typeof(e.currentTarget) != "undefined")) { var el = e.currentTarget } else if (window.event && window.event.srcElement) { var el = window.event.srcElement } // Browser size var xy = getWindowSize(); var ww = xy[0]; var wh = xy[1]; // Title width and height var w = (d.offsetWidth || MIN_WIDTH); var h = (d.offsetHeight || MIN_HEIGHT); if (FOLLOW_MOUSE) { // Mouse position within document (not window) var xy = getMousePosition(e); var mx = xy[0]; var my = xy[1]; // Document scroll position within window var xy = getScrollPosition(); var sx = xy[0]; var sy = xy[1]; // Title element position within document var x = mx + MOUSE_OFFSET; var y = my + MOUSE_OFFSET; } else { // Document scroll position within window // Unused var sx = 0; var sy = 0; // Title element position within document var elPos = findPosition(el); var x = elPos[0]; var y = elPos[1] + el.offsetHeight + MOUSE_OFFSET; } // Find out if we've already snapped var SNAP_RIGHT = false; var SNAP_BOTTOM = false; // Snap title to the right side of the window if ((x + w + SNAP_LENGTH) >= (ww + sx)) { x = ((ww + sx) - w - SNAP_LENGTH); SNAP_RIGHT = true; } // Snap title to the bottom of the window if ((y + h + SNAP_LENGTH) >= (wh + sy)) { y = ((wh + sy) - h - SNAP_LENGTH); SNAP_BOTTOM = true; } // Ensure mouse can never enter the title in the lower right corner of the window if (FOLLOW_MOUSE && SNAP_RIGHT && SNAP_BOTTOM) { y = (my - MOUSE_OFFSET - h); } else if (!FOLLOW_MOUSE && SNAP_BOTTOM) { y = elPos[1] - h - MOUSE_OFFSET; } d.style.left = x + "px"; d.style.top = y + "px"; } function showNiceTitle(e) { if (CURRENT_NICE_TITLE) hideNiceTitle(CURRENT_NICE_TITLE); if (!document.getElementsByTagName) return; if (e && e.currentTarget && (typeof(e.currentTarget) != "undefined")) { var lnk = e.currentTarget } else if (window.event && window.event.srcElement) { var lnk = window.event.srcElement } if (!lnk) return; if (lnk.nodeName.toUpperCase() != "A") { // lnk is not actually the link -- ascend parents until we hit a link lnk = getParent(lnk, "A"); } if (!lnk) return; var nicetitle = lnk.getAttribute("nicetitle"); var d = document.createElementNS(XHTMLNS, "div"); d.style.display = "none"; d.className = "nicetitle"; var nicetitle_parts = nicetitle.split("\n"); nicetitle_parts.forEach(function(textpart) { var pat = document.createElementNS(XHTMLNS, "p"); pat.className = "titletext"; var tnt = document.createTextNode(textpart); pat.appendChild(tnt); var brk = document.createElementNS(XHTMLNS, "br"); pat.appendChild(brk); d.appendChild(pat); }); if (lnk.href && SHOW_LINKS) { var tnd = document.createTextNode(lnk.href); pad = document.createElementNS(XHTMLNS, "p"); pad.className = "destination"; pad.appendChild(tnd); d.appendChild(pad); } var l = get_longest(nicetitle_parts); // Approximate pixel width of longest line in the title var w = ((lnk.href && SHOW_LINKS) ? lnk.href.length : 0) * 6; var t = (l ? l : 0) * 8; // Use the greatest width: title text, link URL, or MIN_WIDTH. Limited to MAX_WIDTH w = ((w > MIN_WIDTH) ? w : MIN_WIDTH); w = ((w > t) ? w : t); w = ((w > MAX_WIDTH) ? MAX_WIDTH : w); d.style.width = w + "px"; document.getElementsByTagName("body")[0].appendChild(d); d.style.display = "block"; CURRENT_NICE_TITLE = d; moveNiceTitle(e); } function hideNiceTitle(e) { if (!document.getElementsByTagName) return; if (CURRENT_NICE_TITLE) { document.getElementsByTagName("body")[0].removeChild(CURRENT_NICE_TITLE); CURRENT_NICE_TITLE = null; } } // Add an eventListener to browsers that can do it somehow. // Originally by the amazing Scott Andrew. function addEvent(obj, evType, fn) { if (obj.addEventListener) { obj.addEventListener(evType, fn, false); return true; } else if (obj.attachEvent) { return obj.attachEvent("on" + evType, fn); } else { return false; } } function getParent(el, pTagName) { if (el == null) return null; else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) return el; else return getParent(el.parentNode, pTagName); } function getMousePosition(e) { var x = 0; var y = 0; if (e && (typeof(window.scrollX) != "undefined")) { x = e.clientX + window.scrollX; y = e.clientY + window.scrollY; } else if (window.event) { x = window.event.clientX + document.documentElement.scrollLeft; y = window.event.clientY + document.documentElement.scrollTop; } return [x, y]; } function getScrollPosition() { var x = 0; var y = 0; if ((typeof(window.scrollX) != "undefined") && (typeof(window.scrollY) != "undefined")) { x = window.scrollX; y = window.scrollY; } else if ((typeof(document.documentElement.scrollLeft) != "undefined") && (typeof(document.documentElement.scrollTop) != "undefined")) { x = document.documentElement.scrollLeft; y = document.documentElement.scrollTop; } return [x, y]; } function getWindowSize() { var x = 0; var y = 0; if ((typeof(window.innerWidth) != "undefined") && (typeof(window.innerHeight) != "undefined")) { x = window.innerWidth; y = window.innerHeight; } else if ((typeof(document.documentElement.clientWidth) != "undefined") && (typeof(document.documentElement.clientHeight) != "undefined")) { x = document.documentElement.clientWidth; y = document.documentElement.clientHeight; } return [x, y]; } // IE does not support the Array.forEach() method... Try to approximate it if (!Array.prototype.forEach) { Array.prototype.forEach = function(action, context) { var len = this.length; for (var i = 0; i < len; i++) { if (this[i] != undefined) action(this[i], context); } }; }