/ Gists / JavaScript

Gists - JavaScript

On gists

unique selector in document (while)

JavaScript

unique.js #

/*!
 * getUniqueClass - v1.1 - 2/13/2010
 * http://benalman.com/projects/jquery-misc-plugins/
 * 
 * Copyright (c) 2010 "Cowboy" Ben Alman
 * Dual licensed under the MIT and GPL licenses.
 * http://benalman.com/about/license/
 */

// For when you really need a unique classname, (like when you're cloning a
// whole bunch of elements and don't exactly know where they're going, but need
// to do something with them after they've gotten there).

jQuery.getUniqueClass = function() {
  var name, i = 0;
  while ( jQuery('.' + (name = 'BA-' + (+new Date) + (i++))).length ) { };
  return name;
};



// 2 my

let s = '.test'
let name, i = ''
while (document.querySelector(name =  s + i)) {
  i += 0
  i++
}

document.write(name)

On gists

Google map (ES 6 / promise)

JavaScript ES 6 Vue.js

googlemap.js #

// Your personal API key.
// Get it here: https://console.cloud.google.com/google/maps-apis
const API_KEY = '***'
const CALLBACK_NAME = 'gmapsCallback'

let initialized = !!window.google
let resolveInitPromise
let rejectInitPromise
// This promise handles the initialization
// status of the google maps script.
const initPromise = new Promise((resolve, reject) => {
  resolveInitPromise = resolve
  rejectInitPromise = reject
})

export default function init() {
  // If Google Maps already is initialized
  // the `initPromise` should get resolved
  // eventually.
  if (initialized) return initPromise

  initialized = true
  // The callback function is called by
  // the Google Maps script if it is
  // successfully loaded.
  window[CALLBACK_NAME] = () => resolveInitPromise(window.google)

  // We inject a new script tag into
  // the `<head>` of our HTML to load
  // the Google Maps script.
  const script = document.createElement('script')
  script.async = true
  script.defer = true
  script.src = `https://maps.googleapis.com/maps/api/js?key=${API_KEY}&callback=${CALLBACK_NAME}`
  script.onerror = rejectInitPromise
  document.querySelector('head').appendChild(script)

  return initPromise
}

On gists

ResizeObserver.html

JavaScript

ResizeObserver.html #

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>

        <style>
            .container {
                display: flex;
                width: 100%; /* This can be changed via the buttons. */
                height: 200px;
                padding: 8px;
                background: #eaeaea;
            }

            /* Image Wrappers */
            .container > div {
                height: 200px;
                min-width: 100px;
                max-width: 200px;
                flex: 1;
                background-size: cover;
                background-repeat: no-repeat;
            }

            /* The rest is just setup. */

            #app {
                display: flex;
                flex-direction: column;
                align-items: center;
                font-family: sans-serif;
                padding: 16px;
            }

            p {
                margin-top: 32px;
                text-align: center;
                color: #4c11f7;
                text-transform: uppercase;
                font-weight: 600;
                font-size: 14px;
                letter-spacing: 0.5px;
            }

            .change-size {
                display: flex;
                align-items: center;
                justify-content: center;
                flex-wrap: wrap;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <div class="container"></div>

            <p>Container Size</p>
            <div class="change-size">
                <button value="100%">100%</button>
                <button value="1400px">1400px</button>
                <button value="640px">640px</button>
                <button value="200px">200px</button>
            </div>
        </div>

        <script>
            /* Attach ResizeObserver to the container. */
            const resizeObserver = new ResizeObserver(onResize);
            resizeObserver.observe(document.querySelector('.container'));

            const IMAGE_MAX_WIDTH = 200;
            const IMAGE_MIN_WIDTH = 100;

            function onResize(entries) {
                const entry = entries[0];
                const container = entry.target;
                /* Calculate how many images can fit in the container. */
                const imagesNeeded = Math.ceil(entry.contentRect.width / IMAGE_MAX_WIDTH);
                let images = container.children;

                console.log(images);

                /* Remove images as needed. */
                while (images.length > imagesNeeded) {
                    images[images.length - 1].remove();
                }
                /* Add images as needed. */
                while (images.length < imagesNeeded) {
                    let seed = Math.random().toString().replace('.', '');
                    const newImage = document.createElement('div');
                    const imageUrl = `https://picsum.photos/seed/${seed}/${IMAGE_MAX_WIDTH}`;
                    newImage.style.backgroundImage = `url(${imageUrl})`;
                    container.append(newImage);
                }
            }

            /* The rest is for the container size buttons. */
            function changeSize(e) {
                if (!e.target.value) return;
                const container = document.querySelector('.container');
                container.style.width = e.target.value;
            }

            const changeSizeButtons = document.querySelector('.change-size');
            changeSizeButtons.addEventListener('click', changeSize);
        </script>
    </body>
</html>

On gists

Resize Observer : only as many images what i need in limited container

JavaScript

ResizeObserver.html #

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>

        <style>
            .container {
                display: flex;
                width: 100%; /* This can be changed via the buttons. */
                height: 200px;
                padding: 8px;
                background: #eaeaea;
            }

            /* Image Wrappers */
            .container > div {
                height: 200px;
                min-width: 100px;
                max-width: 200px;
                flex: 1;
                background-size: cover;
                background-repeat: no-repeat;
            }

            /* The rest is just setup. */

            #app {
                display: flex;
                flex-direction: column;
                align-items: center;
                font-family: sans-serif;
                padding: 16px;
            }

            p {
                margin-top: 32px;
                text-align: center;
                color: #4c11f7;
                text-transform: uppercase;
                font-weight: 600;
                font-size: 14px;
                letter-spacing: 0.5px;
            }

            .change-size {
                display: flex;
                align-items: center;
                justify-content: center;
                flex-wrap: wrap;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <div class="container"></div>

            <p>Container Size</p>
            <div class="change-size">
                <button value="100%">100%</button>
                <button value="1400px">1400px</button>
                <button value="640px">640px</button>
                <button value="200px">200px</button>
            </div>
        </div>

        <script>
            /* Attach ResizeObserver to the container. */
            const resizeObserver = new ResizeObserver(onResize);
            resizeObserver.observe(document.querySelector('.container'));

            const IMAGE_MAX_WIDTH = 200;
            const IMAGE_MIN_WIDTH = 100;

            function onResize(entries) {
                const entry = entries[0];
                const container = entry.target;
                /* Calculate how many images can fit in the container. */
                const imagesNeeded = Math.ceil(entry.contentRect.width / IMAGE_MAX_WIDTH);
                let images = container.children;

                console.log(images);

                /* Remove images as needed. */
                while (images.length > imagesNeeded) {
                    images[images.length - 1].remove();
                }
                /* Add images as needed. */
                while (images.length < imagesNeeded) {
                    let seed = Math.random().toString().replace('.', '');
                    const newImage = document.createElement('div');
                    const imageUrl = `https://picsum.photos/seed/${seed}/${IMAGE_MAX_WIDTH}`;
                    newImage.style.backgroundImage = `url(${imageUrl})`;
                    container.append(newImage);
                }
            }

            /* The rest is for the container size buttons. */
            function changeSize(e) {
                if (!e.target.value) return;
                const container = document.querySelector('.container');
                container.style.width = e.target.value;
            }

            const changeSizeButtons = document.querySelector('.change-size');
            changeSizeButtons.addEventListener('click', changeSize);
        </script>
    </body>
</html>

On gists

CSS Clamp builder (responsive fluid typography)

JavaScript CSS CSS trick

clampBuilder.js #

// https://css-tricks.com/linearly-scale-font-size-with-css-clamp-based-on-the-viewport/#for-those-who-dont-mind-that-edge-case
// https://royalfig.github.io/fluid-typography-calculator/
// https://fluid-typography.netlify.app/

function clampBuilder( minWidthPx, maxWidthPx, minFontSize, maxFontSize ) {
  const root = document.querySelector( "html" );
  const pixelsPerRem = Number( getComputedStyle( root ).fontSize.slice( 0,-2 ) );

  const minWidth = minWidthPx / pixelsPerRem;
  const maxWidth = maxWidthPx / pixelsPerRem;

  const slope = ( maxFontSize - minFontSize ) / ( maxWidth - minWidth );
  const yAxisIntersection = -minWidth * slope + minFontSize

  return `clamp( ${ minFontSize }rem, ${ yAxisIntersection }rem + ${ slope * 100 }vw, ${ maxFontSize }rem )`;
}


console.log(clampBuilder(320, 1920, 1, 3)); // "clamp( 1rem, 0.6rem + 2vw, 3rem )"

On gists

Fast fill array

JavaScript JS oneliners

fast-fill.js #

const newData = Array(20)
      .fill(0)
      .map((_, index) =>  index++);

On gists

Intersection observer (infinity scroll)

JavaScript Web Api

demo.js #

// https://levelup.gitconnected.com/what-is-intersection-observer-api-and-how-is-it-useful-1e91a14579df
// https://codepen.io/ohdylan/pen/ZExqKzx



let secondLastChild = document.querySelectorAll('.box:nth-last-child(2)')[0];
let boxes = document.querySelector('.boxes')
const mockFetchMoreBoxes = () => {
    const startIndex = parseInt(secondLastChild.textContent.replace('Test Element', '')) + 2
    for(let i = startIndex; i < startIndex + 20; i++) {
        const newBox = document.createElement('div')
        newBox.textContent = `Test Element ${i}`
        newBox.classList.add('box')
        boxes.append(newBox)
        if(i == startIndex + 18) {
            observer.unobserve(secondLastChild)
            secondLastChild = newBox
            observer.observe(secondLastChild);
        }
    }
}

let observer = new IntersectionObserver((entries) => {
    console.log(entries[0])
    const secondLastChild = entries[0]
    if(secondLastChild.isIntersecting){
        return mockFetchMoreBoxes()
    }
}, {})

observer.observe(secondLastChild);

On gists

JS Doc

JavaScript DOC Vue.js

example.js #

  data() {
    return {
      // https://medium.com/@trukrs/type-safe-javascript-with-jsdoc-7a2a63209b76
      // https://devhints.io/jsdoc
      // better suggestion ... eg:  this.overlay?. + tab

      /**
       * @type {boolean}
       */
      delaySet: false, // je nastaveny delay?

      /**
       * @type {?number}
       */
      timeout: null, // timeout delay

      /**
       * @type {number}
       */
      ttlIn: 400, // delka prodlevy najeti

      /**
       * @type {number}
       */
      ttlOut: 300, // delka prodlevy pri odjeti

      /**
       * @type {HTMLElement}
       */
      overlay: null, // HTML prvek zacileneho overlaySelector-u

      /**
       * @type {Array}
       */
      listChildren: [] // LI-cka pod zacilenym UL-kem
    }
  },

On gists

Web component

JavaScript Web components

calendar.js #

class AmbiCalendar extends HTMLElement
{
    constructor()
    {
      super();
      this.shadow = this.attachShadow({ mode: "open"});
    }

    connectedCallback()
    {
      this.render(true, []);

      fetch('/api/v1/dk_workshop_date?filters[dk_voucher_id]=' + this.getAttribute('voucherId'))
      .then((response) => {
        if (response.ok) {
          return response.json();
        } else {
          return Promise.reject(response);
        }

      }).then((data) => {
        this.render(false, data);
      }).catch(function (err) {
        // There was an error
        console.warn('Something went wrong.', err);
      });
    }

    render(loading, data)
    {
      let body = '';

      if (loading) {
        body = '<div>loading...</div>';
      } else {
        data.map((item) => {
          body += `<li>${item.date_from} - ${item.date_to}</li>`;
        });
      }

      this.shadow.innerHTML = `
        <h1>Ambi calendar</h1>
        <lu>
            ${body}
        </lu>
      `;
    }
}

customElements.define('ambi-calendar', AmbiCalendar);

On gists

JS Parallax

JavaScript

parallax.js #

// https://github.com/yablko/responzivny-web-kurz/blob/crave-game-verzia-z-kurzu/index.html

		const headerEl = document.querySelector('header')
		const logoEl = document.querySelector('.crave-logo img')
		const setTranslate = (xPos, yPos, el) => {
			el.style.transform = `translate3d(${xPos}, ${yPos}px, 0)`;
		}
		let xScrollPosition;
		let yScrollPosition;
		const scrollLoop = () => {
			xScrollPosition = window.scrollX;
			yScrollPosition = window.scrollY;
			setTranslate(0, yScrollPosition * 0.75, headerEl);
			setTranslate(0, yScrollPosition * -0.25, logoEl);
			requestAnimationFrame(scrollLoop);
		}
		window.addEventListener('DOMContentLoaded', scrollLoop, false);