1- <%= form_for [@problem, @testdatum], :html => {: multipart => true} do |f| %>
1+ <%= form_for [@problem, @testdatum], :html => {multipart: true, id: 'testdata-form'}, remote: true, authenticity_token: true do |f| %>
22 <%= render partial: "shared/errors", locals: {errors: @testdatum.errors, item: 'testdatum'} %>
33
44 <div class ="form-group ">
5- <%= f . label :test_input , "input testdata" %> < br >
6- <%= @testdatum . test_input . to_s . split ( "/" ) . last ( 3 ) . join ( "/" ) if @testdatum . test_input %> < br >
5+ <%= f . label :test_input , "Input testdata" %>
6+ <% if @testdatum . test_input %>
7+ < br > <%= @testdatum . test_input . to_s . split ( "/" ) . last ( 3 ) . join ( "/" ) %>
8+ <% end %>
79 <%= f . file_field :test_input , :class => 'form-control flat' %>
810 </ div >
11+
912 < div class ="form-group ">
10- <%= f . label :test_output , "output testdata" %> < br >
11- <%= @testdatum . test_output . to_s . split ( "/" ) . last ( 3 ) . join ( "/" ) if @testdatum . test_output %> < br >
13+ <%= f . label :test_output , "Output testdata" %>
14+ <% if @testdatum . test_output %>
15+ < br > <%= @testdatum . test_output . to_s . split ( "/" ) . last ( 3 ) . join ( "/" ) %>
16+ <% end %>
1217 <%= f . file_field :test_output , :class => 'form-control flat' %>
1318 </ div >
14- < br >
1519 < div class ="form-group ">
1620 <%= f . label :time_limit , "Time Limit" %>
1721 <%= f . number_field :time_limit , :class => 'form-control flat' %>
3337 <%= f . hidden_field :problem_id %>
3438 </ div >
3539
36- < hr >
37-
38- < div class ="actions ">
39- <%= f . submit :class => 'btn btn-success btn-lg' %>
40+ < div class ="form-group flex " style ="display: flex; margin-bottom: 0.5em; ">
41+ < div class ="actions " style ="margin-right: 1em; flex: 0 0 0%; ">
42+ <%= f . submit :class => 'btn btn-success btn-lg' %>
43+ </ div >
44+ < div class ="fade " id ="progress-fade " style ="flex: 1 0 0%; ">
45+ < div class ="progress progress-striped active " role ="progressbar " style ="margin-bottom: 0.25em; border-radius: 4px; height: 20px; background: #f0faf0; ">
46+ < div id ="progress-inner-bar " class ="progress-bar progress-bar-success " style ="width: 0%; "> </ div >
47+ </ div >
48+ < div id ="progress-text " class ="progress-extended small "> </ div >
49+ </ div >
4050 </ div >
4151
4252<% end %>
53+
54+
55+ < script >
56+ $ ( function ( ) {
57+ $ ( '#testdata-form' ) . submit ( function ( event ) {
58+ event . preventDefault ( ) ;
59+ var _formatFileSize = function ( bytes ) {
60+ if ( typeof bytes !== 'number' ) {
61+ return '' ;
62+ }
63+ if ( bytes >= ( 1024 * 1024 * 1024 ) ) {
64+ return ( bytes / ( 1024 * 1024 * 1024 ) ) . toFixed ( 2 ) + ' GiB' ;
65+ }
66+ if ( bytes >= ( 1024 * 1024 ) ) {
67+ return ( bytes / ( 1024 * 1024 ) ) . toFixed ( 2 ) + ' MiB' ;
68+ }
69+ if ( bytes >= 1024 ) {
70+ return ( bytes / 1024 ) . toFixed ( 2 ) + ' KiB' ;
71+ }
72+ return ( bytes * 1.0 ) . toFixed ( 2 ) + ' byte' ;
73+ } ;
74+ var _formatTime = function ( seconds ) {
75+ var date = new Date ( seconds * 1000 ) , days = Math . floor ( seconds / 86400 ) ;
76+ days = days ? days + 'd ' : '' ;
77+ if ( date . getUTCHours ( ) > 1 ) {
78+ days = days + ( '0' + date . getUTCHours ( ) ) . slice ( - 2 ) + ':' ;
79+ }
80+ return (
81+ days +
82+ ( '0' + date . getUTCMinutes ( ) ) . slice ( - 2 ) +
83+ ':' +
84+ ( '0' + date . getUTCSeconds ( ) ) . slice ( - 2 )
85+ ) ;
86+ } ;
87+ var _formatPercentage = function ( floatValue ) {
88+ return ( floatValue * 100 ) . toFixed ( 2 ) + ' %' ;
89+ } ;
90+ var _renderProgress = function ( data ) {
91+ return (
92+ _formatPercentage ( data . loaded / data . total ) +
93+ ' | ' +
94+ _formatFileSize ( data . loaded ) +
95+ ' / ' +
96+ _formatFileSize ( data . total ) +
97+ ' | ETA ' +
98+ _formatTime ( ( data . total - data . loaded ) / ( data . byterate ) ) +
99+ ' | ' +
100+ _formatFileSize ( data . byterate ) +
101+ '/s'
102+ ) ;
103+ } ;
104+ var formData = new FormData ( this ) ;
105+ var lastUpdate = ( new Date ( ) . getTime ( ) ) - 500 ;
106+ var byterate = 0.0 ;
107+ var prevLoaded = 0 ;
108+ $ . ajax ( {
109+ type : 'POST' ,
110+ url : $ ( this ) . attr ( 'action' ) ,
111+ data : formData ,
112+ processData : false ,
113+ contentType : false ,
114+ xhr : function ( ) {
115+ var xhr = new window . XMLHttpRequest ( ) ;
116+ xhr . upload . onprogress = function ( evt ) {
117+ if ( evt . lengthComputable ) {
118+ var now = new Date ( ) . getTime ( ) ;
119+ $ ( '#progress-fade' ) . addClass ( 'in' ) ;
120+ if ( evt . loaded == evt . total ) {
121+ $ ( '#progress-inner-bar' ) . width ( '100%' ) ;
122+ $ ( '#progress-text' ) . text ( 'Processing...' ) ;
123+ } else if ( now - lastUpdate >= 500 ) {
124+ var curByterate = ( ( evt . loaded - prevLoaded ) / ( now - lastUpdate ) ) * 1000 ;
125+ byterate = byterate * 0.7 + curByterate * 0.3 ;
126+ evt . byterate = curByterate ;
127+ lastUpdate = now ;
128+ prevLoaded = evt . loaded ;
129+ $ ( '#progress-text' ) . text ( _renderProgress ( evt ) ) ;
130+ $ ( '#progress-inner-bar' ) . width ( ( evt . loaded / evt . total * 100 ) + '%' ) ;
131+ }
132+ }
133+ } ;
134+ return xhr ;
135+ } ,
136+ success : function ( data ) {
137+ document . open ( ) ;
138+ document . write ( data ) ;
139+ document . close ( ) ;
140+ } ,
141+ error : function ( xhr , status , error ) {
142+ $ ( '#progress-fade' ) . removeClass ( 'in' ) ;
143+ $ ( '#progress-inner-bar' ) . width ( '0%' ) ;
144+ } ,
145+ abort : function ( ) {
146+ $ ( '#progress-fade' ) . removeClass ( 'in' ) ;
147+ $ ( '#progress-inner-bar' ) . width ( '0%' ) ;
148+ } ,
149+ } ) ;
150+ } ) ;
151+ } ) ;
152+ </ script >
0 commit comments