X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=root%2Fjs%2Frelationship.js;h=8eb8f80418317e9c9493e844a44fde43d0c71408;hb=51ca18ee409cde7cd9d70c147001294ec68006ca;hp=c84b9549c0f022fa64535ab7f494303d468ec190;hpb=485c70ec052eb34891627e7a086edf47eb43aa66;p=scpubgit%2Fstemmaweb.git diff --git a/root/js/relationship.js b/root/js/relationship.js index c84b954..8eb8f80 100644 --- a/root/js/relationship.js +++ b/root/js/relationship.js @@ -226,9 +226,8 @@ function svgEnlargementLoaded() { $.getJSON( rdgpath, function( data ) { readingdata = data; $('#svgenlargement ellipse').each( function( i, el ) { color_inactive( el ) }); - // detach_node(null); + $('#loading_overlay').hide(); }); - $('#loading_overlay').hide(); }); //initialize marquee @@ -254,18 +253,19 @@ function add_relations( callback_fn ) { $.getJSON( textrelpath, function(data) { $.each(data, function( index, rel_info ) { var type_index = $.inArray(rel_info.type, rel_types); - var source_found = get_ellipse( rel_info.source ); - var target_found = get_ellipse( rel_info.target ); + var source_found = get_ellipse( rel_info.source_id ); + var target_found = get_ellipse( rel_info.target_id ); if( type_index != -1 && source_found.size() && target_found.size() ) { - var relation = relation_manager.create( rel_info.source, rel_info.target, type_index ); - relation.data( 'type', rel_info.type ); - relation.data( 'scope', rel_info.scope ); - relation.data( 'note', rel_info.note ); + var relation = relation_manager.create( rel_info.source_id, rel_info.target_id, type_index ); + // Save the relationship data too. + $.each( rel_info, function( k, v ) { + relation.data( k, v ); + }); if( editable ) { - var node_obj = get_node_obj(rel_info.source); + var node_obj = get_node_obj(rel_info.source_id); node_obj.set_selectable( false ); node_obj.ellipse.data( 'node_obj', null ); - node_obj = get_node_obj(rel_info.target); + node_obj = get_node_obj(rel_info.target_id); node_obj.set_selectable( false ); node_obj.ellipse.data( 'node_obj', null ); } @@ -291,19 +291,11 @@ function node_obj(ellipse) { this.ellipse = ellipse; var self = this; - this.ox = 0; - this.oy = 0; this.x = 0; this.y = 0; this.dx = 0; this.dy = 0; this.node_elements = node_elements_for(self.ellipse); - - if( $(self.ellipse).data( 'org_translate' ) != null ) { - var org_translate = $(self.ellipse).data( 'org_translate' ); - this.ox = org_translate[0]; - this.oy = org_translate[1]; - } this.get_id = function() { return $(self.ellipse).parent().attr('id') @@ -376,8 +368,10 @@ function node_obj(ellipse) { var target_node_text = $('ellipse[fill="#ffccff"]').siblings("text").text(); $('#source_node_id').val( source_node_id ); $('#source_node_text').val( source_node_text ); + $('.rel_rdg_a').text( "'" + source_node_text + "'" ); $('#target_node_id').val( target_node_id ); $('#target_node_text').val( target_node_text ); + $('.rel_rdg_b').text( "'" + target_node_text + "'" ); $('#dialog-form').dialog( 'open' ); }; $('body').unbind('mousemove'); @@ -414,15 +408,21 @@ function node_obj(ellipse) { }); } + this.reposition = function( dx, dy ) { + $.each( self.node_elements, function(index, value) { + value.reposition( dx, dy ); + } ); + } + this.move_elements = function() { $.each( self.node_elements, function(index, value) { - value.move( ( self.ox + self.dx ) , ( self.oy + self.dy ) ); + value.move( self.dx, self.dy ); } ); } this.reset_elements = function() { $.each( self.node_elements, function(index, value) { - value.move( self.ox, self.oy ); + value.reset(); } ); } @@ -433,24 +433,30 @@ function node_obj(ellipse) { this.get_witnesses = function() { return readingdata[self.get_id()].witnesses } - - this.relocate = function( dx, dy ) { - self.ox = self.ox + dx; - self.oy = self.oy + dy; - $(self.ellipse).data( 'org_translate', [self.ox, self.oy] ); - self.move_elements(); - } - + self.set_selectable( true ); } function svgshape( shape_element ) { this.shape = shape_element; + this.reposx = 0; + this.reposy = 0; + this.repositioned = this.shape.parent().data( 'repositioned' ); + if( this.repositioned != null ) { + this.reposx = this.repositioned[0]; + this.reposy = this.repositioned[1]; + } + this.reposition = function (dx, dy) { + this.move( dx, dy ); + this.reposx = this.reposx + dx; + this.reposy = this.reposy + dy; + this.shape.parent().data( 'repositioned', [this.reposx,this.reposy] ); + } this.move = function(dx,dy) { - this.shape.attr( "transform", "translate(" + dx + " " + dy + ")" ); + this.shape.attr( "transform", "translate( " + (this.reposx + dx) + " " + (this.reposy + dy) + " )" ); } this.reset = function() { - this.shape.attr( "transform", "translate( 0, 0 )" ); + this.shape.attr( "transform", "translate( " + this.reposx + " " + this.reposy + " )" ); } this.grey_out = function(filter) { if( this.shape.parent(filter).size() != 0 ) { @@ -469,14 +475,24 @@ function svgpath( path_element, svg_element ) { this.path = path_element; this.x = this.path.x; this.y = this.path.y; + + this.reposition = function (dx, dy) { + this.x = this.x + dx; + this.y = this.y + dy; + this.path.x = this.x; + this.path.y = this.y; + } + this.move = function(dx,dy) { this.path.x = this.x + dx; this.path.y = this.y + dy; } + this.reset = function() { this.path.x = this.x; this.path.y = this.y; } + this.grey_out = function(filter) { if( this.svg_element.parent(filter).size() != 0 ) { this.svg_element.attr('stroke', '#e5e5e5'); @@ -591,6 +607,19 @@ function relation_factory() { this.showinfo = function(relation) { $('#delete_relation_type').text( relation.data('type') ); $('#delete_relation_scope').text( relation.data('scope') ); + $('#delete_relation_attributes').empty(); + if( relation.data( 'a_derivable_from_b' ) ) { + $('#delete_relation_attributes').append( + "'" + relation.data('source_text') + "' derivable from '" + relation.data('target_text') + "'
"); + } + if( relation.data( 'b_derivable_from_a' ) ) { + $('#delete_relation_attributes').append( + "'" + relation.data('target_text') + "' derivable from '" + relation.data('source_text') + "'
"); + } + if( relation.data( 'non_independent' ) ) { + $('#delete_relation_attributes').append( + "Variance unlikely to arise coincidentally
"); + } if( relation.data( 'note' ) ) { $('#delete_relation_note').text('note: ' + relation.data( 'note' ) ); } @@ -642,8 +671,7 @@ function draw_relation( source_id, target_id, relation_color ) { var sy = parseInt( source_ellipse.attr('cy') ); var ex = parseInt( target_ellipse.attr('cx') ); var ey = parseInt( target_ellipse.attr('cy') ); - var relation = svg.group( $("#svgenlargement svg g"), - { 'class':'relation', 'id':relation_id } ); + var relation = svg.group( $("#svgenlargement svg g"), { 'class':'relation', 'id':relation_id } ); svg.title( relation, source_id + '->' + target_id ); svg.path( relation, path.move( sx, sy ).curveC( sx + (2*rx), sy, ex + (2*rx), ey, ex, ey ), {fill: 'none', stroke: relation_color, strokeWidth: 4}); var relation_element = $('#svgenlargement .relation').filter( ':last' ); @@ -652,15 +680,19 @@ function draw_relation( source_id, target_id, relation_color ) { } function detach_node( readings ) { - - // This method is work in progress - // Todos: - // 1) Unproven/untested: readings.each will get us in trouble most likely for - // duplicating edges in a strand that both are incoming and outgoing - // like b and c in -i-> a -ii-> b -iii-> c -iv-> - // 2) Added edges and nodes look rough and unsmoothed, what the f.? - // - + // separate out the deleted relationships, discard for now + if( 'DELETED' in readings ) { + // Remove each of the deleted relationship links. + $.each( readings['DELETED'], function( idx, pair ) { + var relation_id = get_relation_id( pair[0], pair[1] ); + var relation = $( jq( relation_id ) ); + if( relation.size() == 0 ) { + relation_id = get_relation_id( pair[1], pair[0] ); + } + relation_manager.remove( relation_id ); + }); + delete readings['DELETED']; + } // add new node(s) $.extend( readingdata, readings ); // remove from existing readings the witnesses for the new nodes/readings @@ -711,7 +743,7 @@ function detach_node( readings ) { if( incoming_remaining.length > 0 ) { $.each( edges, function( index, edge ) { if( edge.get_label() == 'majority' && edge.is_incoming ) { - detached_edges.push( edge.clone_for( outgoing_remaining ) ); + detached_edges.push( edge.clone_for( incoming_remaining ) ); } } ); } @@ -734,16 +766,19 @@ function detach_node( readings ) { duplicate_node = get_ellipse( reading.orig_rdg ).parent().clone(); duplicate_node.attr( 'id', node_id ); duplicate_node.children( 'title' ).text( node_id ); - duplicate_node_data = get_ellipse( reading.orig_rdg ).data( 'org_translate' ); + + // This needs somehow to move to node or even to shapes! #repositioned + duplicate_node_data = get_ellipse( reading.orig_rdg ).parent().data( 'repositioned' ); if( duplicate_node_data != null ) { - duplicate_node.children( 'ellipse' ).data( 'org_translate', duplicate_node_data ); + duplicate_node.children( 'ellipse' ).parent().data( 'repositioned', duplicate_node_data ); } // Add the node and all new edges into the graph var graph_root = $('#svgenlargement svg g.graph'); graph_root.append( duplicate_node ); $.each( detached_edges, function( index, edge ) { - edge.g_elem.attr( 'id', ( edge.g_elem.attr( 'id' ) + "_0" ) ); + id_suffix = node_id.slice( node_id.indexOf( '_' ) ); + edge.g_elem.attr( 'id', ( edge.g_elem.attr( 'id' ) + id_suffix ) ); edge_title = edge.g_elem.children( 'title' ).text(); edge_weight = 0.8 + ( 0.2 * edge.witnesses.length ); edge_title = edge_title.replace( reading.orig_rdg, node_id ); @@ -760,11 +795,58 @@ function detach_node( readings ) { ellipse_elem.data( 'node_obj', new_node ); // Move the node somewhat up for 'dramatic effect' :-p - new_node.relocate( 0, -150 ); + new_node.reposition( 0, -70 ); } ); +} +function merge_nodes( source_node_id, target_node_id, consequences ) { + if( consequences.status != null && consequences.status == 'ok' ) { + merge_node( source_node_id, target_node_id ); + if( consequences.checkalign != null ) { + $.each( consequences.checkalign, function( index, node_ids ) { + var temp_relation = draw_relation( node_ids[0], node_ids[1], "#89a02c" ); + var sy = parseInt( temp_relation.children('path').attr('d').split('C')[0].split(',')[1] ); + var ey = parseInt( temp_relation.children('path').attr('d').split(' ')[2].split(',')[1] ); + var yC = ey + (( sy - ey )/2); + // TODO: compute xC to be always the same distance to the amplitude of the curve + var xC = parseInt( temp_relation.children('path').attr('d').split(' ')[1].split(',')[0] ); + var svg = $('#svgenlargement').children('svg').svg('get'); + parent_g = svg.group( $('#svgenlargement svg g') ); + var ids_text = node_ids[0] + '-' + node_ids[1]; + var merge_id = 'merge-' + ids_text; + svg.image( parent_g, xC, (yC-8), 16, 16, merge_button_yes, { id: merge_id } ); + svg.image( parent_g, (xC+20), (yC-8), 16, 16, merge_button_no, { id: 'no' + merge_id } ); + $( '#' + merge_id ).hover( function(){ $(this).addClass( 'draggable' ) }, function(){ $(this).removeClass( 'draggable' ) } ); + $( '#no' + merge_id ).hover( function(){ $(this).addClass( 'draggable' ) }, function(){ $(this).removeClass( 'draggable' ) } ); + $( '#' + merge_id ).click( function( evt ){ + merge_node( node_ids[0], node_ids[1] ); + temp_relation.remove(); + $( '#' + merge_id ).parent().remove(); + //notify backend + var ncpath = getTextURL( 'merge' ); + var form_values = "source_id=" + node_ids[0] + "&target_id=" + node_ids[1] + "&single=true"; + $.post( ncpath, form_values ); + } ); + $( '#no' + merge_id ).click( function( evt ) { + temp_relation.remove(); + $( '#' + merge_id ).parent().remove(); + } ); + } ); + } + } +} + +function merge_node( source_node_id, target_node_id ) { + $.each( edges_of( get_ellipse( source_node_id ) ), function( index, edge ) { + if( edge.is_incoming == true ) { + edge.attach_endpoint( target_node_id ); + } else { + edge.attach_startpoint( target_node_id ); + } + } ); + $( jq( source_node_id ) ).remove(); } function Marquee() { @@ -834,11 +916,15 @@ function Marquee() { $('#svgenlargement ellipse').each( function( index ) { var cx = parseInt( $(this).attr('cx') ); var cy = parseInt( $(this).attr('cy') ); - var org_translate = $(this).data( 'org_translate' ); + + // This needs somehow to move to node or even to shapes! #repositioned + // We should ask something more aling the lines of: nodes.each { |item| node.selected? } + var org_translate = $(this).parent().data( 'repositioned' ); if( org_translate != null ) { cx = cx + org_translate[0]; cy = cy + org_translate[1]; } + if( cx > cx_min && cx < cx_max) { if( cy > cy_min && cy < cy_max) { // we actually heve no real 'selected' state for nodes, except coloring @@ -969,45 +1055,47 @@ $(document).ready(function () { // merge dialog where appropriate. if( editable ) { - $( "#dialog-form" ).dialog({ + $( '#dialog-form' ).dialog( { autoOpen: false, height: 270, - width: 290, + width: 330, modal: true, buttons: { - "Merge readings": function( evt ) { - $(evt.target).button("disable"); - $('#status').empty(); - form_values = $('#collapse_node_form').serialize(); + 'Merge readings': function( evt ) { + $( evt.target ).button( 'disable' ); + $( '#status' ).empty(); + form_values = $( '#collapse_node_form' ).serialize(); ncpath = getTextURL( 'merge' ); - var jqjson = $.post( ncpath, form_values, function(data) { - alert( "Did a node merge" ); - }); + var jqjson = $.post( ncpath, form_values, function( data ) { + merge_nodes( $( '#source_node_id' ).val(), $( '#target_node_id' ).val(), data ); + $(evt.target).button( 'enable' ); + $( '#dialog-form' ).dialog( 'close' ); + } ); }, OK: function( evt ) { - $(evt.target).button("disable"); - $('#status').empty(); - form_values = $('#collapse_node_form').serialize(); + $( evt.target ).button( 'disable' ); + $( '#status' ).empty(); + form_values = $( '#collapse_node_form' ).serialize(); ncpath = getTextURL( 'relationships' ); - var jqjson = $.post( ncpath, form_values, function(data) { - $.each( data, function(item, source_target) { + var jqjson = $.post( ncpath, form_values, function( data ) { + $.each( data, function( item, source_target ) { var source_found = get_ellipse( source_target[0] ); var target_found = get_ellipse( source_target[1] ); - var relation_found = $.inArray( source_target[2], $('#keymap').data('relations') ); + var relation_found = $.inArray( source_target[2], $( '#keymap' ).data( 'relations' ) ); if( source_found.size() && target_found.size() && relation_found > -1 ) { var relation = relation_manager.create( source_target[0], source_target[1], relation_found ); - relation.data( 'type', source_target[2] ); - relation.data( 'scope', $('#scope :selected').text() ); - relation.data( 'note', $('#note').val() ); relation_manager.toggle_active( relation.attr('id') ); + $.each( $('#collapse_node_form').serializeArray(), function( i, k ) { + relation.data( k.name, k.value ); + }); } - $(evt.target).button("enable"); + $(evt.target).button( 'enable' ); }); - $( "#dialog-form" ).dialog( "close" ); + $( '#dialog-form' ).dialog( 'close' ); }, 'json' ); }, Cancel: function() { - $( this ).dialog( "close" ); + $( this ).dialog( 'close' ); } }, create: function(event, ui) {