-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscripts.js
143 lines (123 loc) · 4.26 KB
/
scripts.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
var blendModes = 'color,color-burn,color-dodge,darken,difference,exclusion,hard-light,hue,lighten,luminosity,multiply,normal,overlay,saturation,screen,soft-light'.split(',')
, $banner
, $ul
, changeBlendModeIntervalRef;
function random (min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
// Trigger callback `cb` when x-axis of `el` has been dragged more than 100px.
// Callback is called with string `'left'` or `'right'` as only argument,
// depending on which direction the element is dragged.
// Good for carousels.
// Will block other events (like scrolling) when touch starts on top of `el`.
//
// `el` is an HTML element
// `cb` is a function accepting a single argument `direction`
//
// stigok, july 2020
function touchslide(el, cb) {
var startX = 0
, active = false
, targetX = 70
, touch;
function touchHandler(ev) {
ev.preventDefault();
switch (ev.type) {
case 'touchstart':
active = true;
touch = ev.touches[0];
startX = touch.clientX;
break;
case 'touchmove':
touch = ev.touches[0];
if (!active) {
return;
}
if (touch.clientX >= startX + targetX) {
active = false;
return cb('left');
}
if (touch.clientX <= startX - targetX) {
active = false;
return cb('right');
}
break;
case 'touchcancel':
case 'touchend':
active = false;
break;
}
}
el.addEventListener('touchstart', touchHandler, true);
el.addEventListener('touchmove', touchHandler, true);
el.addEventListener('touchend', touchHandler, true);
el.addEventListener('touchcancel', touchHandler, true);
}
// Set blend mode to specified index `idx`. Bounds are not checked explicitly.
function setBannerBlendModeIndex (idx) {
$banner.style.backgroundBlendMode = blendModes[idx];
// Set active box state
for (let i = 0; i < blendModes.length; i++) {
$ul.children[i].className = (i === idx) ? 'active' : '';
}
}
// Set blend mode index to a position relative to the current.
// Pass `delta` with `1` for next and `-1` for previous.
function setBannerBlendModeIndexRelative(delta) {
const current = blendModes.indexOf($banner.style.backgroundBlendMode || 0);
// Wrap around when going out of bounds
let next = current + delta;
next = (next < 0) ? blendModes.length - 1: next % blendModes.length;
// Disable auto-change after manual interaction
clearInterval(changeBlendModeIntervalRef);
setBannerBlendModeIndex(next);
}
function setup () {
$banner = document.getElementById('banner');
$ul = document.createElement('ul');
// Remove original image (progressive enhancement)
if ($banner.children.length) {
$banner.children[0].remove();
}
// Make banner interactable
// Add carousel-like selection boxes for active blend mode
for (let li, i = 0; i < blendModes.length; i++) {
li = document.createElement('li');
li.title = blendModes[i];
li.addEventListener('mousedown', function () {
setBannerBlendModeIndex(i);
clearInterval(changeBlendModeIntervalRef);
});
$ul.appendChild(li);
}
$banner.appendChild($ul);
$ul.children[blendModes.indexOf('normal')].dispatchEvent(new Event('mousedown'));
// Allow going left or right in carousel using touch events
touchslide($banner, function (direction) {
if (direction === 'left') {
setBannerBlendModeIndexRelative(-1);
}
else if (direction === 'right') {
setBannerBlendModeIndexRelative(1);
}
});
// Add arrow key navigation (and vim support)
document.addEventListener('keydown', function (event) {
const keys = ['ArrowLeft', 'j', 'ArrowRight', 'k'];
// Return early if key press isn't interesting
if (keys.indexOf(event.key) < 0) {
return;
}
if (event.key === keys[0] || event.key === keys[1]) {
setBannerBlendModeIndexRelative(-1);
} else if (event.key === keys[2] || event.key === keys[3]) {
setBannerBlendModeIndexRelative(1);
}
});
// Set random banner blend mode periodically
changeBlendModeIntervalRef = setInterval(function () {
setBannerBlendModeIndex(random(0, blendModes.length));
}, 20000);
}
document.addEventListener('DOMContentLoaded', setup, false);
console.log('This website was generated by my hands');