/*!
* 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)
// 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
}
<!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>
<!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>
// 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 )"
const newData = Array(20)
.fill(0)
.map((_, index) => index++);
// 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);
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
}
},
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);
// 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);