stexaminer now working to my satisfaction
Tara L Andrews [Wed, 27 Jun 2012 01:45:06 +0000 (03:45 +0200)]
stemmaweb/lib/stemmaweb/Controller/Stexaminer.pm
stemmaweb/root/css/stexaminer.css
stemmaweb/root/js/stexaminer.js
stemmaweb/root/src/stexaminer.tt

index a0f4fcb..d2aa261 100644 (file)
@@ -1,9 +1,12 @@
 package stemmaweb::Controller::Stexaminer;
 use Moose;
 use namespace::autoclean;
+use Encode qw/ decode_utf8 /;
 use File::Temp;
 use JSON;
 use Text::Tradition::Analysis qw/ run_analysis wit_stringify /;
+use Text::Tradition::Collation;
+use Text::Tradition::Stemma;
 
 BEGIN { extends 'Catalyst::Controller' }
 
@@ -18,12 +21,12 @@ The stemma analysis tool with the pretty colored table.
 
 =head1 METHODS
 
+=head2 index
+
  GET stexaminer/$textid
  
 Renders the application for the text identified by $textid.
 
-=head2 index
-
 =cut
 
 sub index :Path :Args(1) {
@@ -32,8 +35,8 @@ sub index :Path :Args(1) {
        my $tradition = $m->tradition( $textid );
        if( $tradition->stemma_count ) {
                my $stemma = $tradition->stemma(0);
-               # TODO Think about caching the stemma in a session 
-               $c->stash->{svg} = $stemma->as_svg;
+               $c->stash->{svg} = $stemma->as_svg( { size => [ 600, 350 ] } );
+               $c->stash->{graphdot} = $stemma->editable({ linesep => ' ' });
                $c->stash->{text_title} = $tradition->name;
                $c->stash->{template} = 'stexaminer.tt'; 
                # TODO Run the analysis as AJAX from the loaded page.
@@ -60,6 +63,34 @@ sub index :Path :Args(1) {
        }
 }
 
+=head2 graphsvg
+
+  POST stexaminer/graphsvg
+       dot: <stemmagraph dot string> 
+       layerwits: [ <a.c. witnesses ] 
+  
+Returns an SVG string of the given graph, extended to include the given 
+layered witnesses.
+
+=cut
+
+sub graphsvg :Local {
+       my( $self, $c ) = @_;
+       my $dot = $c->request->param('dot');
+       my @layerwits = $c->request->param('layerwits[]');
+       open my $stemma_fh, '<', \$dot;
+       binmode( $stemma_fh, ':encoding(UTF-8)' );
+       my $emptycoll = Text::Tradition::Collation->new();
+       my $tempstemma = Text::Tradition::Stemma->new( 
+               collation => $emptycoll, 'dot' => $stemma_fh );
+       my $svgopts = { size => [ 600, 350 ] };
+       if( @layerwits ) {
+               $svgopts->{'layerwits'} = \@layerwits;
+       }
+       $c->stash->{'result'} = $tempstemma->as_svg( $svgopts );
+       $c->forward('View::SVG');
+}
+
 =head2 end
 
 Attempt to render a view, if needed.
index 92c8037..760fbb2 100644 (file)
@@ -1,16 +1,16 @@
 #variants_table {
     float: left;
     width: 90%;
-    height: 90px;
+    height: 190px;
     border: 1px #c6dcf1 solid;
     margin-bottom: 20px;
     overflow: auto;
 }
 #stemma_graph {
-    height: 450px;
+    height: 350px;
     clear: both;
     float: left;
-    width: 700px;
+    width: 600px;
     text-align: center;
     border: 1px #c6dcf1 solid;
 }
     position: relative;
     top: -15px;
 }
+.reading_statistics {
+       margin: 7pt;
+       border-bottom: 1px solid #488dd2;
+}
+.readinglabel {
+       font-weight: bold;
+}
+.readingroots {
+       font-weight: bold;
+       color: #488dd2;
+}
+.reading_copied {
+       color: #33dd33;
+}
+.reading_changed {
+       color: #dd3333;
+}
 .template {
        display: none;
 }
index 106edf3..b38d842 100644 (file)
@@ -1,5 +1,26 @@
 var colors = ['#ffeeaa','#afc6e9','#d5fff6','#ffccaa','#ffaaaa','#e5ff80','#e5d5ff','#ffd5e5'];
 var row_triggered = false;
+var original_svg;
+
+function handle_row_click( row ) {
+       var ridx = row.parent().parent().index()
+       var rs = readingstats[ridx];
+    var imghtml = '<img src="../images/ajax-loader.gif" alt="Loading SVG..."/>'
+    $('#stemma_graph').empty();
+    $('#stemma_graph').append( imghtml );
+       if( rs.layerwits ) {
+               var stemma_form = { 'dot': graphdot, 'layerwits': rs.layerwits };
+               $('#stemma_graph').load( 'graphsvg', stemma_form, function() {
+                       color_row( row );
+                       show_stats( rs );
+               });
+       } else {
+               $('#stemma_graph').empty();
+               $('#stemma_graph').append( original_svg );
+               color_row( row );
+               show_stats( rs );
+       }
+}
 
 function color_row( row ) {
     row_triggered = true;
@@ -38,14 +59,13 @@ function color_nodes( column_index, arr_node_ids, arr_greynode_ids ) {
   });
 }
 
-function show_stats( row_index ) {
-       var rs = readingstats[row_index];
+function show_stats( rs ) {
        var rshtml = $('#stats_template').clone();
        rshtml.find('#statrank').append( rs.id );
        $.each( rs.readings, function( idx, rdghash ) {
                var readinglabel = rdghash.readingid;
                if( rdghash.text ) {
-                       readinglabel += ' (' + rdghash.text + ')';
+                       readinglabel = rdghash.text;
                }
                var readingroots = rdghash.independent_occurrence.join( ', ' );
                var rdgstats = $('#reading_template').clone();
@@ -76,3 +96,8 @@ function show_stats( row_index ) {
        $('#row_statistics').empty();
        $('#row_statistics').append( rshtml.contents() );
 };
+
+// Save the original unextended SVG for when we need it.
+$(document).ready(function () {
+       original_svg = $('#stemma_graph > svg').clone();
+});
index 10c4632..25f1b32 100644 (file)
@@ -5,6 +5,7 @@
 %]
 <script type="text/javascript">
 var readingstats = [% reading_statistics %];
+var graphdot = '[% graphdot %]';
 </script>
 [% END -%]
     <h1>Stexaminer</h1>
@@ -16,18 +17,20 @@ var readingstats = [% reading_statistics %];
 [% END -%]
      </table>
     </div>
-    <div id="stemma_graph">
-      [% svg %]
-    </div>
-    <div id="row_statistics">
-      <h3>Aggregate text statistics</h3>
-      <ul>
-       <li>Total number of variant locations analyzed: [% total %]</li>
-        <li>Number of fully genealogical locations: [% genealogical %]</li>
-        <li>Number of readings that conflict with the stemma: [% conflict %]</li>
-        <li>Genealogical reading transitions by relationship type: [% todo %]</li>
-      </ul>
-      <p>(Choose a row in the table to display statistics about individual readings.)</p>
+    <div>
+               <div id="stemma_graph">
+                 [% svg %]
+               </div>
+               <div id="row_statistics">
+                 <h3>Aggregate text statistics</h3>
+                 <ul>
+                       <li>Total number of variant locations analyzed: [% total %]</li>
+                       <li>Number of fully genealogical locations: [% genealogical %]</li>
+                       <li>Number of readings that conflict with the stemma: [% conflict %]</li>
+                       <li>Genealogical reading transitions by relationship type: [% todo %]</li>
+                 </ul>
+                 <p>(Choose a row in the table to display statistics about individual readings.)</p>
+               </div>
     </div>
     
     <div id="stats_template" class="template">
@@ -35,9 +38,9 @@ var readingstats = [% reading_statistics %];
            <!-- reading_template will be appended here for each reading -->
     </div>
     
-       <div id="reading_template" class="template">  
+       <div id="reading_template" class="template">
                <div class="reading_statistics">
-                       <span class="readinglabel"></span> - copied <span class="reading_copied"></span> times, changed <span class="reading_changed"></span> times<br/>
+                       <span class="readinglabel"></span> - copied <span class="reading_copied"></span> time(s), changed <span class="reading_changed"></span> time(s)<br/>
                        Reading root(s) at <span class="readingroots"></span><br/>
                        <!-- reading_parent_template will be appended here if there are parents -->
                </div>
@@ -57,7 +60,7 @@ var readingstats = [% reading_statistics %];
 [% SET rowclass = 'class="genealogical"' IF row.genealogical -%]
 [% SET rowclass = 'class="coincidental"' UNLESS row.genealogical -%]
         <tr [% rowclass %]>
-          <th><span class="rowid" onclick="color_row($(this));show_stats($(this).parent().parent().index())">[% row.id %]</span></th>
+          <th><span class="rowid" onclick="handle_row_click($(this))">[% row.id %]</span></th>
 [% FOREACH reading IN row.readings -%]
 [% SET cellclass = 'clickable conflict' IF reading.conflict -%]
 [% SET cellclass = 'clickable' IF !reading.conflict -%]