Add demos for Intersection Observer API
authorjond@apple.com <jond@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 4 Feb 2019 18:55:31 +0000 (18:55 +0000)
committerjond@apple.com <jond@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 4 Feb 2019 18:55:31 +0000 (18:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=194219

Reviewed by Simon Fraser.

* demos/intersection-observer/lazy-image-load/index.html: Added.
* demos/intersection-observer/lazy-image-load/scripts.js: Added.
(ImageLoader):
(ImageLoader.prototype.findImages):
(ImageLoader.prototype.smallURLForImage):
(ImageLoader.prototype.largeURLForImage):
(ImageLoader.prototype.setupObserver):
(ImageLoader.prototype.intersectionsChanged):
* demos/intersection-observer/lazy-image-load/style.css: Added.
(body):
(section):
(header):
(.main):
(.main img):
(.stories):
(.world, .local):
(.world):
(.local):
(.ad):
(.contents):
(.sidebar):
(.links):
(.main-story):
(.main-story img):
(.top-story):
(.top-story img):
(.mid-story img):
(.link-group):
(.link-group img):
(.link-group ul):
(.link-group li):
(footer):
(footer ul):
(footer a):
(.footer-col):
* demos/intersection-observer/simple/script.js: Added.
(addToLog):
(clearLog):
(stringFromRect):
(intersectedCallback):
* demos/intersection-observer/simple/simple-observer-iframe.html: Added.
* demos/intersection-observer/simple/simple-observer-root-margin.html: Added.
* demos/intersection-observer/simple/simple-observer.html: Added.
* demos/intersection-observer/simple/styles.css: Added.
(body):
(.results):
(.results button):
(h2):
(#logging):
* demos/intersection-observer/triggered-animation/index.html: Added.
* demos/intersection-observer/triggered-animation/script.js: Added.
(AnimationManager):
(AnimationManager.prototype.setupObserver):
(AnimationManager.prototype.intersectionsChanged):
* demos/intersection-observer/triggered-animation/style.css: Added.
(body):
(p):
(.animation-container h1):
(.animation-container):
(.animation-container .box):
(.slide.box):
(.animation-container.visible > .slide.box):
(.slide.animation-container div:nth-of-type(1)):
(.slide.animation-container div:nth-of-type(2)):
(.slide.animation-container div:nth-of-type(3)):
(.spin):
(.animation-container.visible .spin):
(@keyframes spin):
(to):
(.animation-container.svg):
(.animation-container.svg path):
(.animation-container.svg.visible):
(@keyframes stroke-move):
(.animation-container.svg circle):
(.animation-container.svg.visible circle):
(.animation-container.svg circle:nth-of-type(2)):
(.animation-container.svg circle:nth-of-type(3)):
(.animation-container.svg circle:nth-of-type(4)):
(.animation-container.svg circle:nth-of-type(5)):
(@keyframes circle-scale):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@240932 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
Websites/webkit.org/ChangeLog
Websites/webkit.org/demos/intersection-observer/lazy-image-load/index.html [new file with mode: 0644]
Websites/webkit.org/demos/intersection-observer/lazy-image-load/scripts.js [new file with mode: 0644]
Websites/webkit.org/demos/intersection-observer/lazy-image-load/style.css [new file with mode: 0644]
Websites/webkit.org/demos/intersection-observer/simple/script.js [new file with mode: 0644]
Websites/webkit.org/demos/intersection-observer/simple/simple-observer-iframe.html [new file with mode: 0644]
Websites/webkit.org/demos/intersection-observer/simple/simple-observer-root-margin.html [new file with mode: 0644]
Websites/webkit.org/demos/intersection-observer/simple/simple-observer.html [new file with mode: 0644]
Websites/webkit.org/demos/intersection-observer/simple/styles.css [new file with mode: 0644]
Websites/webkit.org/demos/intersection-observer/triggered-animation/index.html [new file with mode: 0644]
Websites/webkit.org/demos/intersection-observer/triggered-animation/script.js [new file with mode: 0644]
Websites/webkit.org/demos/intersection-observer/triggered-animation/style.css [new file with mode: 0644]

index eac21b5..93467ae 100644 (file)
@@ -1,3 +1,91 @@
+2019-02-04  Jon Davis  <jond@apple.com>
+
+        Add demos for Intersection Observer API
+        https://bugs.webkit.org/show_bug.cgi?id=194219
+
+        Reviewed by Simon Fraser.
+
+        * demos/intersection-observer/lazy-image-load/index.html: Added.
+        * demos/intersection-observer/lazy-image-load/scripts.js: Added.
+        (ImageLoader):
+        (ImageLoader.prototype.findImages):
+        (ImageLoader.prototype.smallURLForImage):
+        (ImageLoader.prototype.largeURLForImage):
+        (ImageLoader.prototype.setupObserver):
+        (ImageLoader.prototype.intersectionsChanged):
+        * demos/intersection-observer/lazy-image-load/style.css: Added.
+        (body):
+        (section):
+        (header):
+        (.main):
+        (.main img):
+        (.stories):
+        (.world, .local):
+        (.world):
+        (.local):
+        (.ad):
+        (.contents):
+        (.sidebar):
+        (.links):
+        (.main-story):
+        (.main-story img):
+        (.top-story):
+        (.top-story img):
+        (.mid-story img):
+        (.link-group):
+        (.link-group img):
+        (.link-group ul):
+        (.link-group li):
+        (footer):
+        (footer ul):
+        (footer a):
+        (.footer-col):
+        * demos/intersection-observer/simple/script.js: Added.
+        (addToLog):
+        (clearLog):
+        (stringFromRect):
+        (intersectedCallback):
+        * demos/intersection-observer/simple/simple-observer-iframe.html: Added.
+        * demos/intersection-observer/simple/simple-observer-root-margin.html: Added.
+        * demos/intersection-observer/simple/simple-observer.html: Added.
+        * demos/intersection-observer/simple/styles.css: Added.
+        (body):
+        (.results):
+        (.results button):
+        (h2):
+        (#logging):
+        * demos/intersection-observer/triggered-animation/index.html: Added.
+        * demos/intersection-observer/triggered-animation/script.js: Added.
+        (AnimationManager):
+        (AnimationManager.prototype.setupObserver):
+        (AnimationManager.prototype.intersectionsChanged):
+        * demos/intersection-observer/triggered-animation/style.css: Added.
+        (body):
+        (p):
+        (.animation-container h1):
+        (.animation-container):
+        (.animation-container .box):
+        (.slide.box):
+        (.animation-container.visible > .slide.box):
+        (.slide.animation-container div:nth-of-type(1)):
+        (.slide.animation-container div:nth-of-type(2)):
+        (.slide.animation-container div:nth-of-type(3)):
+        (.spin):
+        (.animation-container.visible .spin):
+        (@keyframes spin):
+        (to):
+        (.animation-container.svg):
+        (.animation-container.svg path):
+        (.animation-container.svg.visible):
+        (@keyframes stroke-move):
+        (.animation-container.svg circle):
+        (.animation-container.svg.visible circle):
+        (.animation-container.svg circle:nth-of-type(2)):
+        (.animation-container.svg circle:nth-of-type(3)):
+        (.animation-container.svg circle:nth-of-type(4)):
+        (.animation-container.svg circle:nth-of-type(5)):
+        (@keyframes circle-scale):
+
 2019-01-25  Jon Davis  <jond@apple.com>
 
         Added feature status entry for "Removed in Preview"
diff --git a/Websites/webkit.org/demos/intersection-observer/lazy-image-load/index.html b/Websites/webkit.org/demos/intersection-observer/lazy-image-load/index.html
new file mode 100644 (file)
index 0000000..a9d35ff
--- /dev/null
@@ -0,0 +1,237 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+    <link rel="stylesheet" href="style.css">
+    <script src="scripts.js"></script>
+
+    <title>Sign of the Times</title>
+</head>
+<body>
+
+<header>
+    <h1>Sign Of The Times</h1>
+</header>
+
+<section class="main">
+    <div style="grid-area: left">
+        <section class="top-story">
+            <h2>The 13 Biggest Aqueducts From The Twelve Tables</h2>
+            <img data-id="99" data-size-small="20/15" data-size-large="200/150">
+            <p>Suspendisse mauris. Fusce accumsan mollis eros. Pellentesque a diam sit amet mi ullamcorper vehicula. Integer adipiscing risus a sem. Nullam quis massa sit amet nibh viverra malesuada. Nunc sem lacus, accumsan quis, faucibus non, congue vel, arcu.</p>
+        </section>
+
+        <section class="top-story">
+            <h2>19 Praefects Who Need To Be Banned From Celebrating Saturnalia</h2>
+            <img data-id="1021" data-size-small="20/15" data-size-large="200/150">
+            <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+        </section>
+
+        <section class="top-story">
+            <h2>33 Problems Only Cynics Will Understand</h2>
+            <img data-id="302" data-size-small="20/15" data-size-large="200/150">
+            <p>Morbi interdum mollis sapien. Sed ac risus. Phasellus lacinia, magna a ullamcorper laoreet, lectus arcu pulvinar risus, vitae facilisis libero dolor a purus. Sed vel lacus. Mauris nibh felis, adipiscing varius, adipiscing in, lacinia vel, tellus.</p>
+        </section>
+    </div>
+
+    <section style="grid-area: right" class="main-story">
+        <h2>The 22 Greek Tragedies That Should Exist But Don't</h2>
+        <img data-id="476" data-size-small="52/36" data-size-large="520/360">
+    <p>
+    Sem at ac dolor ante, metus ac sed ac quisque eget eget, neque morbi inceptos consequat suspendisse arcu vitae. Et animi dignissim magna sed vivamus, mauris vivamus dapibus quis, dictum lobortis rhoncus sed fringilla in, congue libero sagittis, et at. Ornare gravida leo orci, vel vel turpis, faucibus rutrum duis blandit veniam placerat suscipit, vehicula nam sit vel ligula sapien arcu. Suspendisse purus vivamus sapien integer rutrum pede. In odio neque erat, vestibulum ridiculus vivamus et sapien, lorem in aliquip eget ante litora, etiam feugiat porta nulla arcu.</p>
+    <p>
+    Elit nulla lectus ipsa, felis in. Leo suscipit porttitor sagittis sed pellentesque, aptent praesent morbi ipsum facilisi in, erat porttitor class amet. Sed facilisi vestibulum quam ridiculus dictumst, et tempor. Tempus quam suspendisse velit ante, ultrices risus, sed wisi bibendum. Condimentum dictum donec est natoque, pretium vitae mollis magna proin libero lectus, cras feugiat id condimentum. Vitae hac duis dui augue, arcu sit libero ligula, lacus libero quis pede. In sed semper, mi ac. Dui cursus eget magna integer, eu commodo metus. Magna sit in et sed wisi, in autem vel quis, nam mauris tincidunt. A mauris mauris, inceptos ultrices a expedita, per tortor ante vitae eget.</p>
+    <p>
+    Sem vestibulum ullamcorper non suspendisse, cum risus ac, pulvinar scelerisque ac phasellus amet aliquam auctor. Et lectus lacus sed cursus, molestie nec. Integer quis torquent ullamcorper. Vitae auctor turpis commodo et nec bibendum, iaculis nullam nulla quam. Cras aliquam urna congue erat sit, nec mi purus orci interdum aenean turpis, interdum enim eleifend lobortis, et quam natoque metus tellus, quis quam mauris. Porta volutpat posuere integer quis mauris. Vitae lectus faucibus phasellus tincidunt. Vestibulum varius, ante a nisl egestas sit urna porta. Lectus et a consectetur nec, vitae erat porttitor eu sit eveniet, arcu sociis rhoncus elit ut ac, sit labore ullamcorper sit. Sed nec facilisi placerat, et suscipit.</p>
+    <p>
+    Consequat purus lectus, nibh suspendisse viverra pede. Velit laoreet arcu nec rutrum tristique sit, nulla quis tellus cras justo aenean adipiscing, non neque sodales. Neque lectus nam elementum malesuada, proin sapien. Aliquet id congue proin ut eget nec, erat lectus. Ullamcorper sem nibh consequat massa dolor, erat malesuada iaculis montes eget est, enim euismod, dolores orci, vitae massa velit dolor.</p>
+    <p>
+    Varius nunc nullam laoreet risus fuga, quisque quam litora in maecenas a, nec integer tincidunt, parturient fringilla mollis lectus urna molestie sociis, phasellus neque nibh laoreet ullamcorper egestas. Quisque arcu, eget erat a justo arcu penatibus donec, accumsan id, lacus quis pellentesque ultrices. Justo rutrum in, orci tincidunt accumsan, volutpat cumque augue. Hendrerit posuere, et aliquam mauris placerat id mollis, mollis erat massa commodo fusce, urna hac proin. Sunt morbi erat faucibus ante, amet ut sed vel, pharetra quis commodo consequat molestie commodo, mattis ut duis in. Nunc est, in fringilla, tortor tortor, amet libero lorem congue orci tortor dictum, tortor suspendisse faucibus vitae. Suspendisse vehicula porttitor eget nunc quam. Et sed vulputate aut. Orci quis at.</p>
+</section>
+</section>
+
+<section class="sidebar">
+    <h2>This Week</h2>
+    <ul>
+        <li>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat</li>
+        <li>Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus.</li>
+        <li>Phasellus ultrices nulla quis nibh. Quisque a lectus. Donec consectetuer ligula vulputate sem tristique cursus. Nam nulla quam, gravida non, commodo a, sodales sit amet, nisi.</li>
+        <li>Pellentesque fermentum dolor. Aliquam quam lectus, facilisis auctor, ultrices ut, elementum vulputate, nunc.</li>
+        <li>Sed adipiscing ornare risus. Morbi est est, blandit sit amet, sagittis vel, euismod vel, velit. Pellentesque egestas sem. Suspendisse commodo ullamcorper magna.</li>
+        <li>Nulla sed leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</li>
+        <li>Fusce lacinia arcu et nulla. Nulla vitae mauris non felis mollis faucibus.</li>
+        <li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</li>
+        <li>Donec nec justo eget felis facilisis fermentum. Aliquam porttitor mauris sit amet orci. Aenean dignissim pellentesque felis.</li>
+        <li>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.    </li>
+    </ul>
+
+    <h2>Business</h2>
+    <ul>
+        <li>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat</li>
+        <li>Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus.</li>
+        <li>Phasellus ultrices nulla quis nibh. Quisque a lectus. Donec consectetuer ligula vulputate sem tristique cursus. Nam nulla quam, gravida non, commodo a, sodales sit amet, nisi.</li>
+        <li>Pellentesque fermentum dolor. Aliquam quam lectus, facilisis auctor, ultrices ut, elementum vulputate, nunc.</li>
+        <li>Sed adipiscing ornare risus. Morbi est est, blandit sit amet, sagittis vel, euismod vel, velit. Pellentesque egestas sem. Suspendisse commodo ullamcorper magna.</li>
+        <li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</li>
+        <li>Donec nec justo eget felis facilisis fermentum. Aliquam porttitor mauris sit amet orci. Aenean dignissim pellentesque felis.</li>
+        <li>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.    </li>
+    </ul>
+
+    <h2>Sportsball</h2>
+    <ul>
+        <li>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat</li>
+        <li>Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus.</li>
+        <li>Phasellus ultrices nulla quis nibh. Quisque a lectus. Donec consectetuer ligula vulputate sem tristique cursus. Nam nulla quam, gravida non, commodo a, sodales sit amet, nisi.</li>
+        <li>Pellentesque fermentum dolor. Aliquam quam lectus, facilisis auctor, ultrices ut, elementum vulputate, nunc.</li>
+        <li>Sed adipiscing ornare risus. Morbi est est, blandit sit amet, sagittis vel, euismod vel, velit. Pellentesque egestas sem. Suspendisse commodo ullamcorper magna.</li>
+        <li>Nulla sed leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</li>
+        <li>Fusce lacinia arcu et nulla. Nulla vitae mauris non felis mollis faucibus.</li>
+        <li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</li>
+    </ul>
+</section>
+
+<section class="stories">
+    <h2 style="grid-area: opinions">Opinions</h2>
+    <div class="mid-story">
+        <img data-id="576" data-size-small="22/15" data-size-large="220/150">
+        <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+    </div>
+    <div class="mid-story">
+        <img data-id="577" data-size-small="22/15" data-size-large="220/150">
+        <p>Phasellus pede arcu, dapibus eu, fermentum et, dapibus sed, urna.</p>
+    </div>
+    <div class="mid-story">
+        <img data-id="568" data-size-small="22/15" data-size-large="220/150">
+        <p>Suspendisse ac urna. Etiam pellentesque mauris ut lectus. Nunc tellus ante, mattis eget, gravida vitae, ultricies ac, leo.</p>
+    </div>
+    <div class="mid-story">
+        <img data-id="579" data-size-small="22/15" data-size-large="220/150">
+        <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+    </div>
+    <div class="mid-story">
+        <img data-id="580" data-size-small="22/15" data-size-large="220/150">
+        <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+    </div>
+    <div class="mid-story">
+        <img data-id="583" data-size-small="22/15" data-size-large="220/150">
+        <p>Nullam quis massa sit amet nibh viverra malesuada. Nunc sem lacus, accumsan quis, faucibus non, congue vel, arcu</p>
+    </div>
+
+    <h2 style="grid-area: more">More Top Stories</h2>
+    <div class="mid-story">
+        <img data-id="586" data-size-small="22/15" data-size-large="220/150">
+        <p>Morbi interdum mollis sapien. Sed ac risus. Phasellus lacinia, magna a ullamcorper laoreet, lectus arcu pulvinar risus, vitae facilisis libero dolor a purus. Sed vel lacus.</p>
+    </div>
+    <div class="mid-story">
+        <img data-id="557" data-size-small="22/15" data-size-large="220/150">
+        <p>Fusce accumsan mollis eros. Pellentesque a diam sit amet mi ullamcorper vehicula. Integer adipiscing risus a sem.</p>
+    </div>
+    <div class="mid-story">
+        <img data-id="588" data-size-small="22/15" data-size-large="220/150">
+        <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+    </div>
+    <div class="mid-story">
+        <img data-id="526" data-size-small="22/15" data-size-large="220/150">
+        <p>Cum sociis natoque penatibus et magnis xdis parturient montes, nascetur ridiculus mus.</p>
+    </div>
+    <div class="mid-story">
+        <img data-id="527" data-size-small="22/15" data-size-large="220/150">
+        <p>Pellentesque adipiscing eros ut libero. Ut condimentum mi vel tellus. Suspendisse laoreet. Fusce ut est sed dolor gravida convallis.</p>
+    </div>
+    <div class="mid-story">
+        <img data-id="539" data-size-small="22/15" data-size-large="220/150">
+        <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+    </div>
+</section>
+
+<section class="world">
+    <section>
+        <div class="link-group">
+            <img data-id="439" data-size-small="36/24" data-size-large="360/240">
+            <ul>
+                <li>The 39 Greatest Olives Of The Tetrachy</li>
+                <li>28 Things Only Etruscan Miners Will Understand</li>
+                <li>12 Papyri That Should Be Illegal</li>
+                <li>50 Pack Animals That Will Restore Your Faith In Jupiter</li>
+                <li>The 34 Most Successful State Religions Of The Reign of Augustus</li>
+                <li>The 42 Most Picturesque Colosseums From Suetonius' "The Twelve Caesars"</li>
+            </ul>
+        </div>
+    </section>
+
+    <section>
+        <div class="link-group">
+            <img data-id="603" data-size-small="36/24" data-size-large="360/240">
+            <ul>
+                <li>17 Painful Truths Only Carthaginians Will Understand</li>
+                <li>The 11 Most Awkward Tributes Of The Regin of Dioletian</li>
+                <li>The 10 Most Arrogant Proscriptions Of All Time</li>
+                <li>24 Praetorian Guards Who Will Make You Feel Like A Genius</li>
+                <li>40 Stoics Who Have Performed For Dictators</li>
+                <li>The 30 Most Beloved Grapes Of The Year of the Four Emperors</li>
+            </ul>
+        </div>
+    </section>
+
+    <section>
+        <div class="link-group">
+            <img data-id="604" data-size-small="36/24" data-size-large="360/240">
+            <ul>
+                <li>41 Triumvirs Who Absolutely Nailed It In 82 B.C.</li>
+                <li>23 Plebs Who Tried To Find An Original Way To Go As Cleopatra For Saturnalia</li>
+                <li>13 Quaestors Who Are Clearly Being Raised Right</li>
+                <li>17 Gladitorial Games That Prove You And Your Mother Are The Same Person</li>
+                <li>The 26 Best Imperators From The Works Of Ovid</li>
+                <li>25 Problems Only Stoics Will Understand</li>
+            </ul>
+        </div>
+    </section>
+</section>
+
+<section class="local">
+    <section>
+        <div class="link-group">
+            <img data-id="605" data-size-small="36/24" data-size-large="360/240">
+            <ul>
+                <li>50 Consuls Who Have Performed For Dictators</li>
+                <li>37 Mercenaries Who Had A Worse Year Than You</li>
+                <li>The 23 Most Popular Togas From Caesar's City-Wide Triumph</li>
+                <li>44 Things Only Patriarchs Will Understand</li>
+                <li>The 33 Slowest Sarcophagi From The Twelve Tables</li>
+                <li>The 49 Most Beautiful Colosseums In Eastern Gaul</li>
+            </ul>
+        </div>
+    </section>
+
+    <section>
+        <div class="link-group">
+            <img data-id="606" data-size-small="36/24" data-size-large="360/240">
+            <ul>
+                <li>The 27 Most Unbelievably Flawless And Life-Changing Papyri Since The Fall Of The Republic</li>
+                <li>21 Etruscan Miners Who Tried To Find An Original Way To Go As Cleopatra For Saturnalia</li>
+                <li>30 Deities Who Will Make You Feel Like A Genius</li>
+                <li>The 46 Cutest Triumvirates From Carthage</li>
+                <li>15 Epic Poems That Will Make Your Skin Crawl</li>
+                <li>The 16 Provinces That Will Haunt Your Dreams</li>
+            </ul>
+        </div>
+    </section>
+
+    <section>
+        <div class="link-group">
+            <img data-id="607" data-size-small="36/24" data-size-large="360/240">
+            <ul>
+                <li>18 Painful Truths Only Tribunes Will Understand</li>
+                <li>The 19 Funniest Monuments to Artemis Of The Regin of Dioletian</li>
+                <li>45 Epicureans Who Absolutely Nailed It In 82 B.C.</li>
+                <li>The 29 Most Arrogant Denarii From Suetonius' "The Twelve Caesars"</li>
+                <li>31 Things Only Dictators Will Understand</li>
+                <li>The 36 Most Wanted Comedies From The Works Of Ovid</li>
+            </ul>
+        </div>
+    </section>
+</section>
+
+</body>
+</html>
diff --git a/Websites/webkit.org/demos/intersection-observer/lazy-image-load/scripts.js b/Websites/webkit.org/demos/intersection-observer/lazy-image-load/scripts.js
new file mode 100644 (file)
index 0000000..d6071cf
--- /dev/null
@@ -0,0 +1,61 @@
+
+let imageLoader = undefined;
+
+class ImageLoader {
+    constructor()
+    {
+        this.setupObserver();
+        this.findImages();
+    }
+    
+    findImages()
+    {
+        let images = document.getElementsByTagName('img');
+        for (let image of images) {
+            image.src = this.smallURLForImage(image);
+            this.observer.observe(image);
+        }
+    }
+    
+    smallURLForImage(image)
+    {
+        let imageID = image.getAttribute('data-id');
+        let smallSize = image.getAttribute('data-size-small');
+        return `https://picsum.photos/${smallSize}?image=${imageID}`;
+    }
+
+    largeURLForImage(image)
+    {
+        let imageID = image.getAttribute('data-id');
+        let largeSize = image.getAttribute('data-size-large');
+        return `https://picsum.photos/${largeSize}?image=${imageID}`;
+    }
+
+    setupObserver()
+    {
+        let options = { 
+            rootMargin: "0px 0px" 
+        };
+        this.observer = new IntersectionObserver(observations => {
+            this.intersectionsChanged(observations);
+        }, options);
+    }
+    
+    intersectionsChanged(observations)
+    {
+        for (let obs of observations) {
+            let image = obs.target;
+            // If we haven't done it yet
+            if (obs.isIntersecting) {
+                // timeout just for demo
+                setTimeout(() => {
+                    image.src = this.largeURLForImage(image);
+                }, 500);
+            }
+        }
+    }
+};
+
+window.addEventListener('load', () => {
+    imageLoader = new ImageLoader();
+}, false);
\ No newline at end of file
diff --git a/Websites/webkit.org/demos/intersection-observer/lazy-image-load/style.css b/Websites/webkit.org/demos/intersection-observer/lazy-image-load/style.css
new file mode 100644 (file)
index 0000000..cb76410
--- /dev/null
@@ -0,0 +1,164 @@
+
+body {
+    margin: 0 100px;
+    font-family: Times;
+    display: grid;
+    grid-template-columns: 30% 20% auto 20%;
+    grid-template-rows: auto;
+    grid-template-areas: 
+        "header header header header"
+        "main main main sidebar"
+        "stories stories stories sidebar"
+        "world world world world"
+        "local local local local"
+        "links links links links"
+        "footer footer footer footer";
+    
+    line-height: 1.4em;
+}
+
+section {
+    margin: 10px;
+}
+
+header {
+    grid-area: header;
+    font-size: 24pt;
+    text-align: center;
+    margin-top: 40px;
+    border-top: 1px solid gray;
+    border-bottom: 1px solid gray;
+}
+
+.main {
+    grid-area: main;
+
+    display: grid;
+    grid-template-columns: 40% auto;
+    grid-template-areas: 
+        "left right"
+        "left right"
+}
+
+.main img {
+    float: right;
+    margin: 5px;
+    width: 200px;
+    height: 150px;
+}
+
+.stories {
+    grid-area: stories;
+
+    display: grid;
+    grid-template-columns: 20% auto;
+    grid-template-areas: 
+        "opinions . ."
+        "opinions . ."
+        "opinions . ."
+        "more . ."
+        "more . ."
+        "more . .";
+}
+
+.world, .local {
+    display: grid;
+    grid-template-columns: auto auto auto;
+}
+
+.world {
+    grid-area: world;
+}
+
+.local {
+    grid-area: local;
+}
+
+.ad {
+    grid-area: ad;
+}
+
+.contents {
+    grid-area: contents;
+}
+
+.sidebar {
+    grid-area: sidebar;
+}
+
+
+.links {
+    grid-area: links;
+    border-top: 1px solid gray;
+    text-align: center;
+    margin: 20px;
+    padding: 20px;
+}
+
+.main-story {
+    padding: 10px;
+}
+
+.main-story img {
+    width: 520px;
+    height: 360px;
+}
+
+.top-story {
+    padding: 10px;
+}
+
+.top-story img {
+    float: right;
+    margin: 5px;
+}
+
+.mid-story img {
+    width: 200px;
+    height: 150px;
+}
+
+.link-group {
+    font-weight: bold;
+    font-family: Helvetica;
+    padding: 20px;
+}
+
+.link-group img {
+    display: block;
+    width: 100%;
+}
+
+.link-group ul {
+    list-style-type: none;
+    margin: 0;
+    padding: 0;
+}
+
+.link-group li {
+    display: block;
+    line-height: 1.5em;
+}
+
+footer {
+    grid-area: footer;
+    border-top: 1px solid gray;
+    border-bottom: 1px solid gray;
+
+    display: grid;
+    grid-template-columns: auto auto auto auto;
+}
+
+footer ul {
+    list-style-type: none;
+}
+
+footer a {
+    text-decoration: none;
+    color: black;
+}
+
+.footer-col {
+    float: left;
+}
+
diff --git a/Websites/webkit.org/demos/intersection-observer/simple/script.js b/Websites/webkit.org/demos/intersection-observer/simple/script.js
new file mode 100644 (file)
index 0000000..957c41a
--- /dev/null
@@ -0,0 +1,28 @@
+
+function addToLog(s)
+{
+    let logging = document.getElementById('logging');
+    logging.textContent += s + "\n";
+    logging.scrollTop = 400000;
+}
+
+function clearLog()
+{
+    let logging = document.getElementById('logging');
+    logging.textContent = '';
+}
+
+function stringFromRect(rect)
+{
+    return `${rect.x}, ${rect.y} ${rect.width} x ${rect.height}`;
+}
+
+function intersectedCallback(entries)
+{
+    addToLog('');
+    for (var entry of entries) {
+        addToLog('time: ' + entry.time.toFixed(2));
+        addToLog('intersection:        ' + stringFromRect(entry.intersectionRect));
+        addToLog('intersection ratio:  ' + entry.intersectionRatio.toFixed(3));
+    }
+}
diff --git a/Websites/webkit.org/demos/intersection-observer/simple/simple-observer-iframe.html b/Websites/webkit.org/demos/intersection-observer/simple/simple-observer-iframe.html
new file mode 100644 (file)
index 0000000..3f5f3fc
--- /dev/null
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>Simple Intersection Obsever in iframe</title>
+    <meta name="viewport" content="width=600">
+    <link rel="stylesheet" href="styles.css">
+    <script src="script.js"></script>
+    
+    <style>
+        body {
+            height: 5000px;
+            font-family: Helvetica;
+        }
+
+        section {
+            margin-top: 2000px;
+        }
+
+        iframe {
+            width: 400px;
+            height: 300px;
+        }
+        
+        h2 {
+            margin-top: 0.2em;
+            margin-bottom: 0.25em;
+        }
+    </style>
+    <script>
+        var observer;
+        function doSetup()
+        {
+            observer = new IntersectionObserver(intersectedCallback, { threshold: [
+                0,
+                0.1,
+                0.2,
+                0.3,
+                0.4,
+                0.5,
+                0.6,
+                0.7,
+                0.8,
+                0.9,
+                1
+            ] });
+            
+            let iframe = document.getElementById('iframe');
+            let target = iframe.contentDocument.getElementById('target');
+            observer.observe(target);
+        }
+        window.addEventListener('load', doSetup, false);
+    </script>
+</head>
+<body>
+
+<div class="results">
+<h2>Logging</h2>
+<button onclick="clearLog()" class="clear">🗑</button>
+<pre id="logging"></pre>
+</div>
+
+<p>Scroll down to see the iframe.</p>
+<section>
+<h2>&lt;iframe&gt;</h2>
+<iframe id="iframe" srcdoc="<style>
+        body {
+            height: 5000px;
+            font-family: Helvetica;
+        }
+        
+        #target {
+            position: absolute;
+            left: 10px;
+            width: 170px;
+            height: 200px;
+            top: 2800px;
+            padding: 40px;
+            box-sizing: border-box;
+            font-size: 24pt;
+            background-color: rgba(119, 104, 113, 1);
+            color: white;
+            text-align: center;
+            border-radius: 10px;
+        }
+</style>
+<p>Scroll down to see the target</p>
+<div id='target'>Target</div>"></iframe>
+</section>
+
+</body>
+</html>
diff --git a/Websites/webkit.org/demos/intersection-observer/simple/simple-observer-root-margin.html b/Websites/webkit.org/demos/intersection-observer/simple/simple-observer-root-margin.html
new file mode 100644 (file)
index 0000000..1ac9ce0
--- /dev/null
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>Simple Intersection Obsever</title>
+    <meta name="viewport" content="width=600">
+    <link rel="stylesheet" href="styles.css">
+    <script src="script.js"></script>
+    <style>
+        body {
+            font-family: Helvetica;
+            height: 6000px;
+        }
+        
+        #target {
+            position: absolute;
+            left: 60px;
+            width: 200px;
+            height: 200px;
+            top: 2800px;
+            padding: 40px;
+            box-sizing: border-box;
+            font-size: 24pt;
+            background-color: rgba(119, 104, 113, 1);
+            color: white;
+            text-align: center;
+            border-radius: 10px;
+        }
+        
+        body .root-margin {
+            position: fixed;
+            width: 100%;
+            height: 100%;
+            top: 0;
+            left: 0;
+            border: 50px solid rgba(0, 0, 0, 0.2);
+            box-sizing: border-box;
+            pointer-events: none;
+        }
+    </style>
+    <script>
+        var observer;   
+
+        function doSetup()
+        {
+            observer = new IntersectionObserver(intersectedCallback, {
+                threshold: [ 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1 ],
+                rootMargin: '-50px'
+            });
+            
+            let target = document.getElementById('target');
+            observer.observe(target);
+        }
+        window.addEventListener('load', doSetup, false);
+    </script>
+</head>
+<body>
+
+<p>Scroll down to see the target</p>
+<div class="results">
+<h2>Logging</h2>
+<button onclick="clearLog()" class="clear">🗑</button>
+<pre id="logging"></pre>
+</div>
+
+<div id="target">Target</div>
+
+<div class="root-margin"></div>
+
+</body>
+</html>
diff --git a/Websites/webkit.org/demos/intersection-observer/simple/simple-observer.html b/Websites/webkit.org/demos/intersection-observer/simple/simple-observer.html
new file mode 100644 (file)
index 0000000..8d2dfcc
--- /dev/null
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>Simple Intersection Obsever</title>
+    <meta name="viewport" content="width=600">
+    <link rel="stylesheet" href="styles.css">
+    <script src="script.js"></script>
+    <style>
+        body {
+            font-family: Helvetica;
+            height: 6000px;
+        }
+        
+        #target {
+            position: absolute;
+            left: 60px;
+            width: 200px;
+            height: 200px;
+            top: 2800px;
+            padding: 40px;
+            box-sizing: border-box;
+            font-size: 24pt;
+            background-color: rgba(119, 104, 113, 1);
+            color: white;
+            text-align: center;
+            border-radius: 10px;
+        }
+        
+    </style>
+    <script>
+        var observer;
+        function doSetup()
+        {
+            observer = new IntersectionObserver(intersectedCallback, {
+                threshold: [ 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1 ]
+            });
+            
+            let target = document.getElementById('target');
+            observer.observe(target);
+        }
+        window.addEventListener('load', doSetup, false);
+    </script>
+</head>
+<body>
+
+<p>Scroll down to see the target</p>
+<div class="results">
+<h2>Logging</h2>
+<button onclick="clearLog()" class="clear">🗑</button>
+<pre id="logging"></pre>
+</div>
+
+<div id="target">Target</div>
+
+</body>
+</html>
diff --git a/Websites/webkit.org/demos/intersection-observer/simple/styles.css b/Websites/webkit.org/demos/intersection-observer/simple/styles.css
new file mode 100644 (file)
index 0000000..44abcc1
--- /dev/null
@@ -0,0 +1,43 @@
+body {
+    background-color: rgba(240, 247, 238, 1);
+}
+
+.results {
+    position: fixed;
+    font-size: 16px;
+    top: 10px;
+    left: 450px;
+    width: calc(100% - 500px);
+    height: 600px;
+    padding: 10px;
+    background-color: rgba(0, 0, 0, 0.1);
+    border-radius: 10px;
+    border: 3px solid gray;
+    margin: 5px;
+    color: gray;
+}
+
+.results button {
+    position: absolute;
+    top: 10px;
+    right: 10px;
+    padding: 5px;
+    border: none;
+    background-color: transparent;
+    -webkit-appearance: none;
+}
+
+h2 {
+    margin-top: 0.2em;
+    margin-bottom: 0.25em;
+}
+
+#logging {
+    width: 100%;
+    height: calc(100% - 3.5em);
+    font-size: 16px;
+    overflow: scroll;
+    -webkit-overflow-scrolling: touch;
+    margin: 5px;
+    color: gray;
+}
diff --git a/Websites/webkit.org/demos/intersection-observer/triggered-animation/index.html b/Websites/webkit.org/demos/intersection-observer/triggered-animation/index.html
new file mode 100644 (file)
index 0000000..3ef0860
--- /dev/null
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width">
+    <link rel="stylesheet" href="style.css">
+    <script src="script.js"></script>
+    <title>Triggered Animation</title>
+</head>
+<body>
+<p>Scroll down to see the first animation.</p>
+<div class="slide animation-container">
+    <h1>Slide in after delay</h1>
+    <div class="slide box"></div>
+    <div class="slide box"></div>
+    <div class="slide box"></div>
+</div>
+<p>Keep scrolling to see the next animation.</p>
+<div class="animation-container">
+    <h1>Animate after delay</h1>
+    <div class="spin box">
+    </div>
+</div>
+<p>Keep scrolling to see the next animation.</p>
+<div class="animation-container svg">
+    <h1>Animate after delay</h1>
+    <svg viewBox="0 0 800 400">
+        <path d="M 40,80 c 30,40 60,40 90,0 c 30,-40 60,-40 90,0 c 30,40 60,40 90,0 c 30,-40 60,-40 90,0 c 30,40 60,40 90,0 c 30,-40 60,-40 90,0 c 30,40 60,40 90,0 c 30,-40 60,-40 90,0"/>
+        <path d="M 40,110 c 30,40 60,40 90,0 c 30,-40 60,-40 90,0 c 30,40 60,40 90,0 c 30,-40 60,-40 90,0 c 30,40 60,40 90,0 c 30,-40 60,-40 90,0 c 30,40 60,40 90,0 c 30,-40 60,-40 90,0"/>
+        <path d="M 40,140 c 30,40 60,40 90,0 c 30,-40 60,-40 90,0 c 30,40 60,40 90,0 c 30,-40 60,-40 90,0 c 30,40 60,40 90,0 c 30,-40 60,-40 90,0 c 30,40 60,40 90,0 c 30,-40 60,-40 90,0"/>
+        <circle cx="250" cy="270"/>
+        <circle cx="530" cy="270"/>
+        <circle cx="320" cy="270"/>
+        <circle cx="460" cy="270"/>
+        <circle cx="390" cy="270"/>
+    </svg>
+</div>
+
+</body>
+</html>
diff --git a/Websites/webkit.org/demos/intersection-observer/triggered-animation/script.js b/Websites/webkit.org/demos/intersection-observer/triggered-animation/script.js
new file mode 100644 (file)
index 0000000..6c2fa7c
--- /dev/null
@@ -0,0 +1,33 @@
+let animations = undefined;
+class AnimationManager {
+    constructor()
+    {
+        this.setupObserver();
+        
+        let targets = document.querySelectorAll('.animation-container');
+        for (let target of targets) {
+            this.observer.observe(target);
+        }
+    }
+    
+    setupObserver()
+    {
+        this.observer = new IntersectionObserver((observations) => {
+            this.intersectionsChanged(observations);
+        });
+    }
+    
+    intersectionsChanged(observations)
+    {
+        for (let obs of observations) {
+            if (obs.isIntersecting)
+                obs.target.classList.add('visible');
+            else
+                obs.target.classList.remove('visible');
+        }
+    }
+};
+
+window.addEventListener('load', () => {
+    animations = new AnimationManager();
+}, false);
diff --git a/Websites/webkit.org/demos/intersection-observer/triggered-animation/style.css b/Websites/webkit.org/demos/intersection-observer/triggered-animation/style.css
new file mode 100644 (file)
index 0000000..5ffdc0b
--- /dev/null
@@ -0,0 +1,146 @@
+body {
+    background-color: rgba(239, 175, 82, 1);
+    font-family: Helvetica;
+    color: rgba(230, 131, 99, 1);
+}
+
+p {
+    color: rgba(54, 115, 171, 1);
+}
+
+.animation-container h1 {
+    font-variant: small-caps;
+    margin-top: 0.2em;
+    font-size: 34pt;
+    font-weight: bold;
+    text-align: center;
+}
+
+.animation-container {
+    position: relative;
+    overflow: hidden;
+    height: 400px;
+    width: calc(100% - 100px);
+    margin: 1200px 50px;
+    padding: 20px;
+    box-sizing: border-box;
+    background-color: rgba(54, 115, 171, 1);
+    border: 10px solid rgba(94, 189, 186, 1);
+    border-radius: 20px;
+}
+
+.animation-container .box {
+    position: relative;
+    width: 200px;
+    height: 200px;
+    background-color: rgba(219, 89, 54, 1);
+    border-radius: 10px;
+}
+
+.slide.box {
+    display: inline-block;
+    transform: translateX(2000px);
+}
+
+.animation-container.visible > .slide.box {
+    transform: translateX(20px);
+    transition: transform 2s;
+}
+
+.slide.animation-container div:nth-of-type(1) {
+    transition-delay: 1s !important;
+}
+.slide.animation-container div:nth-of-type(2) {
+    transition-delay: 1.4s !important;;
+}
+.slide.animation-container div:nth-of-type(3) {
+    transition-delay: 1.8s !important;;
+}
+
+.spin {
+    margin: 50px calc((100% - 200px) / 2);
+}
+
+.animation-container.visible .spin {
+    animation: spin 3s 1s 10;
+}
+
+@keyframes spin {
+    from { transform: rotate(0); }
+    to   { transform: rotate(360deg); }
+}
+
+.animation-container.svg {
+    height: 650px;
+}
+
+.animation-container.svg path {
+    stroke-width: 8px;
+    fill: none;
+    stroke: #f9727f;
+    stroke-dasharray: 80px;
+    stroke-linecap: round;
+}
+
+.animation-container.svg.visible {
+    animation-name: stroke-move;
+    animation-duration: 6s;
+    animation-delay: 1s;
+    animation-timing-function: ease-in-out;
+    animation-iteration-count: infinite;
+    animation-direction: alternate;
+}
+
+@keyframes stroke-move {
+  from {
+      stroke-dashoffset: 0;
+  }
+  to {
+      stroke-dashoffset: 500px;
+  }
+}
+
+.animation-container.svg circle {
+    fill: #c26c84;
+    stroke-width: 12px;
+    stroke: #fab193;
+    r: 50px;
+}
+
+.animation-container.svg.visible circle {
+    animation-name: circle-scale;
+    animation-duration: 1.5s;
+    animation-delay: 2s;
+    animation-timing-function: ease-in-out;
+    animation-iteration-count: infinite;
+    animation-direction: alternate;
+}
+
+.animation-container.svg circle:nth-of-type(2) {
+    animation-duration: 1.7s;
+}
+
+.animation-container.svg circle:nth-of-type(3) {
+    animation-duration: 1.2s;
+}
+
+.animation-container.svg circle:nth-of-type(4) {
+    animation-duration: 2.1s;
+}
+
+.animation-container.svg circle:nth-of-type(5) {
+    animation-duration: 1.6s;
+}
+
+@keyframes circle-scale {
+  from {
+      stroke-width: 12px;
+      fill-opacity: 1;
+      r: 50px;
+  }
+  to {
+      stroke-width: 2px;
+      fill-opacity: 0.3;
+      r: 80px;
+  }
+}