From 8be6ab96fff61653c7e09e5d0110fd1d44b3b1d7 Mon Sep 17 00:00:00 2001 From: pa238 Date: Sat, 9 Mar 2024 15:12:38 +0100 Subject: [PATCH] Add website files --- assets/border.svg | 4 + assets/style.css | 326 +++++++++++++++++++++++++++++++++++++++++++++ assets/tobi.css | 280 ++++++++++++++++++++++++++++++++++++++ assets/tobi.min.js | 1 + index.html | 113 ++++++++++++++++ 5 files changed, 724 insertions(+) create mode 100644 assets/border.svg create mode 100644 assets/style.css create mode 100644 assets/tobi.css create mode 100644 assets/tobi.min.js create mode 100644 index.html diff --git a/assets/border.svg b/assets/border.svg new file mode 100644 index 0000000..d96e38c --- /dev/null +++ b/assets/border.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/assets/style.css b/assets/style.css new file mode 100644 index 0000000..1f7337f --- /dev/null +++ b/assets/style.css @@ -0,0 +1,326 @@ +:root { + --font-xl: 42px; + --font-lg: 24px; + --font-md: 20px; + --font-sm: 18px; + --font-xs: 16px; + --font-xxs: 14px; +} +@media (max-width: 768px) { + :root { + --font-xl: 18px; + --font-lg: 16px; + --font-md: 14px; + --font-sm: 12px; + --font-xs: 12px; + --font-xxs: 12px; + } +} + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; + color: #222; + display: flex; + min-height: 100vh; + flex-direction: column; + font-size: var(--font-md); + background-color: #fff; + background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQ4MCIgaGVpZ2h0PSI2NTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+ICAgIDxwYXRoIGQ9Ik03MzEuMjA3IDY0OS44MDJDOTM1LjQ4NCA2NDIuMTQgMTQ4MCAzMzcuMzI1IDE0ODAgMTgwLjg4OGMwLTE1Ni40MzgtMzA5Ljc0NC0zNi4wNTUtNzIwLTM2LjA1NVMwLTE3NC40ODMgMCAxMzUuMTQ0YzAgMzA5LjYyNyA1MjYuOTMgNTIyLjMyIDczMS4yMDcgNTE0LjY1OHoiIGZpbGw9IiNGNkY4RkEiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==); + background-size: cover; + background-position-x: 20vw; + background-position-y: -10vh; + background-repeat: no-repeat; + line-height: 1.4; +} + +main { + flex: 1; + width: 100%; +} + +a { + color: #65638f; + text-decoration: none; +} +a:hover { + color: #5A51FE; +} + +.button { + display: flex; + background: linear-gradient(65deg, #DA552F, #ea8e39); + font-family: "Heebo", sans-serif; + color: #fff; + display: inline-flex; + font-size: var(--font-xxs); + letter-spacing: 0px; + font-weight: 700; + line-height: 16px; + text-transform: uppercase; + text-decoration: none !important; + border: none; + border-radius: 2px; + cursor: pointer; + justify-content: center; + padding: 16px 32px; + text-align: center; + white-space: nowrap; + box-shadow: 0 8px 24px rgba(32, 43, 54, 0.12); + mix-blend-mode: multiply; + transition: all 0.15s ease; +} +.button:hover { + color: #fff; + box-shadow: 0 8px 24px rgba(32, 43, 54, 0.25); +} +.button--link { + background: rgba(0, 0, 0, 0); + color: #5A51FE; + box-shadow: none; +} +.button--link:hover { + color: #8751FE; + box-shadow: none; +} + +.accent { + color: #5A51FE; +} + +.container { + max-width: 960px; + padding: 0 30px; + margin: auto; +} + +h1, h2 { + font-family: "Heebo", sans-serif; +} + +.container-desktop { + max-width: 960px; + padding: 0 30px; + margin: auto; +} +@media (max-width: 768px) { + .container-desktop { + max-width: 100%; + padding: 0; + } +} + +.tobi-zoom__icon { + display: none; +} + +.app__header { + display: flex; + flex-direction: row; + margin-top: 128px; + margin-bottom: 128px; + align-items: center; +} +@media (max-width: 768px) { + .app__header { + align-items: flex-start; + margin-top: 32px; + margin-bottom: 16px; + } +} +.app__logo-wrapper { + display: inline-block; + background-image: url("border.svg"); + background-size: contain; + max-width: 250px; + max-height: 250px; + padding: 1px; + margin-right: 64px; + width: 100%; + height: 100%; + background-repeat: no-repeat; +} +html[dir=rtl] .app__logo-wrapper { + margin-left: 64px; + margin-right: 0; +} +@media (max-width: 768px) { + .app__logo-wrapper { + max-width: 100px; + max-height: 100px; + margin-right: 16px; + } +} +.app__logo { + border-radius: 25.5%; + mask-size: cover; + width: 100%; + height: auto; +} +.app__name { + font-size: var(--font-xl); + margin: 0; +} +.app__description { + font-size: var(--font-lg); +} +@media (max-width: 768px) { + .app__description { + margin-top: 8px; + margin-bottom: 0; + } +} +.app__screenshots-list { + display: grid; + grid-template-columns: 200px 200px 200px 200px 200px 200px; + grid-column-gap: 20px; + padding: 30px 0; +} +@media (max-width: 768px) { + .app__screenshots-list { + padding: 32px; + width: 800px; + } +} +.app__screenshot { + width: 100%; + border-radius: 16px; + box-shadow: 0 12px 48px rgba(17, 16, 62, 0.12); + transition: all 0.3s ease-in-out; + transform: scale(1); + cursor: pointer; +} +.app__screenshot:hover { + box-shadow: 0 24px 48px rgba(17, 16, 62, 0.12); + transform: scale(1.05); +} +.app__screenshots-wrapper { + overflow-y: auto; +} +.app__buttons { + display: flex; + flex-direction: row; + align-items: center; + margin-left: -9.8px; +} +.app__buttons--mobile { + display: none; +} +@media (max-width: 768px) { + .app__buttons { + margin-left: 0; + margin-bottom: 64px; + } + .app__buttons--mobile { + display: flex; + justify-content: center; + } + .app__buttons--desktop { + display: none; + } +} +.app__button-play img { + width: 176.4px; +} +.app__button-ios img { + width: 196.4px; +} +.app__button-web { + margin-left: 12px; +} +.app__button-web img { + width: 157px; +} +@media (max-width: 768px) { + .app__button-play img { + width: 126px; + } + .app__button-ios img { + width: 136px; + } + .app__button-web { + margin-left: 8px; + } + .app__button-web img { + width: 112px; + } +} +.app__section-title { + font-size: var(--font-lg); +} +.app__section { + margin-bottom: 128px; +} +@media (max-width: 768px) { + .app__section { + margin-bottom: 64px; + } +} +.app__featured-content { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-column-gap: 32px; + align-items: center; +} +@media (max-width: 768px) { + .app__featured-content { + display: block; + padding: 32px; + } +} +.app__featured-image { + width: 100%; + margin: auto; +} + +.footer { + padding: 16px 0; + font-size: var(--font-xs) !important; +} +.footer a { + font-size: var(--font-xs) !important; +} +.footer__container { + color: #65638f; + display: flex; + width: 100%; + justify-content: space-between; + align-items: center; +} +@media (max-width: 768px) { + .footer__container { + flex-direction: column-reverse; + align-items: flex-start; + } +} +.footer__links { + list-style: none; + display: flex; + padding-left: 0; +} +.footer__link { + margin-left: 32px; +} +@media (max-width: 768px) { + .footer__link { + margin-left: 0; + margin-right: 8px; + } +} + +.page { + max-width: 960px; + padding: 0 30px; + margin: auto; +} + +.darkmode-toggle { + z-index: 500; +} + +.darkmode-background { + background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQ4MCIgaGVpZ2h0PSI2NTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+ICAgIDxwYXRoIGQ9Ik03MzEuMjA3IDY0OS44MDJDOTM1LjQ4NCA2NDIuMTQgMTQ4MCAzMzcuMzI1IDE0ODAgMTgwLjg4OGMwLTE1Ni40MzgtMzA5Ljc0NC0zNi4wNTUtNzIwLTM2LjA1NVMwLTE3NC40ODMgMCAxMzUuMTQ0YzAgMzA5LjYyNyA1MjYuOTMgNTIyLjMyIDczMS4yMDcgNTE0LjY1OHoiIGZpbGw9IiNGNkY4RkEiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==) !important; + background-size: cover !important; + background-position-x: 20vw !important; + background-position-y: -10vh !important; + background-repeat: no-repeat !important; +} \ No newline at end of file diff --git a/assets/tobi.css b/assets/tobi.css new file mode 100644 index 0000000..e27b2be --- /dev/null +++ b/assets/tobi.css @@ -0,0 +1,280 @@ +.tobi { + background-color: rgba(26, 42, 58, 0.94); + bottom: 0; + box-sizing: border-box; + contain: strict; + font-size: 18px; + left: 0; + line-height: 1.5555555555555556; + overflow: hidden; + position: fixed; + right: 0; + top: 0; + z-index: 1337; +} + +.tobi[aria-hidden="true"] { + display: none; +} + +.tobi *, +.tobi *::before, +.tobi *::after { + box-sizing: inherit; +} + +.tobi-is-open { + overflow-y: hidden; +} + +.tobi__slider { + bottom: 0; + left: 0; + position: absolute; + right: 0; + top: 0; + will-change: transform; +} + +.tobi__slider:not(.tobi__slider--is-dragging) { + transition-duration: 0.3s; + transition-property: transform; + transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1); +} + +@media screen and (prefers-reduced-motion: reduce) { + .tobi__slider:not(.tobi__slider--is-dragging) { + transition: none; + } +} + +.tobi__slider--is-draggable [data-type] { + cursor: -webkit-grab; + cursor: grab; +} + +.tobi__slider--is-dragging [data-type] { + cursor: -webkit-grabbing; + cursor: grabbing; +} + +.tobi__slide { + align-items: center; + display: flex; + height: 100%; + justify-content: center; + width: 100%; +} + +.tobi__slide:not(.tobi__slide--is-active) { + visibility: hidden; +} + +.tobi [data-type] { + max-height: 85vh; + max-width: 85vw; + overflow: hidden; + overflow-y: auto; + overscroll-behavior: contain; +} + +.tobi [data-type] iframe, +.tobi [data-type] video { + display: block !important; +} + +.tobi [data-type] > figure { + margin: 0; + position: relative; +} + +.tobi [data-type] > figure > img { + display: block; + height: auto; + max-height: 85vh; + max-width: 85vw; + width: auto; +} + +.tobi [data-type] > figure > figcaption { + background-color: rgba(255, 255, 255, 0.94); + bottom: 0; + color: #1a2a3a; + padding: 0.22222em 0.44444em; + position: absolute; + white-space: pre-wrap; + width: 100%; +} + +.tobi [data-type="html"] video { + cursor: auto; + max-height: 85vh; + max-width: 85vw; +} + +.tobi [data-type="iframe"] { + /* Fix iframe scrolling on iOS */ + -webkit-overflow-scrolling: touch; + transform: translate3d(0, 0, 0); +} + +.tobi [data-type="iframe"] iframe { + height: 85vh; + width: 85vw; +} + +.tobi > button { + background-color: transparent; + border: 0.05556em solid transparent; + color: #fff; + cursor: pointer; + font: inherit; + line-height: 1; + margin: 0; + opacity: 0.5; + padding: 0.22222em; + position: absolute; + touch-action: manipulation; + transition-duration: 0.3s; + transition-property: opacity, transform; + transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1); + will-change: opacity, transform; + z-index: 1; +} + +@media screen and (prefers-reduced-motion: reduce) { + .tobi > button { + transition: none; + will-change: opacity; + } +} + +.tobi > button svg { + pointer-events: none; + stroke: #fff; + stroke-width: 1; + stroke-linecap: square; + stroke-linejoin: miter; + fill: none; + color: #fff; +} + +.tobi > button:active, .tobi > button:focus, .tobi > button:hover { + opacity: 1; + transform: scale(0.84); +} + +@media screen and (prefers-reduced-motion: reduce) { + .tobi > button:active, .tobi > button:focus, .tobi > button:hover { + transform: none; + } +} + +.tobi > button.tobi__prev, .tobi > button.tobi__next { + top: calc(50% - 1.94444em); +} + +.tobi > button.tobi__prev svg, .tobi > button.tobi__next svg { + height: 3.88889em; + width: 3.88889em; +} + +.tobi > button.tobi__prev { + left: 0; +} + +.tobi > button.tobi__next { + right: 0; +} + +.tobi > button.tobi__close { + right: 0.27778em; + top: 1em; +} + +.tobi > button.tobi__close svg { + height: 3.33333em; + width: 3.33333em; +} + +.tobi > button:disabled, .tobi > button[aria-hidden="true"] { + display: none; +} + +.tobi__counter { + background-color: transparent; + color: #fff; + font-size: 1.11111em; + left: 1em; + line-height: 1; + position: absolute; + top: 2.22222em; + z-index: 1; +} + +.tobi__counter[aria-hidden="true"] { + display: none; +} + +.tobi-loader { + display: inline-block; + height: 5.55556em; + left: calc(50% - 2.77778em); + position: absolute; + top: calc(50% - 2.77778em); + width: 5.55556em; +} + +.tobi-loader::before { + animation: spin 1s infinite; + border-radius: 100%; + border: 0.22222em solid #949ba3; + border-top-color: #fff; + bottom: 0; + content: ""; + left: 0; + position: absolute; + right: 0; + top: 0; + z-index: 1; +} + +.tobi-zoom { + border: 0; + box-shadow: none; + display: inline-block; + position: relative; + text-decoration: none; +} + +.tobi-zoom img { + display: block; +} + +.tobi-zoom__icon { + background-color: rgba(26, 42, 58, 0.94); + bottom: 0; + color: #fff; + line-height: 1; + position: absolute; + right: 0; +} + +.tobi-zoom__icon svg { + color: #fff; + fill: none; + height: 1.11111em; + padding: 0.22222em; + pointer-events: none; + stroke-linecap: square; + stroke-linejoin: miter; + stroke-width: 2; + stroke: #fff; + width: 1.11111em; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} diff --git a/assets/tobi.min.js b/assets/tobi.min.js new file mode 100644 index 0000000..3be1ccb --- /dev/null +++ b/assets/tobi.min.js @@ -0,0 +1 @@ +(function (e, t) { "function" == typeof define && define.amd ? define(t) : "object" == typeof module && module.exports ? module.exports = t() : e.Tobi = t() })(this, function () { "use strict"; const e = function (e) { const t = window, n = ['a[href]:not([tabindex^="-"]):not([inert])', 'area[href]:not([tabindex^="-"]):not([inert])', "input:not([disabled]):not([inert])", "select:not([disabled]):not([inert])", "textarea:not([disabled]):not([inert])", "button:not([disabled]):not([inert])", 'iframe:not([tabindex^="-"]):not([inert])', 'audio:not([tabindex^="-"]):not([inert])', 'video:not([tabindex^="-"]):not([inert])', '[contenteditable]:not([tabindex^="-"]):not([inert])', '[tabindex]:not([tabindex^="-"]):not([inert])'], r = [], o = [], i = { gallery: [], slider: null, sliderElements: [], elementsLength: 0, currentIndex: 0, x: 0 }; let a = {}, s = 0, d = null, l = null, c = null, u = null, p = null, b = {}, f = !1, h = !1, m = !1, g = null, y = null, v = null, A = null, x = null, w = !1, E = !1, L = 0, _ = {}, C = null, S = null; const I = function (e) { const t = { selector: ".lightbox", captions: !0, captionsSelector: "img", captionAttribute: "alt", nav: "auto", navText: ['', ''], navLabel: ["Previous image", "Next image"], close: !0, closeText: '', closeLabel: "Close lightbox", loadingIndicatorLabel: "Image loading", counter: !0, download: !1, downloadText: "", downloadLabel: "Download image", keyboard: !0, zoom: !0, zoomText: '', docClose: !0, swipeClose: !0, hideScrollbar: !0, draggable: !0, threshold: 100, rtl: !1, loop: !1, autoplayVideo: !1 }; return e && Object.keys(e).forEach(function (n) { t[n] = e[n] }), t }, T = { image: { checkSupport: function (e) { return !e.hasAttribute("data-type") && e.href.match(/\.(png|jpe?g|tiff|tif|gif|bmp|webp|svg|ico)(\?.*)?$/i) }, init: function (e, t) { const n = document.createElement("figure"), r = document.createElement("figcaption"), o = document.createElement("img"), i = e.querySelector("img"), d = document.createElement("div"); o.style.opacity = "0", i && (o.alt = i.alt || ""), o.setAttribute("src", ""), o.setAttribute("data-src", e.href), n.appendChild(o), a.captions && (r.style.opacity = "0", "self" === a.captionsSelector && e.getAttribute(a.captionAttribute) ? r.textContent = e.getAttribute(a.captionAttribute) : "img" === a.captionsSelector && i && i.getAttribute(a.captionAttribute) && (r.textContent = i.getAttribute(a.captionAttribute)), r.textContent && (r.id = "tobi-figcaption-" + s, n.appendChild(r), o.setAttribute("aria-labelledby", r.id), ++s)), t.appendChild(n), d.className = "tobi-loader", d.setAttribute("role", "progressbar"), d.setAttribute("aria-label", a.loadingIndicatorLabel), t.appendChild(d), t.setAttribute("data-type", "image") }, onPreload: function (e) { T.image.onLoad(e) }, onLoad: function (e) { const t = e.querySelector("img"); if (!t.hasAttribute("data-src")) return; const n = e.querySelector("figcaption"), r = e.querySelector(".tobi-loader"); t.onload = function () { e.removeChild(r), t.style.opacity = "1", n && (n.style.opacity = "1") }, t.setAttribute("src", t.getAttribute("data-src")), t.removeAttribute("data-src") }, onLeave: function (e) { }, onCleanup: function (e) { } }, html: { checkSupport: function (e) { return pe(e, "html") }, init: function (e, t) { const n = e.hasAttribute("href") ? e.getAttribute("href") : e.getAttribute("data-target"), r = document.querySelector(n); if (!r) throw new Error("Ups, I can't find the target " + n + "."); t.appendChild(r), t.setAttribute("data-type", "html") }, onPreload: function (e) { }, onLoad: function (e) { const t = e.querySelector("video"); t && (t.hasAttribute("data-time") && t.readyState > 0 && (t.currentTime = t.getAttribute("data-time")), a.autoplayVideo && t.play()) }, onLeave: function (e) { const t = e.querySelector("video"); t && (t.paused || t.pause(), t.readyState > 0 && t.setAttribute("data-time", t.currentTime)) }, onCleanup: function (e) { const t = e.querySelector("video"); if (t && t.readyState > 0 && t.readyState < 3 && t.duration !== t.currentTime) { const n = t.cloneNode(!0); be(t), t.load(), t.parentNode.removeChild(t), e.appendChild(n) } } }, iframe: { checkSupport: function (e) { return pe(e, "iframe") }, init: function (e, t) { const n = document.createElement("iframe"), r = e.hasAttribute("href") ? e.getAttribute("href") : e.getAttribute("data-target"); n.setAttribute("frameborder", "0"), n.setAttribute("src", ""), n.setAttribute("data-src", r), e.getAttribute("data-width") && (n.style.maxWidth = e.getAttribute("data-width") + "px"), e.getAttribute("data-height") && (n.style.maxHeight = e.getAttribute("data-height") + "px"), t.appendChild(n), t.setAttribute("data-type", "iframe") }, onPreload: function (e) { }, onLoad: function (e) { const t = e.querySelector("iframe"); t.setAttribute("src", t.getAttribute("data-src")) }, onLeave: function (e) { }, onCleanup: function (e) { } }, youtube: { checkSupport: function (e) { return pe(e, "youtube") }, init: function (e, t) { const n = document.createElement("div"); t.appendChild(n), o[L] = new window.YT.Player(n, { host: "https://www.youtube-nocookie.com", height: e.getAttribute("data-height") || "360", width: e.getAttribute("data-width") || "640", videoId: e.getAttribute("data-id"), playerVars: { controls: e.getAttribute("data-controls") || 1, rel: 0, playsinline: 1 } }), t.setAttribute("data-player", L), t.setAttribute("data-type", "youtube"), L++ }, onPreload: function (e) { }, onLoad: function (e) { a.autoplayVideo && o[e.getAttribute("data-player")].playVideo() }, onLeave: function (e) { 1 === o[e.getAttribute("data-player")].getPlayerState() && o[e.getAttribute("data-player")].pauseVideo() }, onCleanup: function (e) { 1 === o[e.getAttribute("data-player")].getPlayerState() && o[e.getAttribute("data-player")].pauseVideo() } } }; Object.entries || (Object.entries = function (e) { const t = Object.keys(e); let n = t.length; const r = new Array(n); for (; n--;)r[n] = [t[n], e[t[n]]]; return r }); const O = function (e) { a = I(e), d || M(); const t = document.querySelectorAll(a.selector); if (!t) throw new Error("Ups, I can't find the selector " + a.selector + "."); Array.prototype.forEach.call(t, function (e) { k(e) }) }, k = function (e, t) { if (null === document.querySelector('[data-type="youtube"]') || E) P(e, t); else { if (null === document.getElementById("iframe_api")) { const e = document.createElement("script"), t = document.getElementsByTagName("script")[0]; e.id = "iframe_api", e.src = "https://www.youtube.com/iframe_api", t.parentNode.insertBefore(e, t) } -1 === r.indexOf(e) && r.push(e), window.onYouTubePlayerAPIReady = function () { Array.prototype.forEach.call(r, function (e) { P(e, t) }), E = !0 } } }, q = function (e) { return e.hasAttribute("data-group") ? e.getAttribute("data-group") : "default" }, N = function (e) { return JSON.parse(JSON.stringify(e)) }, P = function (e, t) { if (C = q(e), Object.prototype.hasOwnProperty.call(_, C) || (_[C] = N(i), Y()), -1 !== _[C].gallery.indexOf(e)) throw new Error("Ups, element already added to the lightbox."); if (_[C].gallery.push(e), _[C].elementsLength++, a.zoom && e.querySelector("img")) { const t = document.createElement("div"); t.className = "tobi-zoom__icon", t.innerHTML = a.zoomText, e.classList.add("tobi-zoom"), e.appendChild(t) } e.addEventListener("click", Q), j(e), ve() && C === S && (fe(), me()), t && t.call(this) }, X = function (e, t) { const n = q(e); if (-1 === _[n].gallery.indexOf(e)); else { const r = _[n].gallery.indexOf(e), o = _[n].sliderElements[r]; if (_[n].elementsLength--, a.zoom && e.querySelector(".tobi-zoom__icon")) { const t = e.querySelector(".tobi-zoom__icon"); t.parentNode.classList.remove("tobi-zoom"), t.parentNode.removeChild(t) } e.removeEventListener("click", Q), o.parentNode.removeChild(o), ve() && n === S && (fe(), me()), t && t.call(this) } }, M = function () { d = document.createElement("div"), d.setAttribute("role", "dialog"), d.setAttribute("aria-hidden", "true"), d.className = "tobi", l = document.createElement("button"), l.className = "tobi__prev", l.setAttribute("type", "button"), l.setAttribute("aria-label", a.navLabel[0]), l.innerHTML = a.navText[0], d.appendChild(l), c = document.createElement("button"), c.className = "tobi__next", c.setAttribute("type", "button"), c.setAttribute("aria-label", a.navLabel[1]), c.innerHTML = a.navText[1], d.appendChild(c), u = document.createElement("button"), u.className = "tobi__close", u.setAttribute("type", "button"), u.setAttribute("aria-label", a.closeLabel), u.innerHTML = a.closeText, d.appendChild(u), p = document.createElement("div"), p.className = "tobi__counter", d.appendChild(p), t.addEventListener("resize", function () { w || (w = !0, t.requestAnimationFrame(function () { G(), w = !1 })) }), document.body.appendChild(d) }, Y = function () { _[C].slider = document.createElement("div"), _[C].slider.className = "tobi__slider", d.appendChild(_[C].slider) }, j = function (e) { for (let t in T) if (Object.prototype.hasOwnProperty.call(T, t) && T[t].checkSupport(e)) { const n = document.createElement("div"), r = document.createElement("div"); n.className = "tobi__slide", n.style.position = "absolute", n.style.left = 100 * _[C].x + "%", T[t].init(e, r), n.appendChild(r), _[C].slider.appendChild(n), _[C].sliderElements.push(n), ++_[C].x; break } }, z = function (e, t) { if (S = null !== S ? S : C, ve() || e || (e = 0), ve()) { if (!e) throw new Error("Ups, Tobi is aleady open."); if (e === _[S].currentIndex) throw new Error("Ups, slide " + e + " is already selected.") } if (-1 === e || e >= _[S].elementsLength) throw new Error("Ups, I can't find slide " + e + "."); a.hideScrollbar && (document.documentElement.classList.add("tobi-is-open"), document.body.classList.add("tobi-is-open")), fe(), a.close || (u.disabled = !1, u.setAttribute("aria-hidden", "true")), g = document.activeElement, _[S].currentIndex = e, F(), ce(), V(_[S].currentIndex), d.setAttribute("aria-hidden", "false"), me(), U(_[S].currentIndex + 1), U(_[S].currentIndex - 1), t && t.call(this) }, D = function (e) { if (!ve()) throw new Error("Tobi is already closed."); a.hideScrollbar && (document.documentElement.classList.remove("tobi-is-open"), document.body.classList.remove("tobi-is-open")), ue(), g.focus(); const t = _[S].sliderElements[_[S].currentIndex].querySelector("[data-type]"), n = t.getAttribute("data-type"); T[n].onLeave(t), T[n].onCleanup(t), d.setAttribute("aria-hidden", "true"), _[S].currentIndex = 0, e && e.call(this) }, U = function (e) { if (void 0 === _[S].sliderElements[e]) return; const t = _[S].sliderElements[e].querySelector("[data-type]"), n = t.getAttribute("data-type"); T[n].onPreload(t) }, V = function (e) { if (void 0 === _[S].sliderElements[e]) return; const t = _[S].sliderElements[e].querySelector("[data-type]"), n = t.getAttribute("data-type"); _[S].sliderElements[e].classList.add("tobi__slide--is-active"), T[n].onLoad(t) }, H = function (e) { _[S].currentIndex > 0 && (R(_[S].currentIndex), V(--_[S].currentIndex), me("left"), W(_[S].currentIndex + 1), U(_[S].currentIndex - 1), e && e.call(this)) }, B = function (e) { _[S].currentIndex < _[S].elementsLength - 1 && (R(_[S].currentIndex), V(++_[S].currentIndex), me("right"), W(_[S].currentIndex - 1), U(_[S].currentIndex + 1), e && e.call(this)) }, R = function (e) { if (void 0 === _[S].sliderElements[e]) return; const t = _[S].sliderElements[e].querySelector("[data-type]"), n = t.getAttribute("data-type"); _[S].sliderElements[e].classList.remove("tobi__slide--is-active"), T[n].onLeave(t) }, W = function (e) { if (void 0 === _[S].sliderElements[e]) return; const t = _[S].sliderElements[e].querySelector("[data-type]"), n = t.getAttribute("data-type"); T[n].onCleanup(t) }, G = function () { S = null !== S ? S : C, A = -_[S].currentIndex * window.innerWidth, _[S].slider.style.transform = "translate3d(" + A + "px, 0, 0)", x = A }, J = function () { p.textContent = _[S].currentIndex + 1 + "/" + _[S].elementsLength }, K = function (e) { let t = null; a.nav ? (l.disabled = !1, c.disabled = !1, "left" === e ? l.focus() : c.focus(), 1 === _[S].elementsLength ? (l.disabled = !0, c.disabled = !0, a.close && u.focus()) : (0 === _[S].currentIndex && (l.disabled = !0, c.focus()), _[S].currentIndex === _[S].elementsLength - 1 && (c.disabled = !0, l.focus()))) : a.close && u.focus(), t = d.querySelectorAll(".tobi > button:not(:disabled)"), y = t[0], v = 1 === t.length ? t[0] : t[t.length - 1] }, F = function () { b = { startX: 0, endX: 0, startY: 0, endY: 0 } }, $ = function () { const e = b.endX - b.startX, t = b.endY - b.startY, n = Math.abs(e), r = Math.abs(t); e > 0 && n > a.threshold && _[S].currentIndex > 0 ? H() : e < 0 && n > a.threshold && _[S].currentIndex !== _[S].elementsLength - 1 ? B() : t < 0 && r > a.threshold && a.swipeClose ? D() : G() }, Q = function (e) { e.preventDefault(), S = q(this), z(_[S].gallery.indexOf(this)) }, Z = function (e) { e.target === l ? H() : e.target === c ? B() : (e.target === u || e.target.classList.contains("tobi__slide") && a.docClose) && D(), e.stopPropagation() }, ee = function () { return Array.prototype.slice.call(d.querySelectorAll(".tobi__close:not([disabled]), .tobi__prev:not([disabled]), .tobi__next:not([disabled]), .tobi__slide--is-active + " + n.join(", .tobi__slide--is-active "))).filter(function (e) { return !!(e.offsetWidth || e.offsetHeight || e.getClientRects().length) }) }, te = function (e) { const t = ee(), n = t.indexOf(document.activeElement); 9 === e.keyCode || "Tab" === e.code ? e.shiftKey && 0 === n ? (t[t.length - 1].focus(), e.preventDefault()) : e.shiftKey || n !== t.length - 1 || (t[0].focus(), e.preventDefault()) : 27 === e.keyCode || "Escape" === e.code ? (e.preventDefault(), D()) : 37 === e.keyCode || "ArrowLeft" === e.code ? (e.preventDefault(), H()) : 39 !== e.keyCode && "ArrowRight" !== e.code || (e.preventDefault(), B()) }, ne = function (e) { xe(e.target) || (e.stopPropagation(), m = !0, b.startX = e.touches[0].pageX, b.startY = e.touches[0].pageY, _[S].slider.classList.add("tobi__slider--is-dragging")) }, re = function (e) { e.stopPropagation(), m && (e.preventDefault(), b.endX = e.touches[0].pageX, b.endY = e.touches[0].pageY, le()) }, oe = function (e) { e.stopPropagation(), m = !1, _[S].slider.classList.remove("tobi__slider--is-dragging"), b.endX && (f = !1, h = !1, $()), F() }, ie = function (e) { xe(e.target) || (e.preventDefault(), e.stopPropagation(), m = !0, b.startX = e.pageX, b.startY = e.pageY, _[S].slider.classList.add("tobi__slider--is-dragging")) }, ae = function (e) { e.preventDefault(), m && (b.endX = e.pageX, b.endY = e.pageY, le()) }, se = function (e) { e.stopPropagation(), m = !1, _[S].slider.classList.remove("tobi__slider--is-dragging"), b.endX && (f = !1, h = !1, $()), F() }, de = function (e) { m = !1 }, le = function () { Math.abs(b.startX - b.endX) > 0 && !h && a.swipeClose ? (_[S].slider.style.transform = "translate3d(" + (x - Math.round(b.startX - b.endX)) + "px, 0, 0)", f = !0, h = !1) : Math.abs(b.startY - b.endY) > 0 && !f && (_[S].slider.style.transform = "translate3d(" + x + "px, -" + Math.round(b.startY - b.endY) + "px, 0)", f = !1, h = !0) }, ce = function () { a.keyboard && document.addEventListener("keydown", te), d.addEventListener("click", Z), a.draggable && (Ae() && (d.addEventListener("touchstart", ne), d.addEventListener("touchmove", re), d.addEventListener("touchend", oe)), d.addEventListener("mousedown", ie), d.addEventListener("mouseup", se), d.addEventListener("mousemove", ae), d.addEventListener("contextmenu", de)) }, ue = function () { a.keyboard && document.removeEventListener("keydown", te), d.removeEventListener("click", Z), a.draggable && (Ae() && (d.removeEventListener("touchstart", ne), d.removeEventListener("touchmove", re), d.removeEventListener("touchend", oe)), d.removeEventListener("mousedown", ie), d.removeEventListener("mouseup", se), d.removeEventListener("mousemove", ae), d.removeEventListener("contextmenu", de)) }, pe = function (e, t) { return e.getAttribute("data-type") === t }, be = function (e) { const t = e.querySelectorAll("src"); t && Array.prototype.forEach.call(t, function (e) { e.setAttribute("src", "") }) }, fe = function () { a.draggable && _[S].elementsLength > 1 && !_[S].slider.classList.contains("tobi__slider--is-draggable") && _[S].slider.classList.add("tobi__slider--is-draggable"), !a.nav || 1 === _[S].elementsLength || "auto" === a.nav && Ae() ? (l.setAttribute("aria-hidden", "true"), c.setAttribute("aria-hidden", "true")) : (l.setAttribute("aria-hidden", "false"), c.setAttribute("aria-hidden", "false")), a.counter && 1 !== _[S].elementsLength ? p.setAttribute("aria-hidden", "false") : p.setAttribute("aria-hidden", "true") }, he = function () { for (let e in _) Object.prototype.hasOwnProperty.call(_, e) && (_[e].slider.style.display = S === e ? "block" : "none") }, me = function (e) { he(), G(), J(), K(e) }, ge = function (e) { ve() && D(); const t = Object.entries(_); Array.prototype.forEach.call(t, function (e) { const t = e[1].gallery; Array.prototype.forEach.call(t, function (e) { X(e) }) }), _ = {}, C = S = null, s = 0, e && e.call(this) }, ye = function (e) { ge(), d.parentNode.removeChild(d), e && e.call(this) }, ve = function () { return "false" === d.getAttribute("aria-hidden") }, Ae = function () { return "ontouchstart" in window }, xe = function (e) { return -1 !== ["TEXTAREA", "OPTION", "INPUT", "SELECT"].indexOf(e.nodeName) || e === l || e === c || e === u || 1 === _[S].elementsLength }, we = function () { return _[S].currentIndex }, Ee = function () { return null !== S ? S : C }, Le = function (e) { if (ve()) throw new Error("Ups, I can't do this. Tobi is open."); if (e) { if (e && !Object.prototype.hasOwnProperty.call(_, e)) throw new Error("Ups, I don't have a group called \"" + e + '".'); S = e } }; return O(e), { open: z, prev: H, next: B, close: D, add: k, remove: X, reset: ge, destroy: ye, isOpen: ve, currentSlide: we, selectGroup: Le, currentGroup: Ee } }; return e }); \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..a47d329 --- /dev/null +++ b/index.html @@ -0,0 +1,113 @@ + + + + + Free TV + + + + + + + + + + + + + + +
+
+
+
+

Free TV

+

The app is designed for watching TV channels from around the world.

+ +
+
+ +
+
+

Screenshots

+
+ +
+
+

Description

+
+

Open-Source application that does not require registration and all content is free for users.

+

It is possible to play international as well as local channels using a simple player. The player supports gesture control.

+

Add favorite channels to the favorites list and then play them. There is also the option to play your own links.

+

And much more.

+
+
+
+ + + + + + +