block by tophtucker 593964bb8e6984b9f3af

Recirc fetching source

Full Screen

Originally conceived for What Is Code as a recirculation module to link to other pages. The idea is just to show source and rendered html in some animated manner. It doesn’t work cross-origin so I have some dummy html pages here, so they are fetching dummy source but linking to real source, but if it were same-origin it could just fetch the real url.

Uses Fetch API, thus Fetch polyfill, thus es6-promise polyfill.

Should really use d3.timer instead of setInterval incrementing character by character…

index.html

<!DOCTYPE html>
<html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>

<link rel="stylesheet" type="text/css" href="main.css"/>

<body>

</body>

<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script src="//cdn.rawgit.com/gka/d3-jetpack/master/d3-jetpack.js" charset="utf-8"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/es6-promise/3.0.2/es6-promise.min.js" charset="utf-8"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/fetch/0.10.0/fetch.min.js" charset="utf-8"></script>

<script src="main.js" charset="utf-8"></script>

<script>

var pages = [
  {
    "url": "//www.bloomberg.com/bw/articles/2013-10-10/jeff-bezos-and-the-age-of-amazon-excerpt-from-the-everything-store-by-brad-stone",
    "src": "sample1.html"
  },
  {
    "url": "//www.bloomberg.com/news/articles/2015-04-14/docker-said-to-join-1-billion-valuation-club-with-new-funding",
    "src": "sample2.html"
  },
  {
    "url": "//www.bloomberg.com/news/articles/2015-04-02/soon-students-may-learn-to-code-instead-of-taking-french-class",
    "src": "sample3.html"
  },
  {
    "url": "//www.bloomberg.com/news/articles/2015-05-07/coding-classes-attract-college-grads-who-want-better-jobs",
    "src": "sample4.html"
  },
  {
    "url": "//www.bloomberg.com/bw/articles/2013-11-07/the-hidden-technology-that-makes-twitter-huge",
    "src": "sample5.html"
  }
];

d3.select('body').datum(pages).call(recirc);

</script>

</html>

main.css

.recirc {
  width: 300px;
  height: 200px;
  position: relative;
  cursor: pointer;
  display: inline-block;
  margin: 10px;
}
.recirc .title {
  position: absolute;
  top: 0;
  left: 0;
  font-family: helvetica, sans-serif;
  font-weight: bold;
  font-size: 1em;
  z-index: 3;
}
.recirc:hover .title {
  background: black;
  color: white;
}
.recirc .source {
  font-family: Consolas, courier, monospace;
  font-size: .5em;
  line-height: 1em;
  color: #ddd;
  word-wrap: break-word;
  width: 100%;
  height: 100%;
  overflow-x: hidden;
  overflow-y: scroll;
  z-index: 1;
}
.recirc iframe {
  position: absolute;
  width: 133%;
  height: 133%;
  top: 0;
  left: 0;
  opacity: 0;
  border: none;
  pointer-events: none;

  -ms-zoom: 0.75;
  -moz-transform: scale(0.75);
  -moz-transform-origin: 0 0;
  -o-transform: scale(0.75);
  -o-transform-origin: 0 0;
  -webkit-transform: scale(0.75);
  -webkit-transform-origin: 0 0;
}
.recirc:hover iframe {
  opacity: .5;
  z-index: 2;
}

main.js

function recirc(selection) {
  selection.each(function(data) {

    d3.select(this).selectAll("div.recirc")
      .data(data)
      .enter()
      .append("div.recirc")
      .each(render)
      .on("click", function(d) { window.location.href = d.url; });

  });

  function render(d,i) {

    var recirc = d3.select(this);

    recirc.append("div.title");
    recirc.append("div.source");
    recirc.append("iframe");

    fetch(d.src)
      .then(
        function(response) {

          response.text().then(function(rText) {

            // get page title
            var titleStart = rText.indexOf("<title>") + "<title>".length;
            var titleEnd = rText.indexOf("</title>");
            var titleLength = titleEnd - titleStart;
            var title = rText.substr(titleStart, titleLength);
            recirc.select(".title").text(title);

            // get the source between <article...> and </article>
            var start = rText.indexOf("<article");
            var end = rText.indexOf("</article>") + "</article>".length;
            var length = end - start;
            var source = rText.substr(start,length);

            var progress = 0;
            var iframeDocument = recirc.select("iframe").node().contentWindow.document;

            var renderingInterval = setInterval(function() {
              // increment within bounds
              progress=Math.min(progress + 5, source.length)

              // add some text
              recirc.select(".source").text(source.substr(0,progress));
              // scroll to bottom
              recirc.select(".source").node().scrollTop = recirc.select(".source").node().scrollHeight;

              iframeDocument.open();
              iframeDocument.write(source.substr(0,progress));
              iframeDocument.close();
              iframeDocument.getElementsByTagName("body")[0].scrollTop = iframeDocument.getElementsByTagName("body")[0].scrollHeight;

              if(progress === source.length) clearInterval(renderingInterval);
            })
          })
        }
      );
  }

}