active_analytics 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +105 -15
  3. data/app/controllers/active_analytics/application_controller.rb +24 -4
  4. data/app/controllers/active_analytics/assets_controller.rb +29 -0
  5. data/app/controllers/active_analytics/pages_controller.rb +9 -10
  6. data/app/controllers/active_analytics/referrers_controller.rb +9 -5
  7. data/app/controllers/active_analytics/sites_controller.rb +4 -4
  8. data/app/models/active_analytics/views_per_day.rb +22 -3
  9. data/app/views/active_analytics/assets/_charts.css +249 -0
  10. data/app/{assets/stylesheets/active_analytics/style.css → views/active_analytics/assets/_style.css} +37 -38
  11. data/app/views/active_analytics/assets/application.css.erb +2 -0
  12. data/app/{assets/javascripts/active_analytics → views/active_analytics/assets}/application.js +1 -3
  13. data/app/views/active_analytics/assets/ariato.css +875 -0
  14. data/app/views/active_analytics/assets/ariato.js +322 -0
  15. data/app/views/active_analytics/pages/_table.html.erb +6 -17
  16. data/app/views/active_analytics/pages/index.html.erb +1 -1
  17. data/app/views/active_analytics/pages/show.html.erb +7 -8
  18. data/app/views/active_analytics/referrers/_table.html.erb +9 -2
  19. data/app/views/active_analytics/referrers/index.html.erb +2 -2
  20. data/app/views/active_analytics/referrers/show.html.erb +6 -3
  21. data/app/views/active_analytics/sites/_histogram.html.erb +9 -2
  22. data/app/views/active_analytics/sites/_histogram_header.html.erb +10 -0
  23. data/app/views/active_analytics/sites/show.html.erb +2 -2
  24. data/app/views/layouts/active_analytics/_footer.html.erb +3 -3
  25. data/app/views/layouts/active_analytics/_header.html.erb +1 -3
  26. data/app/views/layouts/active_analytics/application.html.erb +5 -3
  27. data/config/routes.rb +2 -1
  28. data/lib/active_analytics/version.rb +1 -1
  29. data/lib/active_analytics.rb +47 -4
  30. metadata +15 -11
  31. data/app/assets/javascripts/active_analytics/ariato.js +0 -746
  32. data/app/assets/stylesheets/active_analytics/application.css +0 -15
  33. data/app/assets/stylesheets/active_analytics/ariato.css +0 -3548
  34. data/app/assets/stylesheets/active_analytics/charts.css +0 -424
@@ -1,746 +0,0 @@
1
- Ariato = {}
2
-
3
- Ariato.launchWhenDomIsReady = function(root) {
4
- if (document.readyState != "loading") {
5
- Ariato.launch()
6
- Ariato.launch(document, "aria-roledescription")
7
- Ariato.launch(document, "data-ariato")
8
- }
9
- else
10
- document.addEventListener("DOMContentLoaded", function() { Ariato.launchWhenDomIsReady(root) } )
11
- }
12
-
13
- Ariato.launch = function(root, attribute, parent) {
14
- attribute || (attribute = "role")
15
- var elements = (root || document).querySelectorAll("[" + attribute + "]")
16
- for (var i = 0; i < elements.length; i++)
17
- Ariato.start(elements[i], attribute, parent)
18
- }
19
-
20
- Ariato.mount = function() {
21
- }
22
-
23
- Ariato.start = function(element, attribute, parent) {
24
- var names = element.getAttribute(attribute).split(" ")
25
- for (var i = 0; i < names.length; i++) {
26
- var name = names[i].charAt(0).toUpperCase() + names[i].slice(1) // Capitalize
27
- var func = Ariato.stringToFunction("Ariato." + name) || Ariato.stringToFunction(name)
28
- if (func instanceof Function)
29
- Ariato.instanciate(func, element, parent)
30
- }
31
- }
32
-
33
- Ariato.instanciate = function(func, element, parent) {
34
- try {
35
- controller = Object.create(func.prototype)
36
- controller.parent = parent
37
- controller.node = element
38
- Ariato.initialize(controller, element)
39
- func.call(controller, element)
40
- } catch (ex) {
41
- console.error(ex)
42
- }
43
- }
44
-
45
- Ariato.stringToFunction = function(fullName) {
46
- var func = window, names = fullName.split(".")
47
- for (var i = 0; i < names.length; i++)
48
- if (!(func = func[names[i]]))
49
- return null
50
- return func
51
- }
52
-
53
- Ariato.initialize = function(controller, container) {
54
- Ariato.listenEvents(container, controller)
55
- Ariato.assignRoles(container, controller)
56
- }
57
-
58
- Ariato.listenEvents = function(root, controller) {
59
- var elements = root.querySelectorAll("[data-event]")
60
- for (var i = 0; i < elements.length; i++) {
61
- elements[i].getAttribute("data-event").split(" ").forEach(function(eventAndAction) {
62
- var array = eventAndAction.split("->")
63
- Ariato.listenEvent(controller, elements[i], array[0], array[1])
64
- })
65
- }
66
- }
67
-
68
- Ariato.listenEvent = function(controller, element, event, action) {
69
- if (controller[action] instanceof Function)
70
- element.addEventListener(event, controller[action].bind(controller))
71
- }
72
-
73
- Ariato.findRoles = function(container) {
74
- var roles = {}, elements = container.querySelectorAll("[data-role]")
75
- for (var i = 0; i < elements.length; i++) {
76
- var name = elements[i].getAttribute("data-role")
77
- roles[name] ? roles[name].push(elements[i]) : roles[name] = [elements[i]]
78
- }
79
- return roles
80
- }
81
-
82
- Ariato.assignRoles = function(container, controller) {
83
- controller.roles = Ariato.findRoles(container)
84
- for (var name in controller.roles)
85
- if (controller.roles[name].length == 1)
86
- controller[name] = controller.roles[name][0]
87
- }
88
-
89
- Ariato.Accordion = function(node) {
90
- this.node = node
91
- node.ariaAccordion = this
92
- this.regions = []
93
- }
94
-
95
- Ariato.Accordion.addRegion = function(region) {
96
- var button = region.labelledBy()
97
-
98
- if (!button)
99
- return
100
-
101
- var accordion = region.node.parentElement.ariaAccordion || new Ariato.Accordion(region.node.parentElement)
102
- accordion.addRegion(region)
103
- return accordion
104
- }
105
-
106
- Ariato.Accordion.prototype.addRegion = function(region) {
107
- this.regions.push(region)
108
- }
109
-
110
- Ariato.Accordion.prototype.hideRegions = function() {
111
- for (var i = 0; i < this.regions.length; i++)
112
- this.regions[i].hide()
113
- }
114
-
115
- Ariato.Accordion.prototype.showRegion = function(region) {
116
- if (this.mutilpleAllowed())
117
- region.expanded() ? region.hide() : region.show()
118
- else {
119
- this.hideRegions()
120
- region.show()
121
- }
122
- }
123
-
124
- Ariato.Accordion.prototype.mutilpleAllowed = function() {
125
- return this.node.hasAttribute("data-allow-multiple")
126
- }
127
-
128
- Ariato.Carousel = function() {
129
- this.currentSlide() || this.showSlide(this.slides()[0])
130
- this.node.addEventListener("keydown", this.keydown.bind(this))
131
-
132
- var nextButton = this.node.querySelector("[data-carousel=next]")
133
- nextButton && nextButton.addEventListener("click", this.clicked.bind(this))
134
-
135
- var previousButton = this.node.querySelector("[data-carousel=previous]")
136
- previousButton.addEventListener("click", this.clicked.bind(this))
137
- }
138
-
139
- Ariato.Carousel.prototype.slides = function() {
140
- return this.node.querySelectorAll("[aria-roledescription=slide]")
141
- }
142
-
143
- Ariato.Carousel.prototype.currentSlide = function() {
144
- return this.node.querySelector("[aria-current=slide]")
145
- }
146
-
147
- Ariato.Carousel.prototype.showSlide = function(slide) {
148
- var slides = this.slides()
149
-
150
- for (var i = 0; i < slides.length; i++)
151
- if (slides[i] == slide)
152
- slides[i].setAttribute("aria-current", "slide")
153
- else
154
- slides[i].removeAttribute("aria-current")
155
- }
156
-
157
- Ariato.Carousel.prototype.nextSlide = function(slide) {
158
- var slides = this.slides()
159
- this.currentSlide()
160
- for (var i = 0; i < slides.length; i++) {
161
- if (slides[i] == slide)
162
- slides[i].setAttribute("aria-current", "slide")
163
- else
164
- slides[i].removeAttribute("aria-current")
165
- }
166
- }
167
-
168
- Ariato.Carousel.prototype.nextSlide = function(slide) {
169
- var current = this.currentSlide()
170
- return current && current.nextElementSibling
171
- }
172
-
173
- Ariato.Carousel.prototype.previousSlide = function(slide) {
174
- var current = this.currentSlide()
175
- return current && current.previousElementSibling
176
- }
177
-
178
- Ariato.Carousel.prototype.keydown = function(event) {
179
- switch(event.key) {
180
- case "ArrowLeft":
181
- this.showSlide(this.previousOrLastSlide())
182
- break
183
- case "ArrowRight":
184
- this.showSlide(this.nextOrFirstSlide())
185
- break
186
- }
187
- }
188
-
189
- Ariato.Carousel.prototype.clicked = function(event) {
190
- switch(event.currentTarget.getAttribute("data-carousel")) {
191
- case "next":
192
- this.showSlide(this.previousOrLastSlide())
193
- break
194
- case "previous":
195
- this.showSlide(this.nextOrFirstSlide())
196
- break
197
- }
198
- }
199
-
200
- Ariato.Carousel.prototype.previousOrLastSlide = function(event) {
201
- var slide = this.previousSlide()
202
- if (slide)
203
- return slide
204
- else {
205
- var slides = this.slides()
206
- return slides[slides.length-1]
207
- }
208
- }
209
-
210
- Ariato.Carousel.prototype.nextOrFirstSlide = function(event) {
211
- var slide = this.nextSlide()
212
- if (slide)
213
- return slide
214
- else {
215
- var slides = this.slides()
216
- return slides[0]
217
- }
218
- }
219
-
220
- Ariato.Dialog = function(node) {
221
- node.setAttribute("hidden", true)
222
- node.addEventListener("open", this.open.bind(this))
223
- node.addEventListener("close", this.close.bind(this))
224
- node.addEventListener("keydown", this.keydown.bind(this))
225
- }
226
-
227
- Ariato.Dialog.open = function(elementOrId) {
228
- var dialog = elementOrId instanceof Element ? elementOrId : document.getElementById(elementOrId)
229
- dialog && dialog.dispatchEvent(new CustomEvent("open"))
230
- }
231
-
232
- Ariato.Dialog.close = function(button) {
233
- var dialog = Ariato.Dialog.current()
234
- if (dialog && dialog.node.contains(button))
235
- dialog.close()
236
- }
237
-
238
- Ariato.Dialog.closeCurrent = function() {
239
- var dialog = Ariato.Dialog.current()
240
- dialog && dialog.close()
241
- }
242
-
243
- Ariato.Dialog.replace = function(elementOrId) {
244
- Ariato.Dialog.closeCurrent()
245
- Ariato.Dialog.open(elementOrId)
246
- }
247
-
248
- Ariato.Dialog.close = function(button) {
249
- var dialog = Ariato.Dialog.current()
250
- if (dialog && dialog.node.contains(button))
251
- dialog.close()
252
- }
253
-
254
- Ariato.Dialog.list = []
255
-
256
- Ariato.Dialog.current = function() {
257
- return this.list[this.list.length - 1]
258
- }
259
-
260
- Ariato.Dialog.prototype.open = function(event) {
261
- Ariato.Dialog.list.push(this)
262
- document.addEventListener("focus", this.bindedLimitFocusScope = this.limitFocusScope.bind(this), true)
263
- this.initiator = document.activeElement
264
- this.node.removeAttribute("hidden")
265
-
266
- this.lockScrolling()
267
- this.createBackdrop()
268
- this.createFocusStoppers()
269
- this.focusFirstDescendant(this.node)
270
- }
271
-
272
- Ariato.Dialog.prototype.close = function(event) {
273
- document.removeEventListener("focus", this.bindedLimitFocusScope, true)
274
- this.node.setAttribute("hidden", true)
275
- this.removeFocusStoppers()
276
- this.removeBackdrop()
277
- this.unlockScrolling()
278
- this.initiator.focus()
279
- Ariato.Dialog.list.pop()
280
- }
281
-
282
- Ariato.Dialog.prototype.keydown = function(event) {
283
- if (event.key == "Escape")
284
- this.close()
285
- }
286
-
287
- Ariato.Dialog.prototype.focusFirstDescendant = function(parent) {
288
- var focusable = ["A", "BUTTON", "INPUT", "SELECT", "TEXTAREA"]
289
-
290
- for (var i = 0; i < parent.children.length; i++) {
291
- var child = parent.children[i]
292
- if (focusable.indexOf(child.nodeName) != -1 && !child.disabled && child.type != "hidden") {
293
- child.focus()
294
- return child
295
- }
296
- else {
297
- var focus = this.focusFirstDescendant(child)
298
- if (focus) return focus
299
- }
300
- }
301
- }
302
-
303
- Ariato.Dialog.prototype.limitFocusScope = function(event) {
304
- if (this == Ariato.Dialog.current())
305
- if (!this.node.contains(event.target))
306
- this.focusFirstDescendant(this.node)
307
- }
308
-
309
- Ariato.Dialog.prototype.lockScrolling = function() {
310
- document.body.style.position = "fixed";
311
- document.body.style.top = "-" + window.scrollY + "px";
312
- }
313
-
314
- Ariato.Dialog.prototype.unlockScrolling = function() {
315
- var scrollY = document.body.style.top
316
- document.body.style.position = ""
317
- document.body.style.top = ""
318
- window.scrollTo(0, parseInt(scrollY || "0") * -1)
319
- }
320
-
321
- Ariato.Dialog.prototype.createFocusStoppers = function() {
322
- this.node.parentNode.insertBefore(this.focusStopper1 = document.createElement("div"), this.node)
323
- this.focusStopper1.tabIndex = 0
324
-
325
- this.node.parentNode.insertBefore(this.focusStopper2 = document.createElement("div"), this.node.nextSibling)
326
- this.focusStopper2.tabIndex = 0
327
- }
328
-
329
- Ariato.Dialog.prototype.removeFocusStoppers = function() {
330
- this.focusStopper1 && this.focusStopper1.parentNode.removeChild(this.focusStopper1)
331
- this.focusStopper2 && this.focusStopper2.parentNode.removeChild(this.focusStopper2)
332
- }
333
-
334
- Ariato.Dialog.prototype.createBackdrop = function() {
335
- this.backdrop = document.createElement("div")
336
- this.backdrop.classList.add("dialog-backdrop")
337
- this.node.parentNode.insertBefore(this.backdrop, this.node)
338
- this.backdrop.appendChild(this.node)
339
- }
340
-
341
- Ariato.Dialog.prototype.removeBackdrop = function() {
342
- this.backdrop.parentNode.insertBefore(this.node, this.backdrop)
343
- this.backdrop.parentNode.removeChild(this.backdrop)
344
- this.backdrop = null
345
- }
346
-
347
- Ariato.Alertdialog = Ariato.Dialog
348
-
349
- Ariato.MenuBar = function() {
350
- this.node.addEventListener("keydown", this.keyDown.bind(this))
351
- }
352
-
353
- // Ariato defines role="menubar" but MenuBar in camel case is nicer
354
- Ariato.Menubar = Ariato.MenuBar
355
-
356
- Ariato.Menubar.prototype.keyDown = function(event) {
357
- switch (event.key) {
358
- case "ArrowDown":
359
- event.preventDefault()
360
- if (event.target.hasAttribute("aria-haspopup"))
361
- this.openItem(event.target)
362
- else
363
- this.focusNextItem(event.target)
364
- break
365
- case "ArrowUp":
366
- event.preventDefault()
367
- if (event.target.hasAttribute("aria-haspopup"))
368
- this.openItem(event.target)
369
- else
370
- this.focusPreviousItem(event.target)
371
- break
372
- case "ArrowRight":
373
- // Open parent next menu
374
- // Open child menu
375
- // Focus next item
376
- this.openNextMenu(event.target)
377
- break
378
- if (event.target.hasAttribute("aria-haspopup"))
379
- this.openItem(event.target)
380
- else
381
- this.openNextMenu(this.findParentMenu(event.target))
382
- case "ArrowLeft":
383
- this.openPreviousMenu(event.target)
384
- break
385
- case "Escape":
386
- this.closeAllExcept()
387
- break
388
- }
389
- }
390
-
391
- Ariato.Menubar.prototype.closeAllExcept = function(item) {
392
- var menus = this.node.querySelectorAll("[role=menu]")
393
- for (var i = 0; i < menus.length; i++)
394
- menus[i].style.display = menus[i].contains(item) ? "block" : null
395
- }
396
-
397
- Ariato.Menubar.prototype.openItem = function(item) {
398
- var menu = item.parentElement.querySelector("[role=menu]")
399
- item.setAttribute("aria-expanded", true)
400
- var subItem = menu.querySelector("[role=menuitem]")
401
- if (subItem) {
402
- this.closeAllExcept(subItem)
403
- subItem.focus()
404
- } else {
405
- this.closeAllExcept(item)
406
- item.focus()
407
- }
408
- }
409
-
410
- Ariato.Menubar.prototype.openNextMenu = function(item) {
411
- var menu = this.findNextMenu(item)
412
- menu && this.openItem(menu.parentElement.querySelector("[role=menuitem]"))
413
- }
414
-
415
- Ariato.Menubar.prototype.openPreviousMenu = function(item) {
416
- var menu = this.findPreviousMenu(item)
417
- menu && this.openItem(menu.parentElement.querySelector("[role=menuitem]"))
418
- }
419
-
420
- Ariato.Menubar.prototype.focusNextItem = function(item) {
421
- var nextItem = this.findNextItem(item)
422
- nextItem && nextItem.focus()
423
- }
424
-
425
- Ariato.Menubar.prototype.focusPreviousItem = function(item) {
426
- var previousItem = this.findPreviousItem(item)
427
- previousItem && previousItem.focus()
428
- }
429
-
430
- Ariato.Menubar.prototype.findParentMenu = function(item) {
431
- var parent = item.parentElement
432
- var menuRoles = ["menu", "menubar"]
433
- while (parent && !menuRoles.includes(parent.getAttribute("role")))
434
- parent = parent.parentElement
435
- return parent
436
- }
437
-
438
- Ariato.Menubar.prototype.findNextItem = function(item) {
439
- var menu = this.findParentMenu(item)
440
- var items = menu.querySelectorAll("[role=menuitem]")
441
- for (var i = 0; i < items.length; i++)
442
- if (items[i] == item)
443
- return items[i+1]
444
- }
445
-
446
- Ariato.Menubar.prototype.findPreviousItem = function(item) {
447
- var menu = this.findParentMenu(item)
448
- var items = menu.querySelectorAll("[role=menuitem]")
449
- for (var i = 0; i < items.length; i++)
450
- if (items[i] == item)
451
- return items[i-1]
452
- }
453
-
454
- Ariato.Menubar.prototype.findNextMenu = function(item) {
455
- var menus = this.rootMenus()
456
- for (var i = 0; i < menus.length; i++)
457
- if (menus[i].contains(item))
458
- return menus[i+1]
459
-
460
- var parent = item.parentElement
461
- for (var i = 0; i < menus.length; i++)
462
- if (parent.contains(menus[i]))
463
- return menus[i+1]
464
- }
465
-
466
- Ariato.Menubar.prototype.findPreviousMenu = function(item) {
467
- var menus = this.rootMenus()
468
- for (var i = 0; i < menus.length; i++)
469
- if (menus[i].contains(item))
470
- return menus[i-1]
471
-
472
- var parent = item.parentElement
473
- for (var i = 0; i < menus.length; i++)
474
- if (parent.contains(menus[i]))
475
- return menus[i-1]
476
- }
477
-
478
- Ariato.Menubar.prototype.rootMenus = function() {
479
- return this.node.querySelectorAll("li > [role=menu]")
480
- }
481
-
482
- Ariato.MenuButton = function(node) {
483
- this.node = this.button = node
484
- this.menu = document.getElementById(this.button.getAttribute("aria-controls"))
485
-
486
- this.menu.addEventListener("keydown", this.keydown.bind(this))
487
- this.button.addEventListener("keydown", this.keydown.bind(this))
488
-
489
- this.button.addEventListener("click", this.clicked.bind(this))
490
- window.addEventListener("click", this.windowClicked.bind(this), true)
491
- }
492
-
493
- Ariato.MenuButton.prototype.clicked = function(event) {
494
- this.node.getAttribute("aria-expanded") == "true" ? this.close() : this.open()
495
- }
496
-
497
- Ariato.MenuButton.prototype.windowClicked = function() {
498
- if (!this.node.contains(event.target) && this.node.getAttribute("aria-expanded") == "true")
499
- this.close()
500
- }
501
-
502
- Ariato.MenuButton.prototype.open = function() {
503
- this.button.setAttribute("aria-expanded", "true")
504
- this.menu.style.display = "block"
505
- }
506
-
507
- Ariato.MenuButton.prototype.close = function() {
508
- this.button.setAttribute("aria-expanded", "false")
509
- this.menu.style.display = null
510
- }
511
-
512
- Ariato.MenuButton.prototype.keydown = function(event) {
513
- switch(event.key) {
514
- case "Escape":
515
- this.close()
516
- break
517
- case "ArrowDown":
518
- event.preventDefault()
519
- this.focusNextItem()
520
- break
521
- case "ArrowUp":
522
- event.preventDefault()
523
- this.focusPreviousItem()
524
- break
525
- case "Tab":
526
- this.close()
527
- case "Home":
528
- case "PageUp":
529
- event.preventDefault()
530
- this.items()[0].focus()
531
- break
532
- case "End":
533
- case "PageDown":
534
- event.preventDefault()
535
- var items = this.items()
536
- items[items.length-1].focus()
537
- break
538
- }
539
- }
540
-
541
- Ariato.MenuButton.prototype.items = function() {
542
- return this.menu.querySelectorAll("[role=menuitem]")
543
- }
544
-
545
- Ariato.MenuButton.prototype.currentItem = function() {
546
- return this.menu.querySelector("[role=menuitem]:focus")
547
- }
548
-
549
- Ariato.MenuButton.prototype.nextItem = function() {
550
- var items = this.items()
551
- var current = this.currentItem()
552
- if (!current) return items[0]
553
- for (var i = 0; i < items.length; i++) {
554
- if (items[i] == current)
555
- return items[i+1]
556
- }
557
- }
558
-
559
- Ariato.MenuButton.prototype.previousItem = function() {
560
- var items = this.items()
561
- var current = this.currentItem()
562
- if (!current) return items[0]
563
- for (var i = 0; i < items.length; i++) {
564
- if (items[i] == current)
565
- return items[i-1]
566
- }
567
- }
568
-
569
- Ariato.MenuButton.prototype.focusNextItem = function() {
570
- var item = this.nextItem()
571
- item && item.focus()
572
- }
573
-
574
- Ariato.MenuButton.prototype.focusPreviousItem = function() {
575
- var item = this.previousItem()
576
- item && item.focus()
577
- }
578
-
579
- Ariato.Menu = function(node) {
580
- var button = this.labelledBy()
581
- button && new Ariato.MenuButton(button)
582
- }
583
-
584
- Ariato.Menu.prototype.labelledBy = function() {
585
- return document.getElementById(this.node.getAttribute("aria-labelledby"))
586
- }
587
-
588
- /*
589
- * A region is a role="region" element which represents a panel of an accordion.
590
- * It is controlled by a button.
591
- */
592
- Ariato.Region = function(node) {
593
- this.node = node
594
- var labelledBy = this.labelledBy()
595
-
596
- if (!labelledBy)
597
- return
598
-
599
- this.accordion = Ariato.Accordion.addRegion(this)
600
- labelledBy.addEventListener("click", this.buttonClicked.bind(this))
601
- }
602
-
603
- Ariato.Region.prototype.labelledBy = function() {
604
- return document.getElementById(this.node.getAttribute("aria-labelledby"))
605
- }
606
-
607
- Ariato.Region.prototype.buttonClicked = function(event) {
608
- this.accordion.showRegion(this)
609
- }
610
-
611
- Ariato.Region.prototype.show = function(event) {
612
- this.labelledBy().setAttribute("aria-expanded", true)
613
- this.node.removeAttribute("hidden")
614
- }
615
-
616
- Ariato.Region.prototype.hide = function(event) {
617
- this.labelledBy().setAttribute("aria-expanded", false)
618
- this.node.setAttribute("hidden", "")
619
- }
620
-
621
- Ariato.Region.prototype.expanded = function() {
622
- return !this.node.hasAttribute("hidden")
623
- }
624
-
625
- Ariato.Tablist = function(node) {
626
- this.node = node
627
- var tabs = this.tabs()
628
- for (var i = 0; i < tabs.length; i++) {
629
- tabs[i].addEventListener("click", this.click.bind(this))
630
- tabs[i].addEventListener("keydown", this.keydown.bind(this))
631
- tabs[i].addEventListener("keyup", this.keyup.bind(this))
632
- }
633
- tabs[0] && this.showTab(tabs[0])
634
- }
635
-
636
- Ariato.Tablist.prototype.click = function(event) {
637
- this.showTab(event.currentTarget)
638
- }
639
-
640
- Ariato.Tablist.prototype.tabs = function() {
641
- return this.node.querySelectorAll("[role=tab]")
642
- }
643
-
644
- Ariato.Tablist.prototype.activeTab = function() {
645
- return this.node.querySelector("[aria-selected=true]")
646
- }
647
-
648
- Ariato.Tablist.prototype.panels = function() {
649
- var tabs = this.tabs(), result = []
650
- for (var i = 0; i < tabs.length; i++)
651
- result.push(document.getElementById(tabs[i].getAttribute("aria-controls")))
652
- return result
653
- }
654
-
655
- Ariato.Tablist.prototype.showTab = function(tab) {
656
- this.hidePanels()
657
- tab.removeAttribute("tabindex")
658
- tab.setAttribute("aria-selected", "true")
659
- document.getElementById(tab.getAttribute("aria-controls")).style.display = null
660
- tab.focus()
661
- }
662
-
663
- Ariato.Tablist.prototype.hidePanels = function() {
664
- var tabs = this.tabs()
665
- for (var i = 0; i < tabs.length; i++) {
666
- tabs[i].setAttribute("tabindex", "-1");
667
- tabs[i].setAttribute("aria-selected", "false");
668
- }
669
-
670
- var panels = this.panels()
671
- for (var i = 0; i < panels.length; i++)
672
- panels[i].style.display = "none"
673
- }
674
-
675
- Ariato.Tablist.prototype.keydown = function(event) {
676
- switch (event.key) {
677
- case "End":
678
- var tabs = this.tabs()
679
- event.preventDefault()
680
- this.showTab(this.tabs()[tabs.length - 1])
681
- break
682
- case "Home":
683
- event.preventDefault()
684
- this.showTab(this.tabs()[0])
685
- break
686
- case "ArrowUp":
687
- event.preventDefault()
688
- this.showPrevious()
689
- break
690
- case "ArrowDown":
691
- event.preventDefault()
692
- this.showNext()
693
- break
694
- }
695
- }
696
-
697
- Ariato.Tablist.prototype.keyup = function(event) {
698
- if (event.key == "ArrowLeft")
699
- this.showPrevious()
700
- else if (event.key == "ArrowRight")
701
- this.showNext(event)
702
- // TODO delete
703
- }
704
-
705
- Ariato.Tablist.prototype.showNext = function() {
706
- var tabs = this.tabs()
707
- var index = Array.prototype.indexOf.call(tabs, this.activeTab())
708
- tabs[index + 1] && this.showTab(tabs[index + 1])
709
- }
710
-
711
- Ariato.Tablist.prototype.showPrevious = function() {
712
- var tabs = this.tabs()
713
- var index = Array.prototype.indexOf.call(tabs, this.activeTab())
714
- tabs[index - 1] && this.showTab(tabs[index - 1])
715
- }
716
-
717
- Ariato.ThemeSwitcher = function() {
718
- Ariato.ThemeSwitcher.initialize()
719
- this.node.addEventListener("click", this.change.bind(this))
720
- }
721
-
722
- Ariato.ThemeSwitcher.initialize = function() {
723
- if (!this.initialized) {
724
- console.log("initialize")
725
- this.initialized = true
726
- this.update()
727
- }
728
- }
729
-
730
- Ariato.ThemeSwitcher.update = function() {
731
- var name = localStorage.getItem("ariato-theme")
732
- document.documentElement.classList.forEach(function(theme) {
733
- theme.startsWith("theme-") && document.documentElement.classList.remove(theme)
734
- })
735
- document.documentElement.classList.add("theme-" + name)
736
-
737
- var buttons = document.querySelectorAll("[data-ariato='ThemeSwitcher']")
738
- for (var i = 0; i < buttons.length; i++)
739
- buttons[i].setAttribute("aria-pressed", buttons[i].getAttribute("data-theme") == name)
740
- }
741
-
742
- Ariato.ThemeSwitcher.prototype.change = function(event) {
743
- var name = event.currentTarget.getAttribute("data-theme")
744
- localStorage.setItem("ariato-theme", name)
745
- name && Ariato.ThemeSwitcher.update(name)
746
- }