properly disable OK button
[scpubgit/stemmatology.git] / stemmaweb / root / js / svginteraction.js
CommitLineData
b90c84a0 1function getRelativePath( action ) {
2 path_elements = window.location.pathname.split('/');
3 if( path_elements[1].length > 0 ) {
4 return window.location.pathname.split('/')[1] + '/' + action;
5 } else {
6 return action;
7 }
8}
9
10function svgLoaded() {
11 $('ellipse').attr( {stroke:'black', fill:'#fff'} );
12 ncpath = getRelativePath( 'node_click' );
13 var jqjson = $.getJSON( ncpath, 'node_id=null', function(data) {
14 $.each( data, function(item, node_id_and_state) {
15 if( node_id_and_state[1] == 1 ) {
16 node_ellipse = $('.node').children('title').filter( function(index) {
17 return $(this).text() == node_id_and_state[0];
18 }).siblings('ellipse');
19 node_ellipse.attr( {stroke:'green', fill:'#b3f36d'} );
20 $('#constructedtext').append( node_ellipse.siblings('text').text() + ' ' );
21 } else {
22 if( node_id_and_state[1] == null ) {
23 $('#constructedtext').append( ' … ' );
24 }
25 }
26 });
27 add_node_objs();
28 });
29}
30
31function add_node_objs() {
32 $('ellipse[fill="#fff"]').each( function() {
33 $(this).data( 'node_obj', new node_obj( $(this) ) );
34 }
35 );
36}
37
38function get_node_obj( node_id ) {
39 return $('.node').children('title').filter( function(index) {
40 return $(this).text() == node_id;
41 }).siblings('ellipse').data( 'node_obj' );
42}
43
44function get_edge( edge_id ) {
45 return $('.edge').filter( function(index) {
46 return $(this).children( 'title' ).text() == $('<div/>').html(edge_id).text() ;
47 });
48}
49
50function node_obj(ellipse) {
51 this.ellipse = ellipse;
52 var self = this;
53
54 this.x = 0;
55 this.y = 0;
56 this.dx = 0;
57 this.dy = 0;
58 this.node_elements = node_elements_for(self.ellipse);
59 this.sub_nodes = [];
60 this.super_node = null;
61
62 this.dblclick_listener = function(evt) {
63 node_id = self.ellipse.siblings('title').text();
64 ncpath = getRelativePath( 'node_click' );
65 var jqjson = $.getJSON( ncpath, 'node_id=' + node_id, function(data) {
66 $('#constructedtext').empty();
67 $.each( data, function(item, node_id_and_state) {
68 node = get_node_obj( node_id_and_state[0] );
69 // 1 -> turn the associated SVG node on, put in the associate word in the text box.
70 // 0 -> turn SVG node off.
71 // null -> turn node off, put in ellipsis in text box at the corresponding place.
72 if( node_id_and_state[1] == 1 ) {
73//TODO: create test suite en refactor this in to more OO! (node and node_ellipse are 'conflated')
74 node_ellipse = $('.node').children('title').filter( function(index) {
75 return $(this).text() == node_id_and_state[0];
76 }).siblings('ellipse');
77 $('#constructedtext').append( node_ellipse.siblings('text').text() + '&#32;' );
78 if( node ) { node.set_draggable( false ) }
79 } else {
80 if( node ) { node.set_draggable( true ) };
81 if( node_id_and_state[1] == null ) {
82 $('#constructedtext').append( ' &hellip; ' );
83 }
84 }
85 });
86 });
87 }
88
89 this.set_draggable = function( draggable ) {
90 if( draggable ) {
91 self.ellipse.attr( {stroke:'black', fill:'#fff'} );
92 self.ellipse.mousedown( this.mousedown_listener );
93 self.ellipse.hover( this.enter_node, this.leave_node );
94 } else {
95 self.ellipse.unbind('mouseenter').unbind('mouseleave').unbind('mousedown');
96 self.ellipse.attr( {stroke:'green', fill:'#b3f36d'} );
97 }
98 }
99
100 this.mousedown_listener = function(evt) {
101 evt.stopPropagation();
102 self.x = evt.clientX;
103 self.y = evt.clientY;
104 $('body').mousemove( self.mousemove_listener );
105 $('body').mouseup( self.mouseup_listener );
106 self.ellipse.unbind('mouseenter').unbind('mouseleave')
107 self.ellipse.attr( 'fill', '#ff66ff' );
108 }
109
110 this.mousemove_listener = function(evt) {
111 self.dx = evt.clientX - self.x;
112 self.dy = evt.clientY - self.y;
113 self.move_elements();
114 }
115
116 this.mouseup_listener = function(evt) {
117 if( $('ellipse[fill="#ffccff"]').size() > 0 ) {
118 $('#source_node_id').val( self.ellipse.siblings('title').text() );
119 $('#target_node_id').val( $('ellipse[fill="#ffccff"]').siblings("title").text() );
120 $( '#dialog-form' ).dialog( 'open' );
121 };
122 $('body').unbind('mousemove');
123 $('body').unbind('mouseup');
124 self.ellipse.attr( 'fill', '#fff' );
125 self.ellipse.hover( self.enter_node, self.leave_node );
126 if( self.super_node ) {
127 self.eclipse();
128 } else {
129 self.reset_elements();
130 }
131 }
132
133 this.cpos = function() {
134 return { x: self.ellipse.attr('cx'), y: self.ellipse.attr('cy') };
135 }
136
137 this.get_g = function() {
138 return self.ellipse.parent('g');
139 }
140
141 this.stack_behind = function( collapse_info ) {
142 self.super_node = get_node_obj( collapse_info.target );
143 self.super_node.sub_nodes.push( self );
144 self.eclipse();
145 if( collapse_info.edges ) {
146 $.each( collapse_info.edges, function( source_edge_id, target_info ) {
147 get_edge(source_edge_id).attr( 'display', 'none' );
148 target_edge = get_edge(target_info.target);
149 // Unfortunately, the simple solution doesn't work...
150 // target_edge.children( 'text' ).replaceWith( '<text x="2270" y="-59.400001525878906"><tspan text-anchor="middle">A, B</tspan><tspan fill="red">, C</tspan></text>' );
151 // ..so we take the long and winding road...
152 var svg = $('#svgbasics').children('svg').svg().svg('get');
153 textx = target_edge.children( 'text' )[0].x.baseVal.getItem(0).value
154 texty = target_edge.children( 'text' )[0].y.baseVal.getItem(0).value
155 current_label = target_edge.children( 'text' ).text();
156 target_edge.children( 'text' ).remove();
157 texts = svg.createText();
158 texts.span(current_label, {'text-anchor': 'middle'}).span(target_info.label, {fill: 'red'});
159 svg.text(target_edge, textx, texty, texts);
160 });
161 }
162 }
163
164 this.eclipse = function() {
165 self.dx = new Number( self.super_node.cpos().x ) - new Number( self.cpos().x ) + ( 10 * (self.super_node.sub_nodes.indexOf(self) + 1) );
166 self.dy = new Number( self.super_node.cpos().y ) - new Number( self.cpos().y ) + ( 5 * (self.super_node.sub_nodes.indexOf(self) + 1) );
167 self.move_elements();
168 eclipse_index = self.super_node.sub_nodes.indexOf(self) - 1;
169 if( eclipse_index > -1 ) {
170 self.get_g().insertBefore( self.super_node.sub_nodes[eclipse_index].get_g() );
171 } else {
172 self.get_g().insertBefore( self.super_node.get_g() );
173 }
174 }
175
176 this.enter_node = function(evt) {
177 self.ellipse.attr( 'fill', '#ffccff' );
178 }
179
180 this.leave_node = function(evt) {
181 self.ellipse.attr( 'fill', '#fff' );
182 }
183
184 this.move_elements = function() {
185 $.each( self.node_elements, function(index, value) {
186 value.move(self.dx,self.dy);
187 });
188 }
189
190 this.reset_elements = function() {
191 $.each( self.node_elements, function(index, value) {
192 value.reset();
193 });
194 }
195
196 this.ellipse.dblclick( this.dblclick_listener );
197 self.set_draggable( true );
198}
199
200function svgshape( shape_element ) {
201 this.shape = shape_element;
202 this.move = function(dx,dy) {
203 this.shape.attr( "transform", "translate(" + dx + " " + dy + ")" );
204 }
205 this.reset = function() {
206 this.shape.attr( "transform", "translate( 0, 0 )" );
207 }
208}
209
210function svgpath( path_element ) {
211 this.path = path_element;
212 this.x = this.path.x;
213 this.y = this.path.y;
214 this.move = function(dx,dy) {
215 this.path.x = this.x + dx;
216 this.path.y = this.y + dy;
217 }
218 this.reset = function() {
219 this.path.x = this.x;
220 this.path.y = this.y;
221 }
222}
223
224function node_elements_for( ellipse ) {
225 node_elements = get_edge_elements_for( ellipse );
226 node_elements.push( new svgshape( ellipse.siblings('text') ) );
227 node_elements.push( new svgshape( ellipse ) );
228 return node_elements;
229}
230
231function get_edge_elements_for( ellipse ) {
232 edge_elements = new Array();
233 node_id = ellipse.siblings('title').text();
234 edge_in_pattern = new RegExp( node_id + '$' );
235 edge_out_pattern = new RegExp( '^' + node_id );
236 $.each( $('.edge').children('title'), function(index) {
237 title = $(this).text();
238 if( edge_in_pattern.test(title) ) {
239 edge_elements.push( new svgshape( $(this).siblings('polygon') ) );
240 path_segments = $(this).siblings('path')[0].pathSegList;
241 edge_elements.push( new svgpath( path_segments.getItem(path_segments.numberOfItems - 1) ) );
242 }
243 if( edge_out_pattern.test(title) ) {
244 path_segments = $(this).siblings('path')[0].pathSegList;
245 edge_elements.push( new svgpath( path_segments.getItem(0) ) );
246 }
247 });
248 return edge_elements;
249}
250
251$(document).ready(function () {
252 $('#graph').ajaxError(function() {
253 console.log( 'Oops.. something went wrong with trying to save this change. Please try again...' );
254 });
255 $('#graph').mousedown(function (event) {
256 $(this)
257 .data('down', true)
258 .data('x', event.clientX)
259 .data('scrollLeft', this.scrollLeft);
260 return false;
261 }).mouseup(function (event) {
262 $(this).data('down', false);
263 }).mousemove(function (event) {
264 if ($(this).data('down') == true ) {
265 this.scrollLeft = $(this).data('scrollLeft') + $(this).data('x') - event.clientX;
266 }
267 }).mousewheel(function (event, delta) {
268 this.scrollLeft -= (delta * 30);
269 }).css({
270 'overflow' : 'hidden',
271 'cursor' : '-moz-grab'
272 });
273 $( "#dialog-form" ).dialog({
274 autoOpen: false,
275 height: 150,
276 width: 250,
277 modal: true,
278 buttons: {
279 "Ok": function() {
280 form_values = $('#collapse_node_form').serialize()
281 ncpath = getRelativePath( 'node_collapse' );
282 var jqjson = $.getJSON( ncpath, form_values, function(data) {
283 $.each( data, function(item, collapse_info) {
284 get_node_obj( item ).stack_behind( collapse_info );
285 });
286 });
287 $( this ).dialog( "close" );
288 },
289 Cancel: function() {
290 $( this ).dialog( "close" );
291 }
292 },
293 close: function() {
294 $('#reason').val( "" ).removeClass( "ui-state-error" );
295 }
296 });
297});
298
299
300$(window).mouseout(function (event) {
301 if ($('#graph').data('down')) {
302 try {
303 if (event.originalTarget.nodeName == 'BODY' || event.originalTarget.nodeName == 'HTML') {
304 $('#graph').data('down', false);
305 }
306 } catch (e) {}
307 }
308});
309
310