diff options
author | erdgeist <erdgeist@erdgeist.org> | 2024-12-22 21:53:57 +0100 |
---|---|---|
committer | erdgeist <erdgeist@erdgeist.org> | 2024-12-22 21:53:57 +0100 |
commit | e3481a4a35091b32b6fbee80c1c9ba2b6d7b50d6 (patch) | |
tree | 58f90b32cbd89599acfaab07377cc0447f1190c1 /static/halfnarp.js |
Rework of halfnarp and fullnarp into a self contained repository. Still WIP
Diffstat (limited to 'static/halfnarp.js')
-rw-r--r-- | static/halfnarp.js | 510 |
1 files changed, 510 insertions, 0 deletions
diff --git a/static/halfnarp.js b/static/halfnarp.js new file mode 100644 index 0000000..878f3ab --- /dev/null +++ b/static/halfnarp.js | |||
@@ -0,0 +1,510 @@ | |||
1 | function toggle_grid(whichDay) { | ||
2 | var vclasses= [['in-list'], ['in-calendar', 'onlyday1'], ['in-calendar', 'onlyday2'], ['in-calendar', 'onlyday3'], | ||
3 | ['in-calendar', 'onlyday4'], ['in-calendar', 'alldays']]; | ||
4 | document.body.classList.remove( 'alldays', 'onlyday1', 'onlyday2', 'onlyday3', 'onlyday4', 'in-list', 'in-calendar'); | ||
5 | if( whichDay < 0 || whichDay > 5 ) return; | ||
6 | document.body.classList.add(...vclasses[whichDay]); | ||
7 | document.getElementById('qrcode').classList.toggle('limit', whichDay == 0); | ||
8 | } | ||
9 | |||
10 | function toggle_corr_mode() { | ||
11 | if (!document.body.classList.contains('correlate')) | ||
12 | document.body.classList.remove('all-tracks', 'languages', 'classifiers'); | ||
13 | document.querySelectorAll('.event').forEach(elem => elem.setAttribute('corr', '')); | ||
14 | } | ||
15 | document.body.classList.toggle('correlate'); | ||
16 | } | ||
17 | |||
18 | function toggle_classifier(classifier, is_track, is_range) { | ||
19 | if (document.body.classList.contains('classifiers') && document.body.getAttribute('classifiers') == classifier) { | ||
20 | document.body.classList.remove('classifiers'); | ||
21 | return; | ||
22 | } | ||
23 | var default_intensity = 0, prefix = ''; | ||
24 | if (is_range) { | ||
25 | default_intensity = 5; | ||
26 | prefix = '+'; | ||
27 | } | ||
28 | is_range = is_range ? '+' : ''; | ||
29 | for (ev of window.top.all_events) { | ||
30 | if (ev.event_classifiers) { | ||
31 | var intensity = default_intensity; | ||
32 | // if track selector and empty, set to 80% | ||
33 | if (ev.event_classifiers[classifier]) | ||
34 | intensity = Math.round(ev.event_classifiers[classifier] / 10); | ||
35 | $('#event_'+ev.event_id).attr('intensity', prefix + intensity); | ||
36 | } | ||
37 | } | ||
38 | document.body.classList.add('classifiers'); | ||
39 | document.body.classList.remove('all-tracks', 'languages', 'correlate'); | ||
40 | document.body.setAttribute('classifier', classifier); | ||
41 | } | ||
42 | |||
43 | function set_random_event() { | ||
44 | var keys = Object.keys(all_events).filter(function(event_id) { | ||
45 | return $('#event_'+event_id+'.selected').length == 0 && | ||
46 | $('#event_'+event_id+'.rejected').length == 0; | ||
47 | }); | ||
48 | |||
49 | if (keys.length == 0) { | ||
50 | $('.narpr').toggleClass('hidden'); | ||
51 | return; | ||
52 | } | ||
53 | |||
54 | item = all_events[keys[ keys.length * Math.random() << 0]]; | ||
55 | $('.narpr_title').text(item.title || ''); | ||
56 | $('.narpr_track').text(item.track_name || ''); | ||
57 | $('.narpr_subtitle').text(item.subtitle || ''); | ||
58 | $('.narpr_speakers').text(item.speaker_names || ''); | ||
59 | $('.narpr_abstract').html(item.abstract || ''); | ||
60 | window.narpr_event = item.event_id; | ||
61 | } | ||
62 | |||
63 | function redraw_qrcode(ids) { | ||
64 | if (!ids) | ||
65 | ids = $('.selected').map( function() { return $(this).attr('event_id'); }).get(); | ||
66 | if ($('#qrcode').hasClass('hidden') && ids.length == 0 ) | ||
67 | return; | ||
68 | var request = JSON.stringify({'talk_ids': ids}); | ||
69 | var size = 68; | ||
70 | if($('body').hasClass('qrcode-huge')) { | ||
71 | size = 400; | ||
72 | } | ||
73 | |||
74 | $('#qrcode').empty(); | ||
75 | $('#qrcode').qrcode({width: size, height: size, text: request}); | ||
76 | $('#qrcode').removeClass('hidden'); | ||
77 | } | ||
78 | |||
79 | function redraw_calendar(myuid, ids) { | ||
80 | if (!ids) | ||
81 | ids = $('.selected').map( function() { return $(this).attr('event_id'); }).get(); | ||
82 | |||
83 | var now = new Date(); | ||
84 | var calendar = 'BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//events.ccc.de//halfnarp//EN\r\nX-WR-TIMEZONE:Europe/Berlin\r\n'; | ||
85 | ids.forEach( function(id) { | ||
86 | var item = all_events[id]; | ||
87 | if ('start_time' in item) { | ||
88 | |||
89 | var start = new Date(item.start_time); | ||
90 | calendar += 'BEGIN:VEVENT\r\n'; | ||
91 | calendar += 'UID:'+myuid+item.event_id+'\r\n'; | ||
92 | calendar += 'DTSTAMP:' + now.toISOString().replace(/-|;|:|\./g, '').replace(/...Z$/, 'Z') + '\r\n'; | ||
93 | calendar += 'DTSTART:' + start.toISOString().replace(/-|;|:|\./g, '').replace(/...Z$/, 'Z') + '\r\n'; | ||
94 | calendar += 'DURATION:PT' + item.duration + 'S\r\n'; | ||
95 | calendar += 'LOCATION:' + item.room_name + '\r\n'; | ||
96 | calendar += 'URL:http://events.ccc.de/congress/2023/Fahrplan/events/' + item.event_id + '.html\r\n'; | ||
97 | calendar += 'SUMMARY:' + item.title + '\r\n'; | ||
98 | calendar += 'DESCRIPTION:' + item.abstract.replace(/\n|\r/g, ' ') + '\r\n'; | ||
99 | // console.log( 'id:' + id + ' ' + all_events[id] ); | ||
100 | // console.log( all_events[id].title ); | ||
101 | calendar += 'END:VEVENT\r\n'; | ||
102 | } | ||
103 | }); | ||
104 | calendar += 'END:VCALENDAR\r\n'; | ||
105 | $('.export-url-a').attr( 'href', "data:text/calendar;filename=38C3.ics," + encodeURIComponent(calendar) ); | ||
106 | $('.export-url').removeClass( 'hidden' ); | ||
107 | } | ||
108 | |||
109 | function do_the_halfnarp() { | ||
110 | // var halfnarpAPI = 'talks_36C3.json'; | ||
111 | var halfnarpAPI = '/-/talkpreferences'; | ||
112 | var halfnarpCorrs = 'corr_array_38c3.json'; | ||
113 | var halfnarpPubAPI = halfnarpAPI + '/public/'; | ||
114 | var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0)); | ||
115 | window.top.all_events = new Object(); | ||
116 | window.top.narpr_rejected = new Array(); | ||
117 | var myuid, mypid, newfriend = new Object(); | ||
118 | var allhours = ['10', '11','12','13','14','15','16','17','18','19','20','21','22','23','00','01','02','03']; | ||
119 | |||
120 | $('.narpr_done').click( function(ev) { | ||
121 | $('.narpr').toggleClass('hidden', true); | ||
122 | if (!window.narpr_alerted) { | ||
123 | window.narpr_alerted = true; | ||
124 | alert("Thank you for using narpr(β). Don't forget to SUBMIT!"); | ||
125 | } | ||
126 | }); | ||
127 | |||
128 | $('.narpr').on({ 'touchstart' : function(ev) { | ||
129 | // alert("foo: " + ev.originalEvent.touches[0].clientX ); | ||
130 | window.touch_startX = ev.originalEvent.touches[0].clientX; | ||
131 | window.touch_curX = ev.originalEvent.touches[0].clientX; | ||
132 | window.touch_valid = true; | ||
133 | $('.narpr').css('background', '#ddd'); | ||
134 | } }); | ||
135 | |||
136 | $('.narpr').on({ 'touchmove' : function(ev) { | ||
137 | var narp_view = $('.narpr'); | ||
138 | if (ev.originalEvent.touches.length > 1) { | ||
139 | narp_view.css('background', 'white'); | ||
140 | window.touch_valid = false; | ||
141 | } | ||
142 | if (!window.touch_valid) | ||
143 | return; | ||
144 | if (ev.originalEvent.touches[0].clientX > window.touch_startX + 100) | ||
145 | narp_view.css('background', 'green'); | ||
146 | else if (ev.originalEvent.touches[0].clientX < window.touch_startX - 100) | ||
147 | narp_view.css('background', 'red'); | ||
148 | else | ||
149 | narp_view.css('background', '#ddd'); | ||
150 | window.touch_curX = ev.originalEvent.touches[0].clientX; | ||
151 | |||
152 | // console.log(narp_view[0].clientHeight + ':' + narp_view[0].scrollHeight); | ||
153 | if( narp_view[0].clientHeight >= narp_view[0].scrollHeight) | ||
154 | ev.preventDefault(); | ||
155 | } }); | ||
156 | |||
157 | $('.narpr').on({ 'touchend' : function(ev) { | ||
158 | if (!window.touch_valid) | ||
159 | return; | ||
160 | if (window.touch_curX > window.touch_startX + 100) { | ||
161 | $('#event_'+window.narpr_event).toggleClass('selected', true); | ||
162 | set_random_event(); | ||
163 | } | ||
164 | if (window.touch_curX < window.touch_startX - 100) { | ||
165 | $('#event_'+window.narpr_event).toggleClass('selected', false); | ||
166 | $('#event_'+window.narpr_event).toggleClass('rejected', true); | ||
167 | set_random_event(); | ||
168 | } | ||
169 | |||
170 | $('.narpr').css('background', 'white'); | ||
171 | } }); | ||
172 | |||
173 | /* Add callback for submit click */ | ||
174 | $('.submit').click( function() { | ||
175 | var myapi; | ||
176 | |||
177 | /* Get user's preferences and try to save them locally */ | ||
178 | var ids = $('.selected').map( function() { | ||
179 | return $(this).attr('event_id'); | ||
180 | }).get(); | ||
181 | try { | ||
182 | localStorage['38C3-halfnarp'] = ids; | ||
183 | myapi = localStorage.getItem('38C3-halfnarp-api'); | ||
184 | if (myapi) { | ||
185 | myapi = myapi.replace(/.*?:\//g, ""); | ||
186 | myapi = 'https:/' + myapi.replace(/.*?:\//g, ""); | ||
187 | } | ||
188 | } catch(err) { | ||
189 | alert('Storing your choices locally is forbidden.'); | ||
190 | } | ||
191 | |||
192 | /* Convert preferences to JSON and post them to backend */ | ||
193 | var request = JSON.stringify({'talk_ids': ids}); | ||
194 | if( !myapi || !myapi.length ) { | ||
195 | /* If we do not have resource URL, post data and get resource */ | ||
196 | $.ajax({ | ||
197 | type: 'POST', | ||
198 | url: halfnarpAPI + '/', | ||
199 | data: request, | ||
200 | headers: { | ||
201 | 'Accept': 'application/json', | ||
202 | 'Content-Type': 'application/json' | ||
203 | }, | ||
204 | contentType: "text/plain", | ||
205 | dataType: 'json', | ||
206 | }).done(function(data) { | ||
207 | $('.info').text('submitted'); | ||
208 | $('.info').removeClass('hidden'); | ||
209 | try { | ||
210 | localStorage['38C3-halfnarp-api'] = data['update_url']; | ||
211 | localStorage['38C3-halfnarp-pid'] = mypid = data['hashed_uid']; | ||
212 | localStorage['38C3-halfnarp-uid'] = myuid = data['uid']; | ||
213 | window.location.hash = mypid; | ||
214 | } catch(err) {} | ||
215 | }, 'json' ).fail(function() { | ||
216 | $('.info').text('failed :('); | ||
217 | $('.info').removeClass('hidden'); | ||
218 | }); | ||
219 | } else { | ||
220 | /* If we do have a resource URL, update resource */ | ||
221 | $.ajax({ | ||
222 | type: 'PUT', | ||
223 | url: myapi, | ||
224 | data: request, | ||
225 | contentType: "application/json", | ||
226 | dataType: 'json', | ||
227 | }).done(function(data) { | ||
228 | localStorage['38C3-halfnarp-uid'] = myuid = data['uid']; | ||
229 | if( localStorage['38C3-halfnarp-pid'] ) { | ||
230 | window.location.hash = localStorage['38C3-halfnarp-pid']; | ||
231 | } | ||
232 | $('.info').text('updated'); | ||
233 | $('.info').removeClass('hidden'); | ||
234 | }).fail(function(msg) { | ||
235 | $('.info').text('failed :('); | ||
236 | $('.info').removeClass('hidden'); | ||
237 | }); | ||
238 | } | ||
239 | |||
240 | /* Tell QRCode library to update and/or display preferences for Apps */ | ||
241 | redraw_qrcode(ids); | ||
242 | |||
243 | if (myuid) | ||
244 | redraw_calendar(myuid, ids); | ||
245 | }); | ||
246 | |||
247 | /* Add handler for type ahead search input field */ | ||
248 | var filter = document.getElementById('filter'); | ||
249 | filter.onpaste = filter.oncut = filter.onkeypress = filter.onkeydown = filter.onkeyup = function() { | ||
250 | var cnt = this.value.toLowerCase(); | ||
251 | if( cnt.length ) | ||
252 | document.querySelectorAll('.event').forEach(elem => elem.style.display = (elem.textContent || elem.innerText || '').toLowerCase().includes(cnt) ? "initial" : "none" ); | ||
253 | else | ||
254 | document.querySelectorAll('.event').forEach(elem => elem.style.display = "initial"); | ||
255 | }; | ||
256 | |||
257 | /* Add click handlers for event div sizers */ | ||
258 | document.querySelector('.vsmallboxes').onclick = function() { | ||
259 | document.body.classList.remove('size-medium', 'size-large'); | ||
260 | document.body.classList.add('size-small'); | ||
261 | }; | ||
262 | |||
263 | document.querySelector('.vmediumboxes').onclick = function() { | ||
264 | document.body.classList.remove('size-small', 'size-large'); | ||
265 | document.body.classList.add('size-medium'); | ||
266 | }; | ||
267 | |||
268 | document.querySelector('.vlargeboxes').onclick = function() { | ||
269 | document.body.classList.remove('size-small', 'size-medium'); | ||
270 | document.body.classList.add('size-large'); | ||
271 | }; | ||
272 | |||
273 | /* Add de-highlighter on touch interface devices */ | ||
274 | if( isTouch ) { | ||
275 | document.body.onclick = function() { | ||
276 | document.querySelector('.highlighted').forEach(elem => elem.classList.remove('highlighted')); | ||
277 | }; | ||
278 | document.querySelector('.touch-only').forEach(elem => elem.classList.remove('hidden')); | ||
279 | } | ||
280 | |||
281 | /* Add callbacks for view selector */ | ||
282 | document.querySelector('.vlist').onclick = function() { toggle_grid(0); }; | ||
283 | document.querySelector('.vday1').onclick = function() { toggle_grid(1); }; | ||
284 | document.querySelector('.vday2').onclick = function() { toggle_grid(2); }; | ||
285 | document.querySelector('.vday3').onclick = function() { toggle_grid(3); }; | ||
286 | document.querySelector('.vday4').onclick = function() { toggle_grid(4); }; | ||
287 | document.querySelector('.vdays').onclick = function() { toggle_grid(5); }; | ||
288 | |||
289 | document.querySelector('.vlang').onclick = function() { document.body.classList.toggle('languages'); }; | ||
290 | document.querySelector('.vtrack').onclick = function() { document.body.classList.toggle('all-tracks'); }; | ||
291 | document.querySelector('.vnarpr').onclick = function() { $('.narpr').toggleClass('hidden'); set_random_event(); }; | ||
292 | |||
293 | document.querySelector('.vcorr').onclick = toggle_corr_mode; | ||
294 | |||
295 | $('.vclass').click( function() { toggle_classifier( $(this).attr('classifier'), $(this).hasClass('track'), $(this).hasClass('two_poles')); }); | ||
296 | |||
297 | /* Create hour guides */ | ||
298 | for (hour of allhours) { | ||
299 | var elem = document.createElement('hr'); | ||
300 | elem.classList.add('guide', 'time_' + hour + '00'); | ||
301 | document.body.append(elem); | ||
302 | elem = document.createElement('div'); | ||
303 | elem.textContent = hour + '00'; | ||
304 | elem.classList.add('guide', 'time_' + hour + '00'); | ||
305 | document.body.append(elem); | ||
306 | } | ||
307 | |||
308 | /* If we've been here before, try to get local preferences. They are authoratative */ | ||
309 | var selection = [], friends = { }; | ||
310 | try { | ||
311 | selection = localStorage['38C3-halfnarp'] || []; | ||
312 | friends = localStorage['38C3-halfnarp-friends'] || { }; | ||
313 | myuid = localStorage['38C3-halfnarp-uid'] || ''; | ||
314 | mypid = localStorage['38C3-halfnarp-pid'] || ''; | ||
315 | } catch(err) { | ||
316 | } | ||
317 | |||
318 | /* Fetch list of lectures to display */ | ||
319 | $.getJSON( halfnarpAPI, { format: 'json' }) | ||
320 | .done(function( data ) { | ||
321 | $.each( data, function( i, item ) { | ||
322 | /* Save event to all_events hash */ | ||
323 | all_events[item.event_id] = item; | ||
324 | |||
325 | /* Take copy of hidden event template div and select them, if they're in | ||
326 | list of previous prereferences */ | ||
327 | var t = $( '#template' ).clone(true); | ||
328 | var event_id = item.event_id.toString(); | ||
329 | t.addClass('event ' + ' lang_' + (item.language || 'en')); | ||
330 | t.attr('event_id', item.event_id.toString()); | ||
331 | t.attr('id', 'event_' + item.event_id.toString()); | ||
332 | if( selection && selection.indexOf(item.event_id) != -1 ) { | ||
333 | t.addClass( 'selected' ); | ||
334 | } | ||
335 | |||
336 | /* Sort textual info into event div */ | ||
337 | t.find('.title').text(item.title); | ||
338 | t.find('.speakers').text(item.speaker_names); | ||
339 | t.find('.abstract').append(item.abstract); | ||
340 | |||
341 | if (item.event_classifiers && item.event_classifiers['Foundations'] && item.event_classifiers['Foundations'] > 40.0) | ||
342 | t.addClass('foundation'); | ||
343 | |||
344 | /* start_time: 2014-12-29T21:15:00+01:00" */ | ||
345 | var start_time = new Date(item.start_time); | ||
346 | |||
347 | var day = start_time.getUTCDate() - 26; | ||
348 | var hour = start_time.getUTCHours() + 1; | ||
349 | var mins = start_time.getUTCMinutes(); | ||
350 | |||
351 | /* After midnight: sort into yesterday */ | ||
352 | if( hour < 9 ) | ||
353 | day--; | ||
354 | if( hour > 23) | ||
355 | hour -= 24; | ||
356 | |||
357 | /* Fix up room for 38C3 */ | ||
358 | room = (item.room_id || '').toString().replace('1','room1').replace('2','room2').replace('3','room3'); | ||
359 | |||
360 | /* Apply attributes to sort events into calendar */ | ||
361 | t.addClass(room + ' duration_' + item.duration + ' day_'+day + ' time_' + (hour<10?'0':'') + hour + '' + (mins<10?'0':'') + mins); | ||
362 | |||
363 | t.click( function(event) { | ||
364 | if ($('body').hasClass('correlate')) { | ||
365 | mark_corr($(this).attr('event_id')); | ||
366 | event.stopPropagation(); | ||
367 | return; | ||
368 | } | ||
369 | /* Transition for touch devices is highlighted => selected => highlighted ... */ | ||
370 | if( isTouch ) { | ||
371 | if ( $( this ).hasClass('highlighted') ) { | ||
372 | $( this ).toggleClass('selected'); | ||
373 | $('.info').addClass('hidden'); | ||
374 | } else { | ||
375 | $('.highlighted').removeClass('highlighted'); | ||
376 | $( this ).addClass('highlighted'); | ||
377 | } | ||
378 | } else { | ||
379 | $( this ).toggleClass('selected'); | ||
380 | $('.info').addClass('hidden'); | ||
381 | } | ||
382 | event.stopPropagation(); | ||
383 | }); | ||
384 | /* Put new event into DOM tree. Track defaults to 'Other' */ | ||
385 | try { | ||
386 | var track = item.track_id.toString(); | ||
387 | } catch(e) { | ||
388 | var track = "Other"; | ||
389 | } | ||
390 | var d = $( '#' + track ); | ||
391 | t.addClass('track_' + track ); | ||
392 | if( !d.length ) { | ||
393 | d = $( '#Other' ); | ||
394 | } | ||
395 | d.append(t); | ||
396 | if( newfriend.pid ) { | ||
397 | newfriend.prefs.forEach( function( eventid ) { | ||
398 | $( '#event_' + eventid ).addClass( 'friend' ); | ||
399 | }); | ||
400 | } | ||
401 | }); | ||
402 | |||
403 | $.getJSON( halfnarpCorrs, { format: 'json' }).done(function(data) { window.top.all_votes = data; }); | ||
404 | toggle_grid(5); | ||
405 | |||
406 | /* Check for a new friends public uid in location's #hash */ | ||
407 | var shared = window.location.hash; | ||
408 | shared = shared ? shared.substr(1) : ''; | ||
409 | if( shared.length ) { | ||
410 | if ( ( friends[shared] ) || ( shared === mypid ) ) { | ||
411 | |||
412 | } else { | ||
413 | $.getJSON( halfnarpPubAPI + shared, { format: 'json' }) | ||
414 | .done(function( data ) { | ||
415 | newfriend.pid = shared; | ||
416 | newfriend.prefs = data.talk_ids; | ||
417 | newfriend.prefs.forEach( function( eventid ) { | ||
418 | $( '#event_' + eventid ).addClass( 'friend' ); | ||
419 | }); | ||
420 | }); | ||
421 | } | ||
422 | } | ||
423 | // window.location.hash = ''; | ||
424 | |||
425 | ids = $('.selected').map( function() { return $(this).attr('event_id'); }).get(); | ||
426 | if (ids.length) { | ||
427 | redraw_qrcode(ids); | ||
428 | if (myuid) | ||
429 | redraw_calendar(myuid, ids); | ||
430 | } | ||
431 | |||
432 | $('#qrcode').click( function() { | ||
433 | $('body').toggleClass('qrcode-huge'); | ||
434 | redraw_qrcode(); | ||
435 | }); | ||
436 | |||
437 | /* Update friends cache */ | ||
438 | for( var friend in friends ) { | ||
439 | $.getJSON( halfnarpPubAPI + friends.pid, { format: 'json' }) | ||
440 | .done(function( data ) { | ||
441 | friend.prefs = data.talk_ids; | ||
442 | localStorage['38C3-halfnarp-friends'] = friends; | ||
443 | update_friends(); | ||
444 | }); | ||
445 | } | ||
446 | |||
447 | }); | ||
448 | document.onkeypress = function(e) { | ||
449 | if( document.activeElement.tagName == 'INPUT' || document.activeElement.tagName == 'TEXTAREA' ) | ||
450 | return; | ||
451 | switch( e.keyCode ) { | ||
452 | case 48: case 94: /* 0 */ | ||
453 | toggle_grid(5); | ||
454 | break; | ||
455 | case 49: case 50: case 51: case 52: /* 1-4 */ | ||
456 | /* toggle_grid(e.keyCode-48); */ | ||
457 | break; | ||
458 | case 76: case 108: /* l */ | ||
459 | toggle_grid(0); | ||
460 | break; | ||
461 | case 68: case 100: /* d */ | ||
462 | /* toggle_grid(5); */ | ||
463 | break; | ||
464 | case 73: case 105: /* i */ | ||
465 | document.body.classList.remove('all-tracks'); | ||
466 | document.body.classList.toggle('languages'); | ||
467 | break; | ||
468 | case 84: case 116: /* t */ | ||
469 | document.body.classList.remove('languages'); | ||
470 | document.body.classList.toggle('all-tracks'); | ||
471 | break; | ||
472 | case 67: case 99: /* c */ | ||
473 | /* toggle_corr_mode(); */ | ||
474 | break; | ||
475 | } | ||
476 | }; | ||
477 | } | ||
478 | |||
479 | function mark_corr(eid) { | ||
480 | /* If JSON with votes is not there, bail */ | ||
481 | if (!all_votes) return; | ||
482 | |||
483 | /* Reset correlation markers */ | ||
484 | document.querySelectorAll('.event').forEach(elem => elem.setAttribute('corr', ''); | ||
485 | |||
486 | /* Get index of reference event id */ | ||
487 | var eoff = all_votes.event_ids.indexOf(eid); | ||
488 | if (eoff==-1) return; | ||
489 | |||
490 | document.querySelectorAll('.event').forEach( function(dest) { | ||
491 | var destid = dest.getAttribute('event_id'); | ||
492 | /* mark reference event at another place */ | ||
493 | if (destid == eid) { | ||
494 | dest.setAttribute('corr', 'x'); | ||
495 | return; | ||
496 | } | ||
497 | |||
498 | var destoff = all_votes.event_ids.indexOf(destid); | ||
499 | if (destoff==-1) { | ||
500 | dest.setAttribute('corr', '0'); | ||
501 | return; | ||
502 | } | ||
503 | |||
504 | /* Only the smaller event-id's string has the info */ | ||
505 | if (eoff < destoff) | ||
506 | dest.setAttribute('corr', all_votes.event_corrs[eoff].charAt(destoff-eoff-1)); | ||
507 | else | ||
508 | dest.setAttribute('corr', all_votes.event_corrs[destoff].charAt(eoff-destoff-1)); | ||
509 | }); | ||
510 | } | ||