diff options
author | erdgeist <erdgeist@erdgeist.org> | 2025-01-04 02:46:47 +0100 |
---|---|---|
committer | erdgeist <erdgeist@erdgeist.org> | 2025-01-04 02:46:47 +0100 |
commit | 7f155dc09e2b8862d68ee40d514de16c064bf449 (patch) | |
tree | 23c8967b2257c8c7748cd60c34ebad9e302793e0 /static/fullnarp.js | |
parent | ab32e563be8d99010245fc546817c5a2526d7b09 (diff) |
Get prototype working
Diffstat (limited to 'static/fullnarp.js')
-rw-r--r-- | static/fullnarp.js | 429 |
1 files changed, 209 insertions, 220 deletions
diff --git a/static/fullnarp.js b/static/fullnarp.js index 8b7d36d..3d60592 100644 --- a/static/fullnarp.js +++ b/static/fullnarp.js | |||
@@ -1,4 +1,9 @@ | |||
1 | let ws; // WebSocket instance | 1 | let ws; // WebSocket instance |
2 | let allrooms = ['1','2','3'] | ||
3 | let allminutes = ['00','05','10','15','20','25','30','35','40','45','50','55'] | ||
4 | let allhours = ['10','11','12','13','14','15','16','17','18','19','20','21','22','23','00','01','02']; | ||
5 | let alldays = ['1','2','3','4']; | ||
6 | let raw_votes; | ||
2 | 7 | ||
3 | function toggle_grid(whichDay) { | 8 | function toggle_grid(whichDay) { |
4 | var vclasses= [['in-list'], ['in-calendar', 'onlyday1'], ['in-calendar', 'onlyday2'], ['in-calendar', 'onlyday3'], | 9 | var vclasses= [['in-list'], ['in-calendar', 'onlyday1'], ['in-calendar', 'onlyday2'], ['in-calendar', 'onlyday3'], |
@@ -8,6 +13,128 @@ function toggle_grid(whichDay) { | |||
8 | document.body.classList.add(...vclasses[whichDay]); | 13 | document.body.classList.add(...vclasses[whichDay]); |
9 | } | 14 | } |
10 | 15 | ||
16 | function render_lectures(data) { | ||
17 | for (item of data) { | ||
18 | /* Take copy of hidden event template div and select them, if they're in | ||
19 | list of previous prereferences */ | ||
20 | var t = document.getElementById('template').cloneNode(true); | ||
21 | var event_id = item.event_id.toString(); | ||
22 | |||
23 | t.classList.add('event', 'duration_' + item.duration, 'lang_' + (item.language || 'en')); | ||
24 | t.setAttribute('event_id', event_id); | ||
25 | t.setAttribute('id', 'event_' + event_id); | ||
26 | t.setAttribute('fullnarp-duration', item.duration); | ||
27 | t.setAttribute('draggable', 'true'); | ||
28 | |||
29 | /* Sort textual info into event div */ | ||
30 | t.querySelector('.title').textContent = item.title; | ||
31 | t.querySelector('.speakers').textContent = item.speaker_names; | ||
32 | t.querySelector('.abstract').append(item.abstract); | ||
33 | |||
34 | /* Store speakers and their availabilities */ | ||
35 | window.event_speakers[event_id] = item.speakers; | ||
36 | for (speaker of item.speakers) { | ||
37 | var have_avails = false; | ||
38 | for (avail of speaker.availabilities) { | ||
39 | if (avail.id ) { | ||
40 | have_avails = true; | ||
41 | break; | ||
42 | } | ||
43 | } | ||
44 | if (!have_avails) | ||
45 | t.classList.add('has_unavailable_speaker'); | ||
46 | } | ||
47 | |||
48 | /* Make the event drag&droppable */ | ||
49 | t.ondragstart = function( event, ui ) { | ||
50 | event.stopPropagation(); | ||
51 | |||
52 | event.dataTransfer.setData('text/plain', this.id ); | ||
53 | event.dataTransfer.dropEffect = 'move'; | ||
54 | event.dataTransfer.effectAllowed = 'move'; | ||
55 | event.target.classList.add('is-dragged'); | ||
56 | } | ||
57 | |||
58 | /* While dragging make source element small enough to allow | ||
59 | dropping below its original area */ | ||
60 | t.ondrag = function( event, ui ) { | ||
61 | event.stopPropagation(); | ||
62 | event.target.classList.add('is-dragged'); | ||
63 | |||
64 | /* When drag starts in list view, switch to calendar view */ | ||
65 | if( document.body.classList.contains('in-list') ) { | ||
66 | toggle_grid(5); | ||
67 | document.body.classList.add('was-list'); | ||
68 | } | ||
69 | if( document.body.classList.contains('in-drag') ) | ||
70 | return; | ||
71 | |||
72 | document.body.classList.add('in-drag'); | ||
73 | /* mark all possible drop points regarding to availability */ | ||
74 | for (hour of allhours) | ||
75 | for (minute of allminutes) | ||
76 | for (day of alldays) | ||
77 | document.querySelectorAll('.grid.day_'+day+'.time_'+hour+minute).forEach(elem => elem.classList.toggle('possible', check_avail(event.target, day, hour+minute))); | ||
78 | |||
79 | } | ||
80 | |||
81 | t.ondragend = function( event, ui ) { | ||
82 | event.stopPropagation(); | ||
83 | |||
84 | /* We removed in-list and the drop did not succeed. Go back to list view */ | ||
85 | if (document.body.classList.contains('was-list')) | ||
86 | toggle_grid(0); | ||
87 | |||
88 | document.querySelectorAll('.over').forEach(elem => elem.classList.remove('over')); | ||
89 | document.querySelectorAll('.is-dragged').forEach(elem => elem.classList.remove('id-dragged')); | ||
90 | document.querySelectorAll('.possible').forEach(elem => elem.classList.remove('possible')); | ||
91 | document.body.classList.remove('in-drag', 'was-list'); | ||
92 | } | ||
93 | |||
94 | /* start_time: 2014-12-29T21:15:00+01:00" */ | ||
95 | var start_time = new Date(item.start_time); | ||
96 | |||
97 | var day = start_time.getDate()-26; | ||
98 | var hour = start_time.getHours(); | ||
99 | var mins = start_time.getMinutes(); | ||
100 | |||
101 | /* After midnight: sort into yesterday */ | ||
102 | if( hour < 9 ) | ||
103 | day--; | ||
104 | |||
105 | /* Fix up room for 38c3 */ | ||
106 | room = (item.room_id || 'room_unknown').toString().replace('471','room1').replace('472','room2').replace('473','room3'); | ||
107 | |||
108 | /* Apply attributes to sort events into calendar */ | ||
109 | t.classList.add(room, 'day_' + day, 'time_' + (hour<10?'0':'') + hour + (mins<10?'0':'') + mins); | ||
110 | t.setAttribute('fullnarp-day', day); | ||
111 | t.setAttribute('fullnarp-time', (hour<10?'0':'') + hour + (mins<10?'0':'') + mins ); | ||
112 | t.setAttribute('fullnarp-room', room.replace('room','')); | ||
113 | |||
114 | mark_avail(t); | ||
115 | |||
116 | t.onclick = function(event) { | ||
117 | _this = this; | ||
118 | document.body.classList.remove('in-drag'); | ||
119 | if (document.body.classList.contains('correlate')) { | ||
120 | document.querySelectorAll('.selected').forEach(elem => elem.classList.remove('selected')); | ||
121 | document.querySelectorAll('.event').forEach(elem => mark_correlation(elem, _this)); | ||
122 | } | ||
123 | _this.classList.toggle('selected'); | ||
124 | document.querySelectorAll('.info').forEach(elem => elem.classList.add('hidden')); | ||
125 | event.stopPropagation(); | ||
126 | } | ||
127 | |||
128 | /* Put new event into DOM tree. Track defaults to 'Other' */ | ||
129 | var track = item.track_id.toString(); | ||
130 | t.classList.add('track_' + track ); | ||
131 | var d = document.getElementById(track); | ||
132 | if (!d) | ||
133 | d = document.getElementById('Other'); | ||
134 | d.append(t); | ||
135 | } | ||
136 | } | ||
137 | |||
11 | function distribute_votes() { | 138 | function distribute_votes() { |
12 | document.querySelectorAll('.event').forEach( function(element) { | 139 | document.querySelectorAll('.event').forEach( function(element) { |
13 | var eid = element.getAttribute('event_id'); | 140 | var eid = element.getAttribute('event_id'); |
@@ -37,8 +164,8 @@ function distribute_votes() { | |||
37 | } | 164 | } |
38 | 165 | ||
39 | function corr_for_eventids(id1, id2) { | 166 | function corr_for_eventids(id1, id2) { |
40 | var d = 0, c = 0, cd = 0, l = window.raw_votes.length; | 167 | var d = 0, c = 0, cd = 0, l = raw_votes.length; |
41 | for (item of window.raw_votes) { | 168 | for (item of raw_votes) { |
42 | var x = 0; | 169 | var x = 0; |
43 | if( item.indexOf(id1) > -1 ) { ++d; x++;} | 170 | if( item.indexOf(id1) > -1 ) { ++d; x++;} |
44 | if( item.indexOf(id2) > -1 ) { ++c; cd+=x; } | 171 | if( item.indexOf(id2) > -1 ) { ++c; cd+=x; } |
@@ -52,42 +179,42 @@ function corr_for_eventids(id1, id2) { | |||
52 | } | 179 | } |
53 | 180 | ||
54 | function show_all_correlates(el) { | 181 | function show_all_correlates(el) { |
55 | /* First identify the room to see what other rooms to consider | 182 | /* First identify the room to see what other rooms to consider |
56 | correlates always grow from the top slot to the right, | 183 | correlates always grow from the top slot to the right, |
57 | unless there's an overlapping event to the left that starts earlier | 184 | unless there's an overlapping event to the left that starts earlier |
58 | */ | 185 | */ |
59 | var event_room = el.getAttribute('fullnarp-room'); | 186 | var event_room = el.getAttribute('fullnarp-room'); |
60 | var event_day = el.getAttribute('fullnarp-day'); | 187 | var event_day = el.getAttribute('fullnarp-day'); |
61 | var event_time = el.getAttribute('fullnarp-time'); | 188 | var event_time = el.getAttribute('fullnarp-time'); |
62 | 189 | ||
63 | if (!event_time) return; | 190 | if (!event_time) return; |
64 | 191 | ||
65 | var event_start; | 192 | var event_start; |
66 | try { event_start = time_to_mins(event_time); } catch(e) { return; } | 193 | try { event_start = time_to_mins(event_time); } catch(e) { return; } |
67 | var event_duration = el.getAttribute('fullnarp-duration') / 60; | 194 | var event_duration = el.getAttribute('fullnarp-duration') / 60; |
68 | 195 | ||
69 | /* Only test events to the right, if they start at the exact same time */ | 196 | /* Only test events to the right, if they start at the exact same time */ |
70 | document.querySelectorAll('.event.day_'+event_day).forEach( function(check_el, index) { | 197 | document.querySelectorAll('.event.day_'+event_day).forEach( function(check_el, index) { |
71 | var check_room = check_el.getAttribute('fullnarp-room'); | 198 | var check_room = check_el.getAttribute('fullnarp-room'); |
72 | if (event_room == check_room) return; | 199 | if (event_room == check_room) return; |
73 | 200 | ||
74 | var check_time = check_el.getAttribute('fullnarp-time'); | 201 | var check_time = check_el.getAttribute('fullnarp-time'); |
75 | if (!check_time) return; | 202 | if (!check_time) return; |
76 | var check_start = time_to_mins(check_time); | 203 | var check_start = time_to_mins(check_time); |
77 | var check_duration = check_el.getAttribute('fullnarp-duration') / 60; | 204 | var check_duration = check_el.getAttribute('fullnarp-duration') / 60; |
78 | var dist = check_el.getAttribute('fullnarp-room') - event_room; | 205 | var dist = check_el.getAttribute('fullnarp-room') - event_room; |
79 | var overlap = check_start < event_start + event_duration && event_start < check_start + check_duration; | 206 | var overlap = check_start < event_start + event_duration && event_start < check_start + check_duration; |
80 | 207 | ||
81 | if (!overlap) return; | 208 | if (!overlap) return; |
82 | if (event_start == check_start && dist <= 0) return; | 209 | if (event_start == check_start && dist <= 0) return; |
83 | if (event_start < check_start) return; | 210 | if (event_start < check_start) return; |
84 | 211 | ||
85 | var corr = corr_for_eventids(el.getAttribute('event_id'), check_el.getAttribute('event_id')); | 212 | var corr = corr_for_eventids(el.getAttribute('event_id'), check_el.getAttribute('event_id')); |
86 | var dir = dist > 0 ? 'r' : 'l'; | 213 | var dir = dist > 0 ? 'r' : 'l'; |
87 | var div = document.createElement('div'); | 214 | var div = document.createElement('div'); |
88 | div.classList.add('corrweb', dir.repeat(Math.abs(dist)), 'day_' + event_day, 'room' + event_room, 'time_' + event_time, 'corr_d_' + corr); | 215 | div.classList.add('corrweb', dir.repeat(Math.abs(dist)), 'day_' + event_day, 'room' + event_room, 'time_' + event_time, 'corr_d_' + corr); |
89 | document.body.appendChild(div); | 216 | document.body.appendChild(div); |
90 | }) | 217 | }); |
91 | } | 218 | } |
92 | 219 | ||
93 | function display_correlation() { | 220 | function display_correlation() { |
@@ -104,8 +231,8 @@ function display_correlation() { | |||
104 | function mark_correlation(dest, comp) { | 231 | function mark_correlation(dest, comp) { |
105 | var id1 = dest.getAttribute('event_id'); | 232 | var id1 = dest.getAttribute('event_id'); |
106 | var id2 = comp.getAttribute('event_id'); | 233 | var id2 = comp.getAttribute('event_id'); |
107 | var d = 0, c = 0, cd = 0, l = window.raw_votes.length; | 234 | var d = 0, c = 0, cd = 0, l =raw_votes.length; |
108 | for (vote of window.raw_votes) { | 235 | for (vote of raw_votes) { |
109 | var x = 0; | 236 | var x = 0; |
110 | if( vote.indexOf(id1) > -1 ) { ++d; x++;} | 237 | if( vote.indexOf(id1) > -1 ) { ++d; x++;} |
111 | if( vote.indexOf(id2) > -1 ) { ++c; cd+=x; } | 238 | if( vote.indexOf(id2) > -1 ) { ++c; cd+=x; } |
@@ -208,8 +335,9 @@ function remove_event(event_id) { | |||
208 | el.classList.add('pending'); | 335 | el.classList.add('pending'); |
209 | if (ws && ws.readyState === WebSocket.OPEN) { | 336 | if (ws && ws.readyState === WebSocket.OPEN) { |
210 | var message = { | 337 | var message = { |
338 | action: "remove_event", | ||
211 | lastupdate: window.lastupdate, | 339 | lastupdate: window.lastupdate, |
212 | removeevent: event_id | 340 | event_id: event_id |
213 | } | 341 | } |
214 | ws.send(JSON.stringify(message)); | 342 | ws.send(JSON.stringify(message)); |
215 | console.log('Sent:', message); | 343 | console.log('Sent:', message); |
@@ -233,8 +361,9 @@ function set_all_attributes(event_id, day, room, time, from_server) { | |||
233 | el.classList.add('pending'); | 361 | el.classList.add('pending'); |
234 | if (ws && ws.readyState === WebSocket.OPEN) { | 362 | if (ws && ws.readyState === WebSocket.OPEN) { |
235 | var message = { | 363 | var message = { |
364 | action: "set_event", | ||
236 | lastupdate: window.lastupdate, | 365 | lastupdate: window.lastupdate, |
237 | setevent: event_id, | 366 | event_id: event_id, |
238 | day: el.getAttribute('fullnarp-day'), | 367 | day: el.getAttribute('fullnarp-day'), |
239 | room: el.getAttribute('fullnarp-room'), | 368 | room: el.getAttribute('fullnarp-room'), |
240 | time: el.getAttribute('fullnarp-time') | 369 | time: el.getAttribute('fullnarp-time') |
@@ -264,26 +393,51 @@ function signalFullnarpConnect(state) { | |||
264 | document.body.classList.add(state); | 393 | document.body.classList.add(state); |
265 | } | 394 | } |
266 | 395 | ||
267 | function getFullnarpData(lastupdate) { | 396 | function getFullnarpData() { |
268 | signalFullnarpConnect('fullnarp-connecting'); | 397 | signalFullnarpConnect('fullnarp-connecting'); |
269 | ws = new WebSocket('wss://erdgeist.org/38C3/halfnarp/fullnarp-ws'); | 398 | ws = new WebSocket('wss://content.events.ccc.de/fullnarp/ws/'); |
270 | 399 | ||
271 | ws.onopen = () => { | 400 | ws.onopen = () => { |
272 | console.log('Connected to WebSocket server'); | 401 | console.log('Connected to WebSocket server'); |
273 | //stateElement.textContent = 'Connected'; | 402 | var message = { |
403 | action: raw_votes ? "reconnect" : "bootstrap" | ||
404 | }; | ||
405 | ws.send(JSON.stringify(message)); | ||
406 | console.log('Sent:', message); | ||
274 | }; | 407 | }; |
275 | 408 | ||
276 | ws.onmessage = (event) => { | 409 | ws.onmessage = (event) => { |
277 | signalFullnarpConnect('fullnarp-connected'); | 410 | signalFullnarpConnect('fullnarp-connected'); |
278 | const data = JSON.parse(event.data); | 411 | const data = JSON.parse(event.data); |
279 | console.log('Received:', data); | 412 | console.log('Received:', data); |
280 | for (const [eventid, event_new] of Object.entries(data.data)) { | 413 | |
281 | if (document.getElementById(eventid)) | 414 | switch (data.property) { |
282 | set_all_attributes(eventid, 'day_'+event_new['day'], 'room'+event_new['room'], 'time_'+event_new['time'], true ) | 415 | |
416 | case 'pretalx': | ||
417 | render_lectures(data.data); | ||
418 | break; | ||
419 | |||
420 | case 'halfnarp': | ||
421 | for (eventidlist of data.data) | ||
422 | for (eventid of eventidlist) | ||
423 | window.votes[eventid] = 1 + (window.votes[eventid] || 0 ); | ||
424 | raw_votes = data.data; | ||
425 | distribute_votes(); | ||
426 | break; | ||
427 | |||
428 | case 'fullnarp': | ||
429 | for (const [eventid, event_new] of Object.entries(data.data)) { | ||
430 | if (document.getElementById(eventid)) | ||
431 | set_all_attributes(eventid, 'day_'+event_new['day'], 'room'+event_new['room'], 'time_'+event_new['time'], true ) | ||
432 | } | ||
433 | window.lastupdate = data.current_version; | ||
434 | current_version_string = ('00000'+data.current_version).slice(-5); | ||
435 | document.querySelector('.version').innerHTML = '<a href="https://content.events.ccc.de/fullnarp/versions/fullnarp_'+current_version_string+'.json">Version: '+data.current_version+'</a>'; | ||
436 | break; | ||
437 | |||
438 | default: | ||
439 | console.log(`Unknown property: ${data['property']}.`); | ||
283 | } | 440 | } |
284 | window.lastupdate = data.current_version; | ||
285 | current_version_string = ('00000'+data.current_version).slice(-5); | ||
286 | document.querySelector('.version').innerHTML = '<a href="https://erdgeist.org/38C3/halfnarp/versions/fullnarp_'+current_version_string+'.json">Version: '+data.current_version+'</a>'; | ||
287 | }; | 441 | }; |
288 | 442 | ||
289 | ws.onerror = (error) => { | 443 | ws.onerror = (error) => { |
@@ -302,11 +456,6 @@ function getFullnarpData(lastupdate) { | |||
302 | function do_the_fullnarp() { | 456 | function do_the_fullnarp() { |
303 | var halfnarpAPI = 'talks_38C3.json'; | 457 | var halfnarpAPI = 'talks_38C3.json'; |
304 | var fullnarpAPI = 'votes_38c3.json'; | 458 | var fullnarpAPI = 'votes_38c3.json'; |
305 | var allrooms = ['1','2','3'] | ||
306 | var allminutes = ['00','05','10','15','20','25','30','35','40','45','50','55'] | ||
307 | var allhours = ['10','11','12','13','14','15','16','17','18','19','20','21','22','23','00','01','02']; | ||
308 | var alldays = ['1','2','3','4']; | ||
309 | var voted = 0; | ||
310 | window.event_speakers = {}; | 459 | window.event_speakers = {}; |
311 | window.votes = {}; | 460 | window.votes = {}; |
312 | 461 | ||
@@ -383,8 +532,8 @@ function do_the_fullnarp() { | |||
383 | elem.classList.add('guide', 'time_' + hour + '00'); | 532 | elem.classList.add('guide', 'time_' + hour + '00'); |
384 | document.body.append(elem); | 533 | document.body.append(elem); |
385 | 534 | ||
386 | for (minute of allminutes) { | 535 | for (minute of allminutes) |
387 | for (room of allrooms) { | 536 | for (room of allrooms) |
388 | for (day of alldays) { | 537 | for (day of alldays) { |
389 | elem = document.createElement('div'); | 538 | elem = document.createElement('div'); |
390 | elem.classList.add('grid', 'time_' + hour + minute, 'day_' + day, 'room' + room ); | 539 | elem.classList.add('grid', 'time_' + hour + minute, 'day_' + day, 'room' + room ); |
@@ -408,170 +557,10 @@ function do_the_fullnarp() { | |||
408 | return false; | 557 | return false; |
409 | } | 558 | } |
410 | } | 559 | } |
411 | } | ||
412 | } | ||
413 | } | 560 | } |
414 | 561 | ||
415 | /* Fetch list of votes to display */ | 562 | window.lastupdate = 0; |
416 | fetch(`${fullnarpAPI}?format=json`) | 563 | getFullnarpData(); |
417 | .then(response => { | ||
418 | if (!response.ok) { | ||
419 | throw new Error(`HTTP error when fetching fullnarp data! status: ${response.status}`); | ||
420 | } | ||
421 | return response.json(); | ||
422 | }).then(data => { | ||
423 | window.raw_votes = data; | ||
424 | for (eventidlist of data) | ||
425 | for (eventid of eventidlist) | ||
426 | window.votes[eventid] = 1 + (window.votes[eventid] || 0 ); | ||
427 | if( ++voted == 2 ) { | ||
428 | window.lastupdate = 0; | ||
429 | distribute_votes(); | ||
430 | getFullnarpData(0); | ||
431 | } | ||
432 | }).catch(error => { | ||
433 | console.error('Fetch error:', error); | ||
434 | }); | ||
435 | |||
436 | |||
437 | /* Fetch list of lectures to display */ | ||
438 | fetch(`${halfnarpAPI}?format=json`) | ||
439 | .then(response => { | ||
440 | if (!response.ok) { | ||
441 | throw new Error(`HTTP error when fetching halfnarp data! status: ${response.status}`); | ||
442 | } | ||
443 | return response.json(); | ||
444 | }).then(data => { | ||
445 | for (item of data) { | ||
446 | /* Take copy of hidden event template div and select them, if they're in | ||
447 | list of previous prereferences */ | ||
448 | var t = document.getElementById('template').cloneNode(true); | ||
449 | var event_id = item.event_id.toString(); | ||
450 | t.classList.add('event', 'duration_' + item.duration, 'lang_' + (item.language || 'en')); | ||
451 | t.setAttribute('event_id', event_id); | ||
452 | t.setAttribute('id', 'event_' + event_id) | ||
453 | t.setAttribute( 'fullnarp-duration', item.duration); | ||
454 | |||
455 | /* Sort textual info into event div */ | ||
456 | t.querySelector('.title').textContent = item.title; | ||
457 | t.querySelector('.speakers').textContent = item.speaker_names; | ||
458 | t.querySelector('.abstract').append(item.abstract); | ||
459 | |||
460 | /* Store speakers and their availabilities */ | ||
461 | window.event_speakers[event_id] = item.speakers; | ||
462 | for (speaker of item.speakers) { | ||
463 | var have_avails = false; | ||
464 | if (!speaker.availabilities) | ||
465 | console.log("Foo"); | ||
466 | for (avail of speaker.availabilities) { | ||
467 | if (avail.id ) { | ||
468 | have_avails = true; | ||
469 | break; | ||
470 | } | ||
471 | } | ||
472 | if (!have_avails) | ||
473 | t.classList.add('has_unavailable_speaker'); | ||
474 | } | ||
475 | |||
476 | t.setAttribute('draggable', 'true'); | ||
477 | |||
478 | /* Make the event drag&droppable */ | ||
479 | t.ondragstart = function( event, ui ) { | ||
480 | event.stopPropagation(); | ||
481 | |||
482 | event.dataTransfer.setData('text/plain', this.id ); | ||
483 | event.dataTransfer.dropEffect = 'move'; | ||
484 | event.dataTransfer.effectAllowed = 'move'; | ||
485 | event.target.classList.add('is-dragged'); | ||
486 | } | ||
487 | |||
488 | /* While dragging make source element small enough to allow | ||
489 | dropping below its original area */ | ||
490 | t.ondrag = function( event, ui ) { | ||
491 | event.stopPropagation(); | ||
492 | event.target.classList.add('is-dragged'); | ||
493 | |||
494 | /* When drag starts in list view, switch to calendar view */ | ||
495 | if( document.body.classList.contains('in-list') ) { | ||
496 | toggle_grid(5); | ||
497 | document.body.classList.add('was-list'); | ||
498 | } | ||
499 | if( document.body.classList.contains('in-drag') ) | ||
500 | return; | ||
501 | |||
502 | document.body.classList.add('in-drag'); | ||
503 | /* mark all possible drop points regarding to availability */ | ||
504 | for (hour of allhours) | ||
505 | for (minute of allminutes) | ||
506 | for (day of alldays) | ||
507 | document.querySelectorAll('.grid.day_'+day+'.time_'+hour+minute).forEach(elem => elem.classList.toggle('possible', check_avail(event.target, day, hour+minute))); | ||
508 | |||
509 | } | ||
510 | |||
511 | t.ondragend = function( event, ui ) { | ||
512 | event.stopPropagation(); | ||
513 | |||
514 | /* We removed in-list and the drop did not succeed. Go back to list view */ | ||
515 | if (document.body.classList.contains('was-list')) | ||
516 | toggle_grid(0); | ||
517 | |||
518 | document.querySelectorAll('.over').forEach(elem => elem.classList.remove('over')); | ||
519 | document.querySelectorAll('.is-dragged').forEach(elem => elem.classList.remove('id-dragged')); | ||
520 | document.querySelectorAll('.possible').forEach(elem => elem.classList.remove('possible')); | ||
521 | document.body.classList.remove('in-drag', 'was-list'); | ||
522 | } | ||
523 | |||
524 | /* start_time: 2014-12-29T21:15:00+01:00" */ | ||
525 | var start_time = new Date(item.start_time); | ||
526 | |||
527 | var day = start_time.getDate()-26; | ||
528 | var hour = start_time.getHours(); | ||
529 | var mins = start_time.getMinutes(); | ||
530 | |||
531 | /* After midnight: sort into yesterday */ | ||
532 | if( hour < 9 ) | ||
533 | day--; | ||
534 | |||
535 | /* Fix up room for 38c3 */ | ||
536 | room = (item.room_id || 'room_unknown').toString().replace('471','room1').replace('472','room2').replace('473','room3'); | ||
537 | |||
538 | /* Apply attributes to sort events into calendar */ | ||
539 | t.classList.add(room, 'day_' + day, 'time_' + (hour<10?'0':'') + hour + (mins<10?'0':'') + mins); | ||
540 | t.setAttribute('fullnarp-day', day); | ||
541 | t.setAttribute('fullnarp-time', (hour<10?'0':'') + hour + (mins<10?'0':'') + mins ); | ||
542 | t.setAttribute('fullnarp-room', room.replace('room','')); | ||
543 | |||
544 | mark_avail(t); | ||
545 | |||
546 | t.onclick = function(event) { | ||
547 | _this = this; | ||
548 | document.body.classList.remove('in-drag'); | ||
549 | if (document.body.classList.contains('correlate')) { | ||
550 | document.querySelectorAll('.selected').forEach(elem => elem.classList.remove('selected')); | ||
551 | document.querySelectorAll('.event').forEach(elem => mark_correlation(elem, _this)); | ||
552 | } | ||
553 | _this.classList.toggle('selected'); | ||
554 | document.querySelectorAll('.info').forEach(elem => elem.classList.add('hidden')); | ||
555 | event.stopPropagation(); | ||
556 | } | ||
557 | |||
558 | /* Put new event into DOM tree. Track defaults to 'Other' */ | ||
559 | var track = item.track_id.toString(); | ||
560 | t.classList.add('track_' + track ); | ||
561 | var d = document.getElementById(track); | ||
562 | if (!d) | ||
563 | d = document.querySelector('#Other'); | ||
564 | d.append(t); | ||
565 | }; | ||
566 | |||
567 | if( ++voted == 2 ) { | ||
568 | window.lastupdate = 0; | ||
569 | distribute_votes(); | ||
570 | getFullnarpData(0); | ||
571 | } | ||
572 | }).catch(error => { | ||
573 | console.error('Fetch error:', error); | ||
574 | }); | ||
575 | 564 | ||
576 | document.onkeypress = function(e) { | 565 | document.onkeypress = function(e) { |
577 | document.body.classList.remove('in-drag'); | 566 | document.body.classList.remove('in-drag'); |