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 | } | ||
