// $Id: util.js 771 2009-11-25 23:21:18Z jason $ /** * Converts an integral duration to HH:MM:SS. * @param timeval duration in seconds * @return @a timeval as HH:MM:SS. */ function _formatInterval( timeval ) { if( timeval <= 0 ) return '00:00:00'; var seconds = parseInt( timeval%60 ); if( seconds <= 9 ) seconds = '0' + (seconds); var minutes = Math.floor(timeval/60)%60; if( minutes <= 9 ) minutes = '0' + (minutes); var hours = Math.floor(timeval/3600); if( hours <= 9 ) hours = '0' + (hours); return hours + ':' + minutes + ':' + seconds; } // Stolen from Chris's autosug.js :) function _make_xhr( ) { var xhr = null; try { xhr = new XMLHttpRequest(); } catch (trymicrosoft) { try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch (othermicrosoft) { try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } catch (failed) { xhr = false; } } } return xhr; } /* from http://onlinetools.org/articles/unobtrusivejavascript/chapter4.html * (in turn based on http://www.scottandrew.com/weblog/articles/cbs-events) */ function _addEvent( obj, evType, fn ) { if (obj.addEventListener){ obj.addEventListener(evType, fn, false); return true; } else if (obj.attachEvent){ var r = obj.attachEvent("on"+evType, fn); return r; } else { return false; } } // from: http://www.openjs.com/articles/prevent_default_action/ function _stopEvent(e) { e = e || window.event; //e.cancelBubble is supported by IE - this will kill the bubbling process. e.cancelBubble = true; e.returnValue = false; //e.stopPropagation works only in Firefox. if (e.stopPropagation) { e.stopPropagation(); e.preventDefault(); } return false; } //---------------------------------------------------- // credit for the following goes to PPK@quirksmode.org // pp]{ function _findPos(obj) { var curleft = 0; var curtop = 0; if (obj.offsetParent) while( obj ) { curtop += obj.offsetTop; curleft += obj.offsetLeft; obj = obj.offsetParent; } else if (obj.x) { curleft += obj.x; curtop += obj.y; } return [ curleft,curtop ]; } function _findMouse( e ) { var posx = 0; var posy = 0; e = e || window.event; if( e.pageX || e.pageY ) { posx = e.pageX; posy = e.pageY; } else if( e.clientX || e.clientY ) { posx = e.clientX + ( document.documentElement.scrollLeft || document.body.scrollLeft || 0 ); posy = e.clientY + ( document.documentElement.scrollTop || document.body.scrollTop || 0 ); } return [ posx,posy ]; } //}[ //-- /** * Returns the value if the selected element of the provided radio button group. * Why radio groups act as single elements rather than one-element arrays when * only one item is present seems like a horrible design flaw. * * @param el radio button element * * @return the value of the selected element, null if none chosen */ function radio_get_selected( el ) { if( typeof el.length == 'undefined' ) return el.checked ? el.value : null; // single element else for( var i=0; i < el.length; ++i ) if( el[i].checked ) return el[i].value; return null; } /** * Request a new page number for a large result set. * @a fieldid is updated to the new page number, and its associated form is * submitted. * @param fieldid ID of the field to update * @param pagenum page number to switch */ function changepage( fieldid, pagenum ) { var field = document.getElementById( fieldid ); field.value = pagenum; field.form.submit( ); } /** * Escapes characters matching [&<>]. * @param str string to escape * @return escaped version of @a str */ function escape_html( str ) { return str.split("&").join("&").split("<").join("<"). split(">").join(">"); } /** * Given a form ID, checks all of its check boxes. * @param formId ID of form * @param selected true to check, false to uncheck * @param name if not null, restrict to inputs with this name */ function form_select_all( formId, selected, name ) { var formEl = document.getElementById( formId ); if( !formEl ) return; for( var i = 0; i < formEl.length; ++i ) if( formEl.elements[i].type == 'checkbox' && (name && formEl.elements[i].name == name) ) formEl.elements[i].checked = selected; } /** * Simple function to push a class name onto a class tag. * @param el element instance * @param classn class tname * @see popclass() */ function pushclass( el, classn ) { if( el.className ) el.className = el.className + " " + classn; else el.className = classn; } /** * Simple function to pop off the last item in a class tag. * @param el element instance * @see pushclass() */ function popclass( el ) { if( !el.className ) return; // dumbass :P len = el.className.length; spaceat = el.className.lastIndexOf( " " ); if( spaceat == -1 ) el.className = ""; else el.className = el.className.substring( 0,spaceat ); } /** * Returns the requested attribute value, or null if it does not exist. * * @note * The whole namespace thing only works with proper XML; that is, the document * must be served as application/xhtml+xml. We don't do that right now. * When we do, @a namespace must contain the namespace URI, not the namespace * prefix. Sigh. * * @note * Okay, I guess this is wholly pointless right now since IE doesn't do * hasAttribute(). * * @param element instantiated element * @param namespace attribute namespace ('' for no namespace) * @param attrname attribute name (local part) * @return attribute value, or null if not found */ function getAttribute( element, namespace, attrname ) { /* applicable when served as application/xhtml+xml...? if( element.getAttributeNS ) return element.hasAttributeNS( namespace, attrname ) ? element.getAttributeNS( namespace, attrname ) : null; else */ return element.hasAttribute( namespace + ':' + attrname ) ? element.getAttribute( namespace + ':' + attrname ) : null; } /** * Creates an XML document from the provided string. * * @note * It is important that the returned document *not* contain a DOCTYPE (or, that * it is correct for the returned document), and/or that the XML prologue is * present. If the IE parser chokes, make sure that you've met these conditions. * * @param xmlstr string representing XML content * @return DOMDocument instance (?) */ function _loadXML( xmlstr ) { if( typeof DOMParser != 'undefined' ) { var parser = new DOMParser(); return parser.parseFromString( xmlstr, 'text/xml' ); } else if( typeof ActiveXObject != 'undefined' ) { var doc = new ActiveXObject( 'Microsoft.XMLDOM' ); doc.async = 'false'; doc.loadXML( xmlstr ); return doc; } else return null; } /** * Inserts a retrieved HTML fragment into the page. * In a post-innerHTML world (specifically, when in XHTML mode) you must add * external nodes to the document using W3C methods. However, simply cloning * those external nodes won't work as they're missing the necessary XHTML * metadata. This function creates the XHTML-ified nodes and inserts them into * the document. * * @param nodeset the DOMXML node set (see _loadXML()) * @param parent parent node * @param insert_before insert new nodes before this; if null, appends * @param clear if true, remove existing children of parent */ function _cloneHTML( nodeset, parent, insert_before, clear ) { if( clear ) while( parent.hasChildNodes() ) parent.removeChild( parent.firstChild ); for( var node_idx = 0; node_idx < nodeset.length; ++node_idx ) { parent.insertBefore( _replicate(nodeset.item(node_idx)), insert_before ); } } /** * _cloneHTML helper function which replicates a node. * @param node node to replicate * @return replicated version of @a node */ function _replicate( node ) { if( node.nodeName == '#text' ) return document.createTextNode( node.nodeValue ); var newnode = document.createElement( node.nodeName ); /* IE has a strange concept of attributes -- they map to element properties. * For example, to set the "class" attribute, you must refer to it as * "className"; to set "colspan", you must refer to "colSpan". Luckily the * latter can be worked around by setting IE's proprietary third argument to * setAttribute() ("case_sensitive") to false. The former workaround must be * hardcoded... :P */ var is_IE = typeof newnode.hasAttribute == 'undefined'; for( var attr_idx = 0; attr_idx < node.attributes.length; ++attr_idx ) { if( !is_IE ) newnode.setAttribute( node.attributes[attr_idx].name, node.attributes[attr_idx].value ); else { var attrname = node.attributes[attr_idx].name; if( attrname == 'class' ) attrname = 'className'; else if( attrname == 'for' ) attrname = 'htmlFor'; // ...any others? newnode.setAttribute( attrname, node.attributes[attr_idx].value, false ); } } for( var node_idx = 0; node_idx < node.childNodes.length; ++node_idx ) newnode.appendChild( _replicate( node.childNodes[node_idx] ) ); return newnode; } /*! * Carlos R. L. Rodrigues * http://jsfromhell.com/array/average [rev. #1] */ average = function(a){ var r = {mean: 0, variance: 0, deviation: 0}, t = a.length; for(var m, s = 0, l = t; l--; s += a[l]); for(m = r.mean = s / t, l = t, s = 0; l--; s += Math.pow(a[l] - m, 2)); return r.deviation = Math.sqrt(r.variance = s / t), r; }