From 663b4dc6d89d21caa6b670d69780754b40910d90 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Tue, 29 Oct 2019 21:18:46 +0100 Subject: live update of next station via javascript --- lib/Travelynx.pm | 30 ++++++++++++++ public/static/js/travelynx-actions.js | 68 +++++++++++++++++++++++++++++-- public/static/js/travelynx-actions.min.js | 2 +- templates/_checked_in.html.ep | 10 +++-- 4 files changed, 102 insertions(+), 8 deletions(-) diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm index b29d63b..84310d9 100755 --- a/lib/Travelynx.pm +++ b/lib/Travelynx.pm @@ -2405,6 +2405,36 @@ sub startup { } ); + $self->helper( + 'journey_to_ajax_route' => sub { + my ( $self, $journey ) = @_; + + my @route; + + for my $station ( @{ $journey->{route_after} } ) { + my $station_desc = $station->[0]; + if ( $station->[1]{rt_arr} ) { + $station_desc .= $station->[1]{sched_arr}->strftime(';%s'); + $station_desc .= $station->[1]{rt_arr}->strftime(';%s'); + if ( $station->[1]{rt_dep} ) { + $station_desc + .= $station->[1]{sched_dep}->strftime(';%s'); + $station_desc .= $station->[1]{rt_dep}->strftime(';%s'); + } + else { + $station_desc .= ';0;0'; + } + } + else { + $station_desc .= ';0;0;0;0'; + } + push( @route, $station_desc ); + } + + return join( '|', @route ); + } + ); + $self->helper( 'get_user_status' => sub { my ( $self, $uid ) = @_; diff --git a/public/static/js/travelynx-actions.js b/public/static/js/travelynx-actions.js index 0df6989..92a0a58 100644 --- a/public/static/js/travelynx-actions.js +++ b/public/static/js/travelynx-actions.js @@ -1,14 +1,40 @@ +var j_departure = 0; var j_duration = 0; var j_arrival = 0; +var j_dest = ''; +var j_stops = []; function upd_journey_data() { $('.countdown').each(function() { - j_duration = $(this).data('duration'); - j_arrival = $(this).data('arrival'); + var journey_data = $(this).data('journey'); + if (journey_data) { + journey_data = journey_data.split(';'); + j_departure = parseInt(journey_data[0]); + j_arrival = parseInt(journey_data[1]); + j_duration = j_arrival - j_departure; + } + var journey_dest = $(this).data('dest'); + if (journey_dest) { + j_dest = journey_dest; + } + var stops = $(this).data('route'); + if (stops) { + stops = stops.split('|'); + j_stops = []; + for (var stop_id in stops) { + var stopdata = stops[stop_id].split(';'); + for (var i = 1; i < 5; i++) { + stopdata[i] = parseInt(stopdata[i]); + } + j_stops.push(stopdata); + } + } }); } function upd_countdown() { var now = Date.now() / 1000; - if (j_arrival > 0) { + if (j_departure > now) { + $('.countdown').text('Abfahrt in ' + Math.round((j_departure - now)/60) + ' Minuten'); + } else if (j_arrival > 0) { if (j_arrival > now) { $('.countdown').text('Ankunft in ' + Math.round((j_arrival - now)/60) + ' Minuten'); } else { @@ -16,6 +42,22 @@ function upd_countdown() { } } } +function hhmm(epoch) { + var date = new Date(epoch * 1000); + var h = date.getHours(); + var m = date.getMinutes(); + return (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m); +} +function odelay(sched, rt) { + if (sched < rt) { + return ' (+' + ((rt - sched) / 60) + ')'; + } + else if (sched == rt) { + return ''; + } + return ' (' + ((rt - sched) / 60) + ')'; +} + function tvly_run(link, req, err_callback) { var error_icon = 'error'; var progressbar = $('
'); @@ -74,6 +116,26 @@ function tvly_journey_progress() { progress = 1; } $('.progress .determinate').css('width', (progress * 100) + '%'); + + for (stop in j_stops) { + var stop_name = j_stops[stop][0]; + var sched_arr = j_stops[stop][1]; + var rt_arr = j_stops[stop][2]; + var sched_dep = j_stops[stop][3]; + var rt_dep = j_stops[stop][4]; + if (stop_name == j_dest) { + $('.next-stop').html(''); + break; + } + if ((rt_arr != 0) && (rt_arr - now > 0)) { + $('.next-stop').html(stop_name + '
' + hhmm(rt_arr) + odelay(sched_arr, rt_arr)); + break; + } + if ((rt_dep != 0) && (rt_dep - now > 0)) { + $('.next-stop').html(stop_name + '
' + hhmm(rt_arr) + ' → ' + hhmm(rt_dep) + odelay(sched_dep, rt_dep)); + break; + } + } setTimeout(tvly_journey_progress, 5000); } } diff --git a/public/static/js/travelynx-actions.min.js b/public/static/js/travelynx-actions.min.js index 8af5f9f..fdfeab8 100644 --- a/public/static/js/travelynx-actions.min.js +++ b/public/static/js/travelynx-actions.min.js @@ -1 +1 @@ -function upd_journey_data(){$(".countdown").each(function(){j_duration=$(this).data("duration"),j_arrival=$(this).data("arrival")})}function upd_countdown(){var t=Date.now()/1e3;j_arrival>0&&(j_arrival>t?$(".countdown").text("Ankunft in "+Math.round((j_arrival-t)/60)+" Minuten"):$(".countdown").text("Ziel erreicht"))}function tvly_run(t,a,e){var n='error',i=$('
');t.hide(),t.after(i),$.post("/action",a,function(a){a.success?$(location).attr("href",a.redirect_to):(M.toast({html:n+" "+a.error}),i.remove(),e&&e(),t.append(" "+n),t.show())})}function tvly_update(){$.get("/ajax/status_card.html",function(t){$(".statuscol").html(t),tvly_reg_handlers(),upd_journey_data(),setTimeout(tvly_update,4e4)}).fail(function(){$(".sync-failed-marker").css("display","block"),upd_countdown(),setTimeout(tvly_update,5e3)})}function tvly_update_public(){var t;$(".publicstatuscol").each(function(){t=$(this).data("user")}),$.get("/ajax/status/"+t+".html",function(t){$(".publicstatuscol").html(t),upd_journey_data(),setTimeout(tvly_update_public,4e4)}).fail(function(){$(".sync-failed-marker").css("display","block"),upd_countdown(),setTimeout(tvly_update_public,5e3)})}function tvly_journey_progress(){var t=Date.now()/1e3,a=0;j_duration>0&&(a=1-(j_arrival-t)/j_duration,a<0&&(a=0),a>1&&(a=1),$(".progress .determinate").css("width",100*a+"%"),setTimeout(tvly_journey_progress,5e3))}function tvly_reg_handlers(){$(".action-checkin").click(function(){var t=$(this);tvly_run(t,{action:"checkin",station:t.data("station"),train:t.data("train"),dest:t.data("dest")})}),$(".action-checkout").click(function(){var t=$(this),a={action:"checkout",station:t.data("station"),force:t.data("force")};tvly_run(t,a,function(){t.append(" – Ohne Echtzeitdaten auschecken?"),t.data("force",!0)})}),$(".action-undo").click(function(){var t=$(this);tvly_run(t,{action:"undo",undo_id:t.data("id")})}),$(".action-cancelled-from").click(function(){var t=$(this);tvly_run(t,{action:"cancelled_from",station:t.data("station"),train:t.data("train")})}),$(".action-cancelled-to").click(function(){var t=$(this);tvly_run(t,{action:"cancelled_to",station:t.data("station"),force:!0})}),$(".action-delete").click(function(){var t=$(this),a={action:"delete",id:t.data("id"),checkin:t.data("checkin"),checkout:t.data("checkout")};really_delete=confirm("Diese Zugfahrt wirklich löschen? Der Eintrag wird sofort aus der Datenbank entfernt und kann nicht wiederhergestellt werden."),really_delete&&tvly_run(t,a)}),$(".action-share").click(function(){navigator.share?(shareObj={text:$(this).data("text")},$(this).data("url")&&(shareObj.url=$(this).data("url")),navigator.share(shareObj)):$(this).data("url")&&(location.href=$(this).data("url"))}),!$(".action-share").length||navigator.share||$(".action-share").data("url")||$(".action-share").css("display","none")}var j_duration=0,j_arrival=0;$(document).ready(function(){tvly_reg_handlers(),$(".statuscol .autorefresh").length&&(upd_journey_data(),setTimeout(tvly_update,4e4),setTimeout(tvly_journey_progress,5e3)),$(".publicstatuscol .autorefresh").length&&(upd_journey_data(),setTimeout(tvly_update_public,4e4),setTimeout(tvly_journey_progress,5e3)),$("a[href]").click(function(){$("nav .preloader-wrapper").addClass("active")})}); +function upd_journey_data(){$(".countdown").each(function(){var t=$(this).data("journey");t&&(t=t.split(";"),j_departure=parseInt(t[0]),j_arrival=parseInt(t[1]),j_duration=j_arrival-j_departure);var a=$(this).data("dest");a&&(j_dest=a);var e=$(this).data("route");if(e){e=e.split("|"),j_stops=[];for(var n in e){for(var r=e[n].split(";"),o=1;o<5;o++)r[o]=parseInt(r[o]);j_stops.push(r)}}})}function upd_countdown(){var t=Date.now()/1e3;j_departure>t?$(".countdown").text("Abfahrt in "+Math.round((j_departure-t)/60)+" Minuten"):j_arrival>0&&(j_arrival>t?$(".countdown").text("Ankunft in "+Math.round((j_arrival-t)/60)+" Minuten"):$(".countdown").text("Ziel erreicht"))}function hhmm(t){var a=new Date(1e3*t),e=a.getHours(),n=a.getMinutes();return(e<10?"0"+e:e)+":"+(n<10?"0"+n:n)}function odelay(t,a){return t
');t.hide(),t.after(r),$.post("/action",a,function(a){a.success?$(location).attr("href",a.redirect_to):(M.toast({html:n+" "+a.error}),r.remove(),e&&e(),t.append(" "+n),t.show())})}function tvly_update(){$.get("/ajax/status_card.html",function(t){$(".statuscol").html(t),tvly_reg_handlers(),upd_journey_data(),setTimeout(tvly_update,4e4)}).fail(function(){$(".sync-failed-marker").css("display","block"),upd_countdown(),setTimeout(tvly_update,5e3)})}function tvly_update_public(){var t;$(".publicstatuscol").each(function(){t=$(this).data("user")}),$.get("/ajax/status/"+t+".html",function(t){$(".publicstatuscol").html(t),upd_journey_data(),setTimeout(tvly_update_public,4e4)}).fail(function(){$(".sync-failed-marker").css("display","block"),upd_countdown(),setTimeout(tvly_update_public,5e3)})}function tvly_journey_progress(){var t=Date.now()/1e3,a=0;if(j_duration>0){a=1-(j_arrival-t)/j_duration,a<0&&(a=0),a>1&&(a=1),$(".progress .determinate").css("width",100*a+"%");for(stop in j_stops){var e=j_stops[stop][0],n=j_stops[stop][1],r=j_stops[stop][2],o=j_stops[stop][3],i=j_stops[stop][4];if(e==j_dest){$(".next-stop").html("");break}if(0!=r&&r-t>0){$(".next-stop").html(e+"
"+hhmm(r)+odelay(n,r));break}if(0!=i&&i-t>0){$(".next-stop").html(e+"
"+hhmm(r)+" → "+hhmm(i)+odelay(o,i));break}}setTimeout(tvly_journey_progress,5e3)}}function tvly_reg_handlers(){$(".action-checkin").click(function(){var t=$(this);tvly_run(t,{action:"checkin",station:t.data("station"),train:t.data("train"),dest:t.data("dest")})}),$(".action-checkout").click(function(){var t=$(this),a={action:"checkout",station:t.data("station"),force:t.data("force")};tvly_run(t,a,function(){t.append(" – Ohne Echtzeitdaten auschecken?"),t.data("force",!0)})}),$(".action-undo").click(function(){var t=$(this);tvly_run(t,{action:"undo",undo_id:t.data("id")})}),$(".action-cancelled-from").click(function(){var t=$(this);tvly_run(t,{action:"cancelled_from",station:t.data("station"),train:t.data("train")})}),$(".action-cancelled-to").click(function(){var t=$(this);tvly_run(t,{action:"cancelled_to",station:t.data("station"),force:!0})}),$(".action-delete").click(function(){var t=$(this),a={action:"delete",id:t.data("id"),checkin:t.data("checkin"),checkout:t.data("checkout")};really_delete=confirm("Diese Zugfahrt wirklich löschen? Der Eintrag wird sofort aus der Datenbank entfernt und kann nicht wiederhergestellt werden."),really_delete&&tvly_run(t,a)}),$(".action-share").click(function(){navigator.share?(shareObj={text:$(this).data("text")},$(this).data("url")&&(shareObj.url=$(this).data("url")),navigator.share(shareObj)):$(this).data("url")&&(location.href=$(this).data("url"))}),!$(".action-share").length||navigator.share||$(".action-share").data("url")||$(".action-share").css("display","none")}var j_departure=0,j_duration=0,j_arrival=0,j_dest="",j_stops=[];$(document).ready(function(){tvly_reg_handlers(),$(".statuscol .autorefresh").length&&(upd_journey_data(),setTimeout(tvly_update,4e4),setTimeout(tvly_journey_progress,5e3)),$(".publicstatuscol .autorefresh").length&&(upd_journey_data(),setTimeout(tvly_update_public,4e4),setTimeout(tvly_journey_progress,5e3)),$("a[href]").click(function(){$("nav .preloader-wrapper").addClass("active")})}); diff --git a/templates/_checked_in.html.ep b/templates/_checked_in.html.ep index 87b94f6..8d59c82 100644 --- a/templates/_checked_in.html.ep +++ b/templates/_checked_in.html.ep @@ -5,8 +5,10 @@ Eingecheckt in <%= $journey->{train_type} %> <%= $journey->{train_no} %>

+ data-journey="<%= $journey->{real_departure}->epoch %>;<%= <%= $journey->{real_arrival}->epoch %>" + data-route="<%= journey_to_ajax_route($journey) %>" + data-dest="<%= $journey->{arr_name} %>" + > % if ($journey->{boarding_countdown} > 120) { Einfahrt in <%= sprintf('%.f', $journey->{boarding_countdown} / 60) %> Minuten
% } @@ -108,7 +110,7 @@ noch nicht bekannt % }
-
+
% for my $station (@{$journey->{route_after}}) { % if ($station->[0] eq $journey->{arr_name}) { % last; @@ -133,7 +135,7 @@
-
+
% for my $station (@{$journey->{route_after}}) { % if ($station->[0] eq $journey->{arr_name}) { % last; -- cgit v1.2.3