PageSourceSearch

https://golfdesignindia.com/wp-content/themes/prague/assets/js/diagonal.js?ver=7.1.2

js golfdesignindia.com collected 2026-10-04 01:34:00 UTC 23,929 bytes, 549 lines download raw bytes

1/**
2 * demo.js
3 * http://www.codrops.com
4 *
5 * Licensed under the MIT license.
6 * http://www.opensource.org/licenses/mit-license.php
7 *
8 * Copyright 2018, Codrops
9 * http://www.codrops.com
10 */
11{
12    // From http://www.quirksmode.org/js/events_properties.html#position
13    // Get the mouse position.
14    const getMousePos = (e) => {
15        let posx = 0;
16        let posy = 0;
17        if (!e) e = window.event;
18        if (e.pageX || e.pageY) 	{
19            posx = e.pageX;
20            posy = e.pageY;
21        }
22        else if (e.clientX || e.clientY) 	{
23            posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
24            posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
25        }
26        return { x : posx, y : posy }
27    };
28    // Gets a random integer.
29    const getRandomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
30    // Equation of a line (y = mx + b ).
31    const lineEq = (y2, y1, x2, x1, currentVal) => {
32        const m = (y2 - y1) / (x2 - x1);
33        const b = y1 - m * x1;
34        return m * currentVal + b;
35    };
36
37    // Some random chars.
38    // const chars = ['$','%','#','&','=','*','a','b','c','d','e','f','g','h','
38i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','.',':',',','^'];
39    // const charsTotal = chars.length;
40    //
41    // // Randomize letters function. Used when navigating the slideshow to switch the curretn slide´s texts.
42    // const randomizeLetters = (letters) => {
43    //     return new Promise((resolve, reject) => {
44    //         const lettersTotal = letters.length;
45    //         let cnt = 0;
46    //
47    //         letters.forEach((letter, pos) => {
48    //             let loopTimeout;
49    //             const loop = () => {
50    //                 letter.innerHTML = chars[getRandomInt(0,charsTotal-1)];
51    //                 loopTimeout = setTimeout(loop, getRandomInt(50,500));
52    //             };
53    //             loop();
54    //
55    //             const timeout = setTimeout(() => {
56    //                 clearTimeout(loopTimeout);
57    //                 letter.style.opacity = 1;
58    //                 letter.innerHTML = letter.dataset.initial;
59    //                 ++cnt;
60    //                 if ( cnt === lettersTotal ) {
61    //                     resolve();
62    //                 }
63    //             }, pos*lineEq(40,0,8,200,lettersTotal));
64    //         });
65    //     });
66    // };
67
68    // Hide each of the letters with random delays. Used when showing the current slide´s content.
69    // const disassembleLetters = (letters) => {
70    //     return new Promise((resolve, reject) => {
71    //         const lettersTotal = letters.length;
72    //         let cnt = 0;
73    //
74    //         letters.forEach((letter, pos) => {
75    //             setTimeout(() => {
76    //                 letter.style.opacity = 0;
77    //                 ++cnt;
78    //                 if ( cnt === lettersTotal ) {
79    //                     resolve();
80    //                 }
81    //             }, pos*30);
82    //         });
83    //     });
84    // }
85
86    // The Slide class.
87    class Slide {
88        constructor(el) {
89            this.DOM = {el: el};
90            // The image wrap element.
91            this.DOM.imgWrap = this.DOM.el.querySelector('.slide__img-wrap');
92            // The image element.
93            this.DOM.img = this.DOM.imgWrap.querySelector('.slide__img');
94            // The texts: the parent wrap, title, number and side text.
95            this.DOM.texts = {
96                wrap: this.DOM.el.querySelector('.slide__title-wrap'),
97                title: this.DOM.el.querySelector('.slide__title'),
98                number: this.DOM.el.querySelector('.slide__number'),
99                side: this.DOM.el.querySelector('.slide__side'),
100            };
101            // Split the title and side texts into spans, one per letter. Sort these so we can later animate then with the
102            // randomizeLetters or disassembleLetters functions when navigating and showing the content.
103            // charming(this.DOM.texts.title);
104            // charming(this.DOM.texts.side);
105            // this.DOM.titleLetters = Array.from(this.DOM.texts.title.querySelectorAll('span')).sort(() => 0.5 - Math.random());
106            // this.DOM.sideLetters = Array.from(this.DOM.texts.side.querySelectorAll('span')).sort(() => 0.5 - Math.random());
107            // this.DOM.titleLetters.forEach(letter => letter.dataset.initial = letter.innerHTML);
108            // this.DOM.sideLetters.forEach(letter => letter.dataset.initial = letter.innerHTML);
109            // Calculate the sizes of the image wrap.
110            this.calcSizes();
111            // And also the transforms needed per position.
112            // We have 5 different possible positions for a slide: center, bottom right, top left and outside the viewport (top left or bottom right).
113            this.calcTransforms();
114            // Init/Bind events.
115            this.initEvents();
116        }
117        // Gets the size of the image wrap.
118        calcSizes() {
119            this.width = this.DOM.imgWrap.offsetWidth;
120            this.height = this.DOM.imgWrap.offsetHeight;
121        }
122        // Gets the transforms per slide position.
123        calcTransforms() {
124            /*
125            Each position corresponds to the position of a given slide:
126            0: left top corner outside the viewport
127            1: left top corner (prev slide position)
128            2: center (current slide position)
129            3: right bottom corner (next slide position)
130            4: right bottom corner outside the viewport
131            5: left side, for when the content is shown
132            */
133            this.transforms = [
134                {x: -1*(winsize.width/2+this.width), y: -1*(winsize.height/2+this.height), rotation: -30},
135                {x: -1*(winsize.width/2-this.width/3), y: -1*(winsize.height/2-this.height/3), rotation: 0},
136                {x: 0, y: 0, rotation: 0},
137                {x: winsize.width/2-this.width/3, y: winsize.height/2-this.height/3, rotation: 0},
138                {x: winsize.width/2+this.width, y: winsize.height/2+this.height, rotation: 30},
139                {x: -1*(winsize.width/2 - this.width/2 - winsize.width*0.075), y: 0, rotation: 0}
140            ];
141        }
142        // Init events:
143        // Mouseevents for mousemove/tilt/scale on the current image, and window resize.
144        initEvents() {
145            this.mouseenterFn = () => {
146                if ( !this.isPositionedCenter() || !allowTilt ) return;
147                clearTimeout(this.mousetime);
148                this.mousetime = setTimeout(() => {
149                    // Scale the image.
150                    TweenMax.to(this.DOM.img, 0.8, {
151                        ease: Power3.easeOut,
152                        scale: 1.1
153                    });
154                }, 40);
155            };
156            this.mousemoveFn = ev => requestAnimationFrame(() => {
157                // Tilt the current slide.
158                if ( !allowTilt || !this.isPositionedCenter() ) return;
159                this.tilt(ev);
160            });
161            this.mouseleaveFn = (ev) => requestAnimationFrame(() => {
162                if ( !allowTilt || !this.isPositionedCenter() ) return;
163                clearTimeout(this.mousetime);
164
165                // Reset tilt and image scale.
166                TweenMax.to([this.DOM.imgWrap,this.DOM.texts.wrap], 1.8, {
167                    ease: 'Power4.easeOut',
168                    x: 0,
169                    y: 0,
170                    rotationX: 0,
171                    rotationY: 0
172                });
173                TweenMax.to(this.DOM.img, 1.8, {
174                    ease: 'Power4.easeOut',
175                    scale: 1
176                });
177            });
178            // When resizing the window recalculate size and transforms, since both will depend on the window size.
179            this.resizeFn = () => {
180                this.calcSizes();
181                this.calcTransforms();
182            };
183            this.DOM.imgWrap.addEventListener('mouseenter', this.mouseenterFn);
184            this.DOM.imgWrap.addEventListener('mousemove', this.mousemoveFn);
185            this.DOM.imgWrap.addEventListener('mouseleave', this.mouseleaveFn);
186            window.addEventListener('resize', this.resizeFn);
187        }
188        // Tilt the image wrap and texts when mouse moving the current slide.
189        tilt(ev) {
190            const mousepos = getMousePos(ev);
191            // Document scrolls.
192            const docScrolls = {
193                left : document.body.scrollLeft + document.documentElement.scrollLeft,
194                top : document.body.scrollTop + document.documentElement.scrollTop
195            };
196            const bounds = this.DOM.imgWrap.getBoundingClientRect();;
197            // Mouse position relative to the main element (this.DOM.el).
198            const relmousepos = {
199                x : mousepos.x - bounds.left - docScrolls.left,
200                y : mousepos.y - bounds.top - docScrolls.top
201            };
202
203            // Move the element from -20 to 20 pixels in both x and y axis.
204            // Rotate the element from -15 to 15 degrees in both x and y axis.
205            let t = {x:[-20,20],y:[-20,20]},
206                r = {x:[-15,15],y:[-15,15]};
207
208            const transforms = {
209                translation : {
210                    x: (t.x[1]-t.x[0])/bounds.width*relmousepos.x + t.x[0],
211                    y: (t.y[1]-t.y[0])/bounds.height*relmousepos.y + t.y[0]
212                },
213                rotation : {
214                    x: (r.x[1]-r.x[0])/bounds.height*relmousepos.y + r.x[0],
215                    y: (r.y[1]-r.y[0])/bounds.width*relmousepos.x + r.y[0]
216                }
217            };
218
219            // Move the image wrap.
220            TweenMax.to(this.DOM.imgWrap, 1.5, {
221                ease: 'Power1.easeOut',
222                x: transforms.translation.x,
223                y: transforms.translation.y,
224                rotationX: transforms.rotation.x,
225                rotationY: transforms.rotation.y
226            });
227
228            // Move the texts wrap.
229            TweenMax.to(this.DOM.texts.wrap, 1.5, {
230                ease: 'Power1.easeOut',
231                x: -1*transforms.translation.x,
232                y: -1*transforms.translation.y
233            });
234        }
235        // Positions one slide (left, right or current) in the viewport.
236        position(pos) {
237            TweenMax.set(this.DOM.imgWrap, {
238                x: this.transforms[pos].x,
239                y: this.transforms[pos].y,
240                rotationX: 0,
241                rotationY: 0,
242                opacity: 1,
243                rotationZ: this.transforms[pos].rotation
244            });
245        }
246        // Sets it as current.
247        setCurrent(isContentOpen) {
248            this.isCurrent = true;
249            this.DOM.el.classList.add('slide--current', 'slide--visible');
250            // Position it on the current´s position.
251            this.position(isContentOpen ? 5 : 2);
252        }
253        // Position the slide on the left side.
254        setLeft(isContentOpen) {
255            this.isRight = this.isCurrent = false;
256            this.isLeft = true;
257            this.DOM.el.classList.add('slide--visible');
258            // Position it on the left position.
259            this.position(isContentOpen ? 0 : 1);
260        }
261        // Position the slide on the right side.
262        setRight(isContentOpen) {
263            this.isLeft = this.isCurrent = false;
264            this.isRight = true;
265            this.DOM.el.classList.add('slide--visible');
266            // Position it on the right position.
267            this.position(isContentOpen ? 4 : 3);
268        }
269        // Check if the slide is positioned on the right side (if it´s the next slide in the slideshow).
270        isPositionedRight() {
271            return this.isRight;
272        }
273        // Check if the slide is positioned on the left side (if it´s the previous slide in the slideshow).
274        isPositionedLeft() {
275            return this.isLeft;
276        }
277        // Check if the slide is the current one.
278        isPositionedCenter() {
279            return this.isCurrent;
280        }
281        // Reset classes and state.
282        reset() {
283            this.isRight = this.isLeft = this.isCurrent = false;
284            this.DOM.el.classList = 'slide';
285        }
286        hide() {
287            TweenMax.set(this.DOM.imgWrap, {x:0, y:0, rotationX:0, rotationY:0, rotationZ:0, opacity:0}
287);
288        }
289        // Moves a slide to a specific position defined in settings.position.
290        // Also, moves it from position settings.from and if we need to reset the image scale when moving the slide then settings.resetImageScale should be true.
291        moveToPosition(settings) {
292            return new Promise((resolve, reject) => {
293                /*
294                Moves the slide to a specific position:
295                -2: left top corner outside the viewport
296                -1: left top corner (prev slide position)
297                0: center (current slide position)
298                1: right bottom corner (next slide position)
299                2: right bottom corner outside the viewport
300                3: left side, for when the content is shown
301                */
302                TweenMax.to(this.DOM.imgWrap, .8, {
303                    ease: Power4.easeInOut,
304                    delay: settings.delay || 0,
305                    startAt: settings.from !== undefined ? {
306                        x: this.transforms[settings.from+2].x,
307                        y: this.transforms[settings.from+2].y,
308                        rotationX: 0,
309                        rotationY: 0,
310                        rotationZ: this.transforms[settings.from+2].rotation
311                    } : {},
312                    x: this.transforms[settings.position+2].x,
313                    y: this.transforms[settings.position+2].y,
314                    rotationX: 0,
315                    rotationY: 0,
316                    rotationZ: this.transforms[settings.position+2].rotation,
317                    onStart: settings.from !== undefined ? () => TweenMax.set(this.DOM.imgWrap, {opacity: 1}) : null,
318                    onComplete: resolve
319                });
320
321                // Reset image scale when showing the content of the current slide.
322                if ( settings.resetImageScale ) {
323                    TweenMax.to(this.DOM.img, .8, {
324                        ease: Power4.easeInOut,
325                        scale: 1
326                    });
327                }
328            });
329        }
330        // Hides the current slide´s texts.
331        hideTexts(animation = false) {
332            if ( animation ) {
333                disassembleLetters(this.DOM.titleLetters).then(() => TweenMax.set(this.DOM.texts.wrap, {opacity: 0}));
334                disassembleLetters(this.DOM.sideLetters).then(() => TweenMax.set(this.DOM.texts.side, {opacity: 0}));
335            }
336            else {
337                TweenMax.set(this.DOM.texts.wrap, {opacity: 0});
338                TweenMax.set(this.DOM.texts.side, {opacity: 0});
339            }
340        }
341        // Shows the current slide´s texts.
342        showTexts(animation = true) {
343            TweenMax.set(this.DOM.texts.wrap, {opacity: 1});
344            TweenMax.set(this.DOM.texts.side, {opacity: 1});
345
346            if ( animation ) {
347                // randomizeLetters(this.DOM.titleLetters);
348                // randomizeLetters(this.DOM.sideLetters);
349                TweenMax.to(this.DOM.texts.number, 0.6, {
350                    ease: Elastic.easeOut.config(1,0.5),
351                    startAt: {x: '-10%', opacity: 0},
352                    x: '0%',
353                    opacity: 1
354                });
355            }
356        }
357    }
358
359    // The Content class. Represents one content item per slide.
360    class Content {
361        constructor(el) {
362            this.DOM = {el: el};
363            this.DOM.number = this.DOM.el.querySelector('.content__number');
364            this.DOM.title = this.DOM.el.querySelector('.content__title');
365            this.DOM.subtitle = this.DOM.el.querySelector('.content__subtitle');
366            this.DOM.text = this.DOM.el.querySelector('.content__text');
367            this.DOM.backCtrl = this.DOM.el.parentNode.querySelector('.content__close');
368            this.DOM.backCtrl.addEventListener('click', () => slideshow.hideContent());
369        }
370        show() {
371            this.DOM.el.classList.add('content__item--current');
372
373            TweenMax.staggerTo([this.DOM.backCtrl,this.DOM.number,this.DOM.title,this.DOM.subtitle,this.DOM.text], 0.8, {
374                ease: Power4.easeOut,
375                delay: 0.4,
376                opacity: 1,
377                startAt: {y: 40},
378                y: 0
379            }, 0.05);
380        }
381        hide() {
382            this.DOM.el.classList.remove('content__item--current');
383
384            TweenMax.staggerTo([this.DOM.backCtrl,this.DOM.number,this.DOM.title,this.DOM.subtitle,this.DOM.text].reverse(), 0.3, {
385                ease: Power3.easeIn,
386                opacity: 0,
387                y: 10
388            }, 0.01);
389        }
390    }
391
392    // The Slideshow class.
393    class Slideshow {
394        constructor(el) {
395            this.DOM = {el: el};
396            // The slides.
397            this.slides = [];
398            Array.from(this.DOM.el.querySelectorAll('.slide')).forEac
398h(slideEl => this.slides.push(new Slide(slideEl)));
399            // The total number of slides.
400            this.slidesTotal = this.slides.length;
401            // At least 4 slides to continue...
402            if ( this.slidesTotal < 4 ) {
403                return false;
404            }
405            // Current slide position.
406            this.current = 0;
407            this.DOM.deco = this.DOM.el.querySelector('.slideshow__deco');
408
409            this.contents = [];
410            Array.from(document.querySelectorAll('.content > .content__item')).forEach(contentEl => this.contents.push(new Content(contentEl)));
411
412            // Set the current/next/previous slides.
413            this.render();
414            this.currentSlide.showTexts(false);
415            // Init/Bind events.
416            this.initEvents();
417        }
418        render() {
419            // The current, next, and previous slides.
420            this.currentSlide = this.slides[this.current];
421            this.nextSlide = this.slides[this.current+1 <= this.slidesTotal-1 ? this.current+1 : 0];
422            this.prevSlide = this.slides[this.current-1 >= 0 ? this.current-1 : this.slidesTotal-1];
423            this.currentSlide.setCurrent();
424            this.nextSlide.setRight();
425            this.prevSlide.setLeft();
426        }
427        initEvents() {
428            // Clicking the next and previous slide starts the navigation / clicking the current shows its content..
429            this.clickFn = (slide) => {
430                if ( slide.isPositionedRight() ) {
431                    this.navigate('next');
432                }
433                else if ( slide.isPositionedLeft() ) {
434                    this.navigate('prev');
435                }
436                else {
437                    this.showContent();
438                }
439            };
440            for (let slide of this.slides) {
441                slide.DOM.imgWrap.addEventListener('click', () => this.clickFn(slide));
442            }
443
444            this.resizeFn = () => {
445                // Reposition the slides.
446                this.nextSlide.setRight(this.isContentOpen);
447                this.prevSlide.setLeft(this.isContentOpen);
448                this.currentSlide.setCurrent(this.isContentOpen);
449
450                if ( this.isContentOpen ) {
451                    TweenMax.set(this.DOM.deco, {
452                        scaleX: winsize.width/this.DOM.deco.offsetWidth,
453                        scaleY: winsize.height/this.DOM.deco.offsetHeight,
454                        x: -20,
455                        y: 20
456                    });
457                }
458            };
459            window.addEventListener('resize', this.resizeFn);
460        }
461        showContent() {
462        }
463        hideContent() {
464        }
465        // Animates the element behind the current slide.
466        bounceDeco(direction, delay) {
467            TweenMax.to(this.DOM.deco, .4, {
468                ease: 'Power2.easeIn',
469                delay: delay+delay*0.2,
470                x: direction === 'next' ? -40 : 40,
471                y: direction === 'next' ? -40 : 40,
472                onComplete: () => {
473                    TweenMax.to(this.DOM.deco, 0.6, {
474                        //ease: Elastic.easeOut.config(1, 0.65),
475                        ease: 'Power2.easeOut',
476                        x: 0,
477                        y: 0
478                    });
479                }
480            });
481        }
482        // Navigate the slideshow.
483        navigate(direction) {
484            // If animating return.
485            if ( this.isAnimating ) return;
486            this.isAnimating = true;
487            allowTilt = false;
488
489            const upcomingPos = direction === 'next' ?
490                this.current < this.slidesTotal-2 ? this.current+2 : Math.abs(this.slidesTotal-2-this.current):
491                this.current >= 2 ? this.current-2 : Math.abs(this.slidesTotal-2+this.current);
492
493            this.upcomingSlide = this.slides[upcomingPos];
494
495            // Update current.
496            this.current = direction === 'next' ?
497                this.current < this.slidesTotal-1 ? this.current+1 : 0 :
498                this.current > 0 ? this.current-1 : this.slidesTotal-1;
499
500            // Move slides (the previous, current, next and upcoming slide).
501            this.prevSlide.moveToPosition({position: direction === 'next' ? -2 : 0, delay: direction === 'next' ? 0 : 0.14}).then(() => {
502                if ( direction === 'next' ) {
503                    this.prevSlide.hide();
504                }
505            });
506
507            this.currentSlide.moveToPosition({position: direction === 'next' ? -1 : 1, delay: 0.07 });
508            this.currentSlide.hideTexts();
509
510            this.bounceDeco(direction, 0.07);
511
512            this.nextSlide.moveToPosition({position: direction === 'next' ? 0 : 2, delay: direction === 'next' ? 0.14 : 0 }).then(() => {
513                if ( direction === 'prev' ) {
514                    this.nextSlide.hide();
515                }
516            });
517
518            if ( direction === 'next' ) {
519                this.nextSlide.showTexts();
520            }
521            else {
522                this.prevSlide.showTexts();
523            }
524
525            this.upcomingSlide.moveToPosition({position: direction === 'next' ? 1 : -1, from: direction === 'next' ? 2 : -2, delay: 0.21 }).then(() => {
526                // Reset classes.
527                [this.nextSlide,this.currentSlide,this.prevSlide].forEach(sli
527de => slide.reset());
528                this.render();
529                allowTilt = true;
530                this.isAnimating = false;
531            });
532        }
533    }
534
535    // Window sizes.
536    let winsize;
537    const calcWinsize = () => winsize = {width: window.innerWidth, height: window.innerHeight};
538    calcWinsize();
539    window.addEventListener('resize', calcWinsize);
540
541    let allowTilt = true;
542
543    // Init slideshow.
544    const slideshow = new Slideshow(document.querySelector('.slideshow'));
545
546    // Preload all the images in the page..
547    const loader = document.querySelector('.loader');
548    imagesLoaded(document.querySelectorAll('.slide__img'), {background: true}, () => document.body.classList.remove('loading'));
549}

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.