761 lines
57 KiB
HTML
761 lines
57 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en" dir="ltr">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>SUBSPACE</title>
|
||
<meta name="description" content="Reactive ÐApp Development">
|
||
<meta http-equiv="X-UA-CompatibleSUBSPACE" content="IE=Edge,chrome=1">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<!-- Canonical links -->
|
||
<link rel="canonical" href="http://localhost:4000/index.html">
|
||
|
||
<!-- Icon -->
|
||
<meta name="msapplication-TileColor" content="#080E1A">
|
||
<link rel="icon" type="image/png" href="/images/favicon.png" sizes="32x32" />
|
||
|
||
<link rel="apple-touch-icon" sizes="76x76" href="/images/apple-touch-icon-60x60-precomposed.png">
|
||
<link rel="apple-touch-icon" sizes="76x76" href="/images/apple-touch-icon-76x76-precomposed.png">
|
||
<link rel="apple-touch-icon" sizes="120x120" href="/images/apple-touch-icon-120x120-precomposed.png">
|
||
<link rel="apple-touch-icon" sizes="152x152" href="/images/apple-touch-icon-152x152-precomposed.png">
|
||
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-precomposed.png">
|
||
<link rel="apple-touch-icon" href="/images/apple-touch-icon-precomposed.png">
|
||
<!-- CSS -->
|
||
|
||
<link rel="stylesheet" href="/css/application.css">
|
||
|
||
<!-- endbuild -->
|
||
|
||
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700" rel="stylesheet">
|
||
|
||
<meta property="og:image" content="/img/share.png?v=0.0.5" />
|
||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.4/styles/dracula.min.css">
|
||
<meta name="generator" content="Hexo 4.2.0"></head>
|
||
<body>
|
||
|
||
|
||
<body>
|
||
<header role="banner" class="o-header">
|
||
<div class="o-header__container c-spotlightbox">
|
||
<div class="o-constrained">
|
||
<div class="o-header__top js-header">
|
||
<div><a href="/" class="a-logo">Keycard</a></div>
|
||
<nav role="navigation" class="o-navigation c-navigation">
|
||
<a href="#" class="c-navigation__trigger js-navigation-open">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="icon"><title>navigation-menu</title><rect x="0.5" y="2.5" width="23" height="3" rx="1" ry="1"/><rect x="0.5" y="10.5" width="23" height="3" rx="1" ry="1"/><rect x="0.5" y="18.5" width="23" height="3" rx="1" ry="1"/></svg>
|
||
</a>
|
||
<div class="o-navigation__list c-navigation__list js-navigation-list">
|
||
<a href="/" class="a-logo"></a>
|
||
<a href="#" class="o-navigation__close js-navigation-close">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="icon"><title>close</title><path d="M14.3,12.179a.25.25,0,0,1,0-.354l9.263-9.262A1.5,1.5,0,0,0,21.439.442L12.177,9.7a.25.25,0,0,1-.354,0L2.561.442A1.5,1.5,0,0,0,.439,2.563L9.7,11.825a.25.25,0,0,1,0,.354L.439,21.442a1.5,1.5,0,0,0,2.122,2.121L11.823,14.3a.25.25,0,0,1,.354,0l9.262,9.263a1.5,1.5,0,0,0,2.122-2.121Z"/></svg>
|
||
</a>
|
||
<a href="/getting-started.html" title="Getting started"
|
||
class="o-navigation__item ">
|
||
Getting started
|
||
</a>
|
||
<a href="/integrations-overview.html" title="Getting started"
|
||
class="o-navigation__item ">
|
||
Integrations
|
||
</a>
|
||
<a href="/api.html" title="Getting started"
|
||
class="o-navigation__item ">
|
||
API
|
||
</a>
|
||
</div>
|
||
</nav>
|
||
</div>
|
||
|
||
<span class="c-divider u-background-color-light o-distance-m"></span>
|
||
|
||
</div>
|
||
|
||
<div class="o-constrained">
|
||
<div class="o-header__body">
|
||
<div class="o-header__content">
|
||
<h1 class="a-title"><strong>Reactive App Development</strong></h1>
|
||
<p class="u-text-color-quiet u-text-l">A powerful tool for building dApps in your favorite reactive framework</p>
|
||
<div class="o-actionbar o-center">
|
||
<div class="o-actionbar__item">
|
||
<a href="#learn" class="a-button a-button--ghost" title="Learn more">Learn more</a>
|
||
</div>
|
||
<div class="o-actionbar__item">
|
||
<a href="/getting-started.html" class="a-button a-button--primary">Getting started</a>
|
||
</div>
|
||
</div>
|
||
<div class="o-grid o-distance">
|
||
<div class="c-spotlightbox__item o-grid__column-1-1 o-grid__column-small-1-2 o-grid__column-large-1-3">
|
||
<div class="o-teaser">
|
||
<span class="o-teaser__symbol">
|
||
<svg class="icon icon--large" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>webpage-live</title><path d="M10.25,5.875v-5a.75.75,0,0,0-1.5,0v5a.75.75,0,0,0,1.5,0Z"/><path d="M12,.125a.75.75,0,0,0-.75.75v1.7A6.593,6.593,0,0,0,12.707,6.04l.169.251a.75.75,0,0,0,1.248,0l.169-.251A6.593,6.593,0,0,0,15.75,2.572V.875a.75.75,0,0,0-1.5,0v1.7a3.355,3.355,0,0,1-.533,1.583.25.25,0,0,1-.434,0,3.355,3.355,0,0,1-.533-1.583V.875A.75.75,0,0,0,12,.125Z"/><path d="M5,.125a.75.75,0,0,0-.75.75v4A1.752,1.752,0,0,0,6,6.625H7a.75.75,0,0,0,0-1.5H6a.25.25,0,0,1-.25-.25v-4A.75.75,0,0,0,5,.125Z"/><path d="M18.25,1.875a.25.25,0,0,1,.25-.25h1a.75.75,0,0,0,0-1.5h-1a1.752,1.752,0,0,0-1.75,1.75v3a1.752,1.752,0,0,0,1.75,1.75h1a.75.75,0,0,0,0-1.5h-1a.25.25,0,0,1,0-.5h1a.75.75,0,0,0,0-1.5h-1a.25.25,0,0,1-.25-.25Z"/><path d="M21,7.375a1,1,0,0,0-1,1v13a.5.5,0,0,1-.5.5H4.5a.5.5,0,0,1-.5-.5v-13a1,1,0,0,0-2,0v13.5a2,2,0,0,0,2,2H20a2,2,0,0,0,2-2V8.375A1,1,0,0,0,21,7.375Z"/><circle cx="7" cy="12.375" r="1.5"/><path d="M17.75,12.375a.75.75,0,0,0-.75-.75H10.5a.75.75,0,0,0,0,1.5H17A.75.75,0,0,0,17.75,12.375Z"/><circle cx="7" cy="17.875" r="1.5"/><path d="M10.5,17.125a.75.75,0,0,0,0,1.5H16a.75.75,0,0,0,0-1.5Z"/></svg>
|
||
</span>
|
||
<div class="o-teaser__content">
|
||
<h3 class="h5">Reactive</h3>
|
||
<p class="u-text-color-quiet">Methods are provided to track and subscribe to events, contract & state balances, and react to changes via observables</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="c-spotlightbox__item o-grid__column-1-1 o-grid__column-small-1-2 o-grid__column-large-1-3">
|
||
<div class="o-teaser">
|
||
<span class="o-teaser__symbol">
|
||
<svg class="icon icon--large" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>programming-team-chat-3</title><path d="M7.524,22.092a.25.25,0,0,0-.06-.322A3.929,3.929,0,0,0,5,20.9a3.98,3.98,0,0,0-3.791,2.774.253.253,0,0,0,.037.224.25.25,0,0,0,.2.1H6.623a.25.25,0,0,0,.244-.194l.031-.139A5.531,5.531,0,0,1,7.524,22.092Z"/><path d="M19,20.9a3.91,3.91,0,0,0-2.12.626.249.249,0,0,0-.074.348,5.417,5.417,0,0,1,.777,1.793l.031.139a.25.25,0,0,0,.244.194h4.7a.25.25,0,0,0,.2-.1.253.253,0,0,0,.037-.224A3.98,3.98,0,0,0,19,20.9Z"/><path d="M15.793,24a.249.249,0,0,0,.238-.326,3.976,3.976,0,0,0-7.594.043A.219.219,0,0,0,8.646,24Z"/><circle cx="5" cy="17.578" r="2.436"/><circle cx="19" cy="17.578" r="2.436"/><path d="M20.37,1.753A1.75,1.75,0,0,0,18.621,0l-13,0A1.75,1.75,0,0,0,3.87,1.75V8.505a3.754,3.754,0,0,0,1.1,2.652L8.09,14.28a.748.748,0,0,0,.53.22.735.735,0,0,0,.287-.057.748.748,0,0,0,.463-.693V11a.5.5,0,0,1,.5-.5h8.75a1.749,1.749,0,0,0,1.75-1.75ZM9.151,6.72A.75.75,0,1,1,8.09,7.78l-2-2a.749.749,0,0,1,0-1.06l2-2A.75.75,0,0,1,9.151,3.78L7.858,5.073a.25.25,0,0,0,0,.354Zm4.64-3.135-2,4a.75.75,0,1,1-1.342-.67l2-4a.75.75,0,1,1,1.342.67Zm4.36,1.135a.749.749,0,0,1,0,1.06l-2,2A.75.75,0,0,1,15.09,6.72l1.293-1.293a.25.25,0,0,0,0-.354L15.09,3.78a.75.75,0,0,1,1.061-1.06Z"/><path d="M13.611,19.591a2.432,2.432,0,1,0-1.37.423A2.433,2.433,0,0,0,13.611,19.591Z"/></svg>
|
||
</span>
|
||
<div class="o-teaser__content">
|
||
<h3 class="h5">Framework Agnostic</h3>
|
||
<p class="u-text-color-quiet">No matter your favorite JS framework, you can use Subspace to simplify your development process. It works with React or Angular in the browser, and of course plays well with nodejs</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="c-spotlightbox__item o-grid__column-1-1 o-grid__column-small-1-2 o-grid__column-large-1-3">
|
||
<div class="o-teaser">
|
||
<span class="o-teaser__symbol">
|
||
<svg class="icon icon--large" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>server-sync</title><path d="M0,3.5A2.5,2.5,0,0,0,2.5,6h17A2.5,2.5,0,0,0,22,3.5v-1A2.5,2.5,0,0,0,19.5,0H2.5A2.5,2.5,0,0,0,0,2.5ZM3.635,3A1.115,1.115,0,1,1,4.75,4.114,1.115,1.115,0,0,1,3.635,3ZM7.5,3A1.115,1.115,0,1,1,8.615,4.114,1.114,1.114,0,0,1,7.5,3Z"/><path d="M17.5,9.5a8.17,8.17,0,0,1,3.783.926A.493.493,0,0,0,22,9.982V9.5A2.5,2.5,0,0,0,19.5,7H2.5A2.5,2.5,0,0,0,0,9.5v1A2.5,2.5,0,0,0,2.5,13h8.019a.491.491,0,0,0,.393-.2A8.233,8.233,0,0,1,17.5,9.5ZM9.729,10A1.115,1.115,0,1,1,8.615,8.885,1.115,1.115,0,0,1,9.729,10ZM5.865,10A1.115,1.115,0,1,1,4.75,8.885,1.115,1.115,0,0,1,5.865,10Z"/><path d="M2.5,20H8.925a.5.5,0,0,0,.491-.593,8.24,8.24,0,0,1,.434-4.73A.5.5,0,0,0,9.386,14H2.5A2.5,2.5,0,0,0,0,16.5v1A2.5,2.5,0,0,0,2.5,20Zm1.135-3A1.115,1.115,0,1,1,4.75,18.114,1.115,1.115,0,0,1,3.635,17Z"/><path d="M11.854,23.033l.969-.97a.25.25,0,0,1,.359.006,6.086,6.086,0,0,0,10.21-2.2,1,1,0,0,0-1.893-.649,4.09,4.09,0,0,1-6.918,1.42.249.249,0,0,1,.008-.344l1.721-1.722a.5.5,0,0,0-.353-.854H11.5a.5.5,0,0,0-.5.5v4.457a.485.485,0,0,0,.068.224.45.45,0,0,0,.087.112.47.47,0,0,0,.154.126A.5.5,0,0,0,11.854,23.033Z"/><path d="M22.121,12.906a.251.251,0,0,1-.358,0,6.1,6.1,0,0,0-10.2,2.227,1,1,0,0,0,1.893.648,4.092,4.092,0,0,1,6.9-1.445.249.249,0,0,1-.007.346l-1.659,1.66a.5.5,0,0,0,.353.853H23.5a.5.5,0,0,0,.5-.5V12.234a.5.5,0,0,0-.309-.462.485.485,0,0,0-.455.061c-.029.018-.064.022-.09.048Z"/></svg>
|
||
</span>
|
||
<div class="o-teaser__content">
|
||
<h3 class="h5">Automatic Syncing</h3>
|
||
<p class="u-text-color-quiet">Subspace saves state to a local database ensuring your dApp always syncs from the last known point, even after reload.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</header>
|
||
|
||
<div class="o-distance">
|
||
|
||
|
||
<main>
|
||
<div class="o-row-xl">
|
||
<div class="o-constrained-medium" id="why">
|
||
<div class="o-heading" id="learn">
|
||
<p class="a-subtitle u-text-color-focus">Features</p>
|
||
<h2 class="a-title">
|
||
You’ll love the thoughtful architecture of Subspace
|
||
</h2>
|
||
</div>
|
||
<article class="o-distance">
|
||
<h3 class="h3">Event Tracking & Event Sourcing</h3>
|
||
<p class="u-text-color-quiet o-distance-xs">You can track events and react to their values. With Subspace observables doing event sourcing is easy.</p>
|
||
<a href="/getting-started.html#Tracking-events" title="" class="o-media-short o-distance-s">
|
||
<svg class="icon icon--smaller o-media-short__icon" width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<g clip-path="url(#clip0)">
|
||
<path d="M16.5297 13.7273L13.433 10.6306C14.3759 9.21922 14.7601 7.50753 14.5108 5.82854C14.2616 4.14954 13.3967 2.62329 12.0844 1.54665C10.7722 0.470017 9.10639 -0.0800194 7.41105 0.00353402C5.71572 0.0870875 4.11207 0.798257 2.91204 1.99871C1.71201 3.19916 1.00141 4.80306 0.918454 6.49843C0.8355 8.1938 1.38613 9.85941 2.46323 11.1713C3.54033 12.4832 5.06689 13.3475 6.74597 13.5961C8.42505 13.8448 10.1366 13.46 11.5477 12.5166L14.6444 15.6126C14.8965 15.8586 15.2348 15.9963 15.587 15.9963C15.9393 15.9963 16.2775 15.8586 16.5297 15.6126C16.7797 15.3626 16.9201 15.0235 16.9201 14.67C16.9201 14.3164 16.7797 13.9773 16.5297 13.7273ZM7.75369 2.00331C8.70963 2.00331 9.64411 2.28678 10.4389 2.81787C11.2338 3.34897 11.8533 4.10383 12.2191 4.98701C12.5849 5.87018 12.6806 6.842 12.4942 7.77958C12.3077 8.71715 11.8473 9.57837 11.1714 10.2543C10.4954 10.9303 9.6342 11.3906 8.69663 11.5771C7.75905 11.7636 6.78723 11.6679 5.90405 11.3021C5.02088 10.9362 4.26601 10.3167 3.73492 9.5219C3.20383 8.72706 2.92036 7.79259 2.92036 6.83664C2.92177 5.5552 3.43145 4.32664 4.33757 3.42052C5.24369 2.5144 6.47224 2.00472 7.75369 2.00331Z" fill="#F1645D"/>
|
||
</g>
|
||
<defs>
|
||
<clipPath id="clip0">
|
||
<rect x="0.92041" width="16" height="16" fill="white"/>
|
||
</clipPath>
|
||
</defs>
|
||
</svg>
|
||
|
||
<span class="u-text-strong">View details</span>
|
||
</a>
|
||
<pre><code class="language-js">import { $average, $latest } from "@embarklabs/subspace";
|
||
|
||
const rating$ = Product.events.Rating.track().map("rating"));
|
||
|
||
rating$.pipe($latest(5), $average()).subscribe((rating) => {
|
||
console.log("average rating of the last 5 events is " + rating)
|
||
});</code></pre>
|
||
</article>
|
||
<article class="o-distance">
|
||
<h3 class="h3">Tracking State</h3>
|
||
<p class="u-text-color-quiet o-distance-xs">You can track changes to a contract state variable, by specifying the view function and arguments to call and query the contract.</p>
|
||
<a href="/getting-started.html#Tracking-state" title="" class="o-media-short o-distance-s">
|
||
<svg class="icon icon--smaller o-media-short__icon" width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<g clip-path="url(#clip0)">
|
||
<path d="M16.5297 13.7273L13.433 10.6306C14.3759 9.21922 14.7601 7.50753 14.5108 5.82854C14.2616 4.14954 13.3967 2.62329 12.0844 1.54665C10.7722 0.470017 9.10639 -0.0800194 7.41105 0.00353402C5.71572 0.0870875 4.11207 0.798257 2.91204 1.99871C1.71201 3.19916 1.00141 4.80306 0.918454 6.49843C0.8355 8.1938 1.38613 9.85941 2.46323 11.1713C3.54033 12.4832 5.06689 13.3475 6.74597 13.5961C8.42505 13.8448 10.1366 13.46 11.5477 12.5166L14.6444 15.6126C14.8965 15.8586 15.2348 15.9963 15.587 15.9963C15.9393 15.9963 16.2775 15.8586 16.5297 15.6126C16.7797 15.3626 16.9201 15.0235 16.9201 14.67C16.9201 14.3164 16.7797 13.9773 16.5297 13.7273ZM7.75369 2.00331C8.70963 2.00331 9.64411 2.28678 10.4389 2.81787C11.2338 3.34897 11.8533 4.10383 12.2191 4.98701C12.5849 5.87018 12.6806 6.842 12.4942 7.77958C12.3077 8.71715 11.8473 9.57837 11.1714 10.2543C10.4954 10.9303 9.6342 11.3906 8.69663 11.5771C7.75905 11.7636 6.78723 11.6679 5.90405 11.3021C5.02088 10.9362 4.26601 10.3167 3.73492 9.5219C3.20383 8.72706 2.92036 7.79259 2.92036 6.83664C2.92177 5.5552 3.43145 4.32664 4.33757 3.42052C5.24369 2.5144 6.47224 2.00472 7.75369 2.00331Z" fill="#F1645D"/>
|
||
</g>
|
||
<defs>
|
||
<clipPath id="clip0">
|
||
<rect x="0.92041" width="16" height="16" fill="white"/>
|
||
</clipPath>
|
||
</defs>
|
||
</svg>
|
||
|
||
<span class="u-text-strong">View details</span>
|
||
</a>
|
||
<pre><code class="language-js">const productTitle$ = ProductList.methods.products(0).track().map("title");
|
||
productTitle$.subscribe((title) => console.log("product title is " + title));
|
||
});</code></pre>
|
||
</article>
|
||
<article class="o-distance">
|
||
<h3 class="h3">Tracking balances</h3>
|
||
<p class="u-text-color-quiet o-distance-xs">You can also track changes in both ETH and ERC20 token balances</p>
|
||
<a href="/getting-started.html#Tracking-balances" title="" class="o-media-short o-distance-s">
|
||
<svg class="icon icon--smaller o-media-short__icon" width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<g clip-path="url(#clip0)">
|
||
<path d="M16.5297 13.7273L13.433 10.6306C14.3759 9.21922 14.7601 7.50753 14.5108 5.82854C14.2616 4.14954 13.3967 2.62329 12.0844 1.54665C10.7722 0.470017 9.10639 -0.0800194 7.41105 0.00353402C5.71572 0.0870875 4.11207 0.798257 2.91204 1.99871C1.71201 3.19916 1.00141 4.80306 0.918454 6.49843C0.8355 8.1938 1.38613 9.85941 2.46323 11.1713C3.54033 12.4832 5.06689 13.3475 6.74597 13.5961C8.42505 13.8448 10.1366 13.46 11.5477 12.5166L14.6444 15.6126C14.8965 15.8586 15.2348 15.9963 15.587 15.9963C15.9393 15.9963 16.2775 15.8586 16.5297 15.6126C16.7797 15.3626 16.9201 15.0235 16.9201 14.67C16.9201 14.3164 16.7797 13.9773 16.5297 13.7273ZM7.75369 2.00331C8.70963 2.00331 9.64411 2.28678 10.4389 2.81787C11.2338 3.34897 11.8533 4.10383 12.2191 4.98701C12.5849 5.87018 12.6806 6.842 12.4942 7.77958C12.3077 8.71715 11.8473 9.57837 11.1714 10.2543C10.4954 10.9303 9.6342 11.3906 8.69663 11.5771C7.75905 11.7636 6.78723 11.6679 5.90405 11.3021C5.02088 10.9362 4.26601 10.3167 3.73492 9.5219C3.20383 8.72706 2.92036 7.79259 2.92036 6.83664C2.92177 5.5552 3.43145 4.32664 4.33757 3.42052C5.24369 2.5144 6.47224 2.00472 7.75369 2.00331Z" fill="#F1645D"/>
|
||
</g>
|
||
<defs>
|
||
<clipPath id="clip0">
|
||
<rect x="0.92041" width="16" height="16" fill="white"/>
|
||
</clipPath>
|
||
</defs>
|
||
</svg>
|
||
|
||
<span class="u-text-strong">View details</span>
|
||
</a>
|
||
<pre><code class="language-js">const address = "0x0001020304050607080900010203040506070809";
|
||
|
||
subspace.trackBalance(address).subscribe((balance) => {
|
||
console.log("ETH balance is ", balance)
|
||
});
|
||
|
||
subspace.trackBalance(address, "0x744d70fdbe2ba4cf95131626614a1763df805b9e").subscribe((balance) => {
|
||
console.log("SNT balance is ", balance)
|
||
});</code></pre>
|
||
</article>
|
||
<article class="o-distance">
|
||
<h3 class="h3">React integration</h3>
|
||
<p class="u-text-color-quiet o-distance-xs">Subspace can make any react component compatible with observables so you easily reactive components</p>
|
||
<a href="/react.html" title="" class="o-media-short o-distance-s">
|
||
<svg class="icon icon--smaller o-media-short__icon" width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<g clip-path="url(#clip0)">
|
||
<path d="M16.5297 13.7273L13.433 10.6306C14.3759 9.21922 14.7601 7.50753 14.5108 5.82854C14.2616 4.14954 13.3967 2.62329 12.0844 1.54665C10.7722 0.470017 9.10639 -0.0800194 7.41105 0.00353402C5.71572 0.0870875 4.11207 0.798257 2.91204 1.99871C1.71201 3.19916 1.00141 4.80306 0.918454 6.49843C0.8355 8.1938 1.38613 9.85941 2.46323 11.1713C3.54033 12.4832 5.06689 13.3475 6.74597 13.5961C8.42505 13.8448 10.1366 13.46 11.5477 12.5166L14.6444 15.6126C14.8965 15.8586 15.2348 15.9963 15.587 15.9963C15.9393 15.9963 16.2775 15.8586 16.5297 15.6126C16.7797 15.3626 16.9201 15.0235 16.9201 14.67C16.9201 14.3164 16.7797 13.9773 16.5297 13.7273ZM7.75369 2.00331C8.70963 2.00331 9.64411 2.28678 10.4389 2.81787C11.2338 3.34897 11.8533 4.10383 12.2191 4.98701C12.5849 5.87018 12.6806 6.842 12.4942 7.77958C12.3077 8.71715 11.8473 9.57837 11.1714 10.2543C10.4954 10.9303 9.6342 11.3906 8.69663 11.5771C7.75905 11.7636 6.78723 11.6679 5.90405 11.3021C5.02088 10.9362 4.26601 10.3167 3.73492 9.5219C3.20383 8.72706 2.92036 7.79259 2.92036 6.83664C2.92177 5.5552 3.43145 4.32664 4.33757 3.42052C5.24369 2.5144 6.47224 2.00472 7.75369 2.00331Z" fill="#F1645D"/>
|
||
</g>
|
||
<defs>
|
||
<clipPath id="clip0">
|
||
<rect x="0.92041" width="16" height="16" fill="white"/>
|
||
</clipPath>
|
||
</defs>
|
||
</svg>
|
||
|
||
<span class="u-text-strong">View details</span>
|
||
</a>
|
||
<pre><code class="language-javascript"><script type="text/plain" class="">import { observe } from "@embarklabs/subspace/react";
|
||
|
||
const ProductComponent = ({ maxRating, minRating, averageRating }) => {
|
||
return <ul>
|
||
<li><b>minimum rating: </b> {minRating}</li>
|
||
<li><b>maximum rating: </b> {maxRating}</li>
|
||
<li><b>average rating: </b> {averageRating}</li>
|
||
</ul>;
|
||
};
|
||
|
||
const ReactiveProductComponent = observe(ProductComponent);
|
||
const Product = subspace.contract({abi, address});
|
||
const rating$ = Product.events.Rating.track().map("rating").pipe(map(x => parseInt(x)));
|
||
|
||
ReactDOM.render(
|
||
<ReactiveProductComponent
|
||
maxRating={rating$.pipe($max())}
|
||
minRating={rating$.pipe($min())}
|
||
averageRating={rating$.pipe($average())}
|
||
/>,
|
||
document.getElementById('hello-example')
|
||
);</script></code></pre>
|
||
</article>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
</div>
|
||
|
||
|
||
<footer role="contentinfo" class="c-spotlightbox o-distance js-inviewport-item">
|
||
<div class="o-constrained">
|
||
<div class="o-banner o-center">
|
||
<p class="h3 o-banner__item">You want to dive <strong>into the framework?</strong></p>
|
||
<a href="/getting-started.html" title="" class="a-button o-banner__item">Getting
|
||
started</a>
|
||
</div>
|
||
<span class="c-divider u-background-color-light o-distance-xl"></span>
|
||
<div class="o-grid o-distance-xl">
|
||
<div class="o-grid__column-1-1 o-grid__column-xlarge-2-4">
|
||
<div>
|
||
<a href="./" class="a-logo">Subspace</a>
|
||
</div>
|
||
<div class="c-box u-inline-block u-border-color-light o-distance-m">
|
||
<div class="o-media-short">
|
||
<span class="u-text-color-quiet">We are part of the embark framework</span>
|
||
<img src="/images/embark-logo.svg" class="o-vertical-alignment__item">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="o-grid__column-1-2 o-grid__column-large-1-4 o-grid__column-xlarge-1-4">
|
||
<p class="h6 u-text-color-quiet u-text-uppercase">Resources</p>
|
||
<ul class="o-list">
|
||
<li><a href="/getting-started.html" title="footer.resources.links.contact">Getting started</a></li>
|
||
<li><a href="/overview-integrations.html" title="footer.resources.links.privacy">Integrations</a></li>
|
||
<li><a href="/api.html" target="_blank" title="footer.resources.links.privacy" target="_blank">API</a></li>
|
||
</ul>
|
||
</div>
|
||
<div class="o-grid__column-1-2 o-grid__column-large-1-4 o-grid__column-xlarge-1-4">
|
||
<p class="h6 u-text-color-quiet u-text-uppercase">The Status Network</p>
|
||
<ul class="o-list">
|
||
<li><a href="https://status.im/" title="footer.status.links.status" target="_blank">Status</a></li>
|
||
<li><a href="https://dap.ps/" title="dap.ps" target="_blank">dap.ps</a></li>
|
||
<li><a href="https://teller.exchange/" title="Teller" target="_blank">Teller</a></li>
|
||
<li><a href="https://assemble.fund/" title="Assemble" target="_blank">Assemble</a></li>
|
||
<li><a href="https://embark.status.im/" title="Embark" target="_blank">Embark</a></li>
|
||
<li><a href="https://subspace.status.im/" title="Subspace" target="_blank">Subspace</a></li>
|
||
<li><a href="https://vac.dev/" title="Vac" target="_blank">Vac</a></li>
|
||
<li><a href="https://nimbus.status.im/" title="Nimbus" target="_blank">Nimbus</a></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div class="o-distance">
|
||
<p class="o-vertical-alignment o-center u-text-color-quiet">
|
||
MIT Licensed | Subspace is part of the Status Network
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
<script
|
||
src="https://code.jquery.com/jquery-3.3.1.min.js"
|
||
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
|
||
crossorigin="anonymous"></script>
|
||
|
||
<script>
|
||
/*!
|
||
* jQuery.anchorScroll jQuery Plugin v1.0
|
||
*
|
||
* Author: Virgiliu Diaconu
|
||
* http://www.virgiliu.com
|
||
* Licensed under the MIT license.
|
||
*/
|
||
!function(o){"use strict";o.anchorScroll=function(l,t){var n=this;n.$el=o(l),n.el=l,n.init=function(){n.options=o.extend({},o.anchorScroll.defaultOptions,t)},n.$el.click(function(t){if(t.preventDefault(),o(t.target).closest("a").length&&o(n.el.hash).length){var e=o(n.el.hash).offset().top-n.options.offsetTop,s="this"===n.$el.data("classTo")?n.el:n.$el.data("classTo"),c=n.$el.data("onScroll"),a=n.$el.data("scrollEnd");"function"==typeof n.options.scrollStart&&n.options.scrollStart.call(l),o(s).addClass(c).removeClass(a),o("html,body").animate({scrollTop:e},n.options.scrollSpeed).promise().done(function(){o(s).addClass(a).removeClass(c),"function"==typeof n.options.scrollEnd&&n.options.scrollEnd.call(l)})}}),n.init()},o.anchorScroll.defaultOptions={scrollSpeed:800,offsetTop:0},o.fn.anchorScroll=function(l){return this.each(function(){new o.anchorScroll(this,l)})}}(jQuery,window,document);
|
||
</script>
|
||
|
||
<script>(function(root, factory) {
|
||
if (typeof define === "function" && define.amd) {
|
||
define([], function() {
|
||
return factory();
|
||
});
|
||
} else if (typeof exports === "object") {
|
||
module.exports = factory();
|
||
} else {
|
||
root.Headhesive = factory();
|
||
}
|
||
})(this, function() {
|
||
"use strict";
|
||
var _mergeObj = function(to, from) {
|
||
for (var p in from) {
|
||
if (from.hasOwnProperty(p)) {
|
||
to[p] = typeof from[p] === "object" ? _mergeObj(to[p], from[p]) : from[p];
|
||
}
|
||
}
|
||
return to;
|
||
};
|
||
var _throttle = function(func, wait) {
|
||
var _now = Date.now || function() {
|
||
return new Date().getTime();
|
||
};
|
||
var context, args, result;
|
||
var timeout = null;
|
||
var previous = 0;
|
||
var later = function() {
|
||
previous = _now();
|
||
timeout = null;
|
||
result = func.apply(context, args);
|
||
context = args = null;
|
||
};
|
||
return function() {
|
||
var now = _now();
|
||
var remaining = wait - (now - previous);
|
||
context = this;
|
||
args = arguments;
|
||
if (remaining <= 0) {
|
||
clearTimeout(timeout);
|
||
timeout = null;
|
||
previous = now;
|
||
result = func.apply(context, args);
|
||
context = args = null;
|
||
} else if (!timeout) {
|
||
timeout = setTimeout(later, remaining);
|
||
}
|
||
return result;
|
||
};
|
||
};
|
||
var _getScrollY = function() {
|
||
return window.pageYOffset !== undefined ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
|
||
};
|
||
var _getElemY = function(elem, side) {
|
||
var pos = 0;
|
||
var elemHeight = elem.offsetHeight;
|
||
while (elem) {
|
||
pos += elem.offsetTop;
|
||
elem = elem.offsetParent;
|
||
}
|
||
if (side === "bottom") {
|
||
pos = pos + elemHeight;
|
||
}
|
||
return pos;
|
||
};
|
||
var Headhesive = function(elem, options) {
|
||
if (!("querySelector" in document && "addEventListener" in window)) {
|
||
return;
|
||
}
|
||
this.visible = false;
|
||
this.options = {
|
||
offset: 300,
|
||
offsetSide: "top",
|
||
classes: {
|
||
clone: "headhesive",
|
||
stick: "headhesive--stick",
|
||
unstick: "headhesive--unstick"
|
||
},
|
||
throttle: 250,
|
||
onInit: function() {},
|
||
onStick: function() {},
|
||
onUnstick: function() {},
|
||
onDestroy: function() {}
|
||
};
|
||
this.elem = typeof elem === "string" ? document.querySelector(elem) : elem;
|
||
this.options = _mergeObj(this.options, options);
|
||
this.init();
|
||
};
|
||
Headhesive.prototype = {
|
||
constructor: Headhesive,
|
||
init: function() {
|
||
this.clonedElem = this.elem.cloneNode(true);
|
||
this.clonedElem.className += " " + this.options.classes.clone;
|
||
document.body.insertBefore(this.clonedElem, document.body.firstChild);
|
||
if (typeof this.options.offset === "number") {
|
||
this.scrollOffset = this.options.offset;
|
||
} else if (typeof this.options.offset === "string") {
|
||
this._setScrollOffset();
|
||
} else {
|
||
throw new Error("Invalid offset: " + this.options.offset);
|
||
}
|
||
this._throttleUpdate = _throttle(this.update.bind(this), this.options.throttle);
|
||
this._throttleScrollOffset = _throttle(this._setScrollOffset.bind(this), this.options.throttle);
|
||
window.addEventListener("scroll", this._throttleUpdate, false);
|
||
window.addEventListener("resize", this._throttleScrollOffset, false);
|
||
this.options.onInit.call(this);
|
||
},
|
||
_setScrollOffset: function() {
|
||
if (typeof this.options.offset === "string") {
|
||
this.scrollOffset = _getElemY(document.querySelector(this.options.offset), this.options.offsetSide);
|
||
}
|
||
},
|
||
destroy: function() {
|
||
document.body.removeChild(this.clonedElem);
|
||
window.removeEventListener("scroll", this._throttleUpdate);
|
||
window.removeEventListener("resize", this._throttleScrollOffset);
|
||
this.options.onDestroy.call(this);
|
||
},
|
||
stick: function() {
|
||
if (!this.visible) {
|
||
this.clonedElem.className = this.clonedElem.className.replace(new RegExp("(^|\\s)*" + this.options.classes.unstick + "(\\s|$)*", "g"), "");
|
||
this.clonedElem.className += " " + this.options.classes.stick;
|
||
this.visible = true;
|
||
this.options.onStick.call(this);
|
||
}
|
||
},
|
||
unstick: function() {
|
||
if (this.visible) {
|
||
this.clonedElem.className = this.clonedElem.className.replace(new RegExp("(^|\\s)*" + this.options.classes.stick + "(\\s|$)*", "g"), "");
|
||
this.clonedElem.className += " " + this.options.classes.unstick;
|
||
this.visible = false;
|
||
this.options.onUnstick.call(this);
|
||
}
|
||
},
|
||
update: function() {
|
||
if (_getScrollY() > this.scrollOffset) {
|
||
this.stick();
|
||
} else {
|
||
this.unstick();
|
||
}
|
||
}
|
||
};
|
||
return Headhesive;
|
||
});</script>
|
||
|
||
<script>
|
||
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):window.jQuery||window.Zepto)}(function(a){var b,c,d,e,f,g,h="Close",i="BeforeClose",j="AfterClose",k="BeforeAppend",l="MarkupParse",m="Open",n="Change",o="mfp",p="."+o,q="mfp-ready",r="mfp-removing",s="mfp-prevent-close",t=function(){},u=!!window.jQuery,v=a(window),w=function(a,c){b.ev.on(o+a+p,c)},x=function(b,c,d,e){var f=document.createElement("div");return f.className="mfp-"+b,d&&(f.innerHTML=d),e?c&&c.appendChild(f):(f=a(f),c&&f.appendTo(c)),f},y=function(c,d){b.ev.triggerHandler(o+c,d),b.st.callbacks&&(c=c.charAt(0).toLowerCase()+c.slice(1),b.st.callbacks[c]&&b.st.callbacks[c].apply(b,a.isArray(d)?d:[d]))},z=function(c){return c===g&&b.currTemplate.closeBtn||(b.currTemplate.closeBtn=a(b.st.closeMarkup.replace("%title%",b.st.tClose)),g=c),b.currTemplate.closeBtn},A=function(){a.magnificPopup.instance||(b=new t,b.init(),a.magnificPopup.instance=b)},B=function(){var a=document.createElement("p").style,b=["ms","O","Moz","Webkit"];if(void 0!==a.transition)return!0;for(;b.length;)if(b.pop()+"Transition"in a)return!0;return!1};t.prototype={constructor:t,init:function(){var c=navigator.appVersion;b.isLowIE=b.isIE8=document.all&&!document.addEventListener,b.isAndroid=/android/gi.test(c),b.isIOS=/iphone|ipad|ipod/gi.test(c),b.supportsTransition=B(),b.probablyMobile=b.isAndroid||b.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),d=a(document),b.popupsCache={}},open:function(c){var e;if(c.isObj===!1){b.items=c.items.toArray(),b.index=0;var g,h=c.items;for(e=0;e<h.length;e++)if(g=h[e],g.parsed&&(g=g.el[0]),g===c.el[0]){b.index=e;break}}else b.items=a.isArray(c.items)?c.items:[c.items],b.index=c.index||0;if(b.isOpen)return void b.updateItemHTML();b.types=[],f="",c.mainEl&&c.mainEl.length?b.ev=c.mainEl.eq(0):b.ev=d,c.key?(b.popupsCache[c.key]||(b.popupsCache[c.key]={}),b.currTemplate=b.popupsCache[c.key]):b.currTemplate={},b.st=a.extend(!0,{},a.magnificPopup.defaults,c),b.fixedContentPos="auto"===b.st.fixedContentPos?!b.probablyMobile:b.st.fixedContentPos,b.st.modal&&(b.st.closeOnContentClick=!1,b.st.closeOnBgClick=!1,b.st.showCloseBtn=!1,b.st.enableEscapeKey=!1),b.bgOverlay||(b.bgOverlay=x("bg").on("click"+p,function(){b.close()}),b.wrap=x("wrap").attr("tabindex",-1).on("click"+p,function(a){b._checkIfClose(a.target)&&b.close()}),b.container=x("container",b.wrap)),b.contentContainer=x("content"),b.st.preloader&&(b.preloader=x("preloader",b.container,b.st.tLoading));var i=a.magnificPopup.modules;for(e=0;e<i.length;e++){var j=i[e];j=j.charAt(0).toUpperCase()+j.slice(1),b["init"+j].call(b)}y("BeforeOpen"),b.st.showCloseBtn&&(b.st.closeBtnInside?(w(l,function(a,b,c,d){c.close_replaceWith=z(d.type)}),f+=" mfp-close-btn-in"):b.wrap.append(z())),b.st.alignTop&&(f+=" mfp-align-top"),b.fixedContentPos?b.wrap.css({overflow:b.st.overflowY,overflowX:"hidden",overflowY:b.st.overflowY}):b.wrap.css({top:v.scrollTop(),position:"absolute"}),(b.st.fixedBgPos===!1||"auto"===b.st.fixedBgPos&&!b.fixedContentPos)&&b.bgOverlay.css({height:d.height(),position:"absolute"}),b.st.enableEscapeKey&&d.on("keyup"+p,function(a){27===a.keyCode&&b.close()}),v.on("resize"+p,function(){b.updateSize()}),b.st.closeOnContentClick||(f+=" mfp-auto-cursor"),f&&b.wrap.addClass(f);var k=b.wH=v.height(),n={};if(b.fixedContentPos&&b._hasScrollBar(k)){var o=b._getScrollbarSize();o&&(n.marginRight=o)}b.fixedContentPos&&(b.isIE7?a("body, html").css("overflow","hidden"):n.overflow="hidden");var r=b.st.mainClass;return b.isIE7&&(r+=" mfp-ie7"),r&&b._addClassToMFP(r),b.updateItemHTML(),y("BuildControls"),a("html").css(n),b.bgOverlay.add(b.wrap).prependTo(b.st.prependTo||a(document.body)),b._lastFocusedEl=document.activeElement,setTimeout(function(){b.content?(b._addClassToMFP(q),b._setFocus()):b.bgOverlay.addClass(q),d.on("focusin"+p,b._onFocusIn)},16),b.isOpen=!0,b.updateSize(k),y(m),c},close:function(){b.isOpen&&(y(i),b.isOpen=!1,b.st.removalDelay&&!b.isLowIE&&b.supportsTransition?(b._addClassToMFP(r),setTimeout(function(){b._close()},b.st.removalDelay)):b._close())},_close:function(){y(h);var c=r+" "+q+" ";if(b.bgOverlay.detach(),b.wrap.detach(),b.container.empty(),b.st.mainClass&&(c+=b.st.mainClass+" "),b._removeClassFromMFP(c),b.fixedContentPos){var e={marginRight:""};b.isIE7?a("body, html").css("overflow",""):e.overflow="",a("html").css(e)}d.off("keyup"+p+" focusin"+p),b.ev.off(p),b.wrap.attr("class","mfp-wrap").removeAttr("style"),b.bgOverlay.attr("class","mfp-bg"),b.container.attr("class","mfp-container"),!b.st.showCloseBtn||b.st.closeBtnInside&&b.currTemplate[b.currItem.type]!==!0||b.currTemplate.closeBtn&&b.currTemplate.closeBtn.detach(),b.st.autoFocusLast&&b._lastFocusedEl&&a(b._lastFocusedEl).focus(),b.currItem=null,b.content=null,b.currTemplate=null,b.prevHeight=0,y(j)},updateSize:function(a){if(b.isIOS){var c=document.documentElement.clientWidth/window.innerWidth,d=window.innerHeight*c;b.wrap.css("height",d),b.wH=d}else b.wH=a||v.height();b.fixedContentPos||b.wrap.css("height",b.wH),y("Resize")},updateItemHTML:function(){var c=b.items[b.index];b.contentContainer.detach(),b.content&&b.content.detach(),c.parsed||(c=b.parseEl(b.index));var d=c.type;if(y("BeforeChange",[b.currItem?b.currItem.type:"",d]),b.currItem=c,!b.currTemplate[d]){var f=b.st[d]?b.st[d].markup:!1;y("FirstMarkupParse",f),f?b.currTemplate[d]=a(f):b.currTemplate[d]=!0}e&&e!==c.type&&b.container.removeClass("mfp-"+e+"-holder");var g=b["get"+d.charAt(0).toUpperCase()+d.slice(1)](c,b.currTemplate[d]);b.appendContent(g,d),c.preloaded=!0,y(n,c),e=c.type,b.container.prepend(b.contentContainer),y("AfterChange")},appendContent:function(a,c){b.content=a,a?b.st.showCloseBtn&&b.st.closeBtnInside&&b.currTemplate[c]===!0?b.content.find(".mfp-close").length||b.content.append(z()):b.content=a:b.content="",y(k),b.container.addClass("mfp-"+c+"-holder"),b.contentContainer.append(b.content)},parseEl:function(c){var d,e=b.items[c];if(e.tagName?e={el:a(e)}:(d=e.type,e={data:e,src:e.src}),e.el){for(var f=b.types,g=0;g<f.length;g++)if(e.el.hasClass("mfp-"+f[g])){d=f[g];break}e.src=e.el.attr("data-mfp-src"),e.src||(e.src=e.el.attr("href"))}return e.type=d||b.st.type||"inline",e.index=c,e.parsed=!0,b.items[c]=e,y("ElementParse",e),b.items[c]},addGroup:function(a,c){var d=function(d){d.mfpEl=this,b._openClick(d,a,c)};c||(c={});var e="click.magnificPopup";c.mainEl=a,c.items?(c.isObj=!0,a.off(e).on(e,d)):(c.isObj=!1,c.delegate?a.off(e).on(e,c.delegate,d):(c.items=a,a.off(e).on(e,d)))},_openClick:function(c,d,e){var f=void 0!==e.midClick?e.midClick:a.magnificPopup.defaults.midClick;if(f||!(2===c.which||c.ctrlKey||c.metaKey||c.altKey||c.shiftKey)){var g=void 0!==e.disableOn?e.disableOn:a.magnificPopup.defaults.disableOn;if(g)if(a.isFunction(g)){if(!g.call(b))return!0}else if(v.width()<g)return!0;c.type&&(c.preventDefault(),b.isOpen&&c.stopPropagation()),e.el=a(c.mfpEl),e.delegate&&(e.items=d.find(e.delegate)),b.open(e)}},updateStatus:function(a,d){if(b.preloader){c!==a&&b.container.removeClass("mfp-s-"+c),d||"loading"!==a||(d=b.st.tLoading);var e={status:a,text:d};y("UpdateStatus",e),a=e.status,d=e.text,b.preloader.html(d),b.preloader.find("a").on("click",function(a){a.stopImmediatePropagation()}),b.container.addClass("mfp-s-"+a),c=a}},_checkIfClose:function(c){if(!a(c).hasClass(s)){var d=b.st.closeOnContentClick,e=b.st.closeOnBgClick;if(d&&e)return!0;if(!b.content||a(c).hasClass("mfp-close")||b.preloader&&c===b.preloader[0])return!0;if(c===b.content[0]||a.contains(b.content[0],c)){if(d)return!0}else if(e&&a.contains(document,c))return!0;return!1}},_addClassToMFP:function(a){b.bgOverlay.addClass(a),b.wrap.addClass(a)},_removeClassFromMFP:function(a){this.bgOverlay.removeClass(a),b.wrap.removeClass(a)},_hasScrollBar:function(a){return(b.isIE7?d.height():document.body.scrollHeight)>(a||v.height())},_setFocus:function(){(b.st.focus?b.content.find(b.st.focus).eq(0):b.wrap).focus()},_onFocusIn:function(c){return c.target===b.wrap[0]||a.contains(b.wrap[0],c.target)?void 0:(b._setFocus(),!1)},_parseMarkup:function(b,c,d){var e;d.data&&(c=a.extend(d.data,c)),y(l,[b,c,d]),a.each(c,function(c,d){if(void 0===d||d===!1)return!0;if(e=c.split("_"),e.length>1){var f=b.find(p+"-"+e[0]);if(f.length>0){var g=e[1];"replaceWith"===g?f[0]!==d[0]&&f.replaceWith(d):"img"===g?f.is("img")?f.attr("src",d):f.replaceWith(a("<img>").attr("src",d).attr("class",f.attr("class"))):f.attr(e[1],d)}}else b.find(p+"-"+c).html(d)})},_getScrollbarSize:function(){if(void 0===b.scrollbarSize){var a=document.createElement("div");a.style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(a),b.scrollbarSize=a.offsetWidth-a.clientWidth,document.body.removeChild(a)}return b.scrollbarSize}},a.magnificPopup={instance:null,proto:t.prototype,modules:[],open:function(b,c){return A(),b=b?a.extend(!0,{},b):{},b.isObj=!0,b.index=c||0,this.instance.open(b)},close:function(){return a.magnificPopup.instance&&a.magnificPopup.instance.close()},registerModule:function(b,c){c.options&&(a.magnificPopup.defaults[b]=c.options),a.extend(this.proto,c.proto),this.modules.push(b)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,prependTo:null,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'<button title="%title%" type="button" class="mfp-close">×</button>',tClose:"Close (Esc)",tLoading:"Loading...",autoFocusLast:!0}},a.fn.magnificPopup=function(c){A();var d=a(this);if("string"==typeof c)if("open"===c){var e,f=u?d.data("magnificPopup"):d[0].magnificPopup,g=parseInt(arguments[1],10)||0;f.items?e=f.items[g]:(e=d,f.delegate&&(e=e.find(f.delegate)),e=e.eq(g)),b._openClick({mfpEl:e},d,f)}else b.isOpen&&b[c].apply(b,Array.prototype.slice.call(arguments,1));else c=a.extend(!0,{},c),u?d.data("magnificPopup",c):d[0].magnificPopup=c,b.addGroup(d,c);return d};var C,D,E,F="inline",G=function(){E&&(D.after(E.addClass(C)).detach(),E=null)};a.magnificPopup.registerModule(F,{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){b.types.push(F),w(h+"."+F,function(){G()})},getInline:function(c,d){if(G(),c.src){var e=b.st.inline,f=a(c.src);if(f.length){var g=f[0].parentNode;g&&g.tagName&&(D||(C=e.hiddenClass,D=x(C),C="mfp-"+C),E=f.after(D).detach().removeClass(C)),b.updateStatus("ready")}else b.updateStatus("error",e.tNotFound),f=a("<div>");return c.inlineElement=f,f}return b.updateStatus("ready"),b._parseMarkup(d,{},c),d}}});var H,I="ajax",J=function(){H&&a(document.body).removeClass(H)},K=function(){J(),b.req&&b.req.abort()};a.magnificPopup.registerModule(I,{options:{settings:null,cursor:"mfp-ajax-cur",tError:'<a href="%url%">The content</a> could not be loaded.'},proto:{initAjax:function(){b.types.push(I),H=b.st.ajax.cursor,w(h+"."+I,K),w("BeforeChange."+I,K)},getAjax:function(c){H&&a(document.body).addClass(H),b.updateStatus("loading");var d=a.extend({url:c.src,success:function(d,e,f){var g={data:d,xhr:f};y("ParseAjax",g),b.appendContent(a(g.data),I),c.finished=!0,J(),b._setFocus(),setTimeout(function(){b.wrap.addClass(q)},16),b.updateStatus("ready"),y("AjaxContentAdded")},error:function(){J(),c.finished=c.loadError=!0,b.updateStatus("error",b.st.ajax.tError.replace("%url%",c.src))}},b.st.ajax.settings);return b.req=a.ajax(d),""}}});var L,M=function(c){if(c.data&&void 0!==c.data.title)return c.data.title;var d=b.st.image.titleSrc;if(d){if(a.isFunction(d))return d.call(b,c);if(c.el)return c.el.attr(d)||""}return""};a.magnificPopup.registerModule("image",{options:{markup:'<div class="mfp-figure"><div class="mfp-close"></div><figure><div class="mfp-img"></div><figcaption><div class="mfp-bottom-bar"><div class="mfp-title"></div><div class="mfp-counter"></div></div></figcaption></figure></div>',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'<a href="%url%">The image</a> could not be loaded.'},proto:{initImage:function(){var c=b.st.image,d=".image";b.types.push("image"),w(m+d,function(){"image"===b.currItem.type&&c.cursor&&a(document.body).addClass(c.cursor)}),w(h+d,function(){c.cursor&&a(document.body).removeClass(c.cursor),v.off("resize"+p)}),w("Resize"+d,b.resizeImage),b.isLowIE&&w("AfterChange",b.resizeImage)},resizeImage:function(){var a=b.currItem;if(a&&a.img&&b.st.image.verticalFit){var c=0;b.isLowIE&&(c=parseInt(a.img.css("padding-top"),10)+parseInt(a.img.css("padding-bottom"),10)),a.img.css("max-height",b.wH-c)}},_onImageHasSize:function(a){a.img&&(a.hasSize=!0,L&&clearInterval(L),a.isCheckingImgSize=!1,y("ImageHasSize",a),a.imgHidden&&(b.content&&b.content.removeClass("mfp-loading"),a.imgHidden=!1))},findImageSize:function(a){var c=0,d=a.img[0],e=function(f){L&&clearInterval(L),L=setInterval(function(){return d.naturalWidth>0?void b._onImageHasSize(a):(c>200&&clearInterval(L),c++,void(3===c?e(10):40===c?e(50):100===c&&e(500)))},f)};e(1)},getImage:function(c,d){var e=0,f=function(){c&&(c.img[0].complete?(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("ready")),c.hasSize=!0,c.loaded=!0,y("ImageLoadComplete")):(e++,200>e?setTimeout(f,100):g()))},g=function(){c&&(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("error",h.tError.replace("%url%",c.src))),c.hasSize=!0,c.loaded=!0,c.loadError=!0)},h=b.st.image,i=d.find(".mfp-img");if(i.length){var j=document.createElement("img");j.className="mfp-img",c.el&&c.el.find("img").length&&(j.alt=c.el.find("img").attr("alt")),c.img=a(j).on("load.mfploader",f).on("error.mfploader",g),j.src=c.src,i.is("img")&&(c.img=c.img.clone()),j=c.img[0],j.naturalWidth>0?c.hasSize=!0:j.width||(c.hasSize=!1)}return b._parseMarkup(d,{title:M(c),img_replaceWith:c.img},c),b.resizeImage(),c.hasSize?(L&&clearInterval(L),c.loadError?(d.addClass("mfp-loading"),b.updateStatus("error",h.tError.replace("%url%",c.src))):(d.removeClass("mfp-loading"),b.updateStatus("ready")),d):(b.updateStatus("loading"),c.loading=!0,c.hasSize||(c.imgHidden=!0,d.addClass("mfp-loading"),b.findImageSize(c)),d)}}});var N,O=function(){return void 0===N&&(N=void 0!==document.createElement("p").style.MozTransform),N};a.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(a){return a.is("img")?a:a.find("img")}},proto:{initZoom:function(){var a,c=b.st.zoom,d=".zoom";if(c.enabled&&b.supportsTransition){var e,f,g=c.duration,j=function(a){var b=a.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),d="all "+c.duration/1e3+"s "+c.easing,e={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},f="transition";return e["-webkit-"+f]=e["-moz-"+f]=e["-o-"+f]=e[f]=d,b.css(e),b},k=function(){b.content.css("visibility","visible")};w("BuildControls"+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.content.css("visibility","hidden"),a=b._getItemToZoom(),!a)return void k();f=j(a),f.css(b._getOffset()),b.wrap.append(f),e=setTimeout(function(){f.css(b._getOffset(!0)),e=setTimeout(function(){k(),setTimeout(function(){f.remove(),a=f=null,y("ZoomAnimationEnded")},16)},g)},16)}}),w(i+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.st.removalDelay=g,!a){if(a=b._getItemToZoom(),!a)return;f=j(a)}f.css(b._getOffset(!0)),b.wrap.append(f),b.content.css("visibility","hidden"),setTimeout(function(){f.css(b._getOffset())},16)}}),w(h+d,function(){b._allowZoom()&&(k(),f&&f.remove(),a=null)})}},_allowZoom:function(){return"image"===b.currItem.type},_getItemToZoom:function(){return b.currItem.hasSize?b.currItem.img:!1},_getOffset:function(c){var d;d=c?b.currItem.img:b.st.zoom.opener(b.currItem.el||b.currItem);var e=d.offset(),f=parseInt(d.css("padding-top"),10),g=parseInt(d.css("padding-bottom"),10);e.top-=a(window).scrollTop()-f;var h={width:d.width(),height:(u?d.innerHeight():d[0].offsetHeight)-g-f};return O()?h["-moz-transform"]=h.transform="translate("+e.left+"px,"+e.top+"px)":(h.left=e.left,h.top=e.top),h}}});var P="iframe",Q="//about:blank",R=function(a){if(b.currTemplate[P]){var c=b.currTemplate[P].find("iframe");c.length&&(a||(c[0].src=Q),b.isIE8&&c.css("display",a?"block":"none"))}};a.magnificPopup.registerModule(P,{options:{markup:'<div class="mfp-iframe-scaler"><div class="mfp-close"></div><iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe></div>',srcAction:"iframe_src",patterns:{youtube:{index:"youtube.com",id:"v=",src:"//www.youtube.com/embed/%id%?autoplay=1"},vimeo:{index:"vimeo.com/",id:"/",src:"//player.vimeo.com/video/%id%?autoplay=1"},gmaps:{index:"//maps.google.",src:"%id%&output=embed"}}},proto:{initIframe:function(){b.types.push(P),w("BeforeChange",function(a,b,c){b!==c&&(b===P?R():c===P&&R(!0))}),w(h+"."+P,function(){R()})},getIframe:function(c,d){var e=c.src,f=b.st.iframe;a.each(f.patterns,function(){return e.indexOf(this.index)>-1?(this.id&&(e="string"==typeof this.id?e.substr(e.lastIndexOf(this.id)+this.id.length,e.length):this.id.call(this,e)),e=this.src.replace("%id%",e),!1):void 0});var g={};return f.srcAction&&(g[f.srcAction]=e),b._parseMarkup(d,g,c),b.updateStatus("ready"),d}}});var S=function(a){var c=b.items.length;return a>c-1?a-c:0>a?c+a:a},T=function(a,b,c){return a.replace(/%curr%/gi,b+1).replace(/%total%/gi,c)};a.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous (Left arrow key)",tNext:"Next (Right arrow key)",tCounter:"%curr% of %total%"},proto:{initGallery:function(){var c=b.st.gallery,e=".mfp-gallery";return b.direction=!0,c&&c.enabled?(f+=" mfp-gallery",w(m+e,function(){c.navigateByImgClick&&b.wrap.on("click"+e,".mfp-img",function(){return b.items.length>1?(b.next(),!1):void 0}),d.on("keydown"+e,function(a){37===a.keyCode?b.prev():39===a.keyCode&&b.next()})}),w("UpdateStatus"+e,function(a,c){c.text&&(c.text=T(c.text,b.currItem.index,b.items.length))}),w(l+e,function(a,d,e,f){var g=b.items.length;e.counter=g>1?T(c.tCounter,f.index,g):""}),w("BuildControls"+e,function(){if(b.items.length>1&&c.arrows&&!b.arrowLeft){var d=c.arrowMarkup,e=b.arrowLeft=a(d.replace(/%title%/gi,c.tPrev).replace(/%dir%/gi,"left")).addClass(s),f=b.arrowRight=a(d.replace(/%title%/gi,c.tNext).replace(/%dir%/gi,"right")).addClass(s);e.click(function(){b.prev()}),f.click(function(){b.next()}),b.container.append(e.add(f))}}),w(n+e,function(){b._preloadTimeout&&clearTimeout(b._preloadTimeout),b._preloadTimeout=setTimeout(function(){b.preloadNearbyImages(),b._preloadTimeout=null},16)}),void w(h+e,function(){d.off(e),b.wrap.off("click"+e),b.arrowRight=b.arrowLeft=null})):!1},next:function(){b.direction=!0,b.index=S(b.index+1),b.updateItemHTML()},prev:function(){b.direction=!1,b.index=S(b.index-1),b.updateItemHTML()},goTo:function(a){b.direction=a>=b.index,b.index=a,b.updateItemHTML()},preloadNearbyImages:function(){var a,c=b.st.gallery.preload,d=Math.min(c[0],b.items.length),e=Math.min(c[1],b.items.length);for(a=1;a<=(b.direction?e:d);a++)b._preloadItem(b.index+a);for(a=1;a<=(b.direction?d:e);a++)b._preloadItem(b.index-a)},_preloadItem:function(c){if(c=S(c),!b.items[c].preloaded){var d=b.items[c];d.parsed||(d=b.parseEl(c)),y("LazyLoad",d),"image"===d.type&&(d.img=a('<img class="mfp-img" />').on("load.mfploader",function(){d.hasSize=!0}).on("error.mfploader",function(){d.hasSize=!0,d.loadError=!0,y("LazyLoadError",d)}).attr("src",d.src)),d.preloaded=!0}}}});var U="retina";a.magnificPopup.registerModule(U,{options:{replaceSrc:function(a){return a.src.replace(/\.\w+$/,function(a){return"@2x"+a})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var a=b.st.retina,c=a.ratio;c=isNaN(c)?c():c,c>1&&(w("ImageHasSize."+U,function(a,b){b.img.css({"max-width":b.img[0].naturalWidth/c,width:"100%"})}),w("ElementParse."+U,function(b,d){d.src=a.replaceSrc(d,c)}))}}}}),A()});
|
||
</script>
|
||
|
||
<script>
|
||
(function (global, factory) {
|
||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('jquery')) :
|
||
typeof define === 'function' && define.amd ? define(['jquery'], factory) :
|
||
(factory(global.jQuery));
|
||
}(this, (function ($) { 'use strict';
|
||
|
||
$ = $ && $.hasOwnProperty('default') ? $['default'] : $;
|
||
|
||
/**
|
||
* @author Mudit Ameta
|
||
* @license https://github.com/zeusdeux/isInViewport/blob/master/license.md MIT
|
||
*/
|
||
|
||
// expose isInViewport as a custom pseudo-selector
|
||
$.extend($.expr.pseudos || $.expr[':'], {
|
||
// if $.expr.createPseudo is available, use it
|
||
'in-viewport': $.expr.createPseudo
|
||
? $.expr.createPseudo(function (argsString) { return function (currElement) { return isInViewport(currElement, getSelectorArgs(argsString)); }; })
|
||
: function (currObj, index, meta) { return isInViewport(currObj, getSelectorArgs(meta[3])); }
|
||
});
|
||
|
||
|
||
// expose isInViewport as a function too
|
||
// this lets folks pass around actual objects as options (like custom viewport)
|
||
// and doesn't tie 'em down to strings. It also prevents isInViewport from
|
||
// having to look up and wrap the dom element corresponding to the viewport selector
|
||
$.fn.isInViewport = function(options) {
|
||
return this.filter(function (i, el) { return isInViewport(el, options); })
|
||
};
|
||
|
||
$.fn.run = run;
|
||
|
||
// lets you chain any arbitrary function or an array of functions and returns a jquery object
|
||
function run(args) {
|
||
var this$1 = this;
|
||
|
||
if (arguments.length === 1 && typeof args === 'function') {
|
||
args = [args];
|
||
}
|
||
|
||
if (!(args instanceof Array)) {
|
||
throw new SyntaxError('isInViewport: Argument(s) passed to .do/.run should be a function or an array of functions')
|
||
}
|
||
|
||
args.forEach(function (arg) {
|
||
if (typeof arg !== 'function') {
|
||
console.warn('isInViewport: Argument(s) passed to .do/.run should be a function or an array of functions');
|
||
console.warn('isInViewport: Ignoring non-function values in array and moving on');
|
||
} else {
|
||
[].slice.call(this$1).forEach(function (t) { return arg.call($(t)); });
|
||
}
|
||
});
|
||
|
||
return this
|
||
}
|
||
|
||
|
||
// gets the width of the scrollbar
|
||
function getScrollbarWidth(viewport) {
|
||
// append a div that has 100% width to get true width of viewport
|
||
var el = $('<div></div>').css({
|
||
width: '100%'
|
||
});
|
||
viewport.append(el);
|
||
|
||
// subtract true width from the viewport width which is inclusive
|
||
// of scrollbar by default
|
||
var scrollBarWidth = viewport.width() - el.width();
|
||
|
||
// remove our element from DOM
|
||
el.remove();
|
||
return scrollBarWidth
|
||
}
|
||
|
||
|
||
// Returns true if DOM element `element` is in viewport
|
||
function isInViewport(element, options) {
|
||
var ref = element.getBoundingClientRect();
|
||
var top = ref.top;
|
||
var bottom = ref.bottom;
|
||
var left = ref.left;
|
||
var right = ref.right;
|
||
|
||
var settings = $.extend({
|
||
tolerance: 0,
|
||
viewport: window
|
||
}, options);
|
||
var isVisibleFlag = false;
|
||
var $viewport = settings.viewport.jquery ? settings.viewport : $(settings.viewport);
|
||
|
||
if (!$viewport.length) {
|
||
console.warn('isInViewport: The viewport selector you have provided matches no element on page.');
|
||
console.warn('isInViewport: Defaulting to viewport as window');
|
||
$viewport = $(window);
|
||
}
|
||
|
||
var $viewportHeight = $viewport.height();
|
||
var $viewportWidth = $viewport.width();
|
||
var typeofViewport = $viewport[0].toString();
|
||
|
||
// if the viewport is other than window recalculate the top,
|
||
// bottom,left and right wrt the new viewport
|
||
// the [object DOMWindow] check is for window object type in PhantomJS
|
||
if ($viewport[0] !== window && typeofViewport !== '[object Window]' && typeofViewport !== '[object DOMWindow]') {
|
||
// use getBoundingClientRect() instead of $.Offset()
|
||
// since the original top/bottom positions are calculated relative to browser viewport and not document
|
||
var viewportRect = $viewport[0].getBoundingClientRect();
|
||
|
||
// recalculate these relative to viewport
|
||
top = top - viewportRect.top;
|
||
bottom = bottom - viewportRect.top;
|
||
left = left - viewportRect.left;
|
||
right = right - viewportRect.left;
|
||
|
||
// get the scrollbar width from cache or calculate it
|
||
isInViewport.scrollBarWidth = isInViewport.scrollBarWidth || getScrollbarWidth($viewport);
|
||
|
||
// remove the width of the scrollbar from the viewport width
|
||
$viewportWidth -= isInViewport.scrollBarWidth;
|
||
}
|
||
|
||
// handle falsy, non-number and non-integer tolerance value
|
||
// same as checking using isNaN and then setting to 0
|
||
// bitwise operators deserve some love too you know
|
||
settings.tolerance = ~~Math.round(parseFloat(settings.tolerance));
|
||
|
||
if (settings.tolerance < 0) {
|
||
settings.tolerance = $viewportHeight + settings.tolerance; // viewport height - tol
|
||
}
|
||
|
||
// the element is NOT in viewport iff it is completely out of
|
||
// viewport laterally or if it is completely out of the tolerance
|
||
// region. Therefore, if it is partially in view then it is considered
|
||
// to be in the viewport and hence true is returned. Because we have adjusted
|
||
// the left/right positions relative to the viewport, we should check the
|
||
// element's right against the viewport's 0 (left side), and the element's
|
||
// left against the viewport's width to see if it is outside of the viewport.
|
||
|
||
if (right <= 0 || left >= $viewportWidth) {
|
||
return isVisibleFlag
|
||
}
|
||
|
||
// if the element is bound to some tolerance
|
||
isVisibleFlag = settings.tolerance ? top <= settings.tolerance && bottom >= settings.tolerance : bottom > 0 && top <= $viewportHeight;
|
||
|
||
return isVisibleFlag
|
||
}
|
||
|
||
|
||
// get the selector args from the args string proved by Sizzle
|
||
function getSelectorArgs(argsString) {
|
||
if (argsString) {
|
||
var args = argsString.split(',');
|
||
|
||
// when user only gives viewport and no tolerance
|
||
if (args.length === 1 && isNaN(args[0])) {
|
||
args[1] = args[0];
|
||
args[0] = void 0;
|
||
}
|
||
|
||
return {
|
||
tolerance: args[0] ? args[0].trim() : void 0,
|
||
viewport: args[1] ? $(args[1].trim()) : void 0
|
||
}
|
||
}
|
||
return {}
|
||
}
|
||
|
||
})));
|
||
|
||
//# sourceMappingURL=isInViewport.js.map
|
||
</script>
|
||
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.19.0/prism.min.js"></script>
|
||
<script>
|
||
$(document).ready(function() {
|
||
$(document).on('scroll',function(e)
|
||
{
|
||
$('h2[id]').each(function()
|
||
{
|
||
if ( $(this).offset().top < window.pageYOffset + 100
|
||
&& $(this).offset().top +
|
||
$(this).height() > window.pageYOffset + 100
|
||
)
|
||
{
|
||
|
||
$(this).addClass('is-active');
|
||
|
||
var data = $(this).attr('id');
|
||
|
||
window.location.hash = '#!' + data;
|
||
|
||
var $location = window.location.hash.replace(/^#!/, '');
|
||
|
||
$('.js-docs-sidebar a').each(function() {
|
||
if($(this).attr('href').indexOf($location) > -1) {
|
||
$(this).addClass('is-active');
|
||
} else {
|
||
$(this).removeClass('is-active');
|
||
}
|
||
});
|
||
}
|
||
|
||
});
|
||
});
|
||
|
||
|
||
$(window).scroll(function() {
|
||
$('.js-inviewport-item').isInViewport({
|
||
tolerance: 0
|
||
})
|
||
.addClass('is-active');
|
||
});
|
||
|
||
var options = {
|
||
classes: {
|
||
clone: 'o-header__top--clone',
|
||
stick: 'is-sticky',
|
||
unstick: 'is-unsticky'
|
||
}
|
||
};
|
||
if($(window).width() >= 767) {
|
||
var header = new Headhesive('.js-header', options);
|
||
}
|
||
$('.js-navigation-open').on('click', function(event) {
|
||
event.preventDefault();
|
||
|
||
$('.js-navigation-list').addClass('is-active');
|
||
});
|
||
|
||
$('.js-navigation-close').on('click', function(event) {
|
||
event.preventDefault();
|
||
|
||
$('.js-navigation-list').removeClass('is-active');
|
||
});
|
||
|
||
$('.js-header-keyvisual').addClass('is-active');
|
||
|
||
// Popup
|
||
$('.js-popup').magnificPopup({
|
||
type: 'inline',
|
||
preloader: false,
|
||
focus: '#name',
|
||
|
||
// When elemened is focused, some mobile browsers in some cases zoom in
|
||
// It looks not nice, so we disable it:
|
||
callbacks: {
|
||
beforeOpen: function() {
|
||
if($(window).width() < 700) {
|
||
this.st.focus = false;
|
||
} else {
|
||
this.st.focus = '#name';
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
// Scroll
|
||
$('.js-anchor-scroll').anchorScroll({
|
||
scrollSpeed: 800, // scroll speed
|
||
offsetTop: 100, // offset for fixed top bars (defaults to 0)
|
||
onScroll: function () {
|
||
// callback on scroll start
|
||
},
|
||
scrollEnd: function () {
|
||
// callback on scroll end
|
||
}
|
||
});
|
||
});
|
||
|
||
$('.js-docs-trigger').on('click', function(event) {
|
||
event.preventDefault();
|
||
|
||
$('.js-docs-sidebar').addClass('is-active');
|
||
});
|
||
|
||
$('.js-docs-trigger-close').on('click', function(event) {
|
||
event.preventDefault();
|
||
|
||
$('.js-docs-sidebar').removeClass('is-active');
|
||
});
|
||
</script>
|
||
</body>
|
||
|
||
|
||
</body>
|
||
</html>
|
||
|