Add old platform coop free software presentation
BIN
platform-coop-free-software/2273635564_efcaf3250a_o.jpg
Normal file
After Width: | Height: | Size: 1,008 KiB |
After Width: | Height: | Size: 686 KiB |
26
platform-coop-free-software/LICENSE
Normal file
|
@ -0,0 +1,26 @@
|
|||
Copyright (c) 2012, Michael Bostock
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* The name Michael Bostock may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
10
platform-coop-free-software/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Platform Cooperatives and Free Software
|
||||
|
||||
Slides for a presentation. <!-- View <a href="http://mlncn.github.io//">index.html</a> in a browser, but view the source for my notes. -->
|
||||
|
||||
# Built on stack.js
|
||||
|
||||
Stack.js is a presentation library with intuitive, scroll-based navigation.
|
||||
|
||||
https://mbostock.github.io/stack/
|
||||
https://github.com/mbostock/stack
|
BIN
platform-coop-free-software/Torn_down_blockbuster_2013.jpeg
Normal file
After Width: | Height: | Size: 191 KiB |
After Width: | Height: | Size: 385 KiB |
After Width: | Height: | Size: 67 KiB |
9294
platform-coop-free-software/d3.v3.js
vendored
Normal file
5
platform-coop-free-software/d3.v3.min.js
vendored
Normal file
387
platform-coop-free-software/index.html
Normal file
|
@ -0,0 +1,387 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Platform Cooperatives and Free Software</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<style>
|
||||
|
||||
@import url(http://fonts.googleapis.com/css?family=Ubuntu:500|Quattrocento+Sans:400,700,400italic);
|
||||
|
||||
section {
|
||||
background-color: white;
|
||||
color: black;
|
||||
padding: 2em;
|
||||
font-family: "Quattrocento Sans", Helvetica, Verdana, sans-serif;
|
||||
font-weight: 400;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
section.reverse {
|
||||
background-color: #0678be;
|
||||
color: white;
|
||||
}
|
||||
|
||||
a:link,
|
||||
a:visited {
|
||||
color: #99CCFF;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
section.reverse a:link,
|
||||
section.reverse a:visited {
|
||||
color: yellow;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
section p {
|
||||
font-size: 1em;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
section strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
font-family: Ubuntu, Arial, sans-serif;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.big li {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
img {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
cite {
|
||||
font-size: .8em;
|
||||
color: #eee;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.dark {
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.dark a {
|
||||
color: #0678be;
|
||||
}
|
||||
|
||||
blockquote cite {
|
||||
color: inherit;
|
||||
display: block;
|
||||
position: relative;
|
||||
text-align: right;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
blockquote cite::before {
|
||||
content: "—";
|
||||
}
|
||||
|
||||
.notes {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@media print {
|
||||
.notes {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section class="reverse" style="padding-top: 2em">
|
||||
<h1>Platform Cooperatives<br />and Free Software</h1>
|
||||
<h2></h2>
|
||||
<h4><a href="https://pad.riseup.org/p/platform-coop-free-software">pad.riseup.org/p/platform-coop-free-software</a></h4>
|
||||
<h4><a href="https://mlncn.withknown.com/">@mlncn</a><br />
|
||||
<a href="http://agaric.com/">agaric.com</a></h4>
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
Hello! All blame in this presentation can go to that guy's twitter handle right there.
|
||||
</div>
|
||||
|
||||
<section style="background-image:url(2273635564_efcaf3250a_o.jpg);">
|
||||
<cite><a href="https://www.flickr.com/photos/neubie/2273635564">Neubie</a>, Money Hand</cite>
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
Free software has a funding problem.
|
||||
|
||||
We were at a Drupal meetup last night. Almost the entire room used directly built on Free Software to earn their living. Ninety percent of the room used proprietary 'integrated development environments' . If free software can't win in this market, how is it going to win among the billions more people who need Free Software to have control over their loves, but don't even know about it yet?
|
||||
</div>
|
||||
|
||||
<section style="background-image:url(jeep-in-ditch-recall-IMG_0724.jpg);">
|
||||
<cite><a href="https://www.wired.com/2015/07/hackers-remotely-kill-jeep-highway/">Andy Greenberg: Hackers Remotely Kill a Jeep on the Highway—With Me in It</a></cite>
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
Here's a hacked jeep driven into a ditch.
|
||||
"Computers and the Internet are everywhere and the world is increasingly made of them."
|
||||
Cory Doctorow
|
||||
</div>
|
||||
|
||||
<section style="background-image:url(plane-crash-do-to-software-bug.jpg);">
|
||||
<cite><a href="http://www.bbc.com/news/technology-32810273">BBC: Airbus A400M plane crash linked to software fault</a></cite>
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
It is hard to convince people — in other audiences — that it matters what code runs on their devices, in their bodies, and for services they use from the cloud. Richard Stallman has been working on this for decades. I have this 50 minute presentation and more things to cover, so here's a scary picture.
|
||||
<p>This is an Airbus A400M crashed due to a software fault, four crew members killed. As a web developer, i have always been very grateful that my mistakes would be hard-pressed to kill anyone. I think the political and economic consequences of not having control of our software is the big danger, but it really is a matter of life and death. Which is not to say that software of all kinds has not made us safer, and won't make great leaps in safety in the future.</p>
|
||||
So free software matters. Why isn't it winning?
|
||||
</div>
|
||||
|
||||
<section style="background-image: url(Walled_Garden_-_geograph.org.uk_-_229821.jpg);">
|
||||
<blockquote><big>walled gardens are winning<br />
|
||||
because they have a superior<br />
|
||||
<strong>user experience</strong></big>
|
||||
<cite>Dries Buytaert</cite>
|
||||
</blockquote>
|
||||
<cite>Dries Buytaert, <a href="http://buytaert.net/winning-back-the-open-web">Winning back the open web</a></cite>
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
The superior user experience is paid for by piles more cash than the average free software project gets, and disciplined by paying customers— whether they are paying with money, or with their time, attention, and personal data.
|
||||
<p>So free software needs a business model. Where could it find one, just one step away?</p>
|
||||
</div>
|
||||
|
||||
<section class="reverse">
|
||||
<h2>Almost all SaaS services are already built on Free Software.</h2>
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
<p>Free Software has the best maintainability and scalability. Every hot startup or excellent service you can think of, from Facebook to Slack to AirBnB to Google, uses Free Software. The entire stack of almost all of them are built on Free Software, from GNU/Linux to Apache to Nginx to PHP to Python to React.js... it's just the last thing they put together with all this Free Software that's not being shared, because the founders or the owners are looking to multiply their investments by hundreds of times, which they can only do by holding a monopoly by any means available, including proprietary software. So we can't re-use the funding model which proprietary software as a service is using, but while we're looking for a business model, software as a service, interpreted broadly, seems to be where it's at.</p>
|
||||
<p>Okay, then, let's look at *Free* Software as a Service. Where does it have a competitive advantage?</p>
|
||||
</div>
|
||||
|
||||
<section class="reverse">
|
||||
<h3>Free Software as a Service</h3>
|
||||
<h2>Freedom to take data <em>and</em> functionality elsewhere</h2>
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
Only Free Software guarantees complete ability to pack up and leave after a crisis—political, economic, technical—with the service provider.
|
||||
</div>
|
||||
|
||||
<section class="reverse">
|
||||
<h3>Free Software as a Service</h3>
|
||||
<h2>Freedom to take the platform in a new direction</h2>
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
Likewise for picking up and going in a new direction.
|
||||
<p>These might map pretty close to a certain four freedoms...</p>
|
||||
</div>
|
||||
|
||||
<section class="reverse">
|
||||
<h3>Free Software as a Service</h3>
|
||||
<h2>Security for development partners</h2>
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
Only Free Software ensures people building their service businesses providing costomizations and design on a platform have an opportunity to take their customizations to another level for select customers who grow into greanter needs.
|
||||
<p>And, like the customers on the platform whom they serve, they can take their clients elsewhere if the platform no longer aligns with their interests.</p>
|
||||
<p>The business-savvy will be noticing that these advantages are attractive to customers and development partners, but still rather altruistic from the perspective of the business itself.</p>
|
||||
</div>
|
||||
|
||||
|
||||
<section class="reverse">
|
||||
<h3>Platform Cooperatives</h3>
|
||||
<h2>Customers first</h2>
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
Only a cooperative puts customers, the people who need the service, in control of if and how any surplus is used.
|
||||
<p>SaaS, like licensed software, too often is used by a company to keep extracting revenue without putting value back in. Atrophying of software platforms is highly innefficient fo the economy at large— for example, competitors have to start from scratch and redo everything, including acquiring customers. Importantly, it is also inefficient for customers specifically, because they often have to incur switching costs to get to a platform that has invested in significant improvements recently.</p>
|
||||
</div>
|
||||
|
||||
|
||||
<section class="reverse">
|
||||
<h3>Platform Cooperatives</h3>
|
||||
<h2>Ownership effect</h2>
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
<p>The primary beneficiaries, stakeholders of the platform, are, as owners, more emotinoally invested in the platform and are more engaged in participatory planning, beta testing, user research, boosting monetary contributions when called for— which can be especially valuable before launch.</p>
|
||||
</div>
|
||||
|
||||
<section style="background-image: url(Torn_down_blockbuster_2013.jpeg);">
|
||||
<blockquote><big>As value shifts from software to the ability to leverage data, companies will have to rethink their businesses, just as Netflix and Google did.</big>
|
||||
<cite>Dries Buytaert</cite>
|
||||
</blockquote>
|
||||
<cite>Dries Buytaert, <a href="http://buytaert.net/the-future-of-software-is-data-driven">The future of software is data-driven</a></cite>
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
This shift has the potential to greatly advantage cooperatives, and, if you'll pardon the phrase, liberate software used by platforms to be free software— like all the components in the stack making this software already, it won't be the competitive edge for most companies. Instead, the competitive edge may be the trustworthiness of networks and the stewardship of data— and the one-member, one-vote ownership of platform cooperatives may engender greater trust.
|
||||
</div>
|
||||
|
||||
<section>
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
</div>
|
||||
|
||||
<section style="background-image:url(internet-of-ownership-first-screen.png);">
|
||||
<h3 style="margin-top: -1em"><a href="http://internetofownership.net/">InternetOfOwnership.net</a></h3>
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
Platform cooperatives, a twist on the century-old ideas of consumer, producer, and solidarity cooperatives, are already becoming a movement. They featured at the national conference of worker cooperatives that ended last week.
|
||||
You can learn about many of the players at InternetOfOwnership.net.
|
||||
[Talk about some favorites.]
|
||||
</div>
|
||||
|
||||
<section style="background-image: url(climate-disaster-photo-by-theritters.jpg);">
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
Can platform cooperativism and free software really save humanity? When global warming is an overarching threat to ... everything? They can help.
|
||||
|
||||
Staying with the example of oil, gas, and coal companies... why do corporations do such evil things as destroy the planet for the profit of a few? The key is in that word 'few'— the benefits are sharply concentrated, and this is made even worse by the stripping of responsibility from the benefit, and the costs are distributed among all.
|
||||
</div>
|
||||
|
||||
<section style="background-image: url(Cities_City_landscape_on_the_shore_of_the_sea_043951_.jpg);">
|
||||
</section>
|
||||
|
||||
<div class="notes">
|
||||
By distributing both benefit and responsibility for oversight more broadly, platform cooperatives help decisions get made with broader societal benefit in mind. Free software helps make power more distributed generally.
|
||||
</div>
|
||||
|
||||
<section class="reverse" style="padding:6em 10em; background-image: url(turtle-in-sand.png); background-size: contain; background-position: bottom center; background-repeat: no-repeat;">
|
||||
<h4><a href="https://pad.riseup.org/p/platform-coop-free-software">pad.riseup.org/p/platform-coop-free-software</a></h4>
|
||||
<h4><a href="http://mlncn.withknown.com/" rel="author">benjamin melançon</a></h4>
|
||||
<h5><a href="mailto:ben@agaric.com">ben@agaric.com</a></h5>
|
||||
<h5><a href="https://twitter.com/mlncn">@mlncn</a></h5>
|
||||
</section>
|
||||
|
||||
<section id="lorenz" style="text-align:center;padding-top:0;">
|
||||
<canvas></canvas>
|
||||
</section>
|
||||
|
||||
<section style="background-image: url(climate-disaster-photo-by-theritters.jpg);">
|
||||
<h2 style="margin-top: 10em">.</h2>
|
||||
<cite><a href="https://www.flickr.com/photos/littlesister/">IndyDina</a>, ""</cite>
|
||||
</section>
|
||||
|
||||
<section class="reverse" style="background-image:url(doctorow-civilwar-spreadsheet.jpeg);">
|
||||
<blockquote style="background-color: black; padding: 0.5em"><big><big> </big></big></blockquote>
|
||||
<cite>Cory Doctorow, <a href="http://boingboing.net/2012/08/23/civilwar.html">"The coming civil war over general purpose computing"</a></cite>
|
||||
</section>
|
||||
|
||||
<section style="background-image:url(1413479953ewaste2.jpg);">
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2></h2>
|
||||
<ul>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
|
||||
<script src="d3.v3.min.js"></script>
|
||||
<script src="stack.v1.js"></script>
|
||||
<script>
|
||||
|
||||
var mystack = stack()
|
||||
.on("activate", activate)
|
||||
.on("deactivate", deactivate);
|
||||
|
||||
var section = d3.selectAll("section"),
|
||||
lorenz = d3.select("#lorenz"),
|
||||
lorenzIndex = section[0].indexOf(lorenz.node());
|
||||
|
||||
function activate(d, i) {
|
||||
if (i === lorenzIndex) startLorenz();
|
||||
}
|
||||
|
||||
function deactivate(d, i) {
|
||||
if (i === lorenzIndex) stopLorenz();
|
||||
}
|
||||
|
||||
var lorenzInterval;
|
||||
|
||||
function startLorenz() {
|
||||
var δτ = 0.003,
|
||||
ρ = 28,
|
||||
σ = 10,
|
||||
β = 8 / 3,
|
||||
x = .5,
|
||||
y = .5,
|
||||
z = 10,
|
||||
n = 30;
|
||||
|
||||
var width = 1280,
|
||||
height = 720;
|
||||
|
||||
var canvas = d3.select("canvas")
|
||||
.style("position", "absolute")
|
||||
.style("top", 0)
|
||||
.style("left", 0)
|
||||
.style("width", "100%")
|
||||
.style("height", "100%")
|
||||
.attr("width", width)
|
||||
.attr("height", height);
|
||||
|
||||
var color = d3.scale.linear()
|
||||
.domain([0, 20, 30, 50])
|
||||
.range(["yellow", "orange", "brown", "purple"])
|
||||
.interpolate(d3.interpolateHcl);
|
||||
|
||||
var context = canvas.node().getContext("2d");
|
||||
|
||||
context.lineWidth = .2;
|
||||
context.fillStyle = "rgba(0,0,0,.03)";
|
||||
|
||||
d3.timer(function() {
|
||||
context.save();
|
||||
context.globalCompositeOperation = "lighter";
|
||||
context.translate(width / 2, height / 2);
|
||||
context.scale(12, 14);
|
||||
context.rotate(30);
|
||||
for (var i = 0; i < n; ++i) {
|
||||
context.strokeStyle = color(z);
|
||||
context.beginPath();
|
||||
context.moveTo(x, y);
|
||||
x += δτ * σ * (y - x);
|
||||
y += δτ * (x * (ρ - z) - y);
|
||||
z += δτ * (x * y - β * z);
|
||||
context.lineTo(x, y);
|
||||
context.stroke();
|
||||
}
|
||||
context.restore();
|
||||
return !lorenzInterval;
|
||||
});
|
||||
|
||||
lorenzInterval = setInterval(function() {
|
||||
context.fillRect(0, 0, width, height);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function stopLorenz() {
|
||||
lorenzInterval = clearInterval(lorenzInterval);
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
After Width: | Height: | Size: 141 KiB |
BIN
platform-coop-free-software/jeep-in-ditch-recall-IMG_0724.jpg
Normal file
After Width: | Height: | Size: 285 KiB |
BIN
platform-coop-free-software/plane-crash-do-to-software-bug.jpg
Normal file
After Width: | Height: | Size: 73 KiB |
55
platform-coop-free-software/stack.v0.css
Normal file
|
@ -0,0 +1,55 @@
|
|||
body {
|
||||
background: #929292;
|
||||
font-family: "Helvetica Neue";
|
||||
margin: auto;
|
||||
width: 1280px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #6baed6;
|
||||
}
|
||||
|
||||
a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.stack {
|
||||
background: #222 url(cartographer.png);
|
||||
color: #fff;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
-o-box-sizing: border-box;
|
||||
display: none;
|
||||
font-size: 48px;
|
||||
height: 800px;
|
||||
padding: 160px 80px;
|
||||
width: 1280px;
|
||||
-webkit-transform: translate3d(0,0,0);
|
||||
}
|
||||
|
||||
.active {
|
||||
box-shadow: 0px 4px 8px rgba(0,0,0,.5);
|
||||
display: block;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.grey {
|
||||
color: #969696;
|
||||
}
|
||||
|
||||
@media
|
||||
screen and (max-device-width: 1024px) {
|
||||
body {
|
||||
width: 1200px;
|
||||
}
|
||||
|
||||
.stack {
|
||||
margin: 40px 0;
|
||||
}
|
||||
|
||||
.stack {
|
||||
display: block;
|
||||
}
|
||||
}
|
219
platform-coop-free-software/stack.v0.js
Normal file
|
@ -0,0 +1,219 @@
|
|||
var stack = (function() {
|
||||
var stack = {},
|
||||
event = d3.dispatch("activate", "deactivate"),
|
||||
section = d3.selectAll("section"),
|
||||
self = d3.select(window),
|
||||
body = document.body,
|
||||
root = document.documentElement,
|
||||
timeout,
|
||||
duration = 250,
|
||||
ease = "cubic-in-out",
|
||||
screenY,
|
||||
size,
|
||||
yActual,
|
||||
yFloor,
|
||||
yTarget,
|
||||
yActive = -1,
|
||||
yMax,
|
||||
yOffset,
|
||||
n = section[0].length;
|
||||
|
||||
// Invert the z-index so the earliest slides are on top.
|
||||
section.classed("stack", true).style("z-index", function(d, i) { return n - i; });
|
||||
|
||||
// Detect the slide height (by showing an active slide).
|
||||
section.classed("active", true);
|
||||
size = section.node().getBoundingClientRect().height;
|
||||
section.classed("active", false);
|
||||
|
||||
// Sets the stack position.
|
||||
stack.position = function(y1) {
|
||||
var y0 = body.scrollTop / size;
|
||||
if (arguments.length < 1) return y0;
|
||||
|
||||
// clamp and round
|
||||
if (y1 >= n) y1 = n - 1;
|
||||
else if (y1 < 0) y1 = Math.max(0, n + y1);
|
||||
y1 = Math.floor(y1);
|
||||
|
||||
if (y0 - y1) {
|
||||
self.on("scroll.stack", null);
|
||||
leap(y1);
|
||||
d3.select(body).transition()
|
||||
.duration(duration)
|
||||
.ease(ease)
|
||||
.tween("scrollTop", tween(yTarget = y1))
|
||||
.each("end", function() { yTarget = null; self.on("scroll.stack", scroll); });
|
||||
}
|
||||
|
||||
location.replace("#" + y1);
|
||||
|
||||
return stack;
|
||||
};
|
||||
|
||||
// Don't do anything fancy for iOS.
|
||||
if (section.style("display") == "block") return;
|
||||
|
||||
self
|
||||
.on("keydown.stack", keydown)
|
||||
.on("resize.stack", resize)
|
||||
.on("scroll.stack", scroll)
|
||||
.on("mousemove.stack", snap)
|
||||
.on("hashchange.stack", hashchange);
|
||||
|
||||
resize();
|
||||
hashchange();
|
||||
scroll();
|
||||
|
||||
// if scrolling up, jump to edge of previous slide
|
||||
function leap(yNew) {
|
||||
if ((yActual < n - 1) && (yActual == yFloor) && (yNew < yActual)) {
|
||||
yActual -= .5 - yOffset / size / 2;
|
||||
scrollTo(0, yActual * size);
|
||||
reactivate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function reactivate() {
|
||||
var yNewActive = Math.floor(yActual) + (yActual % 1 ? .5 : 0);
|
||||
if (yNewActive !== yActive) {
|
||||
var yNewActives = {};
|
||||
yNewActives[Math.floor(yNewActive)] = 1;
|
||||
yNewActives[Math.ceil(yNewActive)] = 1;
|
||||
if (yActive >= 0) {
|
||||
var yOldActives = {};
|
||||
yOldActives[Math.floor(yActive)] = 1;
|
||||
yOldActives[Math.ceil(yActive)] = 1;
|
||||
for (var i in yOldActives) {
|
||||
if (i in yNewActives) delete yNewActives[i];
|
||||
else event.deactivate.call(section[0][+i], +i);
|
||||
}
|
||||
}
|
||||
for (var i in yNewActives) {
|
||||
event.activate.call(section[0][+i], +i);
|
||||
}
|
||||
yActive = yNewActive;
|
||||
}
|
||||
}
|
||||
|
||||
function resize() {
|
||||
yOffset = (window.innerHeight - size) / 2;
|
||||
yMax = 1 + yOffset / size;
|
||||
|
||||
d3.select(body)
|
||||
.style("margin-top", yOffset + "px")
|
||||
.style("margin-bottom", yOffset + "px")
|
||||
.style("height", (n - .5) * size + yOffset + "px");
|
||||
}
|
||||
|
||||
function hashchange() {
|
||||
var hash = +location.hash.slice(1);
|
||||
if (!isNaN(hash) && hash !== yFloor) stack.position(hash);
|
||||
}
|
||||
|
||||
function keydown() {
|
||||
var delta;
|
||||
switch (d3.event.keyCode) {
|
||||
case 39: // right arrow
|
||||
if (d3.event.metaKey) return;
|
||||
case 40: // down arrow
|
||||
case 34: // page down
|
||||
delta = d3.event.metaKey ? Infinity : 1; break;
|
||||
case 37: // left arrow
|
||||
if (d3.event.metaKey) return;
|
||||
case 38: // up arrow
|
||||
case 33: // page up
|
||||
delta = d3.event.metaKey ? -Infinity : -1; break;
|
||||
case 32: // space
|
||||
delta = d3.event.shiftKey ? -1 : 1;
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
if (timeout) timeout = clearTimeout(timeout);
|
||||
if (yTarget == null) yTarget = (delta > 0 ? Math.floor : Math.ceil)(yActual == yFloor ? yFloor : yActual + (.5 - yOffset / size / 2));
|
||||
stack.position(yTarget = Math.max(0, Math.min(n - 1, yTarget + delta)));
|
||||
d3.event.preventDefault();
|
||||
}
|
||||
|
||||
function scroll() {
|
||||
// Detect whether to scroll with documentElement or body.
|
||||
if (body !== root && root.scrollTop) body = root;
|
||||
|
||||
var yNew = Math.max(0, body.scrollTop / size);
|
||||
if (yNew >= n - 1.51 + yOffset / size) yNew = n - 1;
|
||||
|
||||
// if scrolling up, jump to edge of previous slide
|
||||
if (leap(yNew)) return;
|
||||
|
||||
var yNewFloor = Math.max(0, Math.floor(yActual = yNew)),
|
||||
yError = Math.min(yMax, (yActual % 1) * 2);
|
||||
|
||||
if (yFloor != yNewFloor) {
|
||||
location.replace("#" + yNewFloor);
|
||||
yFloor = yNewFloor;
|
||||
}
|
||||
|
||||
section
|
||||
.classed("active", false);
|
||||
|
||||
d3.select(section[0][yFloor])
|
||||
.style("-webkit-transform", yError ? "translate3d(0," + (-yError * size) + "px,0)" : null)
|
||||
.style("-o-transform", yError ? "translate(0," + (-yError * size) + "px)" : null)
|
||||
.style("-moz-transform", yError ? "translate(0," + (-yError * size) + "px)" : null)
|
||||
.style("transform", yError ? "translate(0," + (-yError * size) + "px)" : null)
|
||||
.classed("active", yError != yMax);
|
||||
|
||||
d3.select(section[0][yFloor + 1])
|
||||
.style("-webkit-transform", yError ? "translate3d(0,0,0)" : null)
|
||||
.style("-o-transform", yError ? "translate(0,0)" : null)
|
||||
.style("-moz-transform", yError ? "translate(0,0)" : null)
|
||||
.style("transform", yError ? "translate(0,0)" : null)
|
||||
.classed("active", yError > 0);
|
||||
|
||||
reactivate();
|
||||
}
|
||||
|
||||
function snap() {
|
||||
var y = d3.event.clientY;
|
||||
if (y === screenY) return; // ignore move on scroll
|
||||
screenY = y;
|
||||
|
||||
if (yTarget != null) return; // don't snap if already snapping
|
||||
|
||||
var y0 = stack.position(),
|
||||
y1 = Math.max(0, Math.round(y0 + .25));
|
||||
|
||||
// if we're before the first slide, or after the last slide, do nothing
|
||||
if (y0 <= 0 || y0 >= n - 1.51 + yOffset / size) return;
|
||||
|
||||
// if the previous slide is not visible, immediate jump
|
||||
if (y1 > y0 && y1 - y0 < .5 - yOffset / size) scrollTo(0, y1 * size);
|
||||
|
||||
// else transition
|
||||
else if (y1 !== y0) stack.position(y1);
|
||||
}
|
||||
|
||||
function tween(y) {
|
||||
return function() {
|
||||
var i = d3.interpolateNumber(this.scrollTop, y * size);
|
||||
return function(t) { scrollTo(0, i(t)); scroll(); };
|
||||
};
|
||||
}
|
||||
|
||||
stack.duration = function(_) {
|
||||
if (!arguments.length) return duration;
|
||||
duration = _;
|
||||
return stack;
|
||||
};
|
||||
|
||||
stack.ease = function(_) {
|
||||
if (!arguments.length) return ease;
|
||||
ease = _;
|
||||
return stack;
|
||||
};
|
||||
|
||||
d3.rebind(stack, event, "on");
|
||||
|
||||
return stack;
|
||||
})();
|
1
platform-coop-free-software/stack.v0.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
var stack=function(){function t(t){return K-1>d&&d==f&&d>t?(d-=.5-m/u/2,scrollTo(0,d*u),e(),!0):void 0}function e(){var t=Math.floor(d)+(d%1?.5:0);if(t!==T){var e={};if(e[Math.floor(t)]=1,e[Math.ceil(t)]=1,T>=0){var n={};n[Math.floor(T)]=1,n[Math.ceil(T)]=1;for(var a in n)a in e?delete e[a]:y.deactivate.call(k[0][+a],+a)}for(var a in e)y.activate.call(k[0][+a],+a);T=t}}function n(){m=(window.innerHeight-u)/2,v=1+m/u,d3.select(g).style("margin-top",m+"px").style("margin-bottom",m+"px").style("height",(K-.5)*u+m+"px")}function a(){var t=+location.hash.slice(1);isNaN(t)||t===f||p.position(t)}function l(){var t;switch(d3.event.keyCode){case 39:if(d3.event.metaKey)return;case 40:case 34:t=d3.event.metaKey?1/0:1;break;case 37:if(d3.event.metaKey)return;case 38:case 33:t=d3.event.metaKey?-1/0:-1;break;case 32:t=d3.event.shiftKey?-1:1;break;default:return}c&&(c=clearTimeout(c)),null==h&&(h=(t>0?Math.floor:Math.ceil)(d==f?f:d+(.5-m/u/2))),p.position(h=Math.max(0,Math.min(K-1,h+t))),d3.event.preventDefault()}function o(){g!==x&&x.scrollTop&&(g=x);var n=Math.max(0,g.scrollTop/u);if(n>=K-1.51+m/u&&(n=K-1),!t(n)){var a=Math.max(0,Math.floor(d=n)),l=Math.min(v,2*(d%1));f!=a&&(location.replace("#"+a),f=a),k.classed("active",!1),d3.select(k[0][f]).style("-webkit-transform",l?"translate3d(0,"+-l*u+"px,0)":null).style("-o-transform",l?"translate(0,"+-l*u+"px)":null).style("-moz-transform",l?"translate(0,"+-l*u+"px)":null).style("transform",l?"translate(0,"+-l*u+"px)":null).classed("active",l!=v),d3.select(k[0][f+1]).style("-webkit-transform",l?"translate3d(0,0,0)":null).style("-o-transform",l?"translate(0,0)":null).style("-moz-transform",l?"translate(0,0)":null).style("transform",l?"translate(0,0)":null).classed("active",l>0),e()}}function r(){var t=d3.event.clientY;if(t!==i&&(i=t,null==h)){var e=p.position(),n=Math.max(0,Math.round(e+.25));0>=e||e>=K-1.51+m/u||(n>e&&.5-m/u>n-e?scrollTo(0,n*u):n!==e&&p.position(n))}}function s(t){return function(){var e=d3.interpolateNumber(this.scrollTop,t*u);return function(t){scrollTo(0,e(t)),o()}}}var c,i,u,d,f,h,v,m,p={},y=d3.dispatch("activate","deactivate"),k=d3.selectAll("section"),M=d3.select(window),g=document.body,x=document.documentElement,b=250,w="cubic-in-out",T=-1,K=k[0].length;return k.classed("stack",!0).style("z-index",function(t,e){return K-e}),k.classed("active",!0),u=k.node().getBoundingClientRect().height,k.classed("active",!1),p.position=function(e){var n=g.scrollTop/u;return arguments.length<1?n:(e>=K?e=K-1:0>e&&(e=Math.max(0,K+e)),e=Math.floor(e),n-e&&(M.on("scroll.stack",null),t(e),d3.select(g).transition().duration(b).ease(w).tween("scrollTop",s(h=e)).each("end",function(){h=null,M.on("scroll.stack",o)})),location.replace("#"+e),p)},k.style("display")!="block"?(M.on("keydown.stack",l).on("resize.stack",n).on("scroll.stack",o).on("mousemove.stack",r).on("hashchange.stack",a),n(),a(),o(),p.duration=function(t){return arguments.length?(b=t,p):b},p.ease=function(t){return arguments.length?(w=t,p):w},d3.rebind(p,y,"on"),p):void 0}();
|
231
platform-coop-free-software/stack.v1.js
Normal file
|
@ -0,0 +1,231 @@
|
|||
function stack() {
|
||||
var stack = {},
|
||||
size = [1280, 720],
|
||||
fontSize = 32,
|
||||
sectionHeight,
|
||||
windowHeight,
|
||||
dispatch = d3.dispatch("scroll", "activate", "deactivate"),
|
||||
touchy = "ontouchstart" in document,
|
||||
resize = touchy ? resizeTouchy : resizeNoTouchy,
|
||||
i = NaN,
|
||||
y = 0,
|
||||
yt,
|
||||
scrollRatio = 1 / 6;
|
||||
|
||||
var section = d3.selectAll("section")
|
||||
.style("box-sizing", "border-box")
|
||||
.each(initialize);
|
||||
|
||||
var n = section.size();
|
||||
|
||||
var body = d3.select("body")
|
||||
.style("margin", 0)
|
||||
.style("padding", 0)
|
||||
.style("background", "#333");
|
||||
|
||||
if (touchy) {
|
||||
section
|
||||
.style("position", "relative");
|
||||
|
||||
d3.select(window)
|
||||
.on("resize.stack", resize)
|
||||
.each(resize);
|
||||
} else {
|
||||
var background = d3.select("body").insert("div", "section")
|
||||
.style("background", "#000")
|
||||
.style("box-shadow", "0 8px 16px rgba(0,0,0,.3)")
|
||||
.style("padding", "1px 0")
|
||||
.style("margin-top", "-1px")
|
||||
.style("z-index", 0);
|
||||
|
||||
section
|
||||
.style("display", "none")
|
||||
.style("opacity", 0)
|
||||
.style("z-index", 0);
|
||||
|
||||
var sectionAndBackground = d3.selectAll(section[0].concat(background.node()))
|
||||
.style("position", "fixed")
|
||||
.style("left", 0)
|
||||
.style("top", 0)
|
||||
.style("width", "100%");
|
||||
|
||||
var indicator = d3.select("body").append("div")
|
||||
.attr("class", "indicator")
|
||||
.selectAll("div")
|
||||
.data(d3.range(section.size()))
|
||||
.enter().append("div")
|
||||
.style("position", "absolute")
|
||||
.style("z-index", 10)
|
||||
.style("left", 0)
|
||||
.style("width", "3px")
|
||||
.style("background", "linear-gradient(to top,black,white)");
|
||||
|
||||
var sectionPrevious = d3.select(null),
|
||||
sectionCurrent = d3.select(section[0][0]),
|
||||
sectionNext = d3.select(section[0][1]);
|
||||
|
||||
d3.select(window)
|
||||
.on("resize.stack", resize)
|
||||
.on("scroll.stack", reposition)
|
||||
.on("keydown.stack", keydown)
|
||||
.each(resize);
|
||||
|
||||
d3.timer(function() {
|
||||
reposition();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
function dispatchEvent(event, i) {
|
||||
var target = section[0][i], sourceEvent = event.sourceEvent = d3.event;
|
||||
try {
|
||||
d3.event = event;
|
||||
dispatch[event.type].call(target, target.__data__, i);
|
||||
} finally {
|
||||
d3.event = sourceEvent;
|
||||
}
|
||||
}
|
||||
|
||||
function initialize(d, i) {
|
||||
this.__stack__ = {index: i, active: false};
|
||||
}
|
||||
|
||||
function activate() {
|
||||
if (!this.__stack__.active) {
|
||||
this.__stack__.active = true;
|
||||
dispatchEvent({type: "activate"}, this.__stack__.index);
|
||||
}
|
||||
}
|
||||
|
||||
function deactivate() {
|
||||
if (this.__stack__.active) {
|
||||
this.__stack__.active = false;
|
||||
dispatchEvent({type: "deactivate"}, this.__stack__.index);
|
||||
}
|
||||
}
|
||||
|
||||
function resizeTouchy() {
|
||||
var marginBottom = 20;
|
||||
|
||||
sectionHeight = size[1] / size[0] * innerWidth;
|
||||
windowHeight = innerHeight;
|
||||
|
||||
section
|
||||
.style("height", sectionHeight + "px")
|
||||
.style("box-shadow", "0 4px 4px rgba(0,0,0,.3)")
|
||||
.filter(function(d, i) { return i < n - 1; })
|
||||
.style("margin-bottom", marginBottom + "px");
|
||||
|
||||
body
|
||||
.style("font-size", innerWidth / size[0] * fontSize + "px");
|
||||
}
|
||||
|
||||
function resizeNoTouchy() {
|
||||
if (sectionHeight) var y0 = y;
|
||||
|
||||
sectionHeight = size[1] / size[0] * innerWidth;
|
||||
windowHeight = innerHeight;
|
||||
|
||||
sectionAndBackground
|
||||
.style("top", (windowHeight - sectionHeight) / 2 + "px")
|
||||
.style("height", sectionHeight + "px");
|
||||
|
||||
indicator
|
||||
.style("top", function(i) { return (i + (1 - scrollRatio) / 2) * windowHeight + "px"; })
|
||||
.style("height", windowHeight * scrollRatio + "px");
|
||||
|
||||
body
|
||||
.style("font-size", innerWidth / size[0] * fontSize + "px")
|
||||
.style("height", windowHeight * n + "px");
|
||||
|
||||
// Preserve the current scroll position on resize.
|
||||
if (!isNaN(y0)) scrollTo(0, (y = y0) * windowHeight);
|
||||
}
|
||||
|
||||
function reposition() {
|
||||
var y1 = pageYOffset / windowHeight,
|
||||
i1 = Math.max(0, Math.min(n - 1, Math.floor(y1 + (1 + scrollRatio) / 2)));
|
||||
|
||||
if (i !== i1) {
|
||||
if (i1 === i + 1) { // advance one
|
||||
sectionPrevious.interrupt().style("display", "none").style("opacity", 0).style("z-index", 0).each(deactivate);
|
||||
sectionPrevious = sectionCurrent.interrupt().style("opacity", 1).style("z-index", 1);
|
||||
sectionPrevious.transition().each("end", deactivate);
|
||||
sectionCurrent = sectionNext.interrupt().style("opacity", 0).style("z-index", 2).each(activate);
|
||||
sectionCurrent.transition().style("opacity", 1);
|
||||
sectionNext = d3.select(section[0][i1 + 1]).interrupt().style("display", "block").style("opacity", 0).style("z-index", 0);
|
||||
} else if (i1 === i - 1) { // rewind one
|
||||
sectionNext.interrupt().style("display", "none").style("opacity", 0).style("z-index", 0).each(deactivate);
|
||||
sectionNext = sectionCurrent.interrupt().style("opacity", 1).style("z-index", 1);
|
||||
sectionNext.transition().each("end", deactivate);
|
||||
sectionCurrent = sectionPrevious.interrupt().style("opacity", 0).style("z-index", 2).each(activate);
|
||||
sectionCurrent.transition().style("opacity", 1);
|
||||
sectionPrevious = d3.select(section[0][i1 - 1]).interrupt().style("display", "block").style("opacity", 0).style("z-index", 0);
|
||||
} else { // skip
|
||||
sectionPrevious.interrupt().style("display", "none").style("opacity", 0).style("z-index", 0).each(deactivate);
|
||||
sectionCurrent.interrupt().style("display", "none").style("opacity", 0).style("z-index", 0).each(deactivate);
|
||||
sectionNext.interrupt().style("display", "none").style("opacity", 0).style("z-index", 0).each(deactivate);
|
||||
sectionPrevious = d3.select(section[0][i1 - 1]).interrupt().style("display", "block").style("opacity", 0).style("z-index", 0).each(deactivate);
|
||||
sectionCurrent = d3.select(section[0][i1]).interrupt().style("display", "block").style("opacity", 1).style("z-index", 2).each(activate);
|
||||
sectionNext = d3.select(section[0][i1 + 1]).interrupt().style("display", "block").style("opacity", 0).style("z-index", 0).each(deactivate);
|
||||
}
|
||||
i = i1;
|
||||
}
|
||||
|
||||
dispatchEvent({type: "scroll", offset: y = y1}, i);
|
||||
}
|
||||
|
||||
function keydown() {
|
||||
var delta;
|
||||
switch (d3.event.keyCode) {
|
||||
case 39: // right arrow
|
||||
if (d3.event.metaKey) return;
|
||||
case 40: // down arrow
|
||||
case 34: // page down
|
||||
delta = d3.event.metaKey ? Infinity : 1; break;
|
||||
case 37: // left arrow
|
||||
if (d3.event.metaKey) return;
|
||||
case 38: // up arrow
|
||||
case 33: // page up
|
||||
delta = d3.event.metaKey ? -Infinity : -1; break;
|
||||
case 32: // space
|
||||
delta = d3.event.shiftKey ? -1 : 1;
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
var y0 = isNaN(yt) ? y : yt;
|
||||
|
||||
yt = Math.max(0, Math.min(n - 1, (delta > 0
|
||||
? Math.floor(y0 + (1 + scrollRatio) / 2)
|
||||
: Math.ceil(y0 - (1 - scrollRatio) / 2)) + delta));
|
||||
|
||||
d3.select(document.documentElement)
|
||||
.interrupt()
|
||||
.transition()
|
||||
.duration(500)
|
||||
.tween("scroll", function() {
|
||||
var i = d3.interpolateNumber(pageYOffset, yt * windowHeight);
|
||||
return function(t) { scrollTo(0, i(t)); };
|
||||
})
|
||||
.each("end", function() { yt = NaN; });
|
||||
|
||||
d3.event.preventDefault();
|
||||
}
|
||||
|
||||
stack.size = function(_) {
|
||||
return arguments.length ? (size = [+_[0], +_[1]], resize(), stack) : size;
|
||||
};
|
||||
|
||||
stack.scrollRatio = function(_) {
|
||||
return arguments.length ? (scrollRatio = +_, resize(), stack) : scrollRatio;
|
||||
};
|
||||
|
||||
stack.fontSize = function(_) {
|
||||
return arguments.length ? (fontSize = +_, resize(), stack) : fontSize;
|
||||
};
|
||||
|
||||
d3.rebind(stack, dispatch, "on");
|
||||
|
||||
return stack;
|
||||
}
|
1
platform-coop-free-software/stack.v1.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
function stack(){function e(e,t){var n=b[0][t],i=e.sourceEvent=d3.event;try{d3.event=e,h[e.type].call(n,n.__data__,t)}finally{d3.event=i}}function t(e,t){this.__stack__={index:t,active:!1}}function n(){this.__stack__.active||(this.__stack__.active=!0,e({type:"activate"},this.__stack__.index))}function i(){this.__stack__.active&&(this.__stack__.active=!1,e({type:"deactivate"},this.__stack__.index))}function s(){var e=20;o=p[1]/p[0]*innerWidth,r=innerHeight,b.style("height",o+"px").style("box-shadow","0 4px 4px rgba(0,0,0,.3)").filter(function(e,t){return k-1>t}).style("margin-bottom",e+"px"),z.style("font-size",innerWidth/p[0]*u+"px")}function l(){if(o)var e=_;o=p[1]/p[0]*innerWidth,r=innerHeight,w.style("top",(r-o)/2+"px").style("height",o+"px"),M.style("top",function(e){return(e+(1-g)/2)*r+"px"}).style("height",r*g+"px"),z.style("font-size",innerWidth/p[0]*u+"px").style("height",r*k+"px"),isNaN(e)||scrollTo(0,(_=e)*r)}function a(){var t=pageYOffset/r,s=Math.max(0,Math.min(k-1,Math.floor(t+(1+g)/2)));v!==s&&(s===v+1?(K.interrupt().style("display","none").style("opacity",0).style("z-index",0).each(i),K=N.interrupt().style("opacity",1).style("z-index",1),K.transition().each("end",i),N=W.interrupt().style("opacity",0).style("z-index",2).each(n),N.transition().style("opacity",1),W=d3.select(b[0][s+1]).interrupt().style("display","block").style("opacity",0).style("z-index",0)):s===v-1?(W.interrupt().style("display","none").style("opacity",0).style("z-index",0).each(i),W=N.interrupt().style("opacity",1).style("z-index",1),W.transition().each("end",i),N=K.interrupt().style("opacity",0).style("z-index",2).each(n),N.transition().style("opacity",1),K=d3.select(b[0][s-1]).interrupt().style("display","block").style("opacity",0).style("z-index",0)):(K.interrupt().style("display","none").style("opacity",0).style("z-index",0).each(i),N.interrupt().style("display","none").style("opacity",0).style("z-index",0).each(i),W.interrupt().style("display","none").style("opacity",0).style("z-index",0).each(i),K=d3.select(b[0][s-1]).interrupt().style("display","block").style("opacity",0).style("z-index",0).each(i),N=d3.select(b[0][s]).interrupt().style("display","block").style("opacity",1).style("z-index",2).each(n),W=d3.select(b[0][s+1]).interrupt().style("display","block").style("opacity",0).style("z-index",0).each(i)),v=s),e({type:"scroll",offset:_=t},v)}function c(){var e;switch(d3.event.keyCode){case 39:if(d3.event.metaKey)return;case 40:case 34:e=d3.event.metaKey?1/0:1;break;case 37:if(d3.event.metaKey)return;case 38:case 33:e=d3.event.metaKey?-1/0:-1;break;case 32:e=d3.event.shiftKey?-1:1;break;default:return}var t=isNaN(y)?_:y;y=Math.max(0,Math.min(k-1,(e>0?Math.floor(t+(1+g)/2):Math.ceil(t-(1-g)/2))+e)),d3.select(document.documentElement).interrupt().transition().duration(500).tween("scroll",function(){var e=d3.interpolateNumber(pageYOffset,y*r);return function(t){scrollTo(0,e(t))}}).each("end",function(){y=0/0}),d3.event.preventDefault()}var o,r,y,d={},p=[1280,720],u=32,h=d3.dispatch("scroll","activate","deactivate"),x="ontouchstart"in document,f=x?s:l,v=0/0,_=0,g=1/6,b=d3.selectAll("section").style("box-sizing","border-box").style("line-height","1.35em").each(t),k=b.size(),z=d3.select("body").style("margin",0).style("padding",0).style("background","#333");if(x)b.style("position","relative"),d3.select(window).on("resize.stack",f).each(f);else{var m=d3.select("body").insert("div","section").style("background","#000").style("box-shadow","0 8px 16px rgba(0,0,0,.3)").style("padding","1px 0").style("margin-top","-1px").style("z-index",0);b.style("display","none").style("opacity",0).style("z-index",0);var w=d3.selectAll(b[0].concat(m.node())).style("position","fixed").style("left",0).style("top",0).style("width","100%"),M=d3.select("body").append("div").attr("class","indicator").selectAll("div").data(d3.range(b.size())).enter().append("div").style("position","absolute").style("z-index",10).style("left",0).style("width","3px").style("background","linear-gradient(to top,black,white)"),K=d3.select(null),N=d3.select(b[0][0]),W=d3.select(b[0][1]);d3.select(window).on("resize.stack",f).on("scroll.stack",a).on("keydown.stack",c).each(f),d3.timer(function(){return a(),!0})}return d.size=function(e){return arguments.length?(p=[+e[0],+e[1]],f(),d):p},d.scrollRatio=function(e){return arguments.length?(g=+e,f(),d):g},d.fontSize=function(e){return arguments.length?(u=+e,f(),d):u},d3.rebind(d,h,"on"),d}
|