-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
50 lines (37 loc) · 17.3 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>sortloader</title>
<link rel=stylesheet href="style.css" type="text/css"/>
</head>
<body>
<section>
<h1>What's going on here?</h1>
<p>The letters of the text on this page are initially sorted alphabetically. Afterwards, sorting occurs and the letters eventually assume their appropriate final location.</p>
<p>To see it happen again, <a onclick="location.reload()">reload</a> the page.</p>
<h1>How does it work?</h1>
<p>In HTML, pages <i>("documents")</i> are represented using a tree of nodes. Some of those nodes are Elements, such as the <code><p></code> element, which defines a paragraph. Other nodes are text nodes, which exist to display text.</p>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="90 111 326 177" width="326pt" height="177pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2013-05-05 14:25Z</dc:date><!-- Produced by OmniGraffle Professional 5.3.6 --></metadata><defs><filter id="Shadow" filterUnits="userSpaceOnUse"><feGaussianBlur in="SourceAlpha" result="blur" stdDeviation="3.5582411"/><feOffset in="blur" result="offset" dx="0" dy="4"/><feFlood flood-color="black" flood-opacity=".25" result="flood"/><feComposite in="flood" in2="offset" operator="in"/></filter><font-face font-family="Helvetica" font-size="12" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="522.94922" cap-height="717.28516" ascent="770.01953" descent="-229.98047" font-weight="500"><font-face-src><font-face-name name="Helvetica"/></font-face-src></font-face><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="black" opacity=".25"><g><path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/></g></marker></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title></title><g><title></title><g><use xl:href="#id3_Graphic" filter="url(#Shadow)"/><use xl:href="#id4_Graphic" filter="url(#Shadow)"/><use xl:href="#id5_Graphic" filter="url(#Shadow)"/><use xl:href="#id6_Graphic" filter="url(#Shadow)"/><use xl:href="#id7_Graphic" filter="url(#Shadow)"/></g><g id="id3_Graphic"><rect x="226" y="119" width="62.758606" height="28" fill="white"/><rect x="226" y="119" width="62.758606" height="28" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(231 126)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" x="8.036537" y="11" textLength="36.685547"><html></tspan></text></g><g id="id4_Graphic"><rect x="226" y="163" width="62.758606" height="28" fill="white"/><rect x="226" y="163" width="62.758606" height="28" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(231 170)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x="6.360756" y="11" textLength="40.03711"><body></tspan></text></g><g id="id5_Graphic"><rect x="117.12069" y="207" width="62.758614" height="28" fill="white"/><rect x="117.12069" y="207" width="62.758614" height="28" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(122.1207 214)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x="12.69767" y="11" textLength="27.363281"><h1></tspan></text></g><g id="id6_Graphic"><rect x="226" y="207" width="62.758606" height="28" fill="white"/><rect x="226" y="207" width="62.758606" height="28" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(231 214)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x="16.034584" y="11" textLength="20.689453"><p></tspan></text></g><g id="id7_Graphic"><rect x="334.87927" y="207" width="62.758606" height="28" fill="white"/><rect x="334.87927" y="207" width="62.758606" height="28" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(339.87927 214)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x="16.034584" y="11" textLength="20.689453"><p></tspan></text></g><line x1="257.3793" y1="147.5" x2="257.3793" y2="152.59999" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="257.3793" y1="191.5" x2="257.3793" y2="196.59999" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="225.53668" y1="189.91858" x2="189.51727" y2="204.53168" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="289.22162" y1="189.98523" x2="325.2472" y2="204.67639" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(90.5 260)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x=".296875" y="11" textLength="115.40625">The document begins</tspan><tspan font-family="Helvetica" font-size="12" font-weight="500" x="17.637695" y="25" textLength="80.72461">with a heading.</tspan></text><line x1="148.5" y1="235.5" x2="148.5" y2="250.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(218.3793 260)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x=".32519531" y="11" textLength="64.01953">This is the fi</tspan><tspan font-family="Helvetica" font-size="12" font-weight="500" x="64.344727" y="11" textLength="13.330078">rst</tspan><tspan font-family="Helvetica" font-size="12" font-weight="500" x="9.9785156" y="25" textLength="58.04297">paragraph.</tspan></text><line x1="257.3793" y1="235.5" x2="257.3793" y2="250.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(316.75858 260)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x="6.4804688" y="11" textLength="86.03906">Following that is</tspan><tspan font-family="Helvetica" font-size="12" font-weight="500" x=".12890625" y="25" textLength="98.74219">another paragraph</tspan></text><line x1="366.25858" y1="235.5" x2="366.25858" y2="250.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/></g></g></svg>
<p>By going recursively through each of the text nodes, it's possible to find all of the letters in the document. To make the animation nicer, whitespace characters like spaces and new lines are skipped using a regular expression. So, for the example above, the letters would be:</p>
<div class='example'>The document begins with a heading.This is the first paragraph.Following that is another paragraph.</div>
<p>The above is the final ordering of letters. At this point, each letter's index within this order can be stored in memory—for example, the capital T should be at position 0. The letters can now be scrambled (or in this case, sorted) since the information about its final position is in memory.</p>
<div class='example'>...FTTaaaaaaaaaabcddeeeeeefggggghhhhhhhhhiiiiiiiillmnnnnnoooopppprrrrrrssssstttttttuww</div>
<p>Any ordering of letters can be displayed in the document, by distributing the letters in the text nodes, one-by-one. You can think of each text node as a container that can only hold a certain number of letters -- once it's filled, you move on to the next text node, placing the remaining letters there and repeating.</p>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="105 111 304 193" width="304pt" height="193pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2013-05-05 14:47Z</dc:date><!-- Produced by OmniGraffle Professional 5.3.6 --></metadata><defs><filter id="Shadow" filterUnits="userSpaceOnUse"><feGaussianBlur in="SourceAlpha" result="blur" stdDeviation="3.5582411"/><feOffset in="blur" result="offset" dx="0" dy="4"/><feFlood flood-color="black" flood-opacity=".25" result="flood"/><feComposite in="flood" in2="offset" operator="in"/></filter><font-face font-family="Helvetica" font-size="12" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="522.94922" cap-height="717.28516" ascent="770.01953" descent="-229.98047" font-weight="500"><font-face-src><font-face-name name="Helvetica"/></font-face-src></font-face><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="black" opacity=".25"><g><path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/></g></marker><font-face font-family="Helvetica" font-size="12" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="532.22656" cap-height="719.72656" ascent="770.01953" descent="-229.98047" font-weight="bold"><font-face-src><font-face-name name="Helvetica-Bold"/></font-face-src></font-face></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title></title><g><title></title><g><use xl:href="#id3_Graphic" filter="url(#Shadow)"/><use xl:href="#id4_Graphic" filter="url(#Shadow)"/><use xl:href="#id5_Graphic" filter="url(#Shadow)"/><use xl:href="#id6_Graphic" filter="url(#Shadow)"/><use xl:href="#id7_Graphic" filter="url(#Shadow)"/><use xl:href="#id18_Graphic" filter="url(#Shadow)"/><use xl:href="#id20_Graphic" filter="url(#Shadow)"/><use xl:href="#id21_Graphic" filter="url(#Shadow)"/></g><g id="id3_Graphic"><rect x="226" y="119" width="62.758606" height="28" fill="white"/><rect x="226" y="119" width="62.758606" height="28" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(231 126)" fill="black" fill-opacity=".25"><tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" fill-opacity=".25" x="8.036537" y="11" textLength="36.685547"><html></tspan></text></g><g id="id4_Graphic"><rect x="226" y="163" width="62.758606" height="28" fill="white"/><rect x="226" y="163" width="62.758606" height="28" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(231 170)" fill="black" fill-opacity=".25"><tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" fill-opacity=".25" x="6.360756" y="11" textLength="40.03711"><body></tspan></text></g><g id="id5_Graphic"><rect x="117.12069" y="207" width="62.758614" height="28" fill="white"/><rect x="117.12069" y="207" width="62.758614" height="28" stroke="black" stroke-opacity=".5" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(122.1207 214)" fill="black" fill-opacity=".5"><tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" fill-opacity=".5" x="12.69767" y="11" textLength="27.363281"><h1></tspan></text></g><g id="id6_Graphic"><rect x="226" y="207" width="62.758606" height="28" fill="white"/><rect x="226" y="207" width="62.758606" height="28" stroke="black" stroke-opacity=".5" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(231 214)" fill="black" fill-opacity=".5"><tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" fill-opacity=".5" x="16.034584" y="11" textLength="20.689453"><p></tspan></text></g><g id="id7_Graphic"><rect x="334.87927" y="207" width="62.758606" height="28" fill="white"/><rect x="334.87927" y="207" width="62.758606" height="28" stroke="black" stroke-opacity=".5" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(339.87927 214)" fill="black" fill-opacity=".5"><tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" fill-opacity=".5" x="16.034584" y="11" textLength="20.689453"><p></tspan></text></g><line x1="257.3793" y1="147.5" x2="257.3793" y2="152.59999" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="257.3793" y1="191.5" x2="257.3793" y2="196.59999" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="225.53642" y1="189.86974" x2="189.52158" y2="204.42561" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="289.22217" y1="189.87166" x2="325.23715" y2="204.42982" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><g id="id18_Graphic"><rect x="117.12069" y="260" width="62.758614" height="28" fill="white"/><path d="M 117.12069 260 L 179.8793 260 L 179.8793 288 L 117.12069 288 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" stroke-dasharray="4,4"/><text transform="translate(122.1207 267)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x="21.378334" y="11" textLength="10.001953">...</tspan></text></g><line x1="148.5" y1="235.5" x2="148.5" y2="249.6" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><g id="id20_Graphic"><rect x="226" y="260" width="62.758606" height="28" fill="white"/><path d="M 226 260 L 288.7586 260 L 288.7586 288 L 226 288 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" stroke-dasharray="4,4"/><text transform="translate(231 267)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x="21.378334" y="11" textLength="10.001953">...</tspan></text></g><g id="id21_Graphic"><rect x="334.87927" y="260" width="62.758606" height="28" fill="white"/><path d="M 334.87927 260 L 397.63788 260 L 397.63788 288 L 334.87927 288 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" stroke-dasharray="4,4"/><text transform="translate(339.87927 267)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x="21.378334" y="11" textLength="10.001953">...</tspan></text></g><line x1="257.3793" y1="235.5" x2="257.3793" y2="249.6" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="366.25858" y1="235.5" x2="366.25858" y2="249.6" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-opacity=".25" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/></g></g></svg>
<p>Given this method of laying out text across the page, the letters can be sorted back to their original location over time: in this case, using bubble sort. It's a very inefficient way of sorting, but serves well for showing the animation effect.</p>
<h1>Notes</h1>
<p>If you scroll down while the characters are still shifting around, you might notice that the length of the entire page changes. This happens because the line breaks and paragraph lengths vary, since the characters in a particular paragraph change over time. A paragraph containing mostly punctuation is shorter than a paragraph containing capital letters, even though there are the same number of characters.<p>
<p>You can try a version of this page <a onclick="window.location.hash = 'mono'; location.reload()">with a monospace font</a> to see this effect mostly go away.<p>
<h1>Code</h1>
<p>You can find the source code on my <a href="https://github.com/fzembow/sortloader" target="_blank">>github page</a>.</p>
<p>If you'd rather just run it on your website, you can copy and paste this snippet and run it once your page is loaded:</p>
<textarea onclick="this.select()">function k(a){var b=[];a=a.childNodes;for(var d=0;d<a.length;d++){var c=a[d];1==c.nodeType?b=b.concat(k(c)):3==c.nodeType&&b.push(c)}return b}function l(a,b){for(var d=0,c=0;d<b.length;){for(var e=b[d],f=e.data,r=f.length,g="",h=0;h<r;h++){var n=f[h];n.match(/\S/)?(g+=a[c].a,c++):g+=n}e.data=g;d++}}function m(a,b){var d=!1;for(i=a.length-1;0<i;i--){var c=a[i],e=a[i-1];c.index<e.index&&(a[i-1]=c,a[i]=e,d=!0)}l(a,b);d&&setTimeout(m.bind(this,a,b),1)}
var p=k(document.body),q=function(a){for(var b=[],d=0,c=0;c<a.length;c++)for(var e=a[c].data,f=0;f<e.length;f++)e[f].match(/\S/)&&(b.push({index:d,a:e[f]}),d++);b.sort(function(a,b){return a.a.charCodeAt(0)-b.a.charCodeAt(0)});return b}(p);l(q,p);m(q,p);</textarea>
<h1>About</h1>
<p>Made by Fil Zembowicz on a plane flight from Paris to New York. For more projects, check out <a href="http://filosophy.org/project">filosophy</a>.</p>
</section>
<script src="sort.js"></script>
<script src="ga.js"></script>
</body>
</html>