/* * 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; var browser = new Browser(); 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 (window.event && window.event.srcElement) { var el = window.event.srcElement } else if (e && e.currentTarget) { var el = e.currentTarget } // 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 (window.event && window.event.srcElement) { var lnk = window.event.srcElement } else if (e && e.currentTarget) { var lnk = e.currentTarget } 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"); if (browser.isIE) { /* * IE likes to display the element as soon as it is created. * So let's hide it now and show it after it's been appended to the body */ 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); if (browser.isIE) { 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()) // Gecko bug, supposed to be uppercase return el; else return getParent(el.parentNode, pTagName); } function getMousePosition(event) { if (browser.isIE) { var x = window.event.clientX + document.documentElement.scrollLeft;// + document.body.scrollLeft; var y = window.event.clientY + document.documentElement.scrollTop;// + document.body.scrollTop; } if (browser.isNS) { var x = event.clientX + window.scrollX;// window.pageXOffset; var y = event.clientY + window.scrollY;// window.pageYOffset; } return [x,y]; } function getScrollPosition() { if (browser.isIE) { var x = document.documentElement.scrollLeft;// + document.body.scrollLeft; var y = document.documentElement.scrollTop;// + document.body.scrollTop; } if (browser.isNS) { var x = window.scrollX;// window.pageXOffset; var y = window.scrollY;// window.pageYOffset; } return [x,y]; } function getWindowSize() { if (browser.isIE) { var x = document.documentElement.clientWidth; var y = document.documentElement.clientHeight; } if (browser.isNS) { var x = window.innerWidth; var y = window.innerHeight; } return [x,y]; } // Determine browser and version. function Browser() { // blah, browser detect, but mouse-position stuff doesn't work any other way var ua, s, i; this.isIE = false; this.isNS = false; this.version = null; ua = navigator.userAgent; s = "MSIE"; if ((i = ua.indexOf(s)) >= 0) { this.isIE = true; this.version = parseFloat(ua.substr(i + s.length)); return; } s = "Netscape6/"; if ((i = ua.indexOf(s)) >= 0) { this.isNS = true; this.version = parseFloat(ua.substr(i + s.length)); return; } // Treat any other "Gecko" browser as NS 6.1. s = "Gecko"; if ((i = ua.indexOf(s)) >= 0) { this.isNS = true; this.version = 6.1; return; } } // 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); } }; }