/*! * KachingleX Browser Extension * (C) Copyright 2010, 2011, 2012 Kachingle Inc. * All Rights Reserved * Proprietary * */ // Use window.kachingle_site_id to decide whether this code is being run via embedded script element or via browser extension. // Embedded script: kachingle_site_id should have a value; invoke function kachingle_x() immediately from here, using that value. // Browser extension: kachingle_site_id should have no value; do nothing here and let the other KX code invoke it. // Chr/Saf: KX can't even access kachingle_site_id, so even if embed code sets it, KX will always get undefined, evaluates false, as desired. // FF: In KX, "window" points to the XUL window, unlike the embed code where it points to the document window! So even if embed // code sets window.kachingle_site_id, KX finds it undefined, evaluates false, as desired. (Also in KX FF, this code is only loaded and // executed once, when KX is initialized -- not once for each page!) // IE: KX can see kachingle_site_id. Undefined if no embed code present; if present, KX would get that value, so embed code must turn it off. if (window.kachingle_site_id) (function(){ var data = { site_id: kachingle_site_id, news_msg_txt: "Click to kachingle", news_msg_url: "", server_base_domain: kachingle_domain }; // Turn off the trigger so that if KX (IE) sees that page it doesn't do this a 2nd time. kachingle_site_id = null; // Trigger the medallion insertion immediately. kachingle_x(document, "embedded", data); })(); function kx_get_url(doc){ var url = doc.URL; // YouTube: get the address of the channel owner if (doc.domain == "www.youtube.com") { // New way, see if it works var usertag = doc.getElementById("watch-uploader-info"); if (usertag) { var atags = usertag.getElementsByTagName("a"); if (atags.length == 0) usertag = null; else usertag = atags[0]; } if (!usertag) { // Try old way. Still works for userbanner, but probably not for username var usertag = doc.getElementById("watch-userbanner") || doc.getElementById("watch-username"); } if (usertag && usertag.href) url = usertag.href; } // Remove the protocol part (http and https only) return url.replace(/https?:\/\//, ""); } // Return null if not on a kachingle page or no cookie; cookie content if there is one function kx_domain_cookie(doc){ if (doc.domain && is_kachingle(doc.domain)) { // Based on http://www.w3schools.com/js/js_cookies.asp var i, cookie_name, cookie_val, // doc.cookie contains all the cookies for this page ARRcookies=doc.cookie.split(";"); // find the right one, in the form "cookie_name=cookie_val" for (i=0;i 0 // has a revb medallion || doc.getElementById('kMedallionContainer'); // has a pre-revb medallion host_substitute_gEBCN.restore(); } // Uncomment these temporarily to use for testing: // data.news_msg_txt = "This is where we will tell KX IE users to upgrade to the latest version!"; // data.news_msg_url = "#"; if (data.site_id) { if (pg_has_medallion) special_embedded_actions(); else place_medallion_and_msg(data); } if (is_kachingle(doc.domain)) send_signal(browser); // And that's all! /***** Functions *****/ // Put something in the page so that kachingle pages can tell this extension is installed. function send_signal(browser){ // In case we ever use this to embed bar on our own site: if (browser == "embedded") return; // do nothing // First way is required for IE (because IE can't do innerHTML on a script); // second way is required for Firefox, Chrome, and Safari because no direct access to the in-page function; if (browser == "IE") { // We have direct access to the function, if it's there if (typeof window.kachinglex_is_present == 'function') kachinglex_is_present(); } else { // We are executing in the chrome, not in the page (Firefox); // or in the page but in an "isolated world" (Chrome & Safari); // Make a little script var sc = doc.createElement('script'); sc.type = "text/javascript"; sc.innerHTML = "if (typeof window.kachinglex_is_present == 'function') kachinglex_is_present();"; // Put it in the page -- thereby calling the function from within the document. doc.body.appendChild(sc); } } // Utility functions for cross-browser compatibility // el: reference to the element // property: string in the JS camel-case form: "paddingTop" // Note, may not work for all properties. Test this out for each one. // (Known example: "backgroundImage" normally works, but not on the element in FF 3.6) function get_style(el, property){ if (el.currentStyle) // IE 8 and below return el.currentStyle[property]; else if (doc.defaultView.getComputedStyle) // everything else return doc.defaultView.getComputedStyle(el, null)[property]; // if not found, returns null or "" depending on the browser } function get_style_val(el, property){ return parseInt(get_style(el, property)) || 0; // if no value retrieved, return 0 instead of NaN } function place_medallion_and_msg(data){ var siteID = data.site_id; var target_container = get_target_container(siteID); var medallion_height = 21; // pixel height of K4 bar medallion /* Make a header */ var header = doc.createElement('div'); header.style.width = "100%"; header.style.margin = "0px"; header.style.padding = "0px"; // header.style.backgroundColor = "#640096"; // Kachingle purple, to view while the medallion is loading // Suppress host page styles header.style.border = "none"; header.style.backgroundImage = "none"; header.style.boxShadow = "0 0 0"; header.style.mozBoxShadow = "0 0 0"; header.style.webkitBoxShadow = "0 0 0"; header.style.position = "static"; header.style.top = "0px"; // pixels for our medallion and surrounding div; depends on the above // (in K4, surrounding div no longer contains extra space, so banner and medallion are now the same) var banner_height = medallion_height; header.style.height = banner_height + 'px'; /* Not sure, but I think that with the new method of interpolating an additional abs-positioned div, we may not need this anymore. // header gets between the first page element and the whitespace above. // So gather up all the target_container whitespace, and put it in header margin-bottom instead. // (But if using a non-standard target_container, probably have to handle it as a special case.) if (target_container == doc.body) { var whitespace_px = get_style_val(doc.body, "paddingTop") + get_style_val(doc.body, "marginTop") + get_style_val(doc.documentElement, "paddingTop") + get_style_val(doc.documentElement, "marginTop"); if (whitespace_px) { header.style.marginBottom = whitespace_px + "px"; doc.body.style.paddingTop = '0px'; doc.body.style.marginTop = '0px'; doc.documentElement.style.paddingTop = '0px'; doc.documentElement.style.marginTop = '0px'; } } */ var abs_header = insert_medallion_html(siteID, header, medallion_height); if (data.news_msg_txt) insert_message(data, abs_header, banner_height); // Stick it into the DOM target_container.insertBefore(header, target_container.firstChild); // Sticking stuff in the DOM is actually kind of complicated!... adjust_special_cases(siteID, banner_height, header, abs_header); // embedded may have to be at the bottom in these cases! Or wait // for an element to appear! // Inject the script. // Because of IE, must inject medallion script into the DOM separately, not entire structure at // once (medallion html plus script inside a wrapper). Otherwise in IE the script is not able to // discover either its own script tag or the html elements, whose attributes it needs to see. // I assumed at first I needed to timeout and let the html render first: // setTimeout(function(){insert_medallion_script(doc);}, 10); // But apparently not; just doing two separate DOM insertions is good enough: insert_medallion_script(data.server_base_domain); } function insert_medallion_html(siteID, wrapper, medallion_height){ // Make an absolute-positioned wrapper so we can really put it where we want it; outer wrapper // is static so can't fully avoid margin and padding on the html and body elements; this can. var abs_wrapper = doc.createElement('div'); abs_wrapper.style.position = "absolute"; abs_wrapper.style.top = "0px"; abs_wrapper.style.left = "0px"; abs_wrapper.style.width = "100%"; abs_wrapper.style.height = medallion_height + 'px'; abs_wrapper.style.backgroundColor = "#640096"; // Kachingle purple, to view while the medallion is loading abs_wrapper.style.margin = "0px"; abs_wrapper.style.padding = "0px"; abs_wrapper.style.border = "none"; abs_wrapper.style.backgroundImage = "none"; abs_wrapper.style.boxShadow = "0 0 0"; abs_wrapper.style.mozBoxShadow = "0 0 0"; abs_wrapper.style.webkitBoxShadow = "0 0 0"; wrapper.appendChild(abs_wrapper); // Make the container - the medallion proper var container = doc.createElement('div'); container.className = 'kmedallioncontainer'; container.style.height = medallion_height + 'px'; abs_wrapper.appendChild(container); // Make the iframe var iframe = doc.createElement('iframe'); iframe.setAttribute('site', siteID); iframe.setAttribute('stylename', 'bar'); iframe.style.display = 'none'; iframe.setAttribute('scrolling', 'no'); iframe.setAttribute('frameborder', '0'); container.appendChild(iframe); return abs_wrapper; // because we need to tweak this sometimes, too } function insert_medallion_script(server_base_domain){ // Make the script part, that loads kachingle_controls. // Normal medallion uses window.location.protocol, but this would not work in // Firefox, since "window" is the chrome, not the content. Get it from doc.URL instead. if (server_base_domain == "kachingle.com") { // production: var _protocol = 'http'+(doc.URL.substr(0,5) == 'https' ? 's' : ''); var filename = '/kachingle_controls_revb.js'; } else { // dev envs (warning will occur on https pages): var _protocol = 'http'; var filename = '/kachingle_controls_revb_source.js'; } var sc = doc.createElement('script'); sc.type = "text/javascript"; sc.src = _protocol + "://medallion." + server_base_domain + filename; doc.body.appendChild(sc); } function insert_message(data, wrapper, wrapper_height){ var container = doc.createElement('div'); var msg; if (data.news_msg_url) { // it's a link msg = doc.createElement('a'); msg.href = data.news_msg_url; } else { // it's plain text msg = doc.createElement('span'); } msg.innerHTML = data.news_msg_txt; container.appendChild(msg); // Style the text. Since this is not inside the iframe, have to override host page settings! Forgetting anything? // To do :visited and :hover, would need stylesheet, don't think it can be done in JS except with event handlers. msg.style.color = "white"; msg.style.verticalAlign = "baseline"; msg.style.font = "normal normal normal 12px sans-serif"; if (data.news_msg_url) { // it's a link msg.style.textDecoration = "underline"; msg.style.cursor = "pointer"; } else { // it's plain text msg.style.textDecoration = "none"; msg.style.cursor = "text"; } // Suppress host page styles container.style.border = "none"; container.style.padding = "0px"; container.style.backgroundColor = "transparent"; container.style.backgroundImage = "none"; container.style.fontSize = "13px"; container.style.boxShadow = "0 0 0"; container.style.mozBoxShadow = "0 0 0"; container.style.webkitBoxShadow = "0 0 0"; container.style.textAlign = "right"; // Position over right edge of medallion // wrapper.style.position = "relative"; // (removed when switched to having abs-positioned wrapper) container.style.position = "absolute"; container.style.top = "0px"; container.style.right = "20px"; container.style.paddingTop = "2px"; // Suppress mouseover by getting completely in front of it container.style.zIndex = 1; container.style.height = wrapper_height + "px"; // Note: with clickable bar medallion, plain text messages (but not links) need to be inside the medallion // container, behind the transparent div that intercepts the mouse actions, instead of superimposed over the // whole thing. I could conceivably put it there. However, the clickable bar needs to work with the KX that // existed at the time, v. 2.0.9, which puts it in front. So I changed kachingle_controls to find the element // and, if it is plain text, move it from in front, into the correct position. (So continue to put it in front. // And now the mouseover suppression is not needed for plain text, but is harmless and is still needed for links.) wrapper.appendChild(container); } /***** Site-specific *****/ function get_target_container(siteID){ var tc = null; var d = doc.domain; /* if need to place medallion more deeply nested, change value of tc */ if (d == "www.baycitizen.org") tc = doc.getElementById("hd"); else if (domain_is(d, "stackoverflow.com|stackapps.com|stackexchange.com|serverfault.com|superuser.com|blogoverflow.com|askubuntu.com") && doc.getElementById("notify--1") && get_style(doc.getElementById("notify-container"), "position") == "fixed") tc = doc.getElementById("notify-container"); else if (d == "www.thisamericanlife.org") tc = doc.getElementById("header"); else if (d == "www.pandora.com") tc = doc.getElementById("topnav"); /* // Tried this in Chrome, good try, didn't work -- same domain permission problem? -- this probably could work // by sending a request back to the global page to get this info. I bet it would work as is, in FF and IE. // No time to work on this, though. else if (d == "translate.google.com" && doc.body.tagName == "FRAMESET") { doc = doc.body.getElementsByTagName("frame")[1].contentWindow.document; tc = doc.body; } */ // doc.body unless we looked for a different target... and found it. return tc || doc.body; } function special_embedded_actions(){ if (domain_is(doc.domain, "clpmag.org")) { // embedded jazz wrapped in invisible div suppresses KX bar, so make jazz visible instead. var el = doc.getElementById("___plusone_0"); if (el && el.parentNode) { var sib_divs = el.parentNode.getElementsByTagName("div"); if (sib_divs.length > 1) sib_divs[1].style.display = "inline-block"; } } } // Identify special cases that need formatting fixes function adjust_special_cases(siteID, height_offset, header, abs_header){ var d = doc.domain; var b = doc.body; var s = siteID; var scroll_bkg = true; var el; // to use for elements if (d == "www.huffingtonpost.com") { abs_id("close_button"); abs_id("install_button"); } else if (domain_is(d, "posterous.com")) { // Looks like *all* posterous blogs have this: abs_id("posterous_required_header"); // But the rest looks totally open-ended: var subd = d.slice(0, -14); if (subd == "steveouting"){ abs_id("frame"); abs_id("pbar"); bring_medallion_to_front(); } } // tumblr sites (not all have tumblr URLs; "tumblr.com" gets all the ones that do) // known tumblr URLs: plazadearmastx.tumblr.com, fastcompany.tumblr.com, watchtheguild.tumblr.com else if (domain_is(d, "tumblr.com|agentmlovestacos.com|blog.milkandcookies.com|blog.fastcompany.com")) { abs_id("install-theme"); abs_id("tumblr_controls"); } else if (d == "tardis.wikia.com") bring_medallion_to_front(); else if (d == "blog.wikimedia.org") { // This is different from all the other wikimedia sites below abs_id("column-one"); abs_id("topsearch"); } else if (domain_is(d, "wikipedia.org|wikimedia.org|wikimediafoundation.org|wiktionary.org|wikiquote.org|" + "wikisource.org|wikinews.org|wikiversity.org|mediawiki.org")) { // all language subdomains! abs_id("mw-panel"); abs_id("mw-head"); } else if (domain_is(d, "stumbleupon.com")) { el = doc.getElementById("wrapperPanel"); if (el) el.style.top = "0"; } else if (d == "www.blogger.com") { // the app bring_medallion_to_front(); abs_id("titles"); } else if (domain_is(d, "blogspot.com")) { // the blogs abs_id("navbar-iframe"); if (d == "casualkitchen.blogspot.com") abs_id("background-dish"); // else if (d == "estoniancooking.blogspot.com") // This used to have exactly the same template and problem as tranquillitas.com, until they redesigned } else if (d == "www.tranquillitas.com") { el = doc.getElementById("search"); if (el) { el = el.parentNode; el.style.top = "0px"; } el = doc.getElementById("views"); if (el) avoid_fixed_nav_bar(el.parentNode); // Even though it's actually absolute (until you scroll it!) } else if (domain_is(d, "spiegel.de")) { abs_id("qcFrameColour"); abs_id("qcSuperLayer"); abs_id("qcSkyLayer"); abs_id("eyeDiv"); abs_id("ftdiv255509"); //abs_id("ftotdftdivid_200600"); // can't fix because dynamically repositioned, so: bring_medallion_to_front(); } else if (d == "chrome.angrybirds.com") { b.style.WebkitBoxOrient = "vertical"; b.style.WebkitBoxPack = "start"; b.style.MozBoxOrient = "vertical"; b.style.MozBoxPack = "start"; b.style.MozBoxAlign = "stretch"; b.style.boxOrient = "vertical"; b.style.boxPack = "start"; } else if (domain_is(d, "google.com")) { /* (This version worked. But turns out, have to do over and over, so cannot do it this way.) // in translate, these are abs with no positioned offsetParent, need the adjustment; // in maps, ditto on some pages, but on other pages have an offsetParent with posn relative and *don't* need it if (parents_are_static("gb")) { abs_id("gbz"); abs_id("gbg"); abs_id("gbx3"); abs_id("gbx4"); } if (parents_are_static("loadmessagehtml")) { abs_id("loadmessagehtml"); abs_id("errormessagehtml"); } if (parents_are_static("jsts")) // not created until later, dynamically, so this fails. May not matter. abs_id("jsts"); */ (function googlefix(){ var offset = parents_are_static("gb") ? height_offset : 0; set_absolute("gbz", offset); set_absolute("gbg", offset); set_absolute("gbx3", offset); set_absolute("gbx4", offset); offset = parents_are_static("loadmessagehtml") ? height_offset : 0; set_absolute("loadmessagehtml", offset); set_absolute("errormessagehtml", offset); offset = parents_are_static("jsts") ? height_offset : 0; set_absolute("jsts", offset); setTimeout(googlefix, 100); })(); } else if (d == "www.baycitizen.org") avoid_fixed_nav_bar("top-blue"); else if (d == "www.thisamericanlife.org") abs_header.style.position = "static"; else if (d == "carta.info") { if (browser == "Chrome" || browser == "Safari") // KX unfixably broken in this case, but works fine in other browsers header.style.display = "none"; } else if (domain_is(d, "virtualtrials.com|virtualtrials.org")) { (function virtualtrialsfix(){ el = doc.getElementById("SM1"); if (el) { el = el.parentNode; if (el.offsetTop > 0) // have to wait until this element settles down before fixing it! setTimeout(virtualtrialsfix, 25); else abs_element(el); } })(); } else if (domain_is(d, "stackoverflow.com|stackapps.com|stackexchange.com|serverfault.com|superuser.com|blogoverflow.com|askubuntu.com") && doc.getElementById("notify--1") && get_style(doc.getElementById("notify-container"), "position") == "fixed") { abs_header.style.position = "static"; if (d != "photo.stackexchange.com") scroll_bkg = false; (function stackfix(){ // This has to be absolute 51 rather than "add height_offset to current value" because... doc.body.style.marginTop = "51px"; if (d == "photo.stackexchange.com") doc.body.style.paddingTop = height_offset + "px"; // ...they seem to keep fiddling with it: setTimeout(stackfix, 1000); })(); } else if (domain_is(d, "myspace.com")) // browser bar shows www, but doc.domain does not! avoid_fixed_nav_bar("globalHeader"); else if (d == "www.thegap.at") // (only for pages that don't have the embedded one: clubkultur abs_id("scheisstapetn"); else if (domain_is(d, "thepiratebay.(org|se)")) abs_id("topright"); else if (d == "www.occupyoakland.org") { // Totally invisible element (probably there for screen readers) interfering with bar, just bump it down. el = doc.getElementById("logo").getElementsByTagName("a")[0]; if (el) el.style.top = "-20px"; // instead of -40 } else if (domain_is(d, "mercurynews.com")) { // two abs elements to fix have no id; but can find them from this one: el = doc.getElementById("userbar"); if (el) { el = el.parentNode; // #1 to fix if (el) { abs_element(el); el = el.nextSibling; // next div is #2 to fix while (el && el.nodeName != "DIV") { el = el.nextSibling; } abs_element(el); } } // homepage has different problem than article pages! Also an abs element with no id: el = doc.getElementById("navWrap"); // we want the div previous to this one if (el) { el = el.previousSibling; while (el && el.nodeName != "DIV") { el = el.previousSibling; } } abs_element(el); } else if (d == "22gigantes.com") { // Whoops there is no id; have to find the element: abs_id(""); el = doc.getElementById("ViperBar_main"); if (el) { el = el.nextSibling; // find next iframe while (el && el.nodeName != "IFRAME") el = el.nextSibling; abs_element(el); } } else if (d == "www.gog.com") { // only the homepage has these issues el = doc.getElementById("big_spot_navigation_title"); if (el && el.parentNode) abs_element(el.parentNode); el = doc.getElementById("loginHolder"); if (el) { el = el.previousSibling; // find the div above while (el && el.nodeName != "DIV") el = el.previousSibling; abs_element(el); } } else if (domain_is(d, "picnik.com")) { (function picnikfix(){ // Wait for these to appear. (Note that on homepage they *won't* appear, so this will // run over and over. But once you get into the app ("Start Picniking"), you have to do this.) if (!doc.getElementById("flashcontent") || !doc.getElementById("ifrmPicnikAlt")) setTimeout(picnikfix, 100); else { abs_id("flashcontent"); abs_id("ifrmPicnikAlt"); abs_id("ifrmLeaderboard"); } })(); } else if (d == "www.theonion.com") { doc.getElementById("topnav").style.top = "0px"; avoid_fixed_nav_bar("topnav"); } else if (d == "www.collegehumor.com") { doc.getElementById("site-top").style.top = "0px"; avoid_fixed_nav_bar("site-top"); } else if (d == "www.fastcompany.com") abs_id("usertoolbar"); else if (d == "www.watchtheguild.com") { abs_id("videoBG"); abs_id("fold"); } else if (domain_is(d, "mysql.com")) { abs_id("search_box"); abs_id("login"); abs_id("tagline"); abs_id("contact_rep"); } else if (d == "blog.arcanedomain.com") { abs_id("sidebar"); abs_id("header_desc"); abs_id("header_title"); } else if (d == "www.aljazeera.net") // (Not other subdomains) abs_id("HeaderAds"); else if (d == "skeptoid.com") { abs_id("left_zone"); abs_id("top_zone"); abs_id("right_zone"); } else if (d == "pear.php.net") abs_id("search"); else if (domain_is(d, "cornell.edu")) { // Not *all* of these are abs-positioned (or even found) on *all* Cornell pages. // When static, no prob, "top" style is ignored. // But cu-logo was relative on one page, must not be bumped down then. abs_id("mainnav"); abs_id("search-form"); abs_id("search-navigation"); el = doc.getElementById("cu-logo"); if (el && (get_style(el, "position") == "absolute")) // it isn't always! abs_id("cu-logo"); el = doc.getElementById("campaignsection"); if (el) { var ptags = el.getElementsByTagName("p"); if (ptags.length > 0) abs_element(ptags[0]); } } else if (d == "arxiv.org") { // part of cornell.edu, actually, but not same format abs_id("cu-logo"); abs_id("support-ack"); abs_id("search"); } else if (d == "blog.pandora.com"){ abs_id("dropdown_menu_root_about"); abs_id("dropdown_menu_root_share"); abs_id("container_a"); } else if (d == "www.humblebundle.com") abs_id("bl"); else if (d == "blog.humblebundle.com") { abs_id("hbcomlink"); // This is actually tumblr: el = doc.getElementById("tumblr_controls"); if (el) // Battle of our "!important" over their "!important". Hah! el.style.top = "47px !important"; } else if (d == "www.autostraddle.com") avoid_fixed_nav_bar("wp-admin-bar"); else if (domain_is(d, "case.edu")) { abs_id("leftBody"); abs_id("featureSection"); } else if (domain_is(d, "joindiaspora.com|diasporaproject.org")) avoid_fixed_nav_bar_by_tag("header"); else if (d == "www.mathewingram.com") { abs_id("fc-friendbar-outer"); abs_id("fc-friendbar-outer-shadow"); } else if (d == "www.123rf.com") { el = doc.getElementById("searchform"); if (el) abs_element(el.parentNode.parentNode.parentNode); } // We can almost always do this, so just suppress the exceptions. if (scroll_bkg) { // Adjust background images on elements that don't get pushed down by the medallion. adjust_bkg_imgs(doc.body, height_offset); // it's usually here adjust_bkg_imgs(doc.documentElement, height_offset); // but sometimes it's here on the element! e.g. PLoS journal sites } function abs_id(search_value){ adjust_absolute("id", search_value, height_offset); } function abs_element(search_value){ adjust_absolute("element", search_value, height_offset); } function bring_medallion_to_front(){ // abs_header.style.position = "relative"; // (removed when switched to having abs-positioned sub-header) abs_header.style.zIndex = parseInt("0x7fffffff"); // highest integer CSS understands } function avoid_fixed_nav_bar(nav_bar_el_or_id){ // header.style.position = "relative"; // (removed when switched to having abs-positioned sub-header) var nav_bar = nav_bar_el_or_id; // if it's an element, use this if (typeof nav_bar_el_or_id == "string") nav_bar = doc.getElementById(nav_bar_el_or_id); abs_header.style.top = ( get_style_val(nav_bar, "top") + get_style_val(nav_bar, "marginTop") + get_style_val(nav_bar, "paddingTop") + get_style_val(nav_bar, "borderTopWidth") + get_style_val(nav_bar, "height") + get_style_val(nav_bar, "borderBottomWidth") + get_style_val(nav_bar, "paddingBottom") ) + "px"; abs_header.style.zIndex = get_style(nav_bar, "zIndex") - 1; // need to scroll behind it } // For elements with unique tag names, like "header". (Ahhhh, html5!) function avoid_fixed_nav_bar_by_tag(name){ var els = doc.getElementsByTagName(name); if (els && els.length > 0) avoid_fixed_nav_bar(els[0]); } function parents_are_static(id){ var el = doc.getElementById(id); if (!el) return false; // Pretend *not* static, i.e. no need to do anything. do { var p = el.offsetParent; if (typeof p == "undefined") // Happens if you percolate all the way up to document. return true; // Pretend *is* static, no offsetParent ever found, need to adjust. if (p == null) // Happens if display: none; (need real answer because it can be dynamically displayed later) el = el.parentNode; // Move up the tree to get the answer. } while (p == null); return (get_style(p, "position") == "static"); } } // Adjust position of absolutely positioned elements that didn't get bumped down with the rest of the page // search_key = how to find this element on the page ("id", "name", etc.) // search_value = what id, name, etc. to look for. function adjust_absolute(search_key, search_value, height_offset){ var el; if (search_key == "element") el = search_value; // was already retrieved else if (search_key == "id") el = doc.getElementById(search_value); if (el) el.style.top = (el.offsetTop + height_offset) + "px"; else if (browser == "embedded") // in this case may have to wait for it, if browser isn't finished parsing html yet setTimeout(function(){adjust_absolute(search_key, search_value, height_offset);}, 50); } // Sometimes need to set a specific value rather than adding an offset function set_absolute(id, height){ var el = doc.getElementById(id); if (el) el.style.top = height + "px"; } // Adjust position of background images on body or html element. Can be done as a general instead of special case function adjust_bkg_imgs(el, height_offset) { if (get_style(el, "backgroundAttachment") == "scroll"){ // not for fixed bkg images var bkgX = get_style(el, "backgroundPositionX"); var bkgY = get_style(el, "backgroundPositionY"); if (!bkgY) { // FF doesn't know PositionX & Y, only Position var bkg = get_style(el, "backgroundPosition").split(" "); bkgX = bkg[0]; bkgY = bkg[1]; } // Handle all the possible values. This should get most cases. But if absolute value were in some // other unit than px, or % value is not 0%, there could be trouble... should only affect % // because I think for absolute units, computed values are returned as px regardless how specified. if (bkgY == "bottom" || bkgY == "center") return; if (bkgY == "0%" || bkgY == "top") bkgY = "0px"; bkgY = (parseInt(bkgY) + height_offset) + "px"; el.style.backgroundPosition = bkgX + " " + bkgY; } } }