Skip to content

Commit b7aee3b

Browse files
committed
Add javascript interaction
1 parent c76743a commit b7aee3b

1 file changed

Lines changed: 229 additions & 0 deletions

File tree

js/point.js

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
!(function () {
2+
/*----------------------------------------------------------------------------*/
3+
/* Helpers
4+
/*----------------------------------------------------------------------------*/
5+
var forEach = function (items, fn) {
6+
var len = items.length
7+
for (var i = 0; i < len; i++) {
8+
fn(items[i], i, items)
9+
}
10+
}
11+
12+
/*----------------------------------------------------------------------------*/
13+
/* Toggle
14+
/*----------------------------------------------------------------------------*/
15+
function Toggle(elementOrSelector) {
16+
if (typeof elementOrSelector === 'string') {
17+
this.trigger = document.querySelector(elementOrSelector)
18+
} else if (elementOrSelector instanceof Element) {
19+
this.trigger = elementOrSelector
20+
} else {
21+
throw Error('Invalid trigger selector or element!')
22+
}
23+
24+
if (!this.trigger) {
25+
throw Error('Trigger element does not exist!')
26+
}
27+
28+
var targetId = this.trigger.dataset.target
29+
var toggleServiceName = this.trigger.dataset.toggle
30+
var enterServiceName = this.trigger.dataset.enter
31+
var leaveServiceName = this.trigger.dataset.leave
32+
33+
if (
34+
typeof toggleServiceName !== 'undefined' ||
35+
typeof enterServiceName !== 'undefined' ||
36+
typeof leaveServiceName !== 'undefined'
37+
) {
38+
if (toggleServiceName) {
39+
this.type = 'toggle'
40+
this.service = Toggle.services[toggleServiceName]
41+
} else if (leaveServiceName) {
42+
this.type = 'leave'
43+
this.service = Toggle.services[leaveServiceName]
44+
} else if (enterServiceName) {
45+
this.type = 'enter'
46+
this.service = Toggle.services[enterServiceName]
47+
}
48+
} else {
49+
this.type = 'toggle'
50+
this.service = Toggle.services.default
51+
}
52+
53+
if (typeof targetId !== 'undefined') {
54+
this.target = document.getElementById(targetId)
55+
} else {
56+
this.target = this.trigger
57+
}
58+
59+
if (!this.service || !this.target || this.trigger.__toggler__) return
60+
61+
var self = this;
62+
function listener(e) {
63+
if (self.type === 'toggle') {
64+
self.toggle(e)
65+
} else if (self.type === 'enter') {
66+
self.enter(e)
67+
} else if (self.type === 'leave') {
68+
self.leave(e)
69+
}
70+
}
71+
this.trigger.addEventListener('click', listener)
72+
this.listener = listener
73+
this.trigger.__toggler__ = this
74+
if (this.service.init) {
75+
this.service.init.call(this);
76+
}
77+
}
78+
79+
Toggle.prototype.destroy = function () {
80+
if (this.service.destroy) {
81+
this.service.destroy.call(this);
82+
}
83+
this.trigger.removeEventListener('click', this.listener)
84+
this.trigger.__toggler__ = null
85+
this.trigger = null
86+
this.target = null
87+
this.listener = null
88+
}
89+
90+
Toggle.prototype.toggle = function (e) {
91+
this.service.render.call(this, 'toggle', e)
92+
}
93+
94+
Toggle.prototype.enter = function (e) {
95+
this.service.render.call(this, 'enter', e)
96+
}
97+
98+
Toggle.prototype.leave = function (e) {
99+
this.service.render.call(this, 'leave', e)
100+
}
101+
102+
Toggle.services = {
103+
default: {
104+
render: function (action) {
105+
if (action === 'leave') {
106+
this.target.classList.remove('is-active')
107+
} else if (action === 'enter') {
108+
this.target.classList.add('is-active')
109+
} else {
110+
this.target.classList.toggle('is-active')
111+
}
112+
}
113+
}
114+
}
115+
116+
Toggle.init = function init(elementOrSelector) {
117+
if (!elementOrSelector) {
118+
forEach(document.querySelectorAll('[data-toggle]'), function (trigger) {
119+
new Toggle(trigger)
120+
})
121+
forEach(document.querySelectorAll('[data-enter]'), function (trigger) {
122+
new Toggle(trigger)
123+
})
124+
forEach(document.querySelectorAll('[data-leave]'), function (trigger) {
125+
new Toggle(trigger)
126+
})
127+
} else {
128+
new Toggle(elementOrSelector)
129+
}
130+
}
131+
132+
Toggle.register = function register(option) {
133+
Toggle.services[option.name] = {
134+
init: option.init,
135+
render: option.render
136+
}
137+
}
138+
139+
/*----------------------------------------------------------------------------*/
140+
/* Modal
141+
/*----------------------------------------------------------------------------*/
142+
Toggle.register({
143+
name: 'modal',
144+
render: function(action) {
145+
if (action === 'leave') {
146+
this.target.classList.add('hidden')
147+
} else if (action === 'enter') {
148+
this.target.classList.remove('hidden')
149+
} else {
150+
this.target.classList.toggle('hidden')
151+
}
152+
}
153+
})
154+
155+
/*----------------------------------------------------------------------------*/
156+
/* Dropdown
157+
/*----------------------------------------------------------------------------*/
158+
Toggle.register({
159+
name: 'dropdown',
160+
init: function() {
161+
var self = this;
162+
if (this.target !== this.trigger) return
163+
var sibling = this.trigger.parentNode.firstElementChild
164+
while(sibling) {
165+
if (sibling !== this.trigger && sibling.classList.contains('dropdown__content')) {
166+
this.target = sibling;
167+
break;
168+
}
169+
sibling = sibling.nextElementSibling
170+
}
171+
172+
function clickoutHandler(e) {
173+
if (!self.target.contains(e.target) && !self.trigger.contains(e.target)) {
174+
self.leave()
175+
}
176+
}
177+
178+
document.addEventListener('click', clickoutHandler)
179+
this.clickoutHandler = clickoutHandler
180+
},
181+
destroy: function() {
182+
document.removeEventListener('click', this.clickoutHandler)
183+
},
184+
render: function(action) {
185+
if (action === 'leave') {
186+
this.target.classList.add('hidden')
187+
} else if (action === 'enter') {
188+
this.target.classList.remove('hidden')
189+
} else {
190+
this.target.classList.toggle('hidden')
191+
}
192+
}
193+
})
194+
195+
/*----------------------------------------------------------------------------*/
196+
/* Menu
197+
/*----------------------------------------------------------------------------*/
198+
Toggle.register({
199+
name: 'menu',
200+
render: function(action, e) {
201+
if (!e) return
202+
203+
var el = e.target
204+
while (el && el !== e.currentTarget) {
205+
if (el.classList.contains('menu__link')) {
206+
if (
207+
el.nextElementSibling &&
208+
el.nextElementSibling.classList.contains('menu__list')
209+
) {
210+
if (action === 'leave') {
211+
el.parentNode.classList.remove('is-active')
212+
} else if (action === 'enter') {
213+
el.parentNode.classList.add('is-active')
214+
} else {
215+
el.parentNode.classList.toggle('is-active')
216+
}
217+
}
218+
break;
219+
}
220+
221+
el = el.parentNode
222+
}
223+
}
224+
})
225+
226+
Toggle.init()
227+
window.Toggle = Toggle
228+
229+
})();

0 commit comments

Comments
 (0)