Skip to content

Instantly share code, notes, and snippets.

@tophtucker
Last active September 13, 2019 09:58
Show Gist options
  • Save tophtucker/c2631f2e097d4e3f049f636318abbe98 to your computer and use it in GitHub Desktop.
Save tophtucker/c2631f2e097d4e3f049f636318abbe98 to your computer and use it in GitHub Desktop.
Pagerip

Pinch apart to split the viewport in two, so you can do parallel reading. Pinch together to recombine. Only tested on iPhone & iPad; should work on other multitouch devices?; doesn't do anything (or make any sense) on non-touch single-pointer mouse/trackpad devices, whatever we're calling that classic category these days. But you can see it demo'ed in this tweet.

WHY:

The Web is missing lenses and mirrors and such, I think — images! maps! — fundamental mechanics for getting various views on the same underlying content. We have the freedom to paint any pixel according to any arbitrary rule, and yet it's weirdly hard to . . . like, hold your place in a long document, as one would with a finger marking a page in a book as you skim ahead. Sometimes I highlight the last sentence I read with the mouse so it jumps out when I scroll back up, which is a nice near-unconscious hack that takes advantage of something I know about how document state works; it'll still be there when I scroll back up. It's nice to be able to make that inertial assumption. But it's all so fragile and shallow compared to the deep predictable rules of the "physical world" that enable emergent functionality like bookmarking-by-finger.

I'm sorry if I'm jumping around here. I forget most of why I'm here.

I tried something similar here, with a similarly discombobulated readme, I see.

It's like: take multi-touch seriously!! (Which should set you up nicely to take multi-user seriously!!!) Let independent fingers do independent things on the same underlying things! So they can recombine, augment each other, go in parallel, compare, contrast... like all the mechanics of Braid. :)

Some to-dos, in rough order from narrow to broad:

  • Fix text selection. (Pass single touches through to native behavior, only override for two fingers.)
  • My inertial scroll implementation is a lil glitchy cuz it only remembers the last touchmove dy, so if you stop moving and don't trigger a touchmove before a touchup, the page can jump...
  • Hysteresis! (path dependence): stretch the pages a bit before it snaps into pieces; i.e., provide some resistance to a UI fragmentation that may be slightly jarring.
  • When you recombine pages here, the bottom pane always wins. That's lazy and there's no good reason for it. I'm not sure what the correct behavior would be. Should one win? Should they average? How to indicate priority with gesture? Easiest thing to do would be "bigger pane wins". Maybe there's a metaphor of conservative collisions of different masses; scroll position goes to weighted average of pane sizes ;) ... no....
  • Recursive splitting into arbitrarily many panes!!
  • Problem: it's so easy to scroll that it's hard to, like, robustly mark the beginning of a chapter. So...? Stick panes to a position. Leave a mark where you split. Semantic snapping, like to headers?
  • Save & restore panes. Like: swipe a pane left to save it to some dock / bucket / hopper, right to trash it. Which interacts with a related problem of touch scope bubbling; I wanna zoom out on the whole window..... touch the viewport vs document, etc.
  • Show synchronized document state across views of the document. Start with projecting ghosted pointer & viewport of every pane (view) onto every other. Then, for interactive/dynamic documents... like, if you hover on a button in one view, you should see ghosted pointer ghost-hover in every other. But then, if you change something... what state is shared and what isn't? Braid green-glowy objects unstuck in time. Makes different kinds of mechanics possible.
  • Save all scroll state history (wear & tear) across all readers. Discretize into sessions, read vs skim, discontinuities.
  • Flow content into different containers of different positions, widths, sizes, orientations, while keeping track of field of vision. Flow bottom edge into top edge to make a torus, carousel. Other topologies. Lol.
  • I mean there's generally a lot more to be done with long-reading.

I remember when I made my college newspaper CMS it drove me insane that there was no encoded relationship between an html element representing an article on a homepage / tagpage / authorpage and the article view. They're the same thing!! If the same article appears in different places (e.g. in a category list vs in a most-read list) it should visibly share state. You should be able to see which things represent the same things!! How many unique things are on this page? What am I looking at? What relationships? What's derived from something else, and what's the transformation being applied, like sorted by number of views vs. timestamp?

When I click from a link on the NYT homepage to the article, I want it to resemble a refraction and magnification and focusing.

Naturally I am fond of ZUIs, but they have their drawbacks and haven't really worked, broadly. And I think in part they need more exotic lenses and, uh, optical topologies. I know that sounds super user-hostile lol but I think it could feel really really good and natural and obvious and nobody would have to say bullshit like "optical topologies". It's hard and belabored to try to describe in words before it exists but that's just because it's ... not a literal or linguistic endeavor, maybe? What things are hardest to talk about? A lot of very simple natural human things can be. So it's not an indictment that my words are bad here I think hahahah ok goodnight.

These fragments I have shored against my ruins

<!DOCTYPE html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="stylesheet" href="style.css" />
<body>
<article>
<div>
<h2>T. S. Eliot</h2>
<h1>The Waste Land</h1>
<p class="epigraph">“Nam Sibyllam quidem Cumis ego ipse oculis meis vidi in ampulla pendere, et cum illi pueri dicerent: Σίβυλλα τί θέλεις; respondebat illa: ἀποθανεῖν θέλω.”</p>
<p class="dedication">For Ezra Pound<br/>
<i>il miglior fabbro.</i>
</p>
<h2>I. The Burial of the Dead</h2>
<pre xml:space="preserve">
April is the cruellest month, breeding
Lilacs out of the dead land, mixing
Memory and desire, stirring
Dull roots with spring rain.
Winter kept us warm, covering
Earth in forgetful snow, feeding
A little life with dried tubers.
Summer surprised us, coming over the Starnbergersee
With a shower of rain; we stopped in the colonnade,
And went on in sunlight, into the Hofgarten,
And drank coffee, and talked for an hour.
Bin gar keine Russin, stamm’ aus Litauen, echt deutsch.
And when we were children, staying at the archduke’s,
My cousin’s, he took me out on a sled,
And I was frightened. He said, Marie,
Marie, hold on tight. And down we went.
In the mountains, there you feel free.
I read, much of the night, and go south in the winter.
What are the roots that clutch, what branches grow
Out of this stony rubbish? Son of man,
You cannot say, or guess, for you know only
A heap of broken images, where the sun beats,
And the dead tree gives no shelter, the cricket no relief,
And the dry stone no sound of water. Only
There is shadow under this red rock,
(Come in under the shadow of this red rock),
And I will show you something different from either
Your shadow at morning striding behind you
Or your shadow at evening rising to meet you;
I will show you fear in a handful of dust.
<i>Frisch weht der Wind
Der Heimat zu
Mein Irisch Kind,
Wo weilest du?</i>
“You gave me hyacinths first a year ago;
“They called me the hyacinth girl.”
&mdash;Yet when we came back, late, from the Hyacinth garden,
Your arms full, and your hair wet, I could not
Speak, and my eyes failed, I was neither
Living nor dead, and I knew nothing,
Looking into the heart of light, the silence.
<i>Oed’ und leer das Meer</i>.
Madame Sosostris, famous clairvoyante,
Had a bad cold, nevertheless
Is known to be the wisest woman in Europe,
With a wicked pack of cards. Here, said she,
Is your card, the drowned Phoenician Sailor,
(Those are pearls that were his eyes. Look!)
Here is Belladonna, the Lady of the Rocks,
The lady of situations.
Here is the man with three staves, and here the Wheel,
And here is the one-eyed merchant, and this card,
Which is blank, is something he carries on his back,
Which I am forbidden to see. I do not find
The Hanged Man. Fear death by water.
I see crowds of people, walking round in a ring.
Thank you. If you see dear Mrs. Equitone,
Tell her I bring the horoscope myself:
One must be so careful these days.
Unreal City,
Under the brown fog of a winter dawn,
A crowd flowed over London Bridge, so many,
I had not thought death had undone so many.
Sighs, short and infrequent, were exhaled,
And each man fixed his eyes before his feet.
Flowed up the hill and down King William Street,
To where Saint Mary Woolnoth kept the hours
With a dead sound on the final stroke of nine.
There I saw one I knew, and stopped him, crying “Stetson!
“You who were with me in the ships at Mylae!
“That corpse you planted last year in your garden,
“Has it begun to sprout? Will it bloom this year?
“Or has the sudden frost disturbed its bed?
“Oh keep the Dog far hence, that’s friend to men,
“Or with his nails he’ll dig it up again!
“You! hypocrite lecteur!&mdash;mon semblable,&mdash;mon frère!”
</pre>
<h2>II. A Game of Chess</h2>
<pre xml:space="preserve">
The Chair she sat in, like a burnished throne,
Glowed on the marble, where the glass
Held up by standards wrought with fruited vines
From which a golden Cupidon peeped out
(Another hid his eyes behind his wing)
Doubled the flames of sevenbranched candelabra
Reflecting light upon the table as
The glitter of her jewels rose to meet it,
From satin cases poured in rich profusion.
In vials of ivory and coloured glass
Unstoppered, lurked her strange synthetic perfumes,
Unguent, powdered, or liquid&mdash;troubled, confused
And drowned the sense in odours; stirred by the air
That freshened from the window, these ascended
In fattening the prolonged candle-flames,
Flung their smoke into the laquearia,
Stirring the pattern on the coffered ceiling.
Huge sea-wood fed with copper
Burned green and orange, framed by the coloured stone,
In which sad light a carvèd dolphin swam.
Above the antique mantel was displayed
As though a window gave upon the sylvan scene
The change of Philomel, by the barbarous king
So rudely forced; yet there the nightingale
Filled all the desert with inviolable voice
And still she cried, and still the world pursues,
“Jug Jug” to dirty ears.
And other withered stumps of time
Were told upon the walls; staring forms
Leaned out, leaning, hushing the room enclosed.
Footsteps shuffled on the stair.
Under the firelight, under the brush, her hair
Spread out in fiery points
Glowed into words, then would be savagely still.
“My nerves are bad to-night. Yes, bad. Stay with me.
“Speak to me. Why do you never speak. Speak.
“What are you thinking of? What thinking? What?
“I never know what you are thinking. Think.”
I think we are in rats’ alley
Where the dead men lost their bones.
“What is that noise?”
The wind under the door.
“What is that noise now? What is the wind doing?”
Nothing again nothing.
“Do
“You know nothing? Do you see nothing? Do you remember
“Nothing?”
I remember
Those are pearls that were his eyes.
“Are you alive, or not? Is there nothing in your head?”
But
O O O O that Shakespeherian Rag&mdash;
It’s so elegant
So intelligent
“What shall I do now? What shall I do?”
I shall rush out as I am, and walk the street
“With my hair down, so. What shall we do tomorrow?
“What shall we ever do?”
The hot water at ten.
And if it rains, a closed car at four.
And we shall play a game of chess,
Pressing lidless eyes and waiting for a knock upon the door.
When Lil’s husband got demobbed, I said&mdash;
I didn’t mince my words, I said to her myself,
<small>HURRY UP PLEASE IT’S TIME</small>
Now Albert’s coming back, make yourself a bit smart.
He’ll want to know what you done with that money he gave you
To get yourself some teeth. He did, I was there.
You have them all out, Lil, and get a nice set,
He said, I swear, I can’t bear to look at you.
And no more can’t I, I said, and think of poor Albert,
He’s been in the army four years, he wants a good time,
And if you don’t give it him, there’s others will, I said.
Oh is there, she said. Something o’ that, I said.
Then I’ll know who to thank, she said, and give me a straight look.
<small>HURRY UP PLEASE IT’S TIME</small>
If you don’t like it you can get on with it, I said.
Others can pick and choose if you can’t.
But if Albert makes off, it won’t be for lack of telling.
You ought to be ashamed, I said, to look so antique.
(And her only thirty-one.)
I can’t help it, she said, pulling a long face,
It’s them pills I took, to bring it off, she said.
(She’s had five already, and nearly died of young George.)
The chemist said it would be all right, but I’ve never been the same.
You <i>are</i> a proper fool, I said.
Well, if Albert won’t leave you alone, there it is, I said,
What you get married for if you don’t want children?
<small>HURRY UP PLEASE IT’S TIME</small>
Well, that Sunday Albert was home, they had a hot gammon,
And they asked me in to dinner, to get the beauty of it hot&mdash;
<small>HURRY UP PLEASE IT’S TIME</small>
<small>HURRY UP PLEASE IT’S TIME</small>
Goonight Bill. Goonight Lou. Goonight May. Goonight.
Ta ta. Goonight. Goonight.
Good night, ladies, good night, sweet ladies, good night, good night.
</pre>
<h2>III. The Fire Sermon</h2>
<pre xml:space="preserve">
The river’s tent is broken: the last fingers of leaf
Clutch and sink into the wet bank. The wind
Crosses the brown land, unheard. The nymphs are departed.
Sweet Thames, run softly, till I end my song.
The river bears no empty bottles, sandwich papers,
Silk handkerchiefs, cardboard boxes, cigarette ends
Or other testimony of summer nights. The nymphs are departed.
And their friends, the loitering heirs of city directors;
Departed, have left no addresses.
By the waters of Leman I sat down and wept . . .
Sweet Thames, run softly till I end my song,
Sweet Thames, run softly, for I speak not loud or long.
But at my back in a cold blast I hear
The rattle of the bones, and chuckle spread from ear to ear.
A rat crept softly through the vegetation
Dragging its slimy belly on the bank
While I was fishing in the dull canal
On a winter evening round behind the gashouse
Musing upon the king my brother’s wreck
And on the king my father’s death before him.
White bodies naked on the low damp ground
And bones cast in a little low dry garret,
Rattled by the rat’s foot only, year to year.
But at my back from time to time I hear
The sound of horns and motors, which shall bring
Sweeney to Mrs. Porter in the spring.
O the moon shone bright on Mrs. Porter
And on her daughter
They wash their feet in soda water
<i>Et O ces voix d’enfants, chantant dans la coupole!</i>
Twit twit twit
Jug jug jug jug jug jug
So rudely forc’d.
Tereu
Unreal City
Under the brown fog of a winter noon
Mr. Eugenides, the Smyrna merchant
Unshaven, with a pocket full of currants
C.i.f. London: documents at sight,
Asked me in demotic French
To luncheon at the Cannon Street Hotel
Followed by a weekend at the Metropole.
At the violet hour, when the eyes and back
Turn upward from the desk, when the human engine waits
Like a taxi throbbing waiting,
I Tiresias, though blind, throbbing between two lives,
Old man with wrinkled female breasts, can see
At the violet hour, the evening hour that strives
Homeward, and brings the sailor home from sea,
The typist home at teatime, clears her breakfast, lights
Her stove, and lays out food in tins.
Out of the window perilously spread
Her drying combinations touched by the sun’s last rays,
On the divan are piled (at night her bed)
Stockings, slippers, camisoles, and stays.
I Tiresias, old man with wrinkled dugs
Perceived the scene, and foretold the rest&mdash;
I too awaited the expected guest.
He, the young man carbuncular, arrives,
A small house agent’s clerk, with one bold stare,
One of the low on whom assurance sits
As a silk hat on a Bradford millionaire.
The time is now propitious, as he guesses,
The meal is ended, she is bored and tired,
Endeavours to engage her in caresses
Which still are unreproved, if undesired.
Flushed and decided, he assaults at once;
Exploring hands encounter no defence;
His vanity requires no response,
And makes a welcome of indifference.
(And I Tiresias have foresuffered all
Enacted on this same divan or bed;
I who have sat by Thebes below the wall
And walked among the lowest of the dead.)
Bestows one final patronising kiss,
And gropes his way, finding the stairs unlit . . .
She turns and looks a moment in the glass,
Hardly aware of her departed lover;
Her brain allows one half-formed thought to pass:
“Well now that’s done: and I’m glad it’s over.”
When lovely woman stoops to folly and
Paces about her room again, alone,
She smooths her hair with automatic hand,
And puts a record on the gramophone.
“This music crept by me upon the waters”
And along the Strand, up Queen Victoria Street.
O City city, I can sometimes hear
Beside a public bar in Lower Thames Street,
The pleasant whining of a mandoline
And a clatter and a chatter from within
Where fishmen lounge at noon: where the walls
Of Magnus Martyr hold
Inexplicable splendour of Ionian white and gold.
The river sweats
Oil and tar
The barges drift
With the turning tide
Red sails
Wide
To leeward, swing on the heavy spar.
The barges wash
Drifting logs
Down Greenwich reach
Past the Isle of Dogs.
Weialala leia
Wallala leialala
Elizabeth and Leicester
Beating oars
The stern was formed
A gilded shell
Red and gold
The brisk swell
Rippled both shores
Southwest wind
Carried down stream
The peal of bells
White towers
Weialala leia
Wallala leialala
“Trams and dusty trees.
Highbury bore me. Richmond and Kew
Undid me. By Richmond I raised my knees
Supine on the floor of a narrow canoe.”
“My feet are at Moorgate, and my heart
Under my feet. After the event
He wept. He promised ‘a new start’.
I made no comment. What should I resent?”
“On Margate Sands.
I can connect
Nothing with nothing.
The broken fingernails of dirty hands.
My people humble people who expect
Nothing.”
la la
To Carthage then I came
Burning burning burning burning
O Lord Thou pluckest me out
O Lord Thou pluckest
burning
</pre>
<h2>IV. Death by Water</h2>
<pre xml:space="preserve">
Phlebas the Phoenician, a fortnight dead,
Forgot the cry of gulls, and the deep sea swell
And the profit and loss.
A current under sea
Picked his bones in whispers. As he rose and fell
He passed the stages of his age and youth
Entering the whirlpool.
Gentile or Jew
O you who turn the wheel and look to windward,
Consider Phlebas, who was once handsome and tall as you.
</pre>
<h2>V. What the Thunder Said</h2>
<pre xml:space="preserve">
After the torchlight red on sweaty faces
After the frosty silence in the gardens
After the agony in stony places
The shouting and the crying
Prison and palace and reverberation
Of thunder of spring over distant mountains
He who was living is now dead
We who were living are now dying
With a little patience
Here is no water but only rock
Rock and no water and the sandy road
The road winding above among the mountains
Which are mountains of rock without water
If there were water we should stop and drink
Amongst the rock one cannot stop or think
Sweat is dry and feet are in the sand
If there were only water amongst the rock
Dead mountain mouth of carious teeth that cannot spit
Here one can neither stand nor lie nor sit
There is not even silence in the mountains
But dry sterile thunder without rain
There is not even solitude in the mountains
But red sullen faces sneer and snarl
From doors of mudcracked houses
If there were water
And no rock
If there were rock
And also water
And water
A spring
A pool among the rock
If there were the sound of water only
Not the cicada
And dry grass singing
But sound of water over a rock
Where the hermit-thrush sings in the pine trees
Drip drop drip drop drop drop drop
But there is no water
Who is the third who walks always beside you?
When I count, there are only you and I together
But when I look ahead up the white road
There is always another one walking beside you
Gliding wrapt in a brown mantle, hooded
I do not know whether a man or a woman
&mdash;But who is that on the other side of you?
What is that sound high in the air
Murmur of maternal lamentation
Who are those hooded hordes swarming
Over endless plains, stumbling in cracked earth
Ringed by the flat horizon only
What is the city over the mountains
Cracks and reforms and bursts in the violet air
Falling towers
Jerusalem Athens Alexandria
Vienna London
Unreal
A woman drew her long black hair out tight
And fiddled whisper music on those strings
And bats with baby faces in the violet light
Whistled, and beat their wings
And crawled head downward down a blackened wall
And upside down in air were towers
Tolling reminiscent bells, that kept the hours
And voices singing out of empty cisterns and exhausted wells.
In this decayed hole among the mountains
In the faint moonlight, the grass is singing
Over the tumbled graves, about the chapel
There is the empty chapel, only the wind’s home.
It has no windows, and the door swings,
Dry bones can harm no one.
Only a cock stood on the rooftree
Co co rico co co rico
In a flash of lightning. Then a damp gust
Bringing rain
Ganga was sunken, and the limp leaves
Waited for rain, while the black clouds
Gathered far distant, over Himavant.
The jungle crouched, humped in silence.
Then spoke the thunder
D<small>A</small>
<i>Datta:</i> what have we given?
My friend, blood shaking my heart
The awful daring of a moment’s surrender
Which an age of prudence can never retract
By this, and this only, we have existed
Which is not to be found in our obituaries
Or in memories draped by the beneficent spider
Or under seals broken by the lean solicitor
In our empty rooms
D<small>A</small>
<i>Dayadhvam:</i> I have heard the key
Turn in the door once and turn once only
We think of the key, each in his prison
Thinking of the key, each confirms a prison
Only at nightfall, aetherial rumours
Revive for a moment a broken Coriolanus
D<small>A</small>
<i>Damyata:</i> The boat responded
Gaily, to the hand expert with sail and oar
The sea was calm, your heart would have responded
Gaily, when invited, beating obedient
To controlling hands
I sat upon the shore
Fishing, with the arid plain behind me
Shall I at least set my lands in order?
London Bridge is falling down falling down falling down
<i>Poi s’ascose nel foco che gli affina
Quando fiam ceu chelidon</i>&mdash; O swallow swallow
<i>Le Prince d’Aquitaine à la tour abolie</i>
These fragments I have shored against my ruins
Why then Ile fit you. Hieronymo’s mad againe.
Datta. Dayadhvam. Damyata.
Shantih shantih shantih
</pre>
</div>
</article>
</body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="script.js"></script>
var container = d3.select("body");
var article = d3.select("article");
var clone = d3.select(container.node().appendChild(article.node().cloneNode(true)))
.classed("clone", true);
var touches = [];
var pane = [article, clone];
var panes = 1;
var divider = 0;
var drag = d3.drag()
.on("start", start)
.on("drag", drag)
.on("end", end)
article.call(drag);
function start() {
var paneIndex = d3.event.y < divider * innerHeight ? 1 : 0
touches = touches.filter(d => d.alive || d.pane != paneIndex)
touches.push({
id: d3.event.identifier,
y: d3.event.y,
dy: d3.event.dy,
alive: true,
pane: paneIndex
})
}
function drag() {
var live = d3.touches(this);
if(live.length == 2) {
if(Math.abs(live[0][1] - live[1][1]) > 80) {
if(panes !== 2) {
panes = 2;
pane[1].node().scrollTop = pane[0].node().scrollTop;
pane[1].classed("alive", true)
}
divider = ((live[0][1] + live[1][1]) / 2) / innerHeight
pane[1].style("height", (divider * 100)+"%")
} else {
if(panes !== 1) {
panes = 1;
divider = 0;
pane[1].classed("alive", false)
}
}
}
var pt = touches[touches.map(d => d.id).indexOf(d3.event.identifier)]
if(pt) {
pt.y = d3.event.y
pt.dy = d3.event.dy
pt.pane = d3.event.y < divider * innerHeight ? 1 : 0
pane[pt.pane].node().scrollTop -= pt.dy
}
}
function end() {
var pt = touches[touches.map(d => d.id).indexOf(d3.event.identifier)]
if(pt) {
pt.alive = false;
}
}
// d3.timer(function() {
// console.log(touches)
// })
d3.timer(function() {
touches = touches.filter(d => d.alive || Math.abs(d.dy) > .01);
touches.filter(d => !d.alive).forEach(function(d) {
pane[d.pane].node().scrollTop -= d.dy;
d.dy = d.dy / 1.05;
})
})
html, body {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
h1, h2, h3 {
font-weight: normal;
text-align: center;
}
h1 {
font-size: 2em;
}
h2 {
margin-top: 2em;
}
p.dedication {
text-align: center;
}
pre {
font-family: serif;
}
article {
width: 100%;
overflow: scroll;
height: 100%;
position: fixed;
top: 0;
left: 0;
}
article > div {
max-width: 450px;
margin: 0 auto;
}
@media (max-width: 450px) {
body {
font-size: 11px;
}
article > div {
margin: 0 4px;
}
}
@media (min-width: 560px) {
body {
font-size: 20px;
}
article > div {
max-width: 560px;
}
}
.clone {
pointer-events: none;
opacity: 0;
z-index: 2;
height: 50%;
background: white;
transition: .5s box-shadow, .5s border-bottom;
}
.clone.alive {
opacity: 1;
border-bottom: 1px solid #ccc;
box-shadow: 0px 0px 10px #ccc;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment