...and the new files for the microservice validator
[scpubgit/stemmaweb.git] / root / js / fileparse.js
1 // General-purpose error-handling function.
2 // TODO make sure this gets used throughout, where appropriate.
3 function display_error( jqXHR, el ) {
4         var errmsg;
5         if( jqXHR.responseText == "" ) {
6                 errmsg = "perhaps the server went down?"
7         } else {
8                 var errobj;
9                 try {
10                         errobj = jQuery.parseJSON( jqXHR.responseText );
11                         errmsg = errobj.error;
12                 } catch ( parse_err ) {
13                         errmsg = "something went wrong on the server."
14                 }
15         }
16         var msghtml = $('<span>').attr('class', 'error').text( "An error occurred: " + errmsg );
17         $(el).empty().append( msghtml ).show();
18 }
19
20 // Event to enable the upload button when a file has been selected
21 function file_selected( e ) {
22         if( e.files.length == 1 ) {
23                 $('#upload_button').button('enable');
24                 $('#new_file_name_container').html( '<span id="new_file_name">' + e.files[0].name + '</span>' );
25         } else {
26                 $('#upload_button').button('disable');
27                 $('#new_file_name_container').html( '(Use \'pick file\' to select a tradition file to upload.)' );
28         }
29 }
30
31 // Implement our own AJAX method that uses the features of XMLHttpRequest2
32 // but try to let it have a similar interface to jquery.post
33 // The data var needs to be a FormData() object.
34 // The callback will be given a single argument, which is the response data
35 // of the given type.
36
37 function post_xhr2( url, data, cb, type ) {
38         if( !type ) {
39                 type = 'json';
40         }
41         var xhr = new XMLHttpRequest();
42         // Set the expected response type
43         if( type === 'data' ) {
44                 xhr.responseType = 'blob';
45         } else if( type === 'xml' ) {
46                 xhr.responseType = 'document';
47         } 
48         // Post the form
49         // Gin up an AJAX settings object
50         $.ajaxSetup({ url: url, type: 'POST' });
51         xhr.open( 'POST', url, true );
52         // Handle the results
53         xhr.onload = function( e ) {
54                 // Get the response and parse it
55                 // Call the callback with the response, whatever it was
56                 var xhrs = e.target;
57                 if( xhrs.status > 199 && xhrs.status < 300  ) { // Success
58                         var resp;
59                         if( type === 'json' ) {
60                                 resp = $.parseJSON( xhrs.responseText );
61                         } else if ( type === 'xml' ) {
62                                 resp = xhrs.responseXML;
63                         } else if ( type === 'text' ) {
64                                 resp = xhrs.responseText;
65                         } else {
66                                 resp = xhrs.response;
67                         }
68                         cb( resp );
69                 } else {
70                         // Trigger the ajaxError...
71                         _trigger_ajaxerror( e );
72                 }
73         };
74         xhr.onerror = _trigger_ajaxerror;
75         xhr.onabort = _trigger_ajaxerror;
76         xhr.send( data );
77 }
78
79 function _trigger_ajaxerror( e ) {
80         var xhr = e.target;
81         var thrown = xhr.statusText || 'Request error';
82         jQuery.event.trigger( 'ajaxError', [ xhr, $.ajaxSettings, thrown ]);
83 }
84
85 function upload_new () {
86         // Serialize the upload form, get the file and attach it to the request,
87         // POST the lot and handle the response.
88         var newfile = $('#new_file').get(0).files[0];
89         var reader = new FileReader();
90         reader.onload = function( evt ) {
91                 var data = new FormData();
92                 $.each( $('#new_tradition').serializeArray(), function( i, o ) {
93                                 data.append( o.name, o.value );
94                         });
95                 data.append( 'file', newfile );
96                 var upload_url = _get_url([ 'newtradition' ]);
97                 post_xhr2( upload_url, data, function( ret ) {
98                         if( ret.id ) {
99                                 $('#upload-collation-dialog').dialog('close');
100                                 refreshDirectory();
101                                 loadTradition( ret.id, ret.name, 1 );
102                         } else if( ret.error ) {
103                                 $('#upload_status').empty().append( 
104                                         $('<span>').attr('class', 'error').append( ret.error ) );
105                         }
106                 }, 'json' );
107         };
108         reader.onerror = function( evt ) {
109                 var err_resp = 'File read error';
110                 if( e.name == 'NotFoundError' ) {
111                         err_resp = 'File not found';
112                 } else if ( e.name == 'NotReadableError' ) {
113                         err_resp == 'File unreadable - is it yours?';
114                 } else if ( e.name == 'EncodingError' ) {
115                         err_resp == 'File cannot be encoded - is it too long?';
116                 } else if ( e.name == 'SecurityError' ) {
117                         err_resp == 'File read security error';
118                 }
119                 // Fake a jqXHR object that we can pass to our generic error handler.
120                 var jqxhr = { responseText: '{error:"' + err_resp + '"}' };
121                 display_error( jqxhr, $('#upload_status') );
122                 $('#upload_button').button('disable');
123         }
124         
125         reader.readAsBinaryString( newfile );
126 }
127
128 // Utility function to neatly construct an application URL
129 function _get_url( els ) {
130         return basepath + els.join('/');
131 }
132
133 // TODO Attach unified ajaxError handler to document
134 $(document).ready( function() {
135         // See if we have the browser functionality we need
136         // TODO Also think of a test for SVG readiness
137         if( !!window.FileReader && !!window.File ) {
138                 $('#compatibility_check').empty();
139         }
140
141         $('#upload-collation-dialog').dialog({
142                 autoOpen: false,
143                 height: 360,
144                 width: 480,
145                 modal: true,
146                 buttons: {
147                   upload: {
148                     text: 'Upload',
149                     id: 'upload_button',
150                     click: function() {
151                             $('#upload_status').empty();
152                             $('#upload_button').button("disable");
153                 upload_new();
154             }
155                   },
156                   pick_file: {
157                     text: 'Pick File',
158                     id: 'pick_file_button',
159                     click: function() {
160                 $('#new_file').click();
161             }
162                   },
163                   Cancel: function() {
164                     $('#upload-collation-dialog').dialog('close');
165                   }
166                 },
167                 open: function() {
168                         // Set the upload button to its correct state based on
169                         // whether a file is loaded
170                         file_selected( $('#new_file').get(0) );
171                         $('#upload_status').empty();
172                 }
173         }).ajaxError( function(event, jqXHR, ajaxSettings, thrownError) {
174                 // Reset button state
175                 file_selected( $('#new_file').get(0) );
176                 // Display error message if applicable
177         if( ajaxSettings.url.indexOf( 'newtradition' ) > -1 
178                 && ajaxSettings.type == 'POST' ) {
179                         display_error( jqXHR, $("#upload_status") );
180         }
181         });;
182         
183 });