add index page link to stexaminer and relmapper
[scpubgit/stemmaweb.git] / root / src / index.tt
1 [% WRAPPER header.tt
2         pagetitle = "Stemmaweb - Text tradition tools"
3         applicationjs = c.uri_for( 'js/componentload.js' )
4 %]
5     <script type="text/javascript">
6 var basepath = window.location.pathname
7 if( basepath.lastIndexOf('/') == basepath.length - 1 ) { 
8         basepath = basepath.slice( 0, basepath.length - 1) 
9 };
10 var textOnLoad = "[% withtradition %]";
11 var selectedTextID;
12 var selectedTextInfo;
13 var selectedStemmaID = -1;
14 var stemmata = [];
15
16 function refreshDirectory () {
17         var lmesg = $('#loading_message').clone();
18         $('#directory').empty().append( lmesg.contents() );
19     $('#directory').load( "[% c.uri_for( 'directory' ) %]", 
20         function(response, status, xhr) {
21                         if (status == "error") {
22                                 var msg = "An error occurred: ";
23                                 $("#directory").html(msg + xhr.status + " " + xhr.statusText);
24                         } else {
25                                 if( textOnLoad != "" ) {
26                                         // Call the click callback for the relevant text, if it is
27                                         // in the page.
28                                         $('#'+textOnLoad).click();
29                                         textOnLoad = "";
30                                 }
31                         }
32                 }
33         );
34 }
35
36 function start_upload_dialog() {
37     if( typeof uploader != 'undefined' ){ uploader.destroy() };
38     $('#upload-collation-dialog').dialog('option', 'attach_uploader')();
39     $('#upload_status').empty();
40     $('#upload_button').button('disable');
41     $('#upload-collation-dialog').dialog('open');
42 }
43
44 $(document).ready( function() {
45     // call out to load the directory div
46     $('#textinfo_container').hide();
47     $('#textinfo_waitbox').hide();
48         refreshDirectory();
49         
50         // Set up the textinfo edit dialog
51         $('#textinfo-edit-dialog').dialog({
52                 autoOpen: false,
53                 height: 200,
54                 width: 300,
55                 modal: true,
56                 buttons: {
57                         Save: function (evt) {
58                                 $("#edit_textinfo_status").empty();
59                                 $(evt.target).button("disable");
60                                 var requrl = "[% c.uri_for( '/textinfo' ) %]/" + selectedTextID;
61                                 var reqparam = $('#edit_textinfo').serialize();
62                                 $.post( requrl, reqparam, function (data) {
63                                         // Reload the selected text fields
64                                         selectedTextInfo = data;
65                                         load_textinfo();
66                                         // Reenable the button and close the form
67                                         $(evt.target).button("enable");
68                                         $('#textinfo-edit-dialog').dialog('close');
69                                 }, 'json' );
70                         },
71                         Cancel: function() {
72                                 $('#textinfo-edit-dialog').dialog('close');
73                         }
74                 },
75                 open: function() {
76                         $("#edit_textinfo_status").empty();
77                         // Populate the form fields with the current values
78                         // edit_(name, language, public, owner)
79                         $.each([ 'name', 'language', 'owner' ], function( idx, k ) {
80                                 var fname = '#edit_' + k;
81                                 // Special case: language Default is basically language null
82                                 if( k == 'language' && selectedTextInfo[k] == 'Default' ) {
83                                         $(fname).val( "" );
84                                 } else {
85                                         $(fname).val( selectedTextInfo[k] );
86                                 }
87                         });
88                         if( selectedTextInfo['public'] == true ) {
89                                 $('#edit_public').attr('checked','true');
90                         } else {
91                                 $('#edit_public').removeAttr('checked');
92                         }
93                 },
94         }).ajaxError( function(event, jqXHR, ajaxSettings, thrownError) {
95                 $(event.target).parent().find('.ui-button').button("enable");
96         if( ajaxSettings.url.indexOf( 'textinfo' ) > -1 
97                 && ajaxSettings.type == 'POST' ) {
98                         display_error( jqXHR, $("#edit_textinfo_status") );
99         }
100         });
101
102         
103         // Set up the stemma editor dialog
104         $('#stemma-edit-dialog').dialog({
105                 autoOpen: false,
106                 height: 700,
107                 width: 600,
108                 modal: true,
109                 buttons: {
110                         Save: function (evt) {
111                                 $("#edit_stemma_status").empty();
112                                 $(evt.target).button("disable");
113                                 var stemmaseq = $('#stemmaseq').val();
114                                 var requrl = "[% c.uri_for( '/stemma' ) %]/" + selectedTextID + "/" + stemmaseq;
115                                 var reqparam = { 'dot': $('#dot_field').val() };
116                                 // TODO We need to stash the literal SVG string in stemmata
117                                 // somehow. Implement accept header on server side to decide
118                                 // whether to send application/json or application/xml?
119                                 $.post( requrl, reqparam, function (data) {
120                                         // We received a stemma SVG string in return. 
121                                         // Update the current stemma sequence number
122                                         selectedStemmaID = data.stemmaid;
123                                         // Stash the answer in our SVG array
124                                         stemmata[selectedStemmaID] = data.stemmasvg;
125                                         // Display the new stemma
126                                         load_stemma( selectedStemmaID );
127                                         // Reenable the button and close the form
128                                         $(evt.target).button("enable");
129                                         $('#stemma-edit-dialog').dialog('close');
130                                 }, 'json' );
131                         },
132                         Cancel: function() {
133                                 $('#stemma-edit-dialog').dialog('close');
134                         }
135                 },
136                 open: function(evt) {
137                         $("#edit_stemma_status").empty();
138                         var stemmaseq = $('#stemmaseq').val();
139                         if( stemmaseq == 'n' ) {
140                                 // If we are creating a new stemma, populate the textarea with a
141                                 // bare digraph.
142                                 $(evt.target).dialog('option', 'title', 'Add a new stemma')
143                                 $('#dot_field').val( "digraph stemma {\n\n}" );
144                         } else {
145                                 // If we are editing a stemma, grab its stemmadot and populate the
146                                 // textarea with that.
147                                 $(evt.target).dialog('option', 'title', 'Edit selected stemma')
148                                 $('#dot_field').val( 'Loading, please wait...' );
149                                 var doturl = "[% c.uri_for( '/stemmadot' ) %]/" + selectedTextID + "/" + stemmaseq;
150                                 $.getJSON( doturl, function (data) {
151                                         // Re-insert the line breaks
152                                         var dotstring = data.dot.replace(/\|n/gm, "\n");                                        
153                                         $('#dot_field').val( dotstring );
154                                 });
155                         }
156                 },
157         }).ajaxError( function(event, jqXHR, ajaxSettings, thrownError) {
158                 $(event.target).parent().find('.ui-button').button("enable");
159         if( ajaxSettings.url.indexOf( 'stemma' ) > -1 
160                 && ajaxSettings.type == 'POST' ) {
161                         display_error( jqXHR, $("#edit_stemma_status") );
162         }
163         });
164                 
165         $('#upload-collation-dialog').dialog({
166                 autoOpen: false,
167                 height: 325,
168                 width: 480,
169                 modal: true,
170                 buttons: {
171                   pick: {
172                     text: "Pick File",
173                     id: "pick_uploadfile_button",
174                     click: function() {}       
175                   },
176                   upload: {
177                     text: 'Upload',
178                     id: 'upload_button',
179                     click: function() {
180                             $('#upload_status').empty();
181                 uploader.start();
182                 return false;
183             }
184                   },
185                   Cancel: function() {
186                     $('#upload-collation-dialog').dialog('close');
187                   }
188                 },
189                 attach_uploader: function() {
190                     create_uploader( "[% c.uri_for ( '/newtradition' ) %]" );
191                     $('#filelist').empty().html( 'Use the \'Pick\' button to choose a source file…' );
192                 }
193         });
194         
195         $('#stemma_graph').mousedown( function(evt) {
196         evt.stopPropagation();
197         $('#stemma_graph').data( 'mousedown_xy', [evt.clientX, evt.clientY] );
198         $('body').mousemove( function(evt) {
199             mouse_scale = 1; // for now, was:  mouse_scale = svg_root_element.getScreenCTM().a;
200             dx = (evt.clientX - $('#stemma_graph').data( 'mousedown_xy' )[0]) / mouse_scale;
201             dy = (evt.clientY - $('#stemma_graph').data( 'mousedown_xy' )[1]) / mouse_scale;
202             $('#stemma_graph').data( 'mousedown_xy', [evt.clientX, evt.clientY] );
203             var svg_root = $('#stemma_graph svg').svg().svg('get').root();
204             var g = $('g.graph', svg_root).get(0);
205             current_translate = g.getAttribute( 'transform' ).split(/translate\(/)[1].split(')',1)[0].split(' ');
206             new_transform = g.getAttribute( 'transform' ).replace( /translate\([^\)]*\)/, 'translate(' + (parseFloat(current_translate[0]) + dx) + ' ' + (parseFloat(current_translate[1]) + dy) + ')' );
207             g.setAttribute( 'transform', new_transform );
208             evt.returnValue = false;
209             evt.preventDefault();
210             return false;
211         });
212         $('body').mouseup( function(evt) {
213             $('body').unbind('mousemove');
214             $('body').unbind('mouseup');
215         });
216         });
217          
218         $('#stemma_graph').mousewheel(function (event, delta) {
219         event.returnValue = false;
220         event.preventDefault();
221         if (!delta || delta == null || delta == 0) delta = event.originalEvent.wheelDelta;
222         if (!delta || delta == null || delta == 0) delta = -1 * event.originalEvent.detail;
223         if( delta < -9 ) { delta = -9 }; 
224         var z = 1 + delta/10;
225         z = delta > 0 ? 1 : -1;
226         var svg_root = $('#stemma_graph svg').svg().svg('get').root();
227         var g = $('g.graph', svg_root).get(0);
228         if (g && ((z<1 && (g.getScreenCTM().a * start_element_height) > 4.0) || (z>=1 && (g.getScreenCTM().a * start_element_height) < 1000))) {
229             var scaleLevel = z/10;
230             current_scale = parseFloat( g.getAttribute( 'transform' ).split(/scale\(/)[1].split(')',1)[0].split(' ')[0] );
231             new_transform = g.getAttribute( 'transform' ).replace( /scale\([^\)]*\)/, 'scale(' + (current_scale + scaleLevel) + ')' );
232             g.setAttribute( 'transform', new_transform );
233         }
234     });
235     
236 });
237     </script>
238
239 [% END %]
240
241     <div id="topbanner">
242       <h1>Stemmaweb - a collection of tools for analysis of collated texts</h1>
243       <span class="mainnav">[% IF c.user_exists %]Hello! [% c.user.get_object.email %] <a class="navlink" href="[% c.uri_for( '/logout' ) %]">Sign out</a> | [% ELSE %]<a class="navlink" onclick="window.open('[% c.uri_for( '/login' ) %]', 'loginwindow', 'height=385,width=445')">Login</a> | [% END %]<a class="navlink" href="[% c.uri_for( 'about.html' ) %]">About</a> </span>
244     </div>
245     <div id="directory_container">
246       <h2>Text directory</h2>
247       <div id="directory"></div>
248 [% IF c.user_exists -%]
249           <div class="button" id="new_trad_button" onClick="start_upload_dialog();">
250             <span>Add a new text tradition</span>
251           </div>
252 [% END %]
253     </div>
254     <div id="textinfo_waitbox">
255         <h3>Loading tradition information, please wait...</h3>
256         <img src="[% c.uri_for( 'images', 'ajax-loader.gif' ) %]" alt="Loading tradition info..." />
257     </div>
258     <div id="textinfo_container">
259       <div id="textinfo_load_status"></div>
260       <h2>Text <span class="texttitle"></span></h2>
261       <form id="open_textinfo_edit" action="" method="GET" name="edit_textinfo">
262         <div class="button" id="edit_textinfo_button"
263                 onClick="$('#textinfo-edit-dialog').dialog('open')">
264           <span>Modify information about this tradition</span>
265         </div>
266       </form>
267       <ul>
268           <li>is owned by <span id="owner_id"></span></li>
269           <li>is <span id="not_public"></span>public</li>
270           <li>has <span id="marked_language"></span> as its primary language</li>
271               <li>has <span id="witness_num"></span> witnesses: <span id="witness_list"></span></li>
272       </ul>
273       
274       <div id="textinfo_container_buttons">
275           <form id="stemma_pager" action="" method="GET" name="stemma_pager">
276             <div id="stemma_pager_buttons">
277               <div class="pager_left_button" id="stemma_pager_left_button"></div>
278               <div class="pager_right_button" id="stemma_pager_right_button"></div>
279             </div>
280           </form>
281           <form id="open_stemma_add" action="" method="GET" name="add_new_stemma">
282             <div class="button" id="stemma_add_button" 
283                 onClick="$('#stemmaseq').val('n'); $('#stemma-edit-dialog').dialog('open');">
284                   <span>Add a new stemma</span>
285             </div>
286           </form>
287           <form id="open_stemma_edit" action="" method="GET" name="edit_current_stemma">
288             <div class="button" id="stemma_edit_button" 
289                 onClick="$('#stemmaseq').val(selectedStemmaID); $('#stemma-edit-dialog').dialog('open');">
290                   <span>Edit this stemma</span>
291             </div>
292           </form>
293           <form id="run_stexaminer" action="" method="GET" name="run_stexaminer">
294             <div class="button" id="stexaminer_button" onClick="$('#run_stexaminer').submit()">
295                   <span>Examine variants against this stemma</span>
296             </div>
297           </form>
298           <form id="run_relater" action="" method="GET" name="run_relater">
299             <div class="button" id="relater_button" onClick="$('#run_relater').submit()">
300               <span>Run relationship mapper</span>
301             </div>
302           </form>
303       </div>
304       <div id="stemma_graph"></div>
305     </div>
306
307     <!-- Interim 'loading' message for directory box -->
308     <div id="loading_message">
309         <h3>Loading texts, please wait...</h3>
310         <img src="[% c.uri_for( 'images', 'ajax-loader.gif' ) %]" alt="Loading tradition list..."/>
311     </div>
312     
313     <!-- Textinfo editor dialog -->
314     <div id="textinfo-edit-dialog" title="Edit information about this tradition">
315       <div id="textinfo_edit_container">
316         <form id="edit_textinfo">
317                 <label for="edit_name">Tradition name: </label>
318                 <input id="edit_name" type="text" size="30" name="name"/><br/>
319                 <label for="edit_language">Language: </label>
320                 <input id="edit_language" type="text" size="12" name="language"/>
321                 <label for="edit_public">Publicly viewable: </label>
322                 <input id="edit_public" type="checkbox" name="public"/><br/>
323 [% IF c.user_exists -%]
324 [% IF c.user.get_object.is_admin -%]
325                 <label for="edit_owner">Tradition owner: </label>
326                 <input id="edit_owner" type="text" size="30" name="owner"/><br/>
327 [% END -%]
328 [% END -%]
329                 </form>
330                 <div id="edit_textinfo_status"></div>
331           </div>
332     </div>
333     
334     <!-- Stemma dot editor dialog, simple textarea for now -->
335     <div id="stemma-edit-dialog">
336       <div id="stemma_edit_container">
337         <form id="edit_stemma">
338                 <label for="dot_field">Dot definition for this stemma: </label><br/>
339                 <textarea id="dot_field" rows="30" cols="40"></textarea>
340                 <input id="stemmaseq" type="hidden" name="stemmaseq" val="n"/>
341                         <div id="edit_instructions">
342                                 <p>All definitions begin with the line
343                                         <pre>digraph stemma {</pre>
344                                 and end with the line 
345                                         <pre>}</pre>Please do not change these lines.</p>
346                                 <p>First list each witness in your stemma, whether extant or lost /
347                                 reconstructed / hypothetical, and assign them a class of either "extant"
348                                 or "hypothetical". For example:</p><pre>  
349         α [ class=hypothetical ]
350         C [ class=extant ]
351                                 </pre>
352                                 <p>Next, list the direct links between witnesses, one per line. For example, if 
353                                 witness C descends directly from witness α, note it as follows:</p><pre>
354         α -> C
355                                 </pre>
356                                 <p>A witness may be the exemplar for any number of other witnesses, whether 
357                                 extant or not; likewise, a witness may inherit from any number of other 
358                                 witnesses. Use as may "A -> B" pairings as necessary to describe the links.</p>
359                         </div>
360         </form>
361         <div id="edit_stemma_status"></div>
362       </div>
363     </div>
364
365     <!-- File upload dialog box -->
366     <div id="upload-collation-dialog" title="Upload a collation">
367       <div id="upload_container">
368         <form id="new_tradition">
369             <label for="new_name">Name of this text / tradition: </label>
370             <input id="new_name" type="text" name="name" size="40"/><br/>
371             <label for="new_lang">Primary language of the text: </label>
372             <input id="new_lang" type="text" name="language" size="20"/><br/>
373             <label for="new_public">Allow public display: </label>
374             <input id="new_public" name="public" type="checkbox"/><br/>
375             <div id="filelist"></div>
376         <form>
377         <div id="upload_status"></div>
378         <div>
379           <h4>Supported file types / extensions:</h4>
380           <ul>
381             <li>*.txt - spreadsheet collation, tab-separated values</li>
382             <li>*.csv - spreadsheet collation, comma-separated values</li>
383             <li>*.xls - spreadsheet collation, Excel 97-2004 format</li>
384             <li>*.xlsx - spreadsheet collation, Excel 2007 XML format</li>
385             <li>*.xml - TEI XML parallel segmentation format</li>
386             <li>*.xml - TEI XML export from Classical Text Editor</li>
387             <li>*.xml - GraphML export from the CollateX tool</li>
388           </ul>
389           <p>All spreadsheet collations should be arranged with the witness sigla in the first row, and the words aligned by row each in its correct witness column.</p>
390         </div>
391       </div>
392     </div>    
393 [% PROCESS footer.tt %]