1/* ================================================================================================= 2* NiceTitles 3* 20th September 2004 4* http://neo.dzygn.com/code/nicetitles 5* 6* NiceTitles turns your boring (X)HTML tags into a dynamic experience 7* Modified by Kevin Hale for unfoldedorigami.com use. Nicetitles now works with images and follows the mouse. 8* 9* Copyright (c) 2003 - 2004 Stuart Langridge, Paul McLanahan, Peter Janes, Brad Choate, Dunstan Orchard, Ethan Marcotte, Mark Wubben, Kevin Hale 10* 11* 12* Licensed under MIT - http://www.opensource.org/licenses/mit-license.php 13==================================================================================================*/ 14 15function NiceTitles(sTemplate, nDelay, nStringMaxLength, nMarginX, nMarginY, sContainerID, sClassName){ 16 var oTimer; 17 var isActive = false; 18 var showingAlready = false; //added var to start cursor tracking only AFTER delay occurs in show(); 19 var sNameSpaceURI = "http://www.w3.org/1999/xhtml"; 20 21 if(!sTemplate){ sTemplate = "attr(nicetitle)";} 22 if(!nDelay || nDelay <= 0){ nDelay = false;} 23 if(!nStringMaxLength){ nStringMaxLength = 255; } 24 if(!nMarginX){ nMarginX = 10; } 25 if(!nMarginY){ nMarginY = 20; } 26 if(!sContainerID){ sContainerID = "nicetitlecontainer";} 27 if(!sClassName){ sClassName = "nicetitle";} 28 29 var oContainer = document.getElementById(sContainerID); 30 if(!oContainer){ 31 oContainer = document.createElementNS ? document.createElementNS(sNameSpaceURI, "div") : document.createElement("div"); 32 oContainer.setAttribute("id", sContainerID); 33 oContainer.className = sClassName; 34 oContainer.style.display = "none"; 35 document.getElementsByTagName("body").item(0).appendChild(oContainer); 36 } 37 38 //===================================================================== 39 // Method addElements (Public) 40 //===================================================================== 41 this.addElements = function addElements(collNodes, sAttribute){ 42 var currentNode, sTitle; 43 44 for(var i = 0; i < collNodes.length; i++){ 45 currentNode = collNodes[i]; 46 47 sTitle = currentNode.getAttribute(sAttribute); 48 if(sTitle){ 49 currentNode.setAttribute("nicetitle", sTitle); 50 currentNode.removeAttribute(sAttribute); 51 addEvent(currentNode, 'mouseover', show); 52 addEvent(currentNode, 'mouseout', hide); 53 addEvent(currentNode, 'mousemove', reposition); //added to allow cursor tracking 54 addEvent(currentNode, 'focus', show); 55 addEvent(currentNode, 'blur', hide); 56 } 57 } 58 59 } 60 61 //===================================================================== 62 // Other Methods (All Private) 63 //===================================================================== 64 function show(e){ 65 if (isActive){ hide(); } 66 67 var oNode = window.event ? window.event.srcElement : e.currentTarget; 68 if(!oNode.getAttribute("nicetitle")){ 69 while(oNode.parentNode){ 70 oNode = oNode.parentNode; // immediately goes to the parent, thus we can only have element nodes 71 if(oNode.getAttribute("nicetitle")){ break; } 72 } 73 } 74 75 var sOutput = parseTemplate(oNode); 76 setContainerContent(sOutput); 77 var oPosition = getPosition(e, oNode); 78 oContainer.style.left = oPosition.x; 79 oContainer.style.top = oPosition.y; 80 81 //added showingAlready. cursor tracks only after delay occurs 82 if(nDelay){ 83 oTimer = setTimeout(function(){oContainer.style.display = "block"; showingAlready = true;}, nDelay); 84 } else { 85 oContainer.style.display = "block"; 86 } 87 88 isActive = true; 89 // Let's put this event to a halt before it starts messing things up 90 window.event ? window.event.cancelBubble = true : e.stopPropagation(); 91 } 92 93 function hide(){ 94 clearTimeout(oTimer); 95 oContainer.style.display = "none"; 96 removeContainerContent(); 97 isActive = false; 98 showingAlready = false; 99 } 100 101 //function added to allow cursor tracking 102 function reposition(e){ 103 var oNode = window.event ? window.event.srcElement : e.currentTarget; 104 105 var oPosition = getPosition(e, oNode); 106 oContainer.style.left = oPosition.x; 107 oContainer.style.top = oPosition.y; 108 109 if(showingAlready){ 110 oContainer.style.display = "block";} 111 else{ 112 oContainer.style.display = "none";} 113 114 isActive = true; 115 // Let's put this event to a halt before it starts messing things up 116 window.event ? window.event.cancelBubble = true : e.stopPropagation(); 117 } 118 119 function setContainerContent(sOutput){
120 sOutput = sOutput.replace(/&/g, "&").replace(/\n/g, "<br/>"); 121 if(document.createElementNS && window.DOMParser){ 122 var oXMLDoc = (new DOMParser()).parseFromString("<root xmlns=\""+sNameSpaceURI+"\">"+sOutput+"</root>", "text/xml"); 123 var oOutputNode = document.importNode(oXMLDoc.documentElement, true); 124 var oChild = oOutputNode.firstChild; 125 var nextChild; 126 while(oChild){ 127 nextChild = oChild.nextSibling; // Once the child is appended, the nextSibling reference is gone 128 oContainer.appendChild(oChild); 129 oChild = nextChild; 130 } 131 } else { 132 oContainer.innerHTML = sOutput; 133 } 134 } 135 136 function removeContainerContent(){ 137 var oChild = oContainer.firstChild; 138 var nextChild; 139 140 if(!oChild){ return; } 141 while(oChild){ 142 nextChild = oChild.nextSibling; 143 oContainer.removeChild(oChild); 144 oChild = nextChild; 145 } 146 } 147 148 function getPosition(e, oNode){ 149 var oViewport = getViewport(); 150 var oCoords; 151 var commonEventInterface = window.event ? window.event : e; 152 153 if(commonEventInterface.type == "focus"){ 154 oCoords = getNodePosition(oNode); 155 oCoords.x += nMarginX; 156 oCoords.y += nMarginY; 157 } else { 158 oCoords = { x : commonEventInterface.clientX + oViewport.x + nMarginX, y : commonEventInterface.clientY + oViewport.y + nMarginY}; 159 } 160 161 // oContainer needs to be displayed before width and height can be retrieved 162 if(showingAlready == false) // if statement prevents flickering in os x firefox when tracking cursor 163 {oContainer.style.visiblity = "hidden"; 164 oContainer.style.display = "block";} 165 var containerWidth = oContainer.offsetWidth; 166 var containerHeight = oContainer.offsetHeight; 167 if(showingAlready == false) 168 {oContainer.style.display = "none"; 169 oContainer.style.visiblity = "visible";} 170 171 if(oCoords.x + containerWidth + 10 >= oViewport.width + oViewport.x){ 172 oCoords.x = oViewport.width + oViewport.x - containerWidth - 10; 173 } 174 if(oCoords.y + containerHeight + 10 >= oViewport.height + oViewport.y){ 175 oCoords.y = oViewport.height + oViewport.y - containerHeight - oNode.offsetHeight - 10; 176 } 177 178 oCoords.x += "px"; 179 oCoords.y += "px"; 180 181 return oCoords; 182 } 183 184 function parseTemplate(oNode){ 185 var sAttribute, collOptionalAttributes; 186 var oFound = {}; 187 var sResult = sTemplate; 188 189 if(sResult.match(/content\(\)/)){ 190 sResult = sResult.replace(/content\(\)/g, getContentOfNode(oNode)); 191 } 192 193 var collSearch = sResult.split(/attr\(/); 194 for(var i = 1; i < collSearch.length; i++){ 195 sAttribute = collSearch[i].split(")")[0]; 196 oFound[sAttribute] = oNode.getAttribute(sAttribute); 197 if(oFound[sAttribute] && oFound[sAttribute].length > nStringMaxLength){ 198 oFound[sAttribute] = oFound[sAttribute].substring(0, nStringMaxLength) + "..."; 199 } 200 } 201 202 var collOptional = sResult.split("?") 203 for(var i = 1; i < collOptional.length; i += 2){ 204 collOptionalAttributes = collOptional[i].split("attr("); 205 for(var j = 1; j < collOptionalAttributes.length; j++){ 206 sAttribute = collOptionalAttributes[j].split(")")[0]; 207 208 if(!oFound[sAttribute]){ sResult = sResult.replace(new RegExp("\\?[^\\?]*attr\\("+sAttribute+"\\)[^\\?]*\\?", "g"), ""); } 209 } 210 } 211 sResult = sResult.replace(/\?/g, ""); 212 213 for(sAttribute in oFound){ 214 sResult = sResult.replace("attr\("+sAttribute+"\)", oFound[sAttribute]); 215 } 216 217 return sResult; 218 } 219 220 function getContentOfNode(oNode){ 221 var sContent = ""; 222 var oSearch = oNode.firstChild; 223 224 while(oSearch){ 225 if(oSearch.nodeType == 3){ 226 sContent += oSearch.nodeValue; 227 } else if(oSearch.nodeType == 1 && oSearch.hasChildNodes){ 228 sContent += getContentOfNode(oSearch); 229 } 230 oSearch = oSearch.nextSibling 231 } 232 233 return sContent; 234 } 235 236 function getNodePosition(oNode){ 237 var x = 0; 238 var y = 0; 239 240 do { 241 if(oNode.offsetLeft){ x += oNode.offsetLeft } 242 if(oNode.offsetTop){ y += oNode.offsetTop } 243 } while((oNode = oNode.offsetParent) && !document.all) // IE gets the offset 'right' from the start 244 245 return {x : x, y : y} 246 } 247 248 // Idea from 13thParallel: http://13thparallel.net/?issue=2002.06&title=viewport 249 function getViewport(){ 250 var width = 0; 251 var height = 0; 252 var x = 0; 253 var y = 0; 254 255 if(document.documentElement && document.documentElement.clientWidth){ 256 width = document.documentElement.clientWidth; 257 height = document.documentElement.clientHeight; 258 x = document.documentElement.scrollLeft; 259 y = document.documentElement.scrollTop; 260 } else if(document.body && document.body.clientWidth){ 261 width = document.body.clientWidth; 262 height = document.body.clientHeight; 263 x = document.body.scrollLeft; 264 y = document.body.scrollTop; 265 } 266 // we don't use an else if here, since Opera 7 tends to get the height on the documentElement wrong 267 if(window.innerWidth){ 268 width = window.innerWidth - 18; 269 height = window.innerHeight - 18; 270 } 271 272 x = window.pageXOffset ? window.pageXOffset : window.scrollX ? window.scrollX : x; 273 y = window.pageYOffset ? window.pageYOffset : window.scrollY ? window.scrollY : y; 274 275 return {width : width, height : height, x : x, y : y }; 276 } 277} 278 279//===================================================================== 280// Event Listener 281// by Scott Andrew - http://scottandrew.com 282// edited by Mark Wubben, <useCapture> is now set to false 283//=====================================================================
284function addEvent(obj, evType, fn){ 285 if(obj.addEventListener){ 286 obj.addEventListener(evType, fn, false); 287 return true; 288 } else if (obj.attachEvent){ 289 var r = obj.attachEvent('on'+evType, fn); 290 return r; 291 } else { 292 return false; 293 } 294} 295 296//===================================================================== 297// Here the default nice titles are created 298//===================================================================== 299NiceTitles.autoCreation = function(){ 300 if(!document.getElementsByTagName){ return; } 301 302 NiceTitles.autoCreated = new Object(); 303 304 var delay = 1; 305 306 NiceTitles.autoCreated.anchors = new NiceTitles("<p class=\"titletext\">attr(nicetitle)? <span class=\"accesskey\">[attr(accesskey)]</span>?</p><p class=\"destination\">attr(href)</p>", delay); 307 NiceTitles.autoCreated.acronyms = new NiceTitles("<p class=\"titletext\">content(): attr(nicetitle)</p>", delay); 308 //for image nicetitles based off alt tags 309 NiceTitles.autoCreated.images = new NiceTitles("<p class=\"titletext\">attr(nicetitle)</p>", delay); 310 //for form nicetitles. just add title to input and textarea tags 311 NiceTitles.autoCreated.input = new NiceTitles("<p class=\"titletext\">attr(nicetitle)</p><p class=\"destination\">? <span class=\"accesskey\">Accesskey : [attr(accesskey)]</span>?</p>", delay); 312 NiceTitles.autoCreated.simple = new NiceTitles("<p class=\"titletext\">attr(nicetitle)</p>", delay); 313 314 NiceTitles.autoCreated.anchors.addElements(document.getElementsByTagName("a"), "title"); 315 NiceTitles.autoCreated.images.addElements(document.getElementsByTagName("img"), "title"); //added 316// NiceTitles.autoCreated.acronyms.addElements(document.getElementsByTagName("acronym"), "title"); 317// NiceTitles.autoCreated.acronyms.addElements(document.getElementsByTagName("abbr"), "title"); 318// NiceTitles.autoCreated.input.addElements(document.getElementsByTagName("input"), "id"); //added 319// NiceTitles.autoCreated.input.addElements(document.getElementsByTagName("textarea"), "id"); //added 320 NiceTitles.autoCreated.simple.addElements(document.getElementsByTagName("div"), "title"); 321 NiceTitles.autoCreated.simple.addElements(document.getElementsByTagName("span"), "title"); 322 NiceTitles.autoCreated.simple.addElements(document.getElementsByTagName("button"), "title"); 323} 324 325addEvent(window, "load", NiceTitles.autoCreation);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.