PageSourceSearch

https://filipvabrousek.github.io/comptest/AppShowcase.js

js filipvabrousek.github.io collected 2026-10-03 09:11:41 UTC 19,863 bytes, 682 lines download raw bytes

1const template = document.createElement("template");
2template.innerHTML = `
3
4<div class="appShowcaseApp">
5<h2 class="largeHidden" id="runnyLarge">
6
7</h2>
8
9<p class="descSlot">
10<slot name="desc"></slot>
11</p>
12
13<div id="flexa">
14
15<img src="images/runny-orig.png" class="app-imga" />
16<h2 class="titles"></h2>
17</div>
18
19<div class="add"></div>
20
21<div class="oneMoreOverlay modernSection">
22
23
24  <div class="blobImage blobImageRunny"></div>
25
26<div id="runnyOverlay">
27
28
29
30<div id="runnysa" class="leftIcon leftIconRunny">
31  <div class="sidesImages">
32    <img src="images/runny-orig.png" class="app-img" />
33  </div>
34
35  <div class="leftAppWrapper">
36
37    <h2 class="stroked runnyStroked"><slot></slot></h2>
38    <p class="appDesc">
39    </p>
40
41    <div class="stores">
42     
43    </div>
44  </div>
45</div>
46</div>
47
48<!---Make green gradient blob instead of an image and change its shape on scroll--->
49
50
51
52</div>
53
54
55
56
57</div>
58
59
60<style>
61.titles, .desc, .app-imga, .appstore  {
62opacity: 1;
63transform: translateY(100px);
64}
65
66.titles {
67margin-bottom: 3rem;
68letter-spacing: .4rem;
69font-family: Bebas Neue, Roboto Condensed, Arial;
70text-transform: uppercase;
71}
72
73
74.app-imga {
75margin-left: 2rem;
76opacity: 0;
77}
78
79.appstore {
80width: 200px;
81}
82
83.desc {
84color: black;
85padding-bottom: 3rem;
86font-size: 1.6rem;
87}
88
89#runnyOverlay, .blobImage {
90opacity: 0;
91transform: translateY(100px);
92}
93
94.titles {
95font-size: 6rem;
96margin-left: 2rem;
97
98}
99
100
101@media (max-width: 70rem){
102.titles {
103  font-size: 3rem;
104}
105}
106
107
108* {
109margin: 0;
110}
111
112.appShowCaseApp {
113height: 800px;
114}
115
116#flexa {
117display: flex;
118flex-direction: row;
119
120align-items: center;
121
122}
123
124#flexa img {
125width: 130px;
126height: 100%
127
128}
129
130h2 {
131color: transparent;
132font-family: Arial;
133font-size: 7rem;
134}
135
136.blobImage {
137max-width: 70%; /*was 700px*/
138height: 600px;
139border-radius: 43% 56% 72% 28% / 42% 42% 56% 48%;
140}
141
142.app-img, .app-imga {
143width: 250px;
144border-radius: 30px;
145opacity: 0;
146}
147
148.app-img {
149display: none;
150}
151/*
152.app-img, .blobImage {
153position: absolute;
154}*/
155
156
157
158 .cover > img {
159 border-radius: 1rem;
160 }
161
162 .cover {
163 overflow-x: scroll;
164            display: flex;
165
166            justify-content: flex-start;
167            width: 90%;
168            margin-left: auto;
169             margin-right: auto;
170            height: 700px;
171            grid-area: 1 / 1;
172            z-index: 1;
173            margin-top: 14rem; 
174            
175        }
176
177        .cover::-webkit-scrollbar {
178    display: none;  /* Chrome, Safari, Webkit-based browsers */
179}
180
181        .stroked {
182            z-index: 1;
183            /* Add more styles if necessary */
184        }
185
186        .screenshot {
187            max-width: 460px;
188            margin: 10px;
189        }
190
191        .desc {
192        font-family: Arial;
193        color: gray;
194        } 
195
196
197
198
199@media (max-device-width: 430px) {
200
201            #flexa {
202        flex-direction: column;
203    }
204
205        #flexa img {
206        margin-top: 6rem;
207    }
208
209  
210}
211     
212</style>
213
214<script>
215alert("a");
216</script>
217`;
218
219
220class ScrollDrivenArrayInterpolator {
221  constructor(startArray, endArray, scrollStart, scrollEnd) {
222      if (startArray.length !== endArray.length) {
223          throw new Error("Arrays must be of the same length.");
224      }
225      this.startArray = startArray;
226      this.endArray = endArray;
227      this.scrollStart = scrollStart; // Scroll position at which interpolation starts
228      this.scrollEnd = scrollEnd;     // Scroll position at which interpolation ends
229  }
230
231  interpolateByScroll(scrollY) {
232      // Clamp scrollY to be within the scroll range
233      const clampedScrollY = Math.min(Math.max(scrollY, this.scrollStart), this.scrollEnd);
234
235      // Normalize scrollY between 0 and 1
236      const t = (clampedScrollY - this.scrollStart) / (this.scrollEnd - this.scrollStart);
237      
238      return this.startArray.map((startValue, i) => {
239          const endValue = this.endArray[i];
240          return startValue + (endValue - startValue) * t;
241      });
242  }
243}
244
245
246class AppShowcase extends HTMLElement {
247    constructor(){
248        super();
249        const shadow = this.attachShadow({mode: "open"})
250        shadow.append(template.content.cloneNode(true));
251        this.img = this.shadowRoot.querySelector(".app-img");
252        this.appimga = this.shadowRoot.querySelector(".app-imga");
253        this.blobImg = this.shadowRoot.querySelector(".blobImage");
254        this.cover = this.shadowRoot.querySelector(".cover");
255        this.titles = this.shadowRoot.querySelector(".titles");
256        this.appstore = this.shadowRoot.querySelector(".appstore");
257        this.runnyOverlay = this.shadowRoot.querySelector("#runnyOverlay");
258        this.desc = this.shadowRoot.querySelector(".desc");
259        this.imageRange = {min: 0, max: 1500};
260        this.handleScroll();
261
262
263       this.runnyOverlay.animate([
264        { opacity: 1, transform: "translateY(0)" } // Adjust translation
265      ], {
266        duration: 1000, // Duration of the animation in milliseconds
267        fill: 'forwards' // Retain the last keyframe after animation
268      });
269
270      this.blobImg.animate([
271        { opacity: 1, transform: "translateY(0)" } // Adjust translation
272      ], {
273        duration: 1000, // Duration of the animation in milliseconds
274        fill: 'forwards' // Retain the last keyframe after animation
275      });
276      }
277
278      static get observedAttributes() { return ['greeting-name', "app-title", "app-desc", "app-img", "app-background", "app-anim-range", "fire-at-range", "app-minus-constant"]; }
279      attributeChangedCallback(attr, oldVal, newVal) {
280        if (oldVal === newVal) return; // nothing to do
281        switch (attr) {
282          case 'greeting-name':
283            this.p.textContent = `${newVal || 'world'}!`;
284            break;
285
286            case 'app-title':
287              this.er = newVal;
288              console.log(`oValue is ${newVal}`);
289
290             
291              if (this.er === "SPATIAL-NETWORK"){
292                console.log("IOHO");
293                console.log("OH HELLO");
294              //  alert("Hello")
295               // this.shadowRoot.querySelector(".cover").style.height = "2000px";
296               // this.shadowRoot.querySelector('.titles').style.fontSize = "8rem";
297              } else {
298               // this.shadowRoot.querySelector('.titles').style.fontSize = "8rem";
299              }
300
301              console.log("START IS ");
302              console.log(newVal);
303              // CHANGE THE IMAGE RANGE HERE FROM ATTR
304      
305
306
307               let letters = ["A", "B", "C", "D", "E", "G", "H", "I", "N", "O", "P", "Q", "R", "S",  "T", "U", "V"];
308
309               let h1 = document.createElement("h3");
310               h1.style.textAlign = "center";
311               
312               this.er.split("").map((l, i) => {
313                let gen = document.createElement("span");
314                gen.textContent = l;
315                gen.setAttribute("id", letters[i])
316                h1.appendChild(gen);
317
318                if (this.er === "SPATIAL-NETWORK" && l === "L"){
319                  let wbr = document.createElement("br");
320                  h1.appendChild(wbr);
321                  console.log("LAPPO")
322                }
323
324                 if (this.er === "SPATIAL-GRAVITY" && l === "L"){
325                  let wbr = document.createElement("br");
326                  h1.appendChild(wbr);
327                  console.log("LAPPO")
328                }
329               });
330
331              
332      
333              this.shadowRoot.querySelector('.titles').appendChild(h1);
334             // this.title.textContent = `${newVal || 'world'}!`;
335              break;
336
337              case 'app-desc':
338               // this.shadowRoot.querySelector('.desc').textContent = newVal;
339
340              case 'app-img':
341                console.log(`aValue is ${newVal}`);
342                this.shadowRoot.querySelector('.app-img').src = newVal;
343                this.shadowRoot.querySelector('.app-imga').src = newVal;
344               // this.title.textContent = `${newVal || 'world'}!`;
345                break;
346
347
348                case 'app-limit':
349                  console.log(`Value is ${newVal}`);
350                  this.globalLimit = newVal;
351                  //this.handleScroll(newVal)
352                 // this.title.textContent = `${newVal || 'world'}!`;
353                  break;
354
355                  case 'fire-at-range':
356                    console.warn(`Anim start is ${newVal}`);
357                    let mina = Number(newVal.split("-")[0]);
358                    let maxa = Number(newVal.split("-")[1]);
359
360                    const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
361                    const isEdge = navigator.userAgent.includes("Edg");
362
363                    if (isSafari){
364                     
365                      mina = mina * .85;
366                    //  max = max * 1.25;
367                    }
368
369                    if (isEdge){
370                      mina = mina * 0.85;
371                    }
372
373                    if (window.matchMedia("(max-width: 430px)").matches){
374                      mina = mina * .82; // 1.25
375                      //alert("//")
376                    }
377
378                    this.fireAtRange = {from: mina, to: maxa};
379                    break;
380
381                  case 'app-anim-range':
382                    console.warn(`Anim start is ${newVal}`);
383                    let min = Number(newVal.split("-")[0]);
384                    let max = Number(newVal.split("-")[1]);
385
386    
387
388                    this.imageRange = {min: min, max: max};
389                  //  console.log(rangeObj);
390                   // this.globalLimit = newVal;
391                    //this.handleScroll(newVal)
392                   // this.title.textContent = `${newVal || 'world'}!`;
393                    break;
394
395                  case 'app-background':
396                    console.log(`aValue is ${newVal}`);
397                  //  this.shadowRoot.querySelector('.titles').style.opacity = 0.6;
398                    this.shadowRoot.querySelector('.blobImage').style.backgroundImage = `url("${newVal}")`;
399                    this.shadowRoot.querySelector('.blobImage').style.backgroundSize = "900px";
400                      this.shadowRoot.querySelector('.blobImage').style.backgroundRepeat = "no-repeat";
401                    // .background = //"radial-gradient(#2ecc71, #1abc9c)";
402                    //.backgroundImage = `url("https://res.cloudinary.com/simpleview/image/upload/v1579299474/clients/catalinaislandccvb/Untitled_Panorama1_be5bf235-9ac1-4ed9-9ba1-622fcf38611a.jpg")`;
403                  
404                    // this.title.textContent = `${newVal || 'world'}!`;
405                    break;
406
407
408                    case 'app-minus-constant':
409                      console.log(`aValue is ${newVal}`);
410
411                     
412                      this.appMinusConstant = Number(newVal);
413                    //  this.shadowRoot.querySelector('.titles').style.opacity = 0.6;
414                      //this.shadowRoot.querySelector('.blobImage').style.background = "radial-gradient(#2ecc71, #1abc9c)";
415                      //.backgroundImage = `url("https://res.cloudinary.com/simpleview/image/upload/v1579299474/clients/catalinaislandccvb/Untitled_Panorama1_be5bf235-9ac1-4ed9-9ba1-622fcf38611a.jpg")`;
416                    
417                      // this.title.textContent = `${newVal || 'world'}!`;
418                      break;
419        }
420      }
421
422
423      connectedCallback() {
424        // Listen for the scroll event and expand the image if scrollY > 600
425        window.addEventListener('scroll', this.handleScroll.bind(this));
426      }
427  
428      disconnectedCallback() {
429        // Clean up the event listener when the element is removed from the DOM
430        window.removeEventListener('scroll', this.handleScroll.bind(this));
431      }
432
433      
434      mapRange(value, inMin, inMax, outMin, outMax) {
435        value = Math.max(inMin, Math.min(value, inMax));
436        return ((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
437    }
438  
439      handleScroll() {
440        let progress = this.mapRange(window.scrollY, 0, 150, 0, 100);
441        console.warn("PROG:" + progress);
442      //  this.appimga.style.opacity = 1;
443      //  this.desc.style.opacity = progress / 100;
444
445        let el = this.shadowRoot.querySelector(`#A`);
446   
447        if (el != null){
448
449       
450        //  el.style.transform = `scale(0)`;
451        
452
453       const letters = ["A", "B", "C", "D", "E", "G", "H", "I", "N", "O", "P", "Q", "R", "S",  "T", "U", "V"];
454
455        let word = this.er;
456
457
458        for (var i = 0; i < word.length; i++) {
459          
460        /*  // Define a delay for each letter based on its index
461          let delay = i * 0.1; // Adjust delay as needed (0.1 works well)
462  let progress = this.mapRange(window.scrollY, 0, 150, 0, 1); // Normalized progress (0 to 1)
463
464  // Only start scaling each letter after its delay
465  let adjustedProgress = Math.max(0, (progress - delay) / (1 - delay)); // Adjust for the delay, rescaling to 0-1 range
466
467  // Map scale from 0.3 to 1 as adjustedProgress goes from 0 to 1
468  let scale = this.mapRange(adjustedProgress, 0, 1, 0, 1);
469
470  // Ensure that scale doesn't exceed 1
471  scale = Math.min(scale, 1);*/
472
473
474  let fireAt = this.fireAtRange; 
475
476    if (this.fireAtRange === undefined){
477      return;
478    }
479
480    if (this.er === "SPATIAL-NETWORK") {
481      this.shadowRoot.querySelector("#I").style.color = "transparent";
482    }
483
484    // 05/11/25 235651
485    if (this.er === "SPATIAL-GRAVITY") { // is ok
486      this.shadowRoot.querySelector("#I").style.display = "none" //color = "transparent";
487    }
488
489
490    if (this.er === "RUNNY"){
491      console.log("For runnya");
492      console.warn(fireAt); 
493      
494    }
495    
496
497let maxDelay = 0.5; // Maximum delay (in seconds)
498let wordLength = word.length;
499let adjustedMaxDelay = Math.min(maxDelay, 1 / wordLength); // Scale delay based on word length
500
501  // Adjust the delay for each letter
502  let delay = i * adjustedMaxDelay;
503
504  let progress = this.mapRange(window.scrollY, fireAt.from, fireAt.from + 400, 0, 1); // Normalized progress (0 to 1)
505  
506  // Adjust for delay, rescaling to 0-1 range
507  let adjustedProgress = Math.max(0, (progress - delay) / (1 - delay));
508
509  // Scale and rotation transformations
510  let scale = this.mapRange(adjustedProgress, 0, 1, 0, 1);
511  let rotationAngle = this.mapRange(adjustedProgress, 0, 1, 200, 360);
512  
513  rotationAngle = Math.max(rotationAngle, 270);
514
515  // not applied to all letters in Spatial Network
516  let el = this.shadowRoot.querySelector(`#${letters[i]}`);
517  if (rotationAngle > 0){
518    // alert(this.er);
519
520    if (this.er === "SPATIAL-NETWORK"){
521      el.style.color = "#1abc9c";
522    } if (this.er === "RELAYS"){
523      el.style.color = "#3498db";
524    } else if (this.er === "EVENY"){
525      el.style.color = "#4EABE8";
526    }   else if (this.er === "RUNNY") {
527      el.style.color = "#1abc9c";
528    }  else if (this.er === "SPATIAL-GRAVITY") {
529      el.style.color = "#daa025ff";
530    }
531
532    //  el.style.color = "white";
533    
534   // el.style.color = "black";
535  } else {
536    el.style.color = "transparent";
537  }
538
539
540
541/*
542
543  let scaledScale = scale;
544  //alert(this.er);
545  if (this.er === "SPATIAL-NETWORK"){
546    if (Math.abs(scale) > 0.8){
547      scaledScale = 0.8;
548    }
549  } else {
550    scaledScale = Math.abs(scale);
551  }
552  if (this.er === "SPATIAL-NETWORK"){
553     console.log("SCA" + scaledScale);
554   // alert(scaledScale);
555  }*/
556
557
558
559  this.appimga.style.opacity = 1;
560  //el.style.textShadow = "3px 3px 10px #808080";
561  el.style.transform = `scale(0)`;
562  el.style.display = `inline-block`;
563  el.style.transform = `rotate3D(1, 0, 0, ${rotationAngle}deg)`;
564  this.appimga.style.transform = `rotate3D(1, 0, 0, ${rotationAngle}deg) scale(${Math.abs(scale)})`;
565  // el.style.transform = `scale(${Math.abs(scale)})`;
566        }
567      }
568
569
570
571      
572
573          if (window.scrollY > 0) {
574
575            // Example range (custom scroll range)
576            const scrollRange = { from: this.imageRange.min, to: /*this.imageRange.max*/ this.imageRange.min + 600 }; // Define the custom range
577            const scrollPositionA = Math.max(0, Math.min(window.scrollY, scrollRange.to)); // Clamp between from and to
578
579            // Normalize scroll position within the range [0, 1]
580            const t = (scrollPositionA - scrollRange.from) / (scrollRange.to - scrollRange.from);
581
582            const startBorderRadius = [42, 56, 72, 28, 42, 42, 56, 48]; // Start values
583            const endBorderRadius = [100, 20, 20, 100, 50, 80, 30, 30]; // End values
584            const [beg, stp] = [scrollRange.from, scrollRange.to]; //[20, 400];
585
586            const scrollInterpolator = new ScrollDrivenArrayInterpolator(startBorderRadius, endBorderRadius, beg, stp);
587            const interpolatedBorderRadius = scrollInterpolator.interpolateByScroll(window.scrollY);
588          
589   
590            console.log("INTERPOLAAAA");
591            console.log(interpolatedBorderRadius);
592
593            if (this.er === "SPATIAL-NETWORK"){ // 2900-3400 expecte range
594           // console.clear(); // REAL RANGE IS 1600-2800
595            console.log("SPATIAL RANGE");
596            console.log("SR " + scrollRange.from + " - " + scrollRange.to);
597
598              console.log(window.scrollY);
599              console.log(t);
600            }
601            // Apply the calculated border-radius to the blobImg element
602          
603        //  if (t > 0){
604
605     /*   let offsetScrollYBy = 0;
606        let scroll = ((window.scrollY + offsetScrollYBy) / 10) + 1;
607        scroll = scroll / 50;
608*/
609       /* let r = 42* scroll;
610        if (43 * scroll < 20){
611
612        }*/ // scroll si too small
613         //   console.log("SCROLL-FACTOR:" + scroll);
614            this.blobImg.style.borderRadius = `${interpolatedBorderRadius[0]}% ${interpolatedBorderRadius[1]}% ${interpolatedBorderRadius[2]}% ${interpolatedBorderRadius[3]}% / ${interpolatedBorderRadius[0]}% ${interpolatedBorderRadius[1]}% ${interpolatedBorderRadius[2]}% ${interpolatedBorderRadius[3]}%`;
615        //  }
616
617
618
619        // TEMP HIDE ?
620        this.blobImg.style.display = "none";
621
622
623        this.appMinusConstant = this.imageRange.min;
624
625         //   window.addEventListener("scroll", () => {
626              const scrollPositionAB = window.scrollY - this.appMinusConstant;
627              const maxScrollForW = 300;
628              const clampedScroll = Math.max(0, Math.min(scrollPositionAB, maxScrollForW)); 
629              console.log("CL" + clampedScroll);
630
631            if (clampedScroll < 0){
632              clampedScroll = 0;
633            }
634              
635            const scrollPosition = window.scrollY; // Get current scroll position
636            console.log("Scroll event fired. Current scroll position:", scrollPosition);
637        
638            // Calculate the translation based on scroll position
639            const translateY = Math.min(scrollPosition, 100); // Limit translation to a maximum of 500px
640            const translateX = Math.min(((100) * scrollPosition / 500), window.innerWidth / 2); // Center the image horizontally
641            this.img.style.transform = `translate(${translateX}px, ${translateY}px)`; 
642          } 
643      }
644}
645
646// on monday
647// sheep šíp
648// palma palm
649
650customElements.define("app-showcase", AppShowcase);
651
652
653/*
654class HelloWorld extends HTMLElement {
655  title = document.createElement("h1");
656  p = document.createElement('p');
657  constructor() {
658    super();
659    this.attachShadow({ mode: 'open' }).append(this.title, this.p);//.append(title);
660  }
661  
662  // This has to be here
663  static get observedAttributes() { return ['greeting-name', "app-title"]; }
664  attributeChangedCallback(attr, oldVal, newVal) {
665    if (oldVal === newVal) return; // nothing to do
666    switch (attr) {
667      case 'greeting-name':
668        this.p.textContent = `${newVal || 'world'}!`;
669        break;
670
671        case 'app-title':
672          this.title.textContent = `${newVal || 'world'}!`;
673          break;
674    }
675  }
676  
677  connectedCallback() {
678    if (!this.getAttribute('greeting-name')) { this.setAttribute('greeting-name', 'world'); }
679  }
680}
681
682customElements.define('hello-world', HelloWorld);*/

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.