var _t = ''; _t += ''; _t += '
'; _t += ''; document.write(_t); function generateLoginUrl() { var path = location.pathname; var query = location.search ; var host = "http://" + location.hostname; if (query == '') { query = "?need=prefs"; } else { query += "&need=prefs"; } if (window.location.href.indexOf('blogs') != -1) { var cfu = escape("https://s.foxsports.com/pp/response?blogs=true&cfu=" + host + path + query); } else if (host != "http://msn.foxsports.com") { var cfu = escape("https://s.foxsports.com/pp/response?cfu=" + host + path + query); } else { var cfu = escape("https://s.foxsports.com/pp/response?cfu=" + path + query); } var queryParams = "&seclog=10&wa=wsignin1.0&wreply=" + cfu + "&cb=" + escape("&wa=wsignin1.0&wreply=") + cfu; return "https://login.live.com/ppsecure/secure.srf?wp=MBI_FED_SSL" + queryParams; } var writeString = ''; writeString += ''; writeString += ''; writeString += '
'; if (navigator.appName.indexOf('WebTV') != -1) { document.write(''); } else { writeString += '
'; writeString += ' '; writeString += ' '; writeString += ' '; writeString += ' '; writeString += ' '; writeString += ' '; writeString += ' '; writeString += '
go to MSN.com'; writeString += ' '; writeString += ' '; writeString += ' '; writeString += ' '; writeString += ' '; writeString += ' '; writeString += ' '; writeString += ' '; writeString += ' '; writeString += ' '; writeString += ' '; writeString += ' '; writeString += '
  autos    money    sports    tech    more    
'; writeString += '
'; writeString += ' '; writeString += ' '; writeString += '   MSN Home  |  Mail  |  My MSN  | '; if (typeof(euid)== "undefined" || euid == null || euid == '') { writeString += ' Sign in  '; } else { writeString += ' Sign out  '; } writeString += '
'; writeString += '
'; writeString += '
'; writeString += ' '; writeString += ' '; writeString += '
'; writeString += '
'; writeString += ''; document.write(writeString); } document.write(''); /* Begin: MSN search header (FSCOM-4763) */ ///////////////////////////////////////////////////////////////////////////////// // // File: base.js // Defines: // Dependencies: // Description: this is the base framework module. This must be the first JS // file; all other framework files depend on the prototypes defined // within. // // Copyright (c) 2006 by Microsoft Corporation. All rights reserved. // ///////////////////////////////////////////////////////////////////////////////// Function.prototype.addMethod = function(name,func) { // if the function doesn't already exist if ( !this.prototype[name] ) { // add it now this.prototype[name] = func; } // return this to allow chaining return this; }; Function.addMethod("as", function(ns,isSingleton) { // split the namespace string on the periods var chain = (ns ? ns.split('.') : []); // if the array is empty, then nothing to do if ( chain.length > 0 ) { // the root is the window object var base = window; // start with the first stop with the second-to-last portion // in the namespace chain for(var ndx = 0; ndx < chain.length - 1; ++ndx) { // the token should not be empty -- skip it if it is var token = chain[ndx]; if ( token ) { // if the namespace object for this token doesn't // already exist, then we need to create it now if ( !base[token] ) { // make it an empty object base[token] = {}; } // walk down the chain base = base[token]; } } // the last namespace in the chain is a new instance // of this object base[chain.last()] = (isSingleton ? new this() : this); } return this; }); Function.addMethod("ns",function(ns) { // just define this function as the namespace, but as a singleton // (just a shortcut for readability purposes) this.as(ns,1); }); String.addMethod("trim",function() { // trim off all leading and trailing spaces return this.replace(/^\s*(\S*(\s+\S+)*)\s*$/,"$1"); }); String.addMethod("collapse", function() { // trim off all leading and trailing spaces, and collapse all instances // of whitespace to a single space character return this.replace(/\s+/g,' ').trim(); }); String.addMethod("wrap", function(delim) { // return the text wrapped in the delimeter var close, delims = {"(":")", "{":"}", "[":"]", "<":">", "«":"»", "‹":"›", "“":"”", "‘":"’"}; if ( delims[delim] ) { close = delims[delim]; } else { var m = (/^<(\w+)(\s+\w+\s*=\s*"[^"]*")*\s*>$/).exec( delim ); if ( m ) { close = ""; } } return delim + this + (close ? close : delim); }); String.addMethod("format",function() { // use this string as the format var fmt = this; // walk through each argument passed in for(var ndx=0; ndx < arguments.length; ++ndx) { // replace {0} with argument[0], {1} with argument[1], etc. fmt = fmt.replace( new RegExp('\\{' + ndx + '\\}',"g"), arguments[ndx] ); } // return the formatted string return fmt; }); String.addMethod("encodeHtml",function() { var returnString = this.replace(/\>/g, ">").replace(/\").replace(/</g, "<").replace(/&/g, "&").replace(/'/g, "'").replace(/"/g, '"'); return returnString; }); String.addMethod("encodeURIComponent",function() { return (typeof encodeURIComponent != "undefined" ? encodeURIComponent(this) : escape(this)); }); String.addMethod("decodeURIComponent",function() { return (typeof decodeURIComponent != "undefined" ? decodeURIComponent(this) : unescape(this)); }); Array.addMethod("last",function() { // return the last element in the array, // or "undefined" if the array is empty return (this.length > 0 ? this[this.length-1] : void(0)); }); Array.addMethod("remove",function(obj) { // walk backwards because we might be removing items for(var ndx=this.length-1; ndx >= 0; --ndx) { // if this element is the same as the argument... if ( this[ndx] === obj ) { // splice it out now this.splice(ndx, 1); } } return this; }); Array.addMethod("contains", function(obj) { // walk all the items in the array for(var ndx=0; ndx < this.length; ++ndx) { // check to see if this item is the exact same (no conversion) // as the object passed to us if ( this[ndx] === obj ) { // we can bail as soon as we find it return 1; } } // if we get here, we didn't find it return 0; }); // these methods are typically already defined on more-recent browsers // but we'll try to add them in case this is an older browser that doesn't // support them (since we use them). // examples are IE 5.0 or earlier, IE for the Mac, etc. Array.addMethod("push",function(obj) { // add the object to the end of the array this[this.length] = obj; // return the new array length return this.length; }); Array.addMethod("shift",function() { // splice returns an array of the deleted items, so delete one item // from the head, and return the one element in the returned array return this.splice(0,1)[0]; }); Array.addMethod("splice",function(start,delCount) { // we might be adding new elements -- calculate how many were passed in (if any) var delta; var addCount = arguments.length - 2; // verify some values based on the length of the array // can't start past the end of the array if ( start > this.length ) { start = this.length; } // can't delete more items than we have if ( start + delCount > this.length ) { delCount = this.length - start; } // create the array of deleted items (if any) var deleted = []; for(var ndx = 0; ndx < delCount; ++ndx) { deleted.push(this[start+ndx]); } if ( addCount > delCount ) { // have to push out elements to make room for added items delta = addCount - delCount; for(ndx = this.length + delta - 1; ndx >= start + delta; --ndx) { this[ndx] = this[ndx - delta]; } // don't have to adjust the length when adding -- gets done // automatically by adding items beyond the old length } else if ( addCount < delCount ) { // pushing in elements because more deleted than added delta = delCount - addCount; for(ndx = start + addCount; ndx < this.length - delta; ++ndx) { this[ndx] = this[ndx + delta]; } // delete the excess items starting where we left off for(; ndx < this.length - 1; ++ndx) { delete this[ndx]; } // adjust the length this.length -= delta; } // if we're adding items, add them now for(ndx = 0; ndx < addCount; ++ndx ) { this[start+ndx] = arguments[2+ndx]; } return deleted; }); ///////////////////////////////////////////////////////////////////////////////// // // File: dom.js // Defines: Msn.DOM // Dependencies: base.js // Description: implements framework DOM functionality. Common DOM-walking // methods and event hooking. // // Copyright (c) 2006 by Microsoft Corporation. All rights reserved. // ///////////////////////////////////////////////////////////////////////////////// (function() { // shortcut var dom = this; Function.addMethod("hook",function(element,eventName) { if ( element ) { var isSafari = checkSafari(); if ( !isSafari && element.addEventListener ) { // if the browser supports the w3c model, use it element.addEventListener( eventName, this, false ); } else if ( !isSafari && element.attachEvent ) { // if the browser supports the IE model, use it element.attachEvent( 'on' + eventName, this ); } else { // normally we'd just assign to "on"+eventName, but let's try // to fake it by setting up an array of event handlers as a property // on the element. Then we'll set the real event handler to a function // that walks that array, calling each of the handlers. If any of the handlers // returns false, we stop walking and return false. Otherwise we'll return true. // // see if there's already an event handler for this event var handlers = element["x"+eventName]; if ( handlers && handlers.constructor == Array ) { // yes -- add this new function to the list if it isn't already if ( handlers.contains(this) ) { // already there -- null the handler variable so we do nothing handlers = null; } else { // add it handlers.push(this); } } else { // no -- create a new array with this function as the only item handlers = element["x"+eventName] = [this]; } if ( handlers ) { // set the real handler to be a custom function element['on' + eventName] = function(ev) { var returnValue = true; // the event object ev = dom.Event(ev); // walk the array for(var ndx=0; ndx < handlers.length; ++ndx) { // call the handler var handlerReturn = handlers[ndx](ev); if ( typeof handlerReturn != "undefined" && !handlerReturn ) { // return false to cancel the event and stop calling handlers returnValue = false; } } // everything was fine and dandy return returnValue; }; // the above closure will leak memory under IE. // null out the element reference and the leak won't happen. element = null; } } } return this; }); Function.addMethod("unhook",function(element,eventName) { if ( element ) { var isSafari = checkSafari(); if ( !isSafari && element.removeEventListener ) { // if the browser supports the w3c model, use it element.removeEventListener( eventName, this, false ); } else if ( !isSafari && element.detachEvent ) { // if the browser supports the IE model, use it element.detachEvent( 'on' + eventName, this ); } else { // see if we've set up an array of handlers on a property of this element var arr = element["x"+eventName]; if ( arr && arr.constructor == Array ) { // remove this function from the array arr.remove( this ); } else { // just set the handler to be null, just in case element["on"+eventName] = null; } } } return this; }); // call this method in your handlers in order to cancel an event // and prevent bubbling dom.CancelEvent = function( ev ) { // if no event is passed, pull the event from the window object ev = dom.Event(ev); if ( ev ) { // this cancels the bubble in order to prevent the // event from bubbling up the dom chain // (eg: OOB script won't log link click) ev.cancelBubble = true; if ( ev.stopPropagation ) { ev.stopPropagation(); } // this sets the return value to false and stops the // default action from occurring // (eg: clicks on links won't navigate) ev.returnValue = false; if ( ev.preventDefault ) { ev.preventDefault(); } } // return false in case we want to use in an onclick property return false; }; // this function is pretty easily coded, but once it's crunched, it // will actually save a few bytes for every time it's used. dom.Event = function(ev) { return (ev ? ev : window.event); }; // this function is a shortcut for getting the browser-independent // source element from the event dom.Target = function(ev) { // typically this is done in the calling code, but just in case... ev = dom.Event(ev); // get the browser-independent target property var target = (ev.target ? ev.target : ev.srcElement); // some browsers (like Safari) might give us the actual text element // that was clicked. But we want to return an element, so if the // target isn't an element... if( target && target.nodeType != 1 ) { // get the first parent element from the tree target = dom.ParentElem( target ); } return target; }; // browser-neutral innerText method. // if the browser supports the innerText property, return it; // otherwise calculate the inner text by walking the dom nodes. dom.InnerText = function( el ) { var text = ''; //for each child of the node for (var ndx=0 ; ndx < el.childNodes.length; ndx++) { var child = el.childNodes[ndx]; if (child.nodeType == 1) { // recurse child element nodes, adding their text to the string we're building text += dom.InnerText(child); } else if (child.nodeType == 3) { // just add the value of the text nodes to the string we're building text += child.data; } } return text; }; // given an element, returns the next sibling element in the dom, // or null if there is none // if tagName is specified, it will keep looking until it finds an element of that tag name dom.NextElem = function( element, tagName ) { var nextElement = element.nextSibling; while( nextElement && (nextElement.nodeType != 1 || (tagName && nextElement.nodeName != tagName)) ) { nextElement = nextElement.nextSibling; } return nextElement; }; // given an element, returns the previous sibling element in the dom, // or null if there is none // if tagName is specified, it will keep looking until it finds an element of that tag name dom.PrevElem = function( element, tagName ) { var prevElement = element.previousSibling; while( prevElement && (prevElement.nodeType != 1 || (tagName && prevElement.nodeName != tagName)) ) { prevElement = prevElement.previousSibling; } return prevElement; }; // get the fist element up the dom tree from element. // if tagName is specified, it will keep looking until it finds an element of that tag name dom.ParentElem = function( element, tagName ) { var parentNode = element.parentNode; while( parentNode && (parentNode.nodeType != 1 || (tagName && parentNode.nodeName != tagName)) ) { parentNode = parentNode.parentNode; } return parentNode; }; // get the first child element under node parentNode. // if optional parameter, tagName, is specified, keep looking // until we find the first child with that tag name // if immediate is non-zero, only the immediate children are checked dom.ChildElem = function( parentNode, tagName, immediate ) { var element = null, childNode; // check all our child elements for(var ndx=0; !element && ndx < parentNode.childNodes.length; ++ndx) { childNode = parentNode.childNodes[ndx]; if ( childNode.nodeType == 1 ) { // child is an element. if we are not looking for a particular tag name, // or if we are and they match, then we are done if ( !tagName || childNode.nodeName == tagName ) { // save this element and pop out of the recursion element = childNode; } } } if ( !immediate ) { // now recurse each of the children if we haven't found anything yet for(ndx=0; !element && ndx < parentNode.childNodes.length; ++ndx) { // check to make sure it's an element childNode = parentNode.childNodes[ndx]; if ( childNode.nodeType == 1 ) { // it is -- recurse it element = dom.ChildElem( childNode, tagName ); } } } return element; }; // for each immediate child of the parent node // (optionally only those with the supplied tag name), // call the function provided, passing in the node as the parameter dom.ForEach = function( func, parent, tagName ) { for(var ndx = 0; ndx < parent.childNodes.length; ++ndx) { var child = parent.childNodes[ndx]; if ( child.nodeType == 1 && (!tagName || child.nodeName == tagName) ) { if ( func( child ) ) { break; } } } }; // returns the number of child elements for the given node // if nodeName is supplied, it will only count those child nodes with the given name // returns the new className for the element dom.ChildCount = function( element, nodeName ) { var count = 0; var ndx,child; for(ndx=0; ndx < element.childNodes.length; ++ndx) { child = element.childNodes[ndx]; count += (child.nodeType == 1 && (!nodeName || child.nodeName == nodeName) ? 1 : 0); } return count; } // add the specified class name to the element's list of classes // if it isn't already there dom.AddClass = function( element, className ) { // get the current classes var originalValue = element.className; if ( originalValue ) { // split on spaces (after collapsing all the whitespace) var originalClasses = originalValue.collapse().split(' '); var newClasses = className.collapse().split(' '); for( var ndx = 0; ndx < newClasses.length; ++ndx ) { var newClass = newClasses[ndx]; // if the array doesn't contain the given class name... if ( !originalClasses.contains( newClass ) ) { // add it to the end element.className += ' ' + newClass; } } } else { // nothing there now -- just set the new one element.className = className; } return element.className; }; // if the element has a class name in its class list, remove it. // returns the new className for the element dom.DelClass = function( element, className ) { // get the current classes var originalValue = element.className; // if it's blank, there's nothing to do if ( originalValue ) { // collapse all the whitespace, split on the space, and remove // the given class name from the array (if it exists) var classes = originalValue.collapse().split(' '); var oldClasses = className.collapse().split(' '); for(var ndx = 0; ndx < oldClasses.length; ++ndx) { classes.remove( oldClasses[ndx] ); } // caluclate the new value, separated with a space var newValue = classes.join(' '); // if the newvalue is different from the original value... if ( newValue != originalValue ) { // change it element.className = newValue; } } return element.className; }; // returns true if the element has the given className in its list dom.HasClass = function( element, className ) { return element.className.collapse().split(' ').contains( className ); }; // call this function whenever you update the DOM. // This function expects some other code to add an Impl function // to it for a site-specific implementation of accessibility notification. // This method is mainly provided as a stub that is always present, but can // use multiple implmentations for specific sites in the future, while allowing // other code to remain unchanged. dom.Updated = function() { // if some other code has implemented accessibility feature for the DOM... if (dom.Access && typeof dom.Access.Updated == 'function') { // let's call into it dom.Access.Updated(); } }; function checkSafari() { return (navigator.userAgent.indexOf("Safari") >= 0); } }).ns("Msn.DOM"); ///////////////////////////////////////////////////////////////////////////////// // // File: bind.js // Defines: Msn.Bind // Dependencies: base.js // Description: framework implementation of binding. // "bind" method can bind to an element reference, an array of // element references, the results of getElementsByTagName, or // a string representing a CSS selector. // // Copyright (c) 2006 by Microsoft Corporation. All rights reserved. // ///////////////////////////////////////////////////////////////////////////////// (function() { // shortcut var bind = this; // this is the binding array -- every time we create a binding, we also // add a reference to it here. The unload event is hooked to loop through // this array and call the dispose method (if it exists) on each binding. var allBindings = []; // bind an object of type, typ, to the DOM element(s) specified by // the selector, sel. Function.addMethod("bind",function( sel, args ) { var elements; switch(typeof sel) { case 'object': // could be an element or an array of elements. // if this is an element, we'll have the nodeType property and it will be 1. // if this is the document object, we'll have a nodeType property of 9. // if we are an element, create an array with the element as the one item. // if we have a length property, then assume we are some sort of array // otherwise just return null becasue we don't know what it is elements = (sel.nodeType == 1 || sel.nodeType == 9) ? [sel] : (sel.length ? sel : null); break; case 'string': // a string should be a css selector that we can // evaluate to return an array of elements elements = bind.Select( sel ); break; } if ( elements ) { // walk each element... for(var ndx = 0; ndx < elements.length; ++ndx) { var element = elements[ndx]; // create a new binding object, passing in the element we are binding to, // and the parameters object and add the binding to our reference array // so we can dispose of it during the unload event var binding = new this( element, args ); if ( element.bindings ) { element.bindings.push( binding ); } else { element.bindings = [ binding ]; } allBindings.push( binding ); } } return this; }); // unbind any existing bindings from the given element, el. // if r is true, all child elements of el are recursively unbound. bind.Unbind = function( element, recurse ) { var ndx; // if there are any bindings on this element if ( element.bindings && element.bindings.length ) { // walk the array backwards because we might decide we for(ndx=0; ndx < element.bindings.length; ++ndx) { var binding = element.bindings[ndx]; // if there is a dispose method on the binding, call it if ( binding && typeof binding.dispose == 'function' ) { binding.dispose(); } // remove from the global bindings array allBindings.remove( binding ); } // clear the array element.bindings = null; } // if we want to recursively unbind... if( recurse ) { // for each child node of this element... for(ndx=0; ndx < element.childNodes.length; ++ndx) { var child = element.childNodes[ndx]; // if the child is an element... if ( child.nodeType == 1 ) { // recurse. bind.Unbind( child, recurse ); } } } }; ///////////////////////////////////////////////////////////////////////////// // // this method takes a css-style selector and returns an array of elements // within the DOM that satisfy that criteria. // The selector should follow this pattern: // selector: simpsel [ combinator? simpsel ]* // combinator: [ '>' | '+' | ] // simpsel: element? hash? class* // element: ident // hash: '#' ident // class: '.' ident // ident: [a-zA-Z0-9-]+ // at least one of the three elements of the simpsel must be present. // ///////////////////////////////////////////////////////////////////////////// // given a css selector, returns an array of elements // within the document dom that match that selector bind.Select = function( cssSelector ) { // read an identifier from the selector at the current location function getIdentifier() { var identifier = null; if ( cssSelector ) { // an asterisk means all elements if ( cssSelector.charAt(pos) == '*' ) { identifier = '*'; } else { // loop until the end of the string. // will break out of the loop when encountering a non-identifier char while( pos < cssSelector.length ) { var ch = cssSelector.charAt( pos ); // we allow a-z, A-Z, 0-9, and a hyphen. // Underscores are not allowed. if ( ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ('0' <= ch && ch <= '9') || ch == '-' ) { // add the character to the identifier string identifier = (identifier ? identifier + ch : ch); ++pos; } else { // not a valid ident character -- we're done break; } } } } return identifier; } // skip over any whitespace at the currrent selector position function skipSpace() { while( pos < cssSelector.length && cssSelector.charAt(pos) == ' ' ) { ++pos; } } // return a simple selector combinator character, if any function getCombinator() { var combinator = null; // skip any space skipSpace(); // check the current character for an allowed combinator switch( cssSelector.charAt(pos) ) { case '+': case '>': // this is an allowed combinator combinator = cssSelector.charAt(pos); ++pos; // skip any space after the combinator skipSpace(); break; } return combinator; } // get a hash or class from the selector stream function getHashOrClass() { // skip over the # or the . character -- we don't want it ++pos; // just return the character part return getIdentifier(); } // get a simple selector from the selector stream. // return null if no selector on the stream function getSimpleSelector() { var selector = null; // see if there's an element identifier first var element = getIdentifier(); if ( element !== null ) { // there is -- create a simple selector object from it selector = new SimpSelector( element ); } // loop while we still have characters to read. // we will break out of the loop if we encounter a // character that doesn't make a simple selector while( cssSelector && pos < cssSelector.length ) { var ch = cssSelector.charAt(pos); if ( ch == '#' ) { // ids are prefaced with a hash character // if we don't already have a simple selector object, if ( !selector ) { // create it now with no element selector = new SimpSelector(); } // set the id property on the simple selector object. // there SHOULD only be a single id per simple selector // TODO: if (sel.id) error! selector.setID( getHashOrClass() ); } else if ( ch == '.' ) { // classes are prefaced with a period character // if we don't already have a simple selector object, if ( !selector ) { selector = new SimpSelector(); } // add the class to the simple selector. // add the class to the simple selector. There can be multiple // per simple selector selector.addClass( getHashOrClass() ); } else { // unexpected character; break out of the loop break; } } return selector; } // get the full, complex selector, represented as an array of // simple selector objects. function getSelectors() { // initially empty array var selectors = []; // get the first selector (if any) var simpleSelector = getSimpleSelector(); if ( simpleSelector ) { // add the simple selector to the array selectors.push(simpleSelector); // loop while we still have characters in the selector stream. // we will break out when we can no longer find a simple selector while( pos < cssSelector.length ) { // check for a combinator var combinator = getCombinator(); // get the next simple selector simpleSelector = getSimpleSelector(); if ( simpleSelector ) { // if there was a combinator before this selector, if ( combinator ) { // add the combinator to the new selector's properties simpleSelector.setComb( combinator ); } // push the new selector onto the array selectors.push( simpleSelector ); } else { // no more simple selectors; bail // TODO: if (comb) error! break; } } } return selectors; } // simple selector object // element? [ hash | class ]* // there can be multiple classes for each simple selector, // but there really should only be one id function SimpSelector( element ) { // shortcut var simp = this; // fields var id = ''; var combinator = null; var classes = null; // method to set the id for this selector simp.setID = function(idValue) { id = idValue; }; // set the combinator simp.setComb = function(comb) { combinator = comb; }; // add a class to the array simp.addClass = function( className ) { if ( classes ) { // push the new class to the end of the existing array classes.push( className ); } else { // no class array yet; add this first class in a new array classes = [ className ]; } }; // return a list of nodes under parent that match this simple selector simp.getNodes = function( parent ) { var ndx, node, nextElement, nodeList = []; if ( id ) { // there's an id -- only one node is possible switch ( combinator ) { case '>': // we only want to check the direct children for(ndx=0; ndx < parent.childNodes.length; ++ndx) { // if the child is an element, and the id matched what we're looking for... if ( parent.childNodes[ndx].nodeType == 1 && parent.childNodes[ndx].id == id ) { // we'll save this element for further tests (element and class) node = parent.childNodes[ndx]; break; } } break; case '+': // we only want the next sibling node nextElement = getNextElement( parent ); // and it has to match the desired id if ( nextElement && nextElement.id == id ) { // save this element for further tests (element and class) node = nextElement; } break; default: // any child anywhere under the parent node = parent.getElementById( id ); break; } // if there is a specified element and it's not a star wildcard, it must match // (convert to lower-case, because nodeName is in upper-case for some weird reason). // and the classes must match. if ( node && (!element || element == '*' || element.toLowerCase() == node.nodeName.toLowerCase()) && checkClasses(node) ) { // this is a selected node; add it to the array nodeList.push( node ); } } else if ( element && element != '*' ) { // no id, but there is a specific element we're after switch( combinator ) { case '>': // we only want direct children for(ndx=0; ndx < parent.childNodes.length; ++ndx) { node = parent.childNodes[ndx]; // which match our tag names and our classes if ( node.nodeType == 1 && node.nodeName.toLowerCase() == element && checkClasses(node) ) { // this node is selected nodeList.push( node ); } } break; case '+': // just the next sibling nextElement = getNextElement( parent ); // and only if the tag name matches and the classes check out if ( nextElement && nextElement.nodeName.toLowerCase() == element && checkClasses(nextElement) ) { // this node is selected nodeList.push( nextElement ); } break; default: // any subelements at any depth var elements = parent.getElementsByTagName( element ); // test the classes on each one, adding matching elements to the selected array for( ndx = 0; ndx < elements.length; ++ndx ) { if ( checkClasses(elements[ndx]) ) { nodeList.push( elements[ndx] ); } } break; } } else { // no id and no element, just a class. switch( combinator ) { case '>': // we only want direct children for(ndx=0; ndx < parent.childNodes.length; ++ndx) { node = parent.childNodes[ndx]; // which match our tag names if ( node.nodeType == 1 && checkClasses(node) ) { nodeList.push( node ); } } break; case '+': // just the next sibling nextElement = getNextElement( parent ); // and only if the tag name matches if ( nextElement && checkClasses(nextElement) ) { nodeList.push( nextElement ); } break; default: // easiest just to recursively walk the dom node tree // looking for nodes that match our desired classes checkNodeClasses( parent, nodeList ); break; } } return nodeList; }; function checkNodeClasses( parent, nodes ) { // for each child node.... for( var ndx=0; ndx < parent.childNodes.length; ++ndx ) { var node = parent.childNodes[ndx]; // if this is an element node... if ( node.nodeType == 1 ) { // if the classes check out, then add it to the match list if ( checkClasses(node) ) { nodes.push( node ); } // recursively walk this element node checkNodeClasses( node, nodes ); } } } function checkClasses( element ) { var okay = 1; if ( classes ) { var className = element.className; if ( className ) { // make an array of which classes we have on the node var classNames = className.collapse().split(' '); // each class we want to match must be available or we're not okay for(var ndx=0; ndx < classes.length; ++ndx) { // if the available class array doesn't contain the wanted class... if ( !classNames.contains(classes[ndx]) ) { // then the check fails okay = 0; break; } } } else { // matching classes, but none on the node okay = 0; } } return okay; } } // take the array of elements and apply the given simple selector to // return another array of elements function applySelector( elements, simpleSelector ) { // initially empty array var matchedElements = []; // for each element in the source list... for(var ndx = 0; ndx < elements.length; ++ndx) { // add the elements selected by the selector on this element matchedElements = matchedElements.concat( simpleSelector.getNodes( elements[ndx] ) ); } return matchedElements; } // start at the beginning of the selector var pos = 0; // get the array of simple selectors from the selector string var sels = getSelectors(); // initially we'll start with the entire document var elements = [document]; // for each simple selector, we'll apply the selector to the current list // of elements, then apply the next selector on the results, etc. for(var ndx = 0; ndx < sels.length && elements.length > 0; ++ndx) { elements = applySelector( elements, sels[ndx] ); } return elements; }; // given an element, returns the next sibling element in the dom, // or null if there is none function getNextElement( element ) { var nextElement = element.nextSibling; while( nextElement && nextElement.nodeType != 1 ) { nextElement = nextElement.nextSibling; } return nextElement; } ///////////////////////////////////////////////////////////////////////////// // // this function is automatically hooked into the unload event of the window // to handle calling the dispose method of all our bindings // ///////////////////////////////////////////////////////////////////////////// // this function walks through all the bindings we may have // on our page and calls the dispose method (if there is one). (function() { // make sure all elements are unbound bind.Unbind( document, 1 ); // make sure the global bindings are empty allBindings = []; }).hook(window,"unload"); }).ns("Msn.Bind"); ///////////////////////////////////////////////////////////////////////////////// // // File: header.js // Defines: Msn.Header // Dependencies: base.js bind.js dom.js // Description: implements the javascript routines for the header // // Copyright (c) 2006 by Microsoft Corporation. All rights reserved. // ///////////////////////////////////////////////////////////////////////////////// (function(el, args) { if ( !args ) { args = {}; } var dom = Msn.DOM; var d = document; var w = window; //hide the network navigation more links var elMoreDIV = d.getElementById( "more" ); // div containing network navigation links elMoreDIV.style.display = "none"; //create more Link var elMoreUL = d.getElementById( "xnav" ); var elMoreLI = d.createElement( "li" ); var elMoreA = d.createElement( "a" ); elMoreA.href = "#"; elMoreA.className = "expand"; elMoreA.innerHTML = argWithDefault(args.more,"more"); elMoreLI.appendChild( elMoreA ); elMoreUL.appendChild( elMoreLI ); //bind toggle function to click event of more link toggle.hook(elMoreA, "click"); // click event for more link, toggles display of cross-network navigation div function toggle(ev) { var state = elMoreDIV.style.display; var expand; if (state == "block") { state = "none"; expand = "expand"; elMoreLI.className = ""; } else { state = "block"; expand = "collapse"; elMoreLI.className = "last"; } elMoreDIV.style.display = state; elMoreA.className = expand; ev = dom.Event(ev); return dom.CancelEvent( ev ); } this.dispose = function() { el = null; elMoreDIV = null; elMoreUL = null; elMoreLI = null; elMoreA = null; }; function argWithDefault( arg, def ) { return (typeof arg != "undefined" ? arg : def) } }).as("Msn.Header"); (function(el, args) { if (!args) { args = {}; } //shortcuts var dom = Msn.DOM; var d = document; var w = window; var form = el; //Init variables from args var siteSearchOn = argWithDefault(args.siteSearchOn, "false"); var searchUrl = argWithDefault(args.searchUrl, ""); var searchParam = argWithDefault(args.searchParam, ""); var searchParams = argWithDefault(args.searchParams, ""); var drpButtonImgURL = argWithDefault(args.drpButtonImgURL, "decoration/dropdownButton_FOX.gif"); var drpButtonMouseoverImgURL = argWithDefault(args.drpButtonOverImgURL, "decoration/dropdownButton_over_FOX.gif"); var siteText = argWithDefault(args.sitetext, "Search this site"); var scopesDiv = d.getElementById("ntwscopes"); //if site search not enabled, scope default to web var scope = siteSearchOn == "true" ? "site" : "web"; //create scope tabs if sitesearch is on if (scope == "site") { createScopeDropdown(); } //IE 6 png treatment var onepxgif = argWithDefault(args.onepxgif, "http://blstc.msn.com/br/gbl/css/8/decoration/t.gif"); var nav = navigator.userAgent, index = nav.indexOf("MSIE"); if (index >= 0) { // we have MSIE in the user agent string. parse the float value // immediately following it. if (parseFloat(nav.substring(index + 4)) < 7 && parseFloat(nav.substring(index + 4)) > 5) { pngfix(d.getElementById("leftcorner"), "bgimage", "image"); pngfix(d.getElementById("searchform"), "bgimage", "scale"); pngfix(d.getElementById("ntwlogo"), "bgimage", "scale"); pngfix(d.getElementById("logoimg"), "img", "image"); pngfix(d.getElementById("rightcorner"), "bgimage", "image"); } } // pointer to dom objects var elSitesearchDiv; var elSiteLink; var elWebLink; var elWebDiv; var elSpyglass = d.getElementById("spyglass"); if (scope == "site") { elSpyglass.alt = "Site"; } var elSearchText = d.getElementById("q"); var elDrpButton; var elScopesContainer; var scopeClicked = false; // boolean used to check whether the elDrpButton's blur event is caused by clicking on scopes //some varaible to use in functions var searchTerm = ""; var helperText = (scope == "web") ? argWithDefault(args.helpertext, "") : siteText; elSearchText.className = ""; elSearchText.value = helperText; //set the inputbox to helpertext. //hook up events doSpyglass.hook(elSpyglass, "click"); focusTxtbox.hook(elSearchText, "focus"); blurTxtbox.hook(elSearchText, "blur"); var formOnSubmit = form.onsubmit; //grab onsubmit function form.onsubmit = function() { if (elSearchText.value == helperText) { elSearchText.value = ""; } return formOnSubmit(form); }; // When more than one input type=submit is present, IE processes enter as a click to the // web search button, not the site search button. We hook doEnter to the keypress event to correct. doEnter.hook(elSearchText, "keypress"); function createScopeDropdown() { elDrpButton = d.createElement("input"); elDrpButton.type = "image"; elDrpButton.id = "drpbutton"; elDrpButton.src = drpButtonImgURL; d.getElementById("searchform").style.width = "300px"; //hard code the width here because we don't want to have this button rendered when js is disabled. d.getElementById("searchform").appendChild(elDrpButton); var webText = argWithDefault(args.webtext, "Search web"); elScopesContainer = d.createElement("div"); elScopesContainer.className = "scopescontainer"; // IE6 need this extra container to render correctly when collapsed. elScopesContainer.style.display = "none" elSitesearchDiv = d.createElement("div"); elSitesearchDiv.className = "selected"; elSiteLink = d.createElement("a"); elSiteLink.innerHTML = siteText; elSiteLink.href = searchUrl; elSitesearchDiv.appendChild(elSiteLink); elWebDiv = d.createElement("div"); elWebLink = d.createElement("a"); elWebLink.innerHTML = webText; elWebLink.href = form.action; elWebDiv.appendChild(elWebLink); scopesDiv.appendChild(elScopesContainer); elScopesContainer.appendChild(elSitesearchDiv); elScopesContainer.appendChild(elWebDiv); //hookup events doDrpButtonMouseover.hook(elDrpButton, "mouseover"); doDrpButtonMouseout.hook(elDrpButton, "mouseout"); doDrpButtonBlur.hook(elDrpButton, "blur"); doDrpButton.hook(elDrpButton, "click"); doSiteSearch.hook(elSiteLink, "click"); doWebSearch.hook(elWebLink, "click"); } function pngfix(elem, mode, method) { if (!elem) return; var imagesrc; if (mode == "bgimage") { imagesrc = elem.currentStyle.backgroundImage; } else if (mode == "img") { imagesrc = elem.src; } if (imagesrc == "") return; var pngsrc = imagesrc.search(new RegExp('(http://.+\\.png)', 'i')) === -1 ? "" : RegExp.$1; if (pngsrc.length > 0) { if (mode == "bgimage") { elem.style.backgroundImage = "none"; } else if (mode == "img") { elem.src = onepxgif; } elem.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod='" + method + "', src='" + pngsrc + "')"; } } function doDrpButtonMouseover(ev) { elDrpButton.src = drpButtonMouseoverImgURL; } function doDrpButtonMouseout(ev) { elDrpButton.src = drpButtonImgURL; } function doDrpButtonBlur(ev) { setTimeout( //need to settimeout so we can check the blur is actually coming from clicking scopes links in the scope options dropdown. function() { if (!scopeClicked) { elScopesContainer.style.display = "none"; } } , 500); } function doDrpButton(ev) { if (elScopesContainer.style.display == "none") { elScopesContainer.style.display = "block"; } else { elScopesContainer.style.display = "none"; } if (dom.Target(ev) == elDrpButton) { ev = dom.Event(ev); return dom.CancelEvent(ev); //need to cancel event to stop form submission } } function doEnter(ev) { if (ev.keyCode == 13) { switch (scope) { //Use switch for more tabs in the future //Do not need t a case for web, since it textbox in the form default to submit when enter. case "site": doSiteSearch(null); ev = dom.Event(ev); return dom.CancelEvent(ev); //need to cancel event to stop form submission break; } } } function doSiteSearch(ev) { if (ev) scopeClicked = true; var url = searchUrl + "?" + searchParam + "=" + getSearchTerm(); if (searchParams) { url = url + "&" + searchParams.replace(/&/g, "&"); } if (ev && dom.Target(ev).tagName.toLowerCase() == "a") { dom.Target(ev).href = url; //set href with search term, so omniture linktrack will have search term tracked. } else { window.top.location.href = url; //for doSiteSearch(null) to work } } function doWebSearch(ev) { if (ev !== null) { scopeClicked = true; if (dom.Target(ev).tagName.toLowerCase() == "a") { dom.Target(ev).href = "#"; } } if (elSearchText.value == helperText) { elSearchText.value = ""; } formOnSubmit(form); form.submit(); } function getSearchTerm() { searchTerm = elSearchText ? elSearchText.value : ""; searchTerm = (searchTerm == helperText) ? "" : searchTerm; return encodeURIComponent(searchTerm); } function doSpyglass(ev) { switch (scope) { case "site": form.onsubmit = cancelSubmit; //cancel form submit, doSiteSearch instead. doSiteSearch(null); break; case "web": doWebSearch(null); break; } } function cancelSubmit(ev) { ev = dom.Event(ev); return dom.CancelEvent(ev); } function focusTxtbox(ev) { elSearchText.className = "typing"; if (elSearchText.value == helperText) elSearchText.value = ""; } function blurTxtbox(ev) { if (elSearchText.value.trim() == "") { elSearchText.className = ""; elSearchText.value = helperText; } } this.dispose = function() { //unhook events to avoid MM leak if (scope = "site") { doSiteSearch.unhook(elSiteLink, "click"); doWebSearch.unhook(elWebLink, "click"); } doSpyglass.unhook(elSpyglass, "click"); focusTxtbox.unhook(elSearchText, "focus"); blurTxtbox.unhook(elSearchText, "blur"); doEnter.unhook(elSearchText, "keypress"); doDrpButtonMouseover.unhook(elDrpButton, "mouseover"); doDrpButtonMouseout.unhook(elDrpButton, "mouseout"); doDrpButtonBlur.unhook(elDrpButton, "blur"); doDrpButton.unhook(elDrpButton, "click"); form.onsubmit = null; el = null; }; //helper function function argWithDefault(arg, def) { return (typeof arg != "undefined" ? arg : def) } }).as("Msn.SiteSearch"); /* End: MSN Search Header (FSCOM-4763) */ Msn.SiteSearch.bind("#search", { searchParam: "sp_q", searchParams: "", searchUrl: "http://msn.foxsports.com/search", sitetext: "Search FOX Sports", webtext: "Search web", siteSearchOn: "true", helpertext: "", onepxgif: "http://blstc.msn.com/br//gbl/css/9/decoration/t.gif", drpButtonImgURL: "http://msn.foxsports.com/fe/img/MSN/Header/Search/dropdownButton_FOX.gif", drpButtonOverImgURL: "http://msn.foxsports.com/fe/img/MSN/Header/Search/dropdownButton_over_FOX.gif" });