/*jshint browser:true, strict:false, curly:false, indent:3*/ (function(){ // returns the origin we should post messages to (if on same host), or null if // no suitable origin is found var getOrigin = function() { var origin = null; // if an origin is supplied by RStudio, use it directly. var rstudio_origin_meta = $('meta[name="rstudio_origin"]'); if (rstudio_origin_meta.length > 0) { var rstudio_origin = rstudio_origin_meta.attr('content'); return window.location.protocol + "//" + rstudio_origin; } // function to normalize hostnames var normalize = function(hostname) { if (hostname == "127.0.0.1") return "localhost"; else return hostname; }; // construct the parent origin if the hostnames match var parentUrl = (parent !== window) ? document.referrer : null; if (parentUrl) { // parse the parent href var a = document.createElement('a'); a.href = parentUrl; if (normalize(a.hostname) == normalize(window.location.hostname)) { var protocol = a.protocol.replace(':',''); // browser compatability origin = protocol + '://' + a.hostname; if (a.port) origin = origin + ':' + a.port; } } return origin; }; // property application ------------------------------------------------------ // sets the location hash var setHash = function(hash) { // special case for ioslides: if the hash is numeric and we have a slide // controller, use it to change the slides (ioslides doesn't respond to // onhashchange) if (/[0-9]+/.test(hash) && window.slidedeck) { window.slidedeck.loadSlide(parseInt(hash)); } else { location.hash = hash; } }; // sets the document scroll position. this could be called before that part of // the document has loaded, so if the position specified is not yet available, // wait a few ms and try again. var setScrollPos = function(pos) { if (pos > document.body.scrollHeight) { window.setTimeout(function() { setScrollPos(pos); }, 100); } else { document.body.scrollTop = pos; } }; // cross-domain communication ------------------------------------------------ // obtain and validate the origin var origin = getOrigin(); if (origin === null) return; // set up cross-domain send/receive var send = function(data) { data.type = "ShinyFrameEvent"; // only send the message if we have a parent if (parent && (parent !== window)) parent.postMessage(data, origin); }; var recv = function(evt) { // validate that message is from expected origin (i.e. our parent) if (evt.origin !== origin) return; switch (evt.data.method) { case "rs_set_scroll_pos": setScrollPos(evt.data.arg); break; case "rs_set_hash": setHash(evt.data.arg); break; } }; window.addEventListener("message", recv, false); // document event handlers --------------------------------------------------- // notify parent when scroll stops changing for ~0.25 s (don't spam during // continuous/smooth scrolling) var scrollTimer = 0; var onScroll = function(pos) { if (scrollTimer !== 0) window.clearTimeout(scrollTimer); scrollTimer = window.setTimeout(function() { send({ event: "doc_scroll_change", data: document.body.scrollTop }); }, 250); }; // test the href for changes every 100ms, and notify parent if it has changed. // ordinarily we'd hook an event handler to 'hashchange' here, but in some // cases (e.g. ioslides) the document can change the hash without triggering // a hashchange event. var currentHref = location.href; var testHrefChange = function() { if (currentHref !== location.href) { currentHref = location.href; send({ event: "doc_hash_change", data: location.href }); } }; window.setInterval(testHrefChange, 100); window.addEventListener("scroll", onScroll, false); // let parent know we're ready once the event loop finishes window.setTimeout(function() { send({ event: "doc_ready", data: null }); }, 0); // mathjax setup ------------------------------------------------------------- // if this is a Qt-based browser on Windows, inject the MathJax configuration // data. at the time this runs it's not possible to know whether the document // uses MathJax or not. if (window.navigator.userAgent.indexOf(" Qt/") > 0 && window.navigator.userAgent.indexOf("Windows") > 0) { var s = document.createElement("script"); s.type = "text/x-mathjax-config"; s.textContent = 'MathJax.Hub.Config({' + ' "HTML-CSS": { minScaleAdjust: 125, availableFonts: [] } ' + '});'; document.head.appendChild(s); } })();