From: Tara L Andrews Date: Wed, 15 Feb 2012 21:22:12 +0000 (+0100) Subject: pull new relationship mapper interface X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=72874569483d50155776bbd894c140ef3c3e8793;p=scpubgit%2Fstemmatology.git pull new relationship mapper interface --- diff --git a/stemmaweb/lib/stemmaweb/Controller/Relation.pm b/stemmaweb/lib/stemmaweb/Controller/Relation.pm index 77de49e..00c97eb 100644 --- a/stemmaweb/lib/stemmaweb/Controller/Relation.pm +++ b/stemmaweb/lib/stemmaweb/Controller/Relation.pm @@ -24,24 +24,12 @@ Renders the application for the text identified by $textid. =cut -sub index :Path :Args(1) { - my( $self, $c, $textid ) = @_; - my $m = $c->model('Directory'); - my $tradition = $m->tradition( $textid ); - my $collation = $tradition->collation; - my $svg_str = $collation->as_svg; - $svg_str =~ s/\n//gs; - $c->stash->{'svg_string'} = $svg_str; +sub index :Path :Args(0) { + my( $self, $c ) = @_; $c->stash->{'template'} = 'relate.tt'; } -sub dispatcher :Path :Args(2) { - my( $self, $c, $textid, $forward ) = @_; - $c->stash->{'tradition'} = $c->model('Directory')->tradition( $textid ); - $c->forward( $forward ); -} - -=head2 relationship_definition +=head2 definitions GET relation/definitions @@ -51,76 +39,100 @@ Returns a data structure giving the valid types and scopes for a relationship. sub definitions :Local :Args(0) { my( $self, $c ) = @_; - my $valid_relationships = [ qw/ spelling orthographic grammatical meaning / ]; + my $valid_relationships = [ qw/ spelling orthographic grammatical meaning + lexical transposition / ]; my $valid_scopes = [ qw/ local global / ]; $c->stash->{'result'} = { 'types' => $valid_relationships, 'scopes' => $valid_scopes }; $c->forward('View::JSON'); } -=head2 relationship - - POST relation/$textid/relationship - source_id: $source, target_id: $target, rel_type: $type, scope: $scope - -Sets the specified relationship between the readings in $source and $target. -Returns 200 and a list of node pairs where the relationship was added on success; -returns 403 and an { error: message } struct on failure. +=head2 text + GET relation/$textid/ + + Runs the relationship mapper for the specified text ID. + =cut -sub relationship :Private { +sub text :Chained('/') :PathPart('relation') :CaptureArgs(1) { + my( $self, $c, $textid ) = @_; + $c->stash->{'tradition'} = $c->model('Directory')->tradition( $textid ); +} + +sub main :Chained('text') :PathPart('') :Args(0) { my( $self, $c ) = @_; my $tradition = delete $c->stash->{'tradition'}; my $collation = $tradition->collation; - my $node = $c->request->param('source_id'); - my $target = $c->request->param('target_id'); - my $relation = $c->request->param('rel_type'); - my $note = $c->request->param('note'); - my $scope = $c->request->param('scope'); - - my $opts = { 'type' => $relation, - 'scope' => $scope }; - - try { - my @vectors = $collation->add_relationship( $node, $target, $opts ); - my $m = $c->model('Directory'); - $m->save( $tradition ); - $c->stash->{'result'} = \@vectors; - } catch( Text::Tradition::Error $e ) { - $c->response->status( '403' ); - $c->stash->{'result'} = { 'error' => $e->message }; - } - $c->forward('View::JSON'); + my $svg_str = $collation->as_svg; + $svg_str =~ s/\n//gs; + $c->stash->{'svg_string'} = $svg_str; + $c->stash->{'text_title'} = $tradition->name; + $c->stash->{'template'} = 'relate.tt'; + } =head2 relationships - GET relation/$textid/relationships + GET $textid/relationships + +Returns the list of relationships defined for this text. -Returns a list of relationships that exist in the specified text. Each -relationship is returned in a struct that looks like: + POST $textid/relationships { request } + +Attempts to define the requested relationship within the text. Returns 200 on +success or 403 on error. -{ source: $sid, target: $tid, type: $rel_type, scope: $rel_scope } + DELETE $textid/relationships { request } + =cut -sub relationships :Private { +sub relationships :Chained('text') :PathPart :Args(0) { my( $self, $c ) = @_; my $tradition = delete $c->stash->{'tradition'}; my $collation = $tradition->collation; - # TODO make this API - my @pairs = $collation->relationships; # returns the edges - my @all_relations; - foreach my $p ( @pairs ) { - my $relobj = $collation->relations->get_relationship( @$p ); - push( @all_relations, - { source => $p->[0], target => $p->[1], - type => $relobj->type, scope => $relobj->scope } ); + if( $c->request->method eq 'GET' ) { + my @pairs = $collation->relationships; # returns the edges + my @all_relations; + foreach my $p ( @pairs ) { + my $relobj = $collation->relations->get_relationship( @$p ); + push( @all_relations, + { source => $p->[0], target => $p->[1], + type => $relobj->type, scope => $relobj->scope } ); + } + $c->stash->{'result'} = \@all_relations; + } elsif( $c->request->method eq 'POST' ) { + my $node = $c->request->param('source_id'); + my $target = $c->request->param('target_id'); + my $relation = $c->request->param('rel_type'); + my $note = $c->request->param('note'); + my $scope = $c->request->param('scope'); + + my $opts = { 'type' => $relation, + 'scope' => $scope }; + + try { + my @vectors = $collation->add_relationship( $node, $target, $opts ); + $c->stash->{'result'} = \@vectors; + } catch( Text::Tradition::Error $e ) { + $c->response->status( '403' ); + $c->stash->{'result'} = { 'error' => $e->message }; + } + } elsif( $c->request->method eq 'DELETE' ) { + my $node = $c->request->param('source_id'); + my $target = $c->request->param('target_id'); + + try { + my @vectors = $collation->del_relationship( $node, $target ); + $c->stash->{'result'} = \@vectors; + } catch( Text::Tradition::Error $e ) { + $c->response->status( '403' ); + $c->stash->{'result'} = { 'error' => $e->message }; + } } - $c->stash->{'result'} = \@all_relations; $c->forward('View::JSON'); } - + =head2 end diff --git a/stemmaweb/root/css/relationship.css b/stemmaweb/root/css/relationship.css index 7d1f179..a260414 100644 --- a/stemmaweb/root/css/relationship.css +++ b/stemmaweb/root/css/relationship.css @@ -8,11 +8,53 @@ body { .error { color: red; } -#graph_container { - height: 104px; - width: 90%; - margin-top: 5px; - border: 2px solid #B0C6F7; +#topbanner { + width: 100%; + height: 100px; + margin-top: 20px; +} +#logoimg { + float: left; + margin-left: 20px; +} +#logotitle { + float: left; + margin-left: 30px; + height: 55px; + padding-top: 40px; +} +h1.title a:link, h1.title a:visited, h1.title a:active { + color: #666; + font-weight: bold; + text-decoration: none; +} +h1.title a:hover { + color: #222; +} +h1.title { + margin: 0; + padding: 0; + letter-spacing: -1px; + line-height: 1.0em; + font-family: tahoma, arial, sans-serif; + font-size: 240%; +} +p.tagline { + margin: 0; + padding: 0; + font-size: 1.2em; + font-weight: bold; + color: #666; +} +.term { + font-style: italic; +} +p.api { + font-weight: bold; + font-family: Courier; +} +span.apimore { + font-family: Courier; } #enlargement_container { height: 504px; @@ -26,7 +68,7 @@ body { #dialog_overlay { display: none; position: absolute; - background-image: url("../css/cupertino/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png"); + background-image: url("/css/cupertino/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png"); background-repeat: repeat; background-attachment: scroll; background-position: 50% 50%; @@ -37,16 +79,17 @@ body { border: 2px solid #B0C6F7; } #update_workspace_button { - position: relative; - top: -538px; - left: 44%; - height: 17px; - width: 17px; - margin-top: 8px; - border: 1px solid #B0C6F7; - background-image: url('../images/act_arrs.gif'); - background-position: 0px 0px; - background-color: #fcfcfc; + position: absolute; + left: 74.5%; + top: 126px; + height: 44px; + width: 46px; + margin-top: 17px; + border: none; + background-image: url('/images/act_icons.png'); + background-position: 0px 44px; + background-color: none; + background-repeat: none; z-index: 50; } #workspace_container { @@ -97,9 +140,14 @@ body { #keymap { position: absolute; left: 80%; - top: 100px; + top: 140px; border: 2px solid #B0C6F7; background: #fff; + background: url("/css/cupertino/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png"); + background-repeat: repeat-x; + background-scroll: scroll; + background-position: 50% top; + background-color: #F2F5F7; } #keymap ul { padding: 10px; diff --git a/stemmaweb/root/images/act_icons.png b/stemmaweb/root/images/act_icons.png new file mode 100644 index 0000000..0ec9c2d Binary files /dev/null and b/stemmaweb/root/images/act_icons.png differ diff --git a/stemmaweb/root/js/relationship.js b/stemmaweb/root/js/relationship.js index b615f5a..b135c71 100644 --- a/stemmaweb/root/js/relationship.js +++ b/stemmaweb/root/js/relationship.js @@ -10,54 +10,62 @@ function getTextPath() { return path_parts; } -function svgLoaded() { - // some initial scaling - var svg_element = $('#svgbasics').children('svg'); - var svg_graph = svg_element.svg().svg('get').root(); - var svg_vbwidth = svg_graph.viewBox.baseVal.width; - var svg_vbheight = svg_graph.viewBox.baseVal.height; - var scroll_padding = $('#graph_container').width(); - // (Use attr('width') to set width attr, otherwise style="width: npx;" is set.) - var svg_element_width = svg_vbwidth/svg_vbheight * parseInt(svg_element.attr('height')); - svg_element_width += scroll_padding; - svg_element.attr( 'width', svg_element_width ); - $('ellipse').attr( {stroke:'black', fill:'#fff'} ); +function getRelativePath() { + var path_parts = getTextPath(); + return path_parts[0]; +} + +function getRelationshipURL() { + var path_parts = getTextPath(); + return path_parts[0] + '/' + path_parts[1] + '/relationships'; } function svgEnlargementLoaded() { - // some initial scaling - var svg_element = $('#svgenlargement').children('svg'); - var svg_graph = svg_element.svg().svg('get').root() - var svg_vbwidth = svg_graph.viewBox.baseVal.width; - var svg_vbheight = svg_graph.viewBox.baseVal.height; - var scroll_padding = $('#enlargement_container').width(); - // (Use attr('width') to set width attr, otherwise style="width: npx;" is set.) - var svg_element_width = svg_vbwidth/svg_vbheight * parseInt(svg_element.attr('height')); - svg_element_width += scroll_padding; - svg_element.attr( 'width', svg_element_width ); - $('ellipse').attr({ - stroke: 'black', - fill: '#fff' - }); - var svg_height = parseInt( $('#svgenlargement').height() ); - scroll_enlargement_ratio = svg_height/svg_vbheight; + //Set viewbox widht and height to widht and height of $('#svgenlargement svg'). + //This is essential to make sure zooming and panning works properly. + $('#svgenlargement ellipse').attr( {stroke:'green', fill:'#b3f36d'} ); + var graph_svg = $('#svgenlargement svg'); + var svg_g = $('#svgenlargement svg g')[0]; + svg_root = graph_svg.svg().svg('get').root(); + svg_root.viewBox.baseVal.width = graph_svg.attr( 'width' ); + svg_root.viewBox.baseVal.height = graph_svg.attr( 'height' ); + //Now set scale and translate so svg height is about 150px and vertically centered in viewbox. + //This is just to create a nice starting enlargement. + var initial_svg_height = 250; + var scale = initial_svg_height/graph_svg.attr( 'height' ); + var additional_translate = (graph_svg.attr( 'height' ) - initial_svg_height)/(2*scale); + var transform = svg_g.getAttribute('transform'); + var translate = parseFloat( transform.match( /translate\([^\)]*\)/ )[0].split('(')[1].split(' ')[1].split(')')[0] ); + translate += additional_translate; + var transform = 'rotate(0) scale(' + scale + ') translate(4 ' + translate + ')'; + svg_g.setAttribute('transform', transform); + //used to calculate min and max zoom level: + start_element_height = $("#svgenlargement .node title:contains('#START#')").siblings('ellipse')[0].getBBox().height; add_relations(); } function add_relations() { - var pathparts = getTextPath(); - $.getJSON( pathparts[0] + '/definitions', function(data) { + var basepath = getRelativePath(); + var textrelpath = getRelationshipURL(); + $.getJSON( basepath + '/definitions', function(data) { var rel_types = data.types.sort(); - var pathparts = getTextPath(); - $.getJSON( pathparts[0] + '/' + pathparts[1] + '/relationships', + $.getJSON( textrelpath, function(data) { $.each(data, function( index, rel_info ) { var type_index = $.inArray(rel_info.type, rel_types); if( type_index != -1 ) { - relation_manager.create( rel_info.source, rel_info.target, type_index ); + 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 ); + var node_obj = get_node_obj(rel_info.source); + node_obj.set_draggable( false ); + node_obj.ellipse.data( 'node_obj', null ); + node_obj = get_node_obj(rel_info.target); + node_obj.set_draggable( false ); + node_obj.ellipse.data( 'node_obj', null ); } }) - }); + }); }); } @@ -68,7 +76,11 @@ function get_ellipse( node_id ) { } function get_node_obj( node_id ) { - return get_ellipse( node_id ).data( 'node_obj' ); + var node_ellipse = get_ellipse( node_id ); + if( node_ellipse.data( 'node_obj' ) == null ) { + node_ellipse.data( 'node_obj', new node_obj(node_ellipse) ); + }; + return node_ellipse.data( 'node_obj' ); } function get_edge( edge_id ) { @@ -115,11 +127,8 @@ function node_obj(ellipse) { } this.mousemove_listener = function(evt) { - // magnification on workspace lock temporarily disabled - // self.dx = (evt.clientX - self.x) / mousemove_enlargement_ratio; - // self.dy = (evt.clientY - self.y) / mousemove_enlargement_ratio; - self.dx = (evt.clientX - self.x) / scroll_enlargement_ratio; - self.dy = (evt.clientY - self.y) / scroll_enlargement_ratio; + self.dx = (evt.clientX - self.x) / mouse_scale; + self.dy = (evt.clientY - self.y) / mouse_scale; self.move_elements(); } @@ -135,7 +144,7 @@ function node_obj(ellipse) { $('body').unbind('mouseup'); self.ellipse.attr( 'fill', '#fff' ); self.ellipse.hover( self.enter_node, self.leave_node ); - self.reset_elements(); + self.reset_elements(); } this.cpos = function() { @@ -270,13 +279,13 @@ function relation_factory() { this.relation_colors = [ "#5CCCCC", "#67E667", "#F9FE72", "#6B90D4", "#FF7673", "#E467B3", "#AA67D5", "#8370D8", "#FFC173" ]; this.create_temporary = function( source_node_id, target_node_id ) { - var relation = $('#svgenlargement .relation').filter( function(index) { - var relation_id = $(this).children('title').text(); + var relation = $('#svgenlargement .relation').filter( function(index) { + var relation_id = $(this).children('title').text(); if( ( relation_id == ( source_node_id + '->' + target_node_id ) ) || ( relation_id == ( target_node_id + '->' + source_node_id ) ) ) { - return true; - } - } ); - if( relation.size() == 0 ) { + return true; + } + } ); + if( relation.size() == 0 ) { draw_relation( source_node_id, target_node_id, self.temp_color ); } else { self.color_memo = relation.children('path').attr( 'stroke' ); @@ -289,74 +298,140 @@ function relation_factory() { path_element.attr( 'stroke', self.color_memo ); self.color_memo = null; } else { - path_element.parent('g').remove(); + var temporary = path_element.parent('g').remove(); + temporary.empty(); + temporary = null; } } this.create = function( source_node_id, target_node_id, color_index ) { //TODO: Protect from (color_)index out of bound.. var relation_color = self.relation_colors[ color_index ]; - draw_relation( source_node_id, target_node_id, relation_color ); - var source_node = get_node_obj( source_node_id ); - var target_node = get_node_obj( target_node_id ); - if( source_node != null ) { source_node.update_elements() }; - if( target_node != null ) { target_node.update_elements() }; + var relation = draw_relation( source_node_id, target_node_id, relation_color ); + get_node_obj( source_node_id ).update_elements(); + get_node_obj( target_node_id ).update_elements(); + return relation; } - this.remove = function( source_node_id, target_id ) { - //TODO (When needed) - console.log( "Unsupported function node_obj.remove()." ); + this.toggle_active = function( relation_id ) { + var relation = $("#svgenlargement .relation:has(title:contains('" + relation_id + "'))"); + var relation_path = relation.children('path'); + if( !relation.data( 'active' ) ) { + relation_path.css( {'cursor':'pointer'} ); + relation_path.mouseenter( function(event) { + outerTimer = setTimeout( function() { + timer = setTimeout( function() { + var title = relation.children('title').text(); + var source_node_id = title.substring( 0, title.indexOf( "->" ) ); + var target_node_id = title.substring( (title.indexOf( "->" ) + 2) ); + $('#delete_source_node_id').val( source_node_id ); + $('#delete_target_node_id').val( target_node_id ); + self.showinfo(relation); + }, 500 ) + }, 1000 ); + }); + relation_path.mouseleave( function(event) { + clearTimeout(outerTimer); + if( timer != null ) { clearTimeout(timer); } + }); + relation.data( 'active', true ); + } else { + relation_path.unbind( 'mouseenter' ); + relation_path.unbind( 'mouseleave' ); + relation_path.css( {'cursor':'inherit'} ); + relation.data( 'active', false ); + } + } + this.showinfo = function(relation) { + $('#delete-form-text').html( 'type: ' + relation.data( 'type' ) + '
scope: ' + relation.data( 'scope' ) ); + var points = relation.children('path').attr('d').slice(1).replace('C',' ').split(' '); + var xs = parseFloat( points[0].split(',')[0] ); + var xe = parseFloat( points[1].split(',')[0] ); + var ys = parseFloat( points[0].split(',')[1] ); + var ye = parseFloat( points[3].split(',')[1] ); + var p = svg_root.createSVGPoint(); + p.x = xs + ((xe-xs)*1.1); + p.y = ye - ((ye-ys)/2); + var ctm = svg_root.children[0].getScreenCTM(); + var nx = p.matrixTransform(ctm).x; + var ny = p.matrixTransform(ctm).y; + var dialog_aria = $ ("div[aria-labelledby='ui-dialog-title-delete-form']"); + $('#delete-form').dialog( 'open' ); + dialog_aria.offset({ left: nx, top: ny }); + } + this.remove = function( relation_id ) { + var relation = $("#svgenlargement .relation:has(title:contains('" + relation_id + "'))"); + relation.remove(); } } function draw_relation( source_id, target_id, relation_color ) { - var source_ellipse = get_ellipse( source_id ); - var target_ellipse = get_ellipse( target_id ); - var svg = $('#svgenlargement').children('svg').svg().svg('get'); - var path = svg.createPath(); - var sx = parseInt( source_ellipse.attr('cx') ); - var rx = parseInt( source_ellipse.attr('rx') ); - 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'} ); - 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 source_ellipse = get_ellipse( source_id ); + var target_ellipse = get_ellipse( target_id ); + var svg = $('#svgenlargement').children('svg').svg().svg('get'); + var path = svg.createPath(); + var sx = parseInt( source_ellipse.attr('cx') ); + var rx = parseInt( source_ellipse.attr('rx') ); + 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'} ); + 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' ); relation_element.insertBefore( $('#svgenlargement g g').filter(':first') ); + return relation_element; } + $(document).ready(function () { - + + timer = null; relation_manager = new relation_factory(); + $('#update_workspace_button').data('locked', false); - scroll_ratio = $('#enlargement').height() / $('#graph').height(); - - $('#graph').mousedown(function (event) { + $('#enlargement').mousedown(function (event) { $(this) - .data('down', true) - .data('x', event.clientX) - .data('scrollLeft', this.scrollLeft); - return false; + .data('down', true) + .data('x', event.clientX) + .data('y', event.clientY) + .data('scrollLeft', this.scrollLeft) + stateTf = svg_root.children[0].getCTM().inverse(); + var p = svg_root.createSVGPoint(); + p.x = event.clientX; + p.y = event.clientY; + stateOrigin = p.matrixTransform(stateTf); + return false; }).mouseup(function (event) { - $(this).data('down', false); + $(this).data('down', false); }).mousemove(function (event) { - if ($(this).data('down') == true ) { - if ( $('#update_workspace_button').data('locked') != true ) { - var scroll_left = $(this).data('scrollLeft') + $(this).data('x') - event.clientX; - this.scrollLeft = scroll_left; - var enlarged_scroll_left = scroll_left * scroll_ratio; - $('#enlargement').scrollLeft( enlarged_scroll_left ); - color_enlarged(); - } + if( timer != null ) { clearTimeout(timer); } + if ( ($(this).data('down') == true) && ($('#update_workspace_button').data('locked') == false) ) { + var p = svg_root.createSVGPoint(); + p.x = event.clientX; + p.y = event.clientY; + p = p.matrixTransform(stateTf); + var matrix = stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y); + var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")"; + svg_root.children[0].setAttribute("transform", s); } }).mousewheel(function (event, delta) { - if ( $('#update_workspace_button').data('locked') != true ) { - var scroll_left = delta * 30; - this.scrollLeft -= scroll_left; - var enlarged_scroll_left = $('#enlargement').scrollLeft(); - enlarged_scroll_left -= (scroll_left * scroll_ratio); - $('#enlargement').scrollLeft( enlarged_scroll_left ); - color_enlarged(); - } + event.returnValue = false; + event.preventDefault(); + if ( $('#update_workspace_button').data('locked') == false ) { + if( delta < -9 ) { delta = -9 }; + var z = 1 + delta/10; + var g = svg_root.children[0]; + if( (z<1 && (g.getScreenCTM().a * start_element_height) > 4.0) || (z>1 && (g.getScreenCTM().a * start_element_height) < 100) ) { + var root = svg_root; + var p = root.createSVGPoint(); + p.x = event.clientX; + p.y = event.clientY; + p = p.matrixTransform(g.getCTM().inverse()); + var k = root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y); + var matrix = g.getCTM().multiply(k); + var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")"; + g.setAttribute("transform", s); + } + } }).css({ 'overflow' : 'hidden', 'cursor' : '-moz-grab' @@ -372,26 +447,27 @@ $(document).ready(function () { "Ok": function() { $('#status').empty(); form_values = $('#collapse_node_form').serialize() - pathparts = getTextPath(); - ncpath = pathparts[0] + '/' + pathparts[1] + '/relationship'; + ncpath = getRelationshipURL(); + $(':button :contains("Ok")').attr("disabled", true); var jqjson = $.post( ncpath, form_values, function(data) { $.each( data, function(item, source_target) { - relation_manager.create( source_target[0], source_target[1], $('#rel_type').attr('selectedIndex') ); + var relation = relation_manager.create( source_target[0], source_target[1], $('#rel_type').attr('selectedIndex') ); + relation.data( 'type', $('#rel_type :selected').text() ); + relation.data( 'scope', $('#scope :selected').text() ); + relation_manager.toggle_active( relation.children('title').text() ); }); - relation_manager.remove_temporary(); $( "#dialog-form" ).dialog( "close" ); - }, 'json'); + }, 'json' ); }, Cancel: function() { - relation_manager.remove_temporary(); $( this ).dialog( "close" ); } }, create: function(event, ui) { $(this).data( 'relation_drawn', false ); //TODO? Err handling? - var pathparts = getTextPath(); - var jqjson = $.getJSON( pathparts[0] + '/definitions', function(data) { + var basepath = getRelativePath(); + var jqjson = $.getJSON( basepath + '/definitions', function(data) { var types = data.types.sort(); $.each( types, function(index, value) { $('#rel_type').append( $('