// The following code is used to support the small popups that give the full // description of an event when the user moves the mouse over it. // Thanks to Klaus Knopper (www.knoppix.com) for this script. // It has been modified to work with the existing WebCalendar // architecture on 02/25/2005. // // 03/05/2005 Prevent popup from going off screen by setting maximum width, // which is configurable. // // Bubblehelp infoboxes, (c) 2002 Klaus Knopper // You can copy/modify and distribute this code under the conditions // of the GNU GENERAL PUBLIC LICENSE Version 2. var ns4, // Are we using Netscape4? ie4, // Are we using Internet Explorer Version 4? ie5, // Are we using Internet Explorer Version 5 and up? kon, // Are we using KDE Konqueror? followMe = 1, // allow popup to follow cursor...turn off for better performance idiv = null, // Pointer to infodiv container maxwidth = 300, // maximum width of popup window popupH, // height of popup popupW, // width of popup px = 'px', // position suffix with "px" in some cases x, y, winW, winH, // Current help position and main window size xoffset = 8, // popup distance from cursor x coordinate yoffset = 12; // popup distance from cursor y coordinate function nsfix () { setTimeout ( 'window.onresize = rebrowse', 2000 ); } if ( typeof document.getElementsBySelector == 'undefined' ) { /* document.getElementsBySelector ( selector ) - returns an array of element objects from the current document matching the CSS selector. Selectors can contain element names, class names and ids and can be nested. For example: elements = document.getElementsBySelect('div#main p a.external') Will return an array of all 'a' elements with 'external' in their class attribute that are contained inside 'p' elements that are contained inside the 'div' element which has id="main". New in version 0.4: Support for CSS2 and CSS3 attribute selectors: See http://www.w3.org/TR/css3-selectors/#attribute-selectors Version 0.4 - Simon Willison, March 25th 2003 -- Works in Phoenix 0.5, Mozilla 1.3, Opera 7, Internet Explorer 6, Internet Explorer 5 on Windows. -- Opera 7 fails. */ function getAllChildren ( e ) { // Returns all children of element. Workaround required for IE5/Windows. Ugh. return ( e.all ? e.all : e.getElementsByTagName ( '*' ) ); } document.getElementsBySelector = function ( selector ) { // Attempt to fail gracefully in lesser browsers. if ( ! document.getElementsByTagName ) return new Array (); // Split selector in to tokens. var tokens = selector.split ( ' ' ), currentContext = new Array ( document ); for ( var i = 0; i < tokens.length; i++ ) { token = tokens[i].replace ( /^\s+/,'' ).replace ( /\s+$/,'' ); if ( token.indexOf ( '#' ) > -1 ) { // Token is an ID selector. var bits = token.split ( '#' ), tagName = bits[0], id = bits[1], element = document.getElementById ( id ); if ( tagName && element.nodeName.toLowerCase () != tagName ) { // Tag with that ID not found, return false. return new Array (); } // Set currentContext to contain just this element. currentContext = new Array ( element ); continue; // Skip to next token. } if ( token.indexOf ( '.' ) > -1 ) { // Token contains a class selector. var bits = token.split ( '.' ), tagName = bits[0], className = bits[1]; if ( ! tagName ) tagName = '*'; // Get elements matching tag, filter them for class selector. var found = new Array, foundCount = 0; for ( var h = 0; h < currentContext.length; h++ ) { var elements; elements = ( tagName == '*' ? getAllChildren ( currentContext[h] ) : currentContext[h].getElementsByTagName ( tagName ) ); for ( var j = 0; j < elements.length; j++ ) { found[foundCount++] = elements[j]; } } currentContext = new Array; var currentContextIndex = 0; for ( var k = 0; k < found.length; k++ ) { if ( found[k].className && found[k].className.match ( new RegExp ( '\\b'+className+'\\b' ) ) ) currentContext[currentContextIndex++] = found[k]; } continue; // Skip to next token. } // Code to deal with attribute selectors. if ( token.match ( /^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/ ) ) { var tagName = RegExp.$1, attrName = RegExp.$2, attrOperator = RegExp.$3, attrValue = RegExp.$4; if ( ! tagName ) tagName = '*'; // Grab all of the tagName elements within current context. var found = new Array, foundCount = 0; for ( var h = 0; h < currentContext.length; h++ ) { var elements; elements = ( tagName == '*' ? getAllChildren(currentContext[h]) : currentContext[h].getElementsByTagName ( tagName ) ); for ( var j = 0; j < elements.length; j++ ) { found[foundCount++] = elements[j]; } } currentContext = new Array; var currentContextIndex = 0, checkFunction; // This function will be used to filter the elements. switch ( attrOperator ) { case '=': // Equality checkFunction = function ( e ) { return ( e.getAttribute ( attrName ) == attrValue ); }; break; case '~': // Match one of space seperated words. checkFunction = function ( e ) { return ( e.getAttribute ( attrName ).match ( new RegExp ( '\\b'+attrValue+'\\b' ) ) ); }; break; case '|': // Match start with value followed by optional hyphen. checkFunction = function ( e ) { return ( e.getAttribute ( attrName ).match ( new RegExp ( '^'+attrValue+'-?' ) ) ); }; break; case '^': // Match starts with value. checkFunction = function ( e ) { return ( e.getAttribute(attrName ).indexOf ( attrValue ) == 0); }; break; case '$': // Match ends with value - fails with "Warning" in Opera 7. checkFunction = function ( e ) { return ( e.getAttribute ( attrName ).lastIndexOf ( attrValue ) == e.getAttribute ( attrName ).length - attrValue.length ); }; break; case '*': // Match ends with value. checkFunction = function ( e ) { return ( e.getAttribute ( attrName ).indexOf ( attrValue ) > -1); }; break; default: // Just test for existence of attribute. checkFunction = function ( e ) { return e.getAttribute ( attrName ); }; } currentContext = new Array; var currentContextIndex = 0; for ( var k = 0; k < found.length; k++ ) { if ( checkFunction ( found[k] ) ) currentContext[currentContextIndex++] = found[k]; } continue; // Skip to next token. } // If we get here, token is JUST an element (not a class or ID selector). tagName = token; var found = new Array, foundCount = 0; for ( var h = 0; h < currentContext.length; h++ ) { var elements = currentContext[h].getElementsByTagName ( tagName ); for ( var j = 0; j < elements.length; j++ ) { found[foundCount++] = elements[j]; } } currentContext = found; } return currentContext; } /* That revolting regular expression explained. /^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/ \---/ \---/\-------------/ \-------/ | | | | | | | The value | | ~,|,^,$,* or = | Attribute Tag */ } function rebrowse () { window.location.reload (); } function infoinit () { ns4 = ( document.layers ); ie4 = ( document.all ); ie5 = ( ie4 && ( navigator.userAgent.indexOf ( 'MSIE 5' ) > 0 || navigator.userAgent.indexOf ( 'MSIE 6' ) > 0 || navigator.userAgent.indexOf ( 'MSIE 7' ) > 0 ) ); kon = ( navigator.userAgent.indexOf ( 'konqueror' ) > 0 ); idiv = null; winW = 800; winH = 600; x = y = 0; if ( followMe ) { document.onmousemove = mousemove; if ( ns4 && document.captureEvents ) document.captureEvents ( Event.MOUSEMOVE ); } // Workaround for another Netscape bug: Fix browser confusion on resize. // Obviously Konqueror has a similar problem. :-( if ( ns4 || kon ) nsfix (); if ( ns4 ) px = ''; var entries = document.getElementsBySelector ( 'a.entry' ); entries = entries.concat ( document.getElementsBySelector ( 'a.layerentry' ) ); entries = entries.concat ( document.getElementsBySelector ( 'a.unapprovedentry' ) ); entries = entries.concat ( document.getElementsBySelector ( 'tr.task' ) ); for ( var i = 0; i < entries.length; i++ ) { entries[i].onmouseover = function ( event ) { showPopUp ( event, 'eventinfo-' + this.id ); return true; } entries[i].onmouseout = function () { hidePopUp ( 'eventinfo-' + this.id ); return true; } } } function hidePopUp ( name ) { idiv.style.visibility = ( ns4 ? 'hide' : 'hidden' ); idiv = null; } function gettip ( name ) { return ( document.layers && document.layers[name] ? document.layers[name] : ( document.all && document.all[name] ? document.all[name] : ( document[name] ? document[name] : ( document.getElementById ( name ) ? document.getElementById ( name ) : 0 ) ) ) ); } function showPopUp ( evt, name ) { if ( idiv ) hide ( name ); idiv = gettip ( name ); if ( idiv ) { scrollX = scrollY = 0; scrollX = ( typeof window.pageXOffset == 'number' ? window.pageXOffset : ( document.documentElement && document.documentElement.scrollLeft ? document.documentElement.scrollLeft : ( document.body && document.body.scrollLeft ? document.body.scrollLeft : window.scrollX ) ) ); scrollY = ( typeof window.pageYOffset == 'number' ? window.pageYOffset : ( document.documentElement && document.documentElement.scrollTop ? document.documentElement.scrollTop : ( document.body && document.body.scrollTop ? document.body.scrollTop : window.scrollY ) ) ); winW = ( window.innerWidth ? window.innerWidth + window.pageXOffset - 16 : document.body.offsetWidth - 20 ); winH = ( window.innerHeight ? window.innerHeight : ( ie5 ? 500 : document.body.offsetHeight ) ) + scrollY; popupW = idiv.offsetWidth; popupH = idiv.offsetHeight; showtip ( evt ); } } function recursive_resize ( ele, width, height ) { if ( ele.nodeType != 1 ) return; if ( width != null && ele.offsetWidth > width ) ele.style.width = width + px; if ( height != null && ele.offsetHeight > height ) ele.style.height = height + px; for ( var i = 0; i < ele.childNodes.length; i++ ) { recursive_resize ( ele.childNodes[i], width - ele.childNodes[i].offsetLeft, height - ele.childNodes[i].offsetTop ); } } function showtip ( e ) { e = ( e ? e : window.event ); if ( idiv ) { if ( e ) { x = ( e.pageX ? e.pageX : ( e.clientX ? e.clientX + scrollX : 0 ) ); y = ( e.pageY ? e.pageY : ( e.clientY ? e.clientY + scrollY : 0 ) ); } else { x = y = 0; } // Make sure we don't go off screen. recursive_resize ( idiv, maxwidth ); popupW = idiv.offsetWidth; popupH = idiv.offsetHeight; idiv.style.top = ( y + popupH + yoffset > winH - yoffset ? ( winH - popupH - yoffset < 0 ? 0 : winH - popupH - yoffset ) : y + yoffset ) + px ; idiv.style.left = ( x + popupW + xoffset > winW - xoffset ? x - popupW - xoffset : x + xoffset ) + px; idiv.style.visibility = ( ns4 ? 'show' : 'visible' ); } } function mousemove ( e ) { showtip ( e ); } // Initialize after loading the page. if ( typeof addLoadHandler == 'undefined' ) { function addLoadHandler ( handler ) { if ( window.addEventListener ) { window.addEventListener ( 'load',handler,false); } else if ( window.attachEvent ) { window.attachEvent ( 'onload',handler ); } else if ( window.onload ) { var oldHandler = window.onload; window.onload = function piggyback () { oldHandler (); handler (); }; } else { window.onload = handler; } } } addLoadHandler ( infoinit );