001package com.hfg.javascript; 002 003import com.hfg.html.HTMLTag; 004import com.hfg.html.HTML; 005import com.hfg.graphics.ColorUtil; 006 007import java.awt.*; 008 009//------------------------------------------------------------------------------ 010/** 011 Generic hoverboard generation javascript. 012 You will also need to add generateJS() to the javascript in the page's <head> tag. 013 <div> 014 See <a href='doc-files/tooltipTest.html' target='_parent'>this page</a> for tooltip examples. 015 </div> 016 017 <div>Simple code example: 018 <pre> 019 HoverboardMaker hoverboardMaker = new HoverboardMaker(); 020 021 HTMLDoc htmlDoc = new HTMLDoc(); 022 023 // Keep IE from going into quirks mode. 024 htmlDoc.setDoctype(Doctype.HTML_4_01_TRANSITIONAL_NO_URL); 025 026 HTML html = new HTML(); 027 htmlDoc.setRootTag(html); 028 html.getHead().addSubtag(Meta.CONTENT_TYPE_ISO_8859_1); 029 030 // Add the necessary javascript to the page. 031 html.getHead().addJavascript(hoverboardMaker.generateJS()); 032 html.getHead().addJavascript(generateJS()); 033 034 // Add CSS 035 html.getHead().addStyle(hoverboardMaker.generateCSS()); 036 037 Body body = html.getBody(); 038 body.br(2); 039 040 // Create the target tag (in this case a span in a span) that the hoverboard will function on. 041 Span span = body.addSpan("The quick "); 042 hoverboardMaker.addHoverboard(span, "generateHoverboardContent"); 043 Span targetSpan = span.addSpan("brown").setId("hoverTarget"); 044 045 span.addContent(" fox jumped over the lazy dog"); 046 047 ... 048 049 private String generateJS() 050 { 051 Pre content = new Pre(); 052 content.addSpan("Choose a door to open:\n").setStyle(CSS.BOLD + CSS.fontSize(24)); 053 content.addSpan("1. ").addLink("javascript:void(0);", "One"); 054 content.addSpan("\n2. ").addLink("javascript:void(0);", "Two"); 055 content.addSpan("\n3. ").addLink("javascript:void(0);", "Three"); 056 057 String contentString = content.toHTML(); 058 059 String safeString = StringUtil.replaceAll(contentString, "'", "\\'"); 060 safeString = StringUtil.replaceAll(safeString, "\n", "\\n"); 061 safeString = StringUtil.replaceAll(safeString, "\r", "\\r"); 062 063 StringBuffer js = new StringBuffer(); 064 065 js.append("//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n" 066 + "function generateHoverboardContent(inTargetElement)\n" 067 + "{\n" 068 + " if (inTargetElement.id && inTargetElement.id == 'hoverTarget') {" 069 + " return '" + safeString + "';\n" 070 + " }\n" 071 + "}\n"); 072 073 return js.toString(); 074 } 075 076 </pre> 077 </div> 078 079 @author J. Alex Taylor, hairyfatguy.com 080 */ 081//------------------------------------------------------------------------------ 082// com.hfg XML/HTML Coding Library 083// 084// This library is free software; you can redistribute it and/or 085// modify it under the terms of the GNU Lesser General Public 086// License as published by the Free Software Foundation; either 087// version 2.1 of the License, or (at your option) any later version. 088// 089// This library is distributed in the hope that it will be useful, 090// but WITHOUT ANY WARRANTY; without even the implied warranty of 091// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 092// Lesser General Public License for more details. 093// 094// You should have received a copy of the GNU Lesser General Public 095// License along with this library; if not, write to the Free Software 096// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 097// 098// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 099// jataylor@hairyfatguy.com 100//------------------------------------------------------------------------------ 101 102public class HoverboardMaker 103{ 104 //########################################################################## 105 // PRIVATE FIELDS 106 //########################################################################## 107 108 private int mDelay = 500; 109 private int mXOffset = 10; 110 private int mYOffset = 20; 111 private int mWidth = 300; 112 private String mBorder = "1px ridge #cccccc"; 113 private String mFont = "arial,sans-serif"; 114 private String mFontSize = "11px"; 115 private String mFontColor = "#006600"; 116 private Color mBgColor = Color.decode("#cccccc"); 117 private int mPadding = 3; 118 private String mShadowColor = "#000000"; 119 private int mShadowWidth = 0;//2; 120 private boolean mViaOnClick = true; 121 122 //########################################################################## 123 // CONSTRUCTORS 124 //########################################################################## 125 126 //-------------------------------------------------------------------------- 127 public HoverboardMaker() 128 { 129 } 130 131 //########################################################################## 132 // PUBLIC METHODS 133 //########################################################################## 134 135 136 //-------------------------------------------------------------------------- 137 /** 138 Sets whether to trigger the hoverboard via an onclick() or an onmouseover(). 139 */ 140 public void activateViaOnClick(boolean inValue) 141 { 142 mViaOnClick = inValue; 143 } 144 145 //-------------------------------------------------------------------------- 146 public void setDelay(int inValue) 147 { 148 mDelay = inValue; 149 } 150 151 //-------------------------------------------------------------------------- 152 public void setXOffset(int inValue) 153 { 154 mXOffset = inValue; 155 } 156 157 //-------------------------------------------------------------------------- 158 public void setYOffset(int inValue) 159 { 160 mYOffset = inValue; 161 } 162 163 //-------------------------------------------------------------------------- 164 public void setWidth(int inValue) 165 { 166 mWidth = inValue; 167 } 168 169 //-------------------------------------------------------------------------- 170 public void setBorder(String inValue) 171 { 172 mBorder = inValue; 173 } 174 175 //-------------------------------------------------------------------------- 176 public void setFont(String inValue) 177 { 178 mFont = inValue; 179 } 180 181 //-------------------------------------------------------------------------- 182 public void setFontSize(String inValue) 183 { 184 mFontSize = inValue; 185 } 186 187 //-------------------------------------------------------------------------- 188 public void setFontColor(String inValue) 189 { 190 mFontColor = inValue; 191 } 192 193 //-------------------------------------------------------------------------- 194 public void setBackgroundColor(Color inValue) 195 { 196 mBgColor = inValue; 197 } 198 199 //-------------------------------------------------------------------------- 200 public void setPadding(int inValue) 201 { 202 mPadding = inValue; 203 } 204 205 //-------------------------------------------------------------------------- 206 public void setShadowColor(String inValue) 207 { 208 mShadowColor = inValue; 209 } 210 211 //-------------------------------------------------------------------------- 212 public void setShadowWidth(int inValue) 213 { 214 mShadowWidth = inValue; 215 } 216 217 //-------------------------------------------------------------------------- 218 /** 219 * Hoverboards can be added to any tag which supports onmouseover and onmouseout. 220 * You will also need to add generateJS() to the javascript in the page's <head> tag. 221 * @param inTag the tag to which the onclick() or onmouseover() attribute will 222 * be set to display a hoverboard. 223 * @param inJSMethodForContent the javascript method to call for content generation. 224 */ 225 public void addHoverboard(HTMLTag inTag, String inJSMethodForContent) 226 { 227 String currentValue = inTag.getAttributeValue(mViaOnClick ? HTML.ONCLICK : HTML.ONMOUSEOVER); 228 inTag.setAttribute(mViaOnClick ? HTML.ONCLICK : HTML.ONMOUSEOVER, 229 (currentValue != null ? currentValue + ";" : "") + "showHoverboard(event, " + inJSMethodForContent + ")"); 230 231 currentValue = inTag.getAttributeValue(HTML.CLASS); 232 inTag.setAttribute(HTML.CLASS, (currentValue != null ? currentValue + " " : "") + "hoverboard"); 233 } 234 235 236 //-------------------------------------------------------------------------- 237 public String generateCSS() 238 { 239 StringBuffer css = new StringBuffer(); 240 241 242 css.append(".hoverboard:hover {\n" 243 + " background-color: #" + ColorUtil.colorToHex(mBgColor) + ";\n" 244 + " }\n\n"); 245 246 247 return css.toString(); 248 } 249 250 //-------------------------------------------------------------------------- 251 public String generateJS() 252 { 253 StringBuffer js = new StringBuffer(); 254 255 line(js, "var hoverboard_delay = " + (mViaOnClick ? 0 : mDelay) + ";"); 256 line(js, "var hoverboard_border = '" + mBorder + "';"); 257 if (mShadowWidth > 0) 258 { 259 line(js, "var hoverboard_shadowColor = '" + mShadowColor + "';"); 260 line(js, "var hoverboard_shadowWidth = " + mShadowWidth + ";"); 261 } 262 line(js, ""); 263 line(js, ""); 264 line(js, "var _hoverboard;"); 265 line(js, "var _hoverboard_timeout;"); 266 line(js, "var _hoverboard_text;"); 267 line(js, "var _hoverboard_eventX;"); 268 line(js, "var _hoverboard_eventY;"); 269 line(js, "var _hoverboard_width;"); 270 line(js, "var _hoverboard_height;"); 271 line(js, "var _hoverboard_parent;"); 272 line(js, "var _hoverboard_content;"); 273 line(js, "var _hoverboard_content_method;"); 274 line(js, ""); 275 line(js, "//----------------------------------"); 276 line(js, "function isSupported() {"); 277 line(js, " return (Boolean(document.getElementsByTagName)"); 278 line(js, " && Boolean(document.getElementById));"); 279 line(js, "}"); 280 line(js, "//----------------------------------"); 281 line(js, "function showHoverboard(event, content_method) {"); 282 line(js, " if (!isSupported() || _hoverboard_parent) return;"); 283 line(js, ""); 284 line(js, " event = event || window.event || window.Event;"); 285 line(js, " _hoverboard_parent = event.originalTarget || event.srcElement;"); 286 line(js, " _hoverboard_parent._bgColor_cache = _hoverboard_parent.style.backgroundColor;"); 287 line(js, " _hoverboard_content_method = content_method;"); 288 line(js, " _hoverboard_timeout = setTimeout('initHoverboard()', hoverboard_delay);"); 289 line(js, "}"); 290 line(js, "//----------------------------------"); 291 line(js, "function initHoverboard() {"); 292 line(js, " // Check to see if there is content for this srcElement"); 293 line(js, " _hoverboard_content = _hoverboard_content_method(_hoverboard_parent)"); 294 line(js, " if (!_hoverboard_content) {"); 295 line(js, " destroyHoverboard();"); 296 line(js, " return;"); 297 line(js, " }"); 298 line(js, ""); 299 line(js, " // Hoverboard"); 300 line(js, " _hoverboard = document.createElement('div');"); 301 line(js, " _hoverboard.style.visibility='hidden';"); 302 line(js, " _hoverboard.style.position='absolute';"); 303 line(js, ""); 304 line(js, " _hoverboard_parent.appendChild(_hoverboard);"); 305 line(js, ""); 306 if (mShadowWidth > 0) 307 { 308 line(js, " // Shadow Div"); 309 line(js, " var shadowDiv = document.createElement('div');"); 310 line(js, " shadowDiv.style.position = 'absolute';"); 311 line(js, " shadowDiv.style.display = 'block';"); 312 line(js, " shadowDiv.style.backgroundColor = hoverboard_shadowColor;"); 313 line(js, " shadowDiv.style.width = '100%';"); 314 line(js, " shadowDiv.style.height = '100%';"); 315 line(js, " shadowDiv.style.left = hoverboard_shadowWidth + 'px';"); 316 line(js, " shadowDiv.style.top = hoverboard_shadowWidth + 'px';"); 317 line(js, ""); 318 line(js, " // Opacity"); 319 line(js, " if (shadowDiv.style.MozOpacity) shadowDiv.style.MozOpacity=0.75;"); 320 line(js, " else if (shadowDiv.style.filter) shadowDiv.style.filter='alpha(opacity=85)';"); 321 line(js, ""); 322 line(js, " _hoverboard.appendChild(shadowDiv);"); 323 line(js, ""); 324 } 325 line(js, " // Content Div"); 326 line(js, " var contentDiv = document.createElement('div');"); 327 line(js, " contentDiv.style.position = 'relative';"); 328 line(js, " contentDiv.style.display = 'block';"); 329 line(js, " contentDiv.style.border = hoverboard_border;"); 330 line(js, " _hoverboard.appendChild(contentDiv);"); 331 line(js, ""); 332 line(js, " if (document.createRange) {"); 333 line(js, " // Gecko & KHTML flavors should be able to handle this."); 334 line(js, " var range = document.createRange();"); 335 line(js, " range.setStartBefore(contentDiv);"); 336 line(js, " var domfrag = range.createContextualFragment(_hoverboard_content);"); 337 line(js, " contentDiv.appendChild(domfrag);"); 338 line(js, " }"); 339 line(js, " else {"); 340 line(js, " contentDiv.innerHTML = '<table><tr><td>' "); 341 line(js, " + _hoverboard_content"); 342 line(js, " + '<\\/td><\\/tr><\\/table>';"); 343 line(js, " }"); 344 line(js, ""); 345 line(js, " _hoverboard_height = (_hoverboard.pixelHeight ? _hoverboard.pixelHeight :"); 346 line(js, " _hoverboard.offsetHeight ? _hoverboard.offsetHeight : 0);"); 347 line(js, " _hoverboard_width = (_hoverboard.pixelWidth ? _hoverboard.pixelWidth :"); 348 line(js, " _hoverboard.offsetWidth ? _hoverboard.offsetWidth : 0);"); 349 line(js, ""); 350 line(js, " if (_hoverboard.style.width) {"); 351 line(js, " _hoverboard.style.width = _hoverboard_width + 'px';"); 352 line(js, " }"); 353 line(js, ""); 354 line(js, " positionHoverboard();"); 355 line(js, " _hoverboard_parent.style.backgroundColor = '#" + ColorUtil.colorToHex(mBgColor) + "';"); 356 line(js, " _hoverboard.style.visibility='visible';"); 357 line(js, ""); 358 line(js, " _hoverboard_parent._onmouseout_cache = _hoverboard_parent.onmouseout || function() {};"); 359 line(js, " _hoverboard_parent.onmouseout = function(event) {"); 360 line(js, " if (_hoverboard) {"); 361 line(js, " event = event || window.event || window.Event;"); 362 line(js, " var x = event.pageX || event.clientX || 0;"); 363 line(js, " var y = event.pageY || event.clientY || 0;"); 364 365 line(js, " // Safari has a problem with onmouseout() being called while still within the parent's rectangle."); 366 line(js, " var offsetTrail = _hoverboard_parent;"); 367 line(js, " var offsetLeft = 0;"); 368 line(js, " var offsetTop = 0;"); 369 line(js, " while (offsetTrail) {"); 370 line(js, " offsetLeft += offsetTrail.offsetLeft;"); 371 line(js, " offsetTop += offsetTrail.offsetTop;"); 372 line(js, " offsetTrail = offsetTrail.offsetParent;"); 373 line(js, " }"); 374 line(js, " if (x >= offsetLeft && x <= offsetLeft + _hoverboard_parent.offsetWidth"); 375 line(js, " && y >= offsetTop && y <= offsetTop + _hoverboard_parent.offsetHeight)"); 376 line(js, " {"); 377 line(js, " // Still inside the parent."); 378 line(js, " return true;"); 379 line(js, " }"); 380 381 line(js, " offsetTrail = _hoverboard;"); 382 line(js, " offsetLeft = 0;"); 383 line(js, " offsetTop = 0;"); 384 line(js, " while (offsetTrail) {"); 385 line(js, " offsetLeft += offsetTrail.offsetLeft;"); 386 line(js, " offsetTop += offsetTrail.offsetTop;"); 387 line(js, " offsetTrail = offsetTrail.offsetParent;"); 388 line(js, " }"); 389// line(js, " alert('y:' + y + ' ' + offsetTop + ' ' + _hoverboard_height);");//////////// 390 line(js, " if (x <= offsetLeft || x >= offsetLeft + _hoverboard_width"); 391 line(js, " || y <= offsetTop || y >= offsetTop + _hoverboard_height)"); 392 393// line(js, " if (x < parseInt(_hoverboard.style.left) || x > parseInt(_hoverboard.style.left) + _hoverboard_width"); 394// line(js, " || y < parseInt(_hoverboard.style.top) || y > parseInt(_hoverboard.style.top) + _hoverboard_height)"); 395 line(js, " {"); 396 line(js, " destroyHoverboard(event);"); 397 line(js, " }"); 398 399 400 line(js, " }"); 401 line(js, " else {"); 402 line(js, " destroyHoverboard(event);"); 403 line(js, " }"); 404 line(js, " return true;"); 405 line(js, " }"); 406 407 408 line(js, "}"); 409 line(js, "//----------------------------------"); 410 line(js, "function destroyHoverboard(event) {"); 411 line(js, " if (!isSupported()) return;"); 412 line(js, ""); 413 line(js, " if (_hoverboard_timeout) {"); 414 line(js, " clearTimeout(_hoverboard_timeout);"); 415 line(js, " }"); 416 line(js, ""); 417 line(js, " if (_hoverboard) {"); 418 line(js, " _hoverboard_parent.removeChild(_hoverboard);"); 419 line(js, " _hoverboard = null;"); 420 line(js, " }"); 421 line(js, ""); 422 line(js, " if (_hoverboard_parent) {"); 423 line(js, " _hoverboard_parent.style.backgroundColor = _hoverboard_parent._bgColor_cache;"); 424 line(js, " if (_hoverboard_parent._onmouseout_cache) {"); 425 line(js, " _hoverboard_parent.onmouseout = _hoverboard_parent._onmouseout_cache;"); 426 line(js, " _hoverboard_parent.onmouseout(event);"); 427 line(js, " }"); 428 line(js, " _hoverboard_parent = null;"); 429 line(js, " }"); 430 line(js, ""); 431 line(js, "}"); 432 line(js, "//----------------------------------"); 433 line(js, "function positionHoverboard() {"); 434 line(js, " var offsetTrail = _hoverboard_parent;"); 435 line(js, " var offsetLeft = 0;"); 436 line(js, " var offsetTop = 0;"); 437 line(js, " while (offsetTrail) {"); 438 line(js, " offsetLeft += offsetTrail.offsetLeft;"); 439 line(js, " offsetTop += offsetTrail.offsetTop;"); 440 line(js, " offsetTrail = offsetTrail.offsetParent;"); 441 line(js, " }"); 442 line(js, " var x = offsetLeft;"); 443 line(js, " var y = offsetTop + _hoverboard_parent.offsetHeight;"); 444 line(js, " var body = document.compatMode && document.compatMode != 'BackCompat' ? document.documentElement : document.body? document.body : null;"); 445 line(js, ""); 446 line(js, " if (_hoverboard) {"); 447 line(js, " var windowWidth = 0;"); 448 line(js, " if (body.clientWidth) {"); 449 line(js, " if (window.innerWidth) {"); 450 line(js, " windowWidth = Math.max(body.clientWidth, window.innerWidth);"); 451 line(js, " }"); 452 line(js, " else {"); 453 line(js, " windowWidth = body.clientWidth;"); 454 line(js, " }"); 455 line(js, " }"); 456 line(js, " else {"); 457 line(js, " windowWidth = window.innerWidth;"); 458 line(js, " }"); 459 line(js, ""); 460 line(js, " var windowHeight = 0;"); 461 line(js, " if (body.clientHeight) {"); 462 line(js, " if (window.innerHeight) {"); 463 line(js, " windowHeight = Math.max(body.clientHeight, window.innerHeight);"); 464 line(js, " }"); 465 line(js, " else {"); 466 line(js, " windowHeight = body.clientHeight;"); 467 line(js, " }"); 468 line(js, " }"); 469 line(js, " else {"); 470 line(js, " windowHeight = window.innerHeight;"); 471 line(js, " }"); 472 line(js, ""); 473 line(js, " var xLimit = windowWidth"); 474 line(js, " + (window.pageXOffset ? window.pageXOffset : body.scrollLeft ? body.scrollLeft : 0)"); 475 line(js, " - _hoverboard_width - 10;"); 476 line(js, ""); 477 line(js, " var yLimit = windowHeight"); 478 line(js, " + (window.pageYOffset ? window.pageYOffset : body.scrollTop ? body.scrollTop : 0)"); 479 line(js, " - _hoverboard_height;"); 480 line(js, ""); 481 line(js, " if (x > xLimit) x = xLimit;"); 482 line(js, ""); 483 line(js, " if (y > yLimit) {"); 484 line(js, " if (hoverboard_yOffset > 0) {"); 485 line(js, " // Flip display to above the cursor"); 486 line(js, " y = y - hoverboard_yOffset - hoverboard_yOffset - _hoverboard_height;"); 487 line(js, " }"); 488 line(js, " if (y > yLimit) y = yLimit;"); 489 line(js, " }"); 490 line(js, ""); 491 line(js, " _hoverboard.style.left = x + 'px';"); 492 line(js, " _hoverboard.style.top = y + 'px';"); 493 line(js, " }"); 494 line(js, "}"); 495 496 return js.toString(); 497 } 498 499 //-------------------------------------------------------------------------- 500 private static void line(StringBuffer inBuffer, String inLine) 501 { 502 inBuffer.append(inLine + "\n"); 503 } 504 505}