Commit | Line | Data |
b28e606e |
1 | function 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 | |
10 | function svgLoaded() { |
11 | // some initial scaling |
12 | var svg_element = $('#svgbasics').children('svg'); |
13 | var svg_graph = svg_element.svg().svg('get').root(); |
14 | var svg_vbwidth = svg_graph.viewBox.baseVal.width; |
15 | var svg_vbheight = svg_graph.viewBox.baseVal.height; |
16 | var scroll_padding = $('#graph_container').width(); |
17 | // (Use attr('width') to set width attr, otherwise style="width: npx;" is set.) |
18 | var svg_element_width = svg_vbwidth/svg_vbheight * parseInt(svg_element.attr('height')); |
19 | svg_element_width += scroll_padding; |
20 | svg_element.attr( 'width', svg_element_width ); |
21 | $('ellipse').attr( {stroke:'black', fill:'#fff'} ); |
22 | } |
23 | |
24 | function svgEnlargementLoaded() { |
25 | // some initial scaling |
26 | var svg_element = $('#svgenlargement').children('svg'); |
27 | var svg_graph = svg_element.svg().svg('get').root() |
28 | var svg_vbwidth = svg_graph.viewBox.baseVal.width; |
29 | var svg_vbheight = svg_graph.viewBox.baseVal.height; |
30 | var scroll_padding = $('#enlargement_container').width(); |
31 | // (Use attr('width') to set width attr, otherwise style="width: npx;" is set.) |
32 | var svg_element_width = svg_vbwidth/svg_vbheight * parseInt(svg_element.attr('height')); |
33 | svg_element_width += scroll_padding; |
34 | svg_element.attr( 'width', svg_element_width ); |
35 | $('ellipse').attr( {stroke:'black', fill:'#fff'} ); |
36 | var svg_height = parseInt( $('#svgenlargement').height() ); |
37 | scroll_enlargement_ratio = svg_height/svg_vbheight; |
38 | } |
39 | |
40 | function get_ellipse( node_id ) { |
41 | return $('#svgenlargement .node').children('title').filter( function(index) { |
42 | return $(this).text() == node_id; |
43 | }).siblings('ellipse'); |
44 | } |
45 | |
46 | function get_node_obj( node_id ) { |
47 | return get_ellipse( node_id ).data( 'node_obj' ); |
48 | } |
49 | |
50 | function get_edge( edge_id ) { |
51 | return $('#svgenlargement .edge').filter( function(index) { |
52 | return $(this).children( 'title' ).text() == $('<div/>').html(edge_id).text() ; |
53 | }); |
54 | } |
55 | |
56 | function node_obj(ellipse) { |
57 | this.ellipse = ellipse; |
58 | var self = this; |
59 | |
60 | this.x = 0; |
61 | this.y = 0; |
62 | this.dx = 0; |
63 | this.dy = 0; |
64 | this.node_elements = node_elements_for(self.ellipse); |
65 | |
66 | this.get_id = function() { |
67 | return self.ellipse.siblings('title').text() |
68 | } |
69 | |
70 | this.set_draggable = function( draggable ) { |
71 | if( draggable ) { |
72 | self.ellipse.attr( {stroke:'black', fill:'#fff'} ); |
73 | self.ellipse.mousedown( this.mousedown_listener ); |
74 | self.ellipse.hover( this.enter_node, this.leave_node ); |
75 | } else { |
76 | self.ellipse.unbind('mouseenter').unbind('mouseleave').unbind('mousedown'); |
77 | self.ellipse.attr( {stroke:'green', fill:'#b3f36d'} ); |
78 | } |
79 | } |
80 | |
81 | this.mousedown_listener = function(evt) { |
82 | evt.stopPropagation(); |
83 | self.x = evt.clientX; |
84 | self.y = evt.clientY; |
85 | $('body').mousemove( self.mousemove_listener ); |
86 | $('body').mouseup( self.mouseup_listener ); |
87 | self.ellipse.unbind('mouseenter').unbind('mouseleave') |
88 | self.ellipse.attr( 'fill', '#ff66ff' ); |
89 | first_node_g_element = $("#svgenlargement g .node" ).filter( ":first" ); |
90 | if( first_node_g_element.attr('id') !== self.get_g().attr('id') ) { self.get_g().insertBefore( first_node_g_element ) }; |
91 | } |
92 | |
93 | this.mousemove_listener = function(evt) { |
94 | self.dx = (evt.clientX - self.x) / mousemove_enlargement_ratio; |
95 | self.dy = (evt.clientY - self.y) / mousemove_enlargement_ratio; |
96 | self.move_elements(); |
97 | } |
98 | |
99 | this.mouseup_listener = function(evt) { |
100 | if( $('ellipse[fill="#ffccff"]').size() > 0 ) { |
101 | var source_node_id = self.ellipse.siblings('title').text(); |
102 | var target_node_id = $('ellipse[fill="#ffccff"]').siblings("title").text(); |
103 | $('#source_node_id').val( source_node_id ); |
104 | $('#target_node_id').val( target_node_id ); |
105 | $('#dialog-form').dialog( 'open' ); |
106 | }; |
107 | $('body').unbind('mousemove'); |
108 | $('body').unbind('mouseup'); |
109 | self.ellipse.attr( 'fill', '#fff' ); |
110 | self.ellipse.hover( self.enter_node, self.leave_node ); |
111 | self.reset_elements(); |
112 | } |
113 | |
114 | this.cpos = function() { |
115 | return { x: self.ellipse.attr('cx'), y: self.ellipse.attr('cy') }; |
116 | } |
117 | |
118 | this.get_g = function() { |
119 | return self.ellipse.parent('g'); |
120 | } |
121 | |
122 | this.enter_node = function(evt) { |
123 | self.ellipse.attr( 'fill', '#ffccff' ); |
124 | } |
125 | |
126 | this.leave_node = function(evt) { |
127 | self.ellipse.attr( 'fill', '#fff' ); |
128 | } |
129 | |
130 | this.greyout_edges = function() { |
131 | $.each( self.node_elements, function(index, value) { |
132 | value.grey_out('.edge'); |
133 | }); |
134 | } |
135 | |
136 | this.ungreyout_edges = function() { |
137 | $.each( self.node_elements, function(index, value) { |
138 | value.un_grey_out('.edge'); |
139 | }); |
140 | } |
141 | |
142 | this.move_elements = function() { |
143 | $.each( self.node_elements, function(index, value) { |
144 | value.move(self.dx,self.dy); |
145 | }); |
146 | } |
147 | |
148 | this.reset_elements = function() { |
149 | $.each( self.node_elements, function(index, value) { |
150 | value.reset(); |
151 | }); |
152 | } |
153 | |
154 | this.update_elements = function() { |
155 | self.node_elements = node_elements_for(self.ellipse); |
156 | } |
157 | |
158 | self.set_draggable( true ); |
159 | } |
160 | |
161 | function svgshape( shape_element ) { |
162 | this.shape = shape_element; |
163 | this.move = function(dx,dy) { |
164 | this.shape.attr( "transform", "translate(" + dx + " " + dy + ")" ); |
165 | } |
166 | this.reset = function() { |
167 | this.shape.attr( "transform", "translate( 0, 0 )" ); |
168 | } |
169 | this.grey_out = function(filter) { |
170 | if( this.shape.parent(filter).size() != 0 ) { |
171 | this.shape.attr({'stroke':'#e5e5e5', 'fill':'#e5e5e5'}); |
172 | } |
173 | } |
174 | this.un_grey_out = function(filter) { |
175 | if( this.shape.parent(filter).size() != 0 ) { |
176 | this.shape.attr({'stroke':'#000000', 'fill':'#000000'}); |
177 | } |
178 | } |
179 | } |
180 | |
181 | function svgpath( path_element, svg_element ) { |
182 | this.svg_element = svg_element; |
183 | this.path = path_element; |
184 | this.x = this.path.x; |
185 | this.y = this.path.y; |
186 | this.move = function(dx,dy) { |
187 | this.path.x = this.x + dx; |
188 | this.path.y = this.y + dy; |
189 | } |
190 | this.reset = function() { |
191 | this.path.x = this.x; |
192 | this.path.y = this.y; |
193 | } |
194 | this.grey_out = function(filter) { |
195 | if( this.svg_element.parent(filter).size() != 0 ) { |
196 | this.svg_element.attr('stroke', '#e5e5e5'); |
197 | this.svg_element.siblings('text').attr('fill', '#e5e5e5'); |
198 | } |
199 | } |
200 | this.un_grey_out = function(filter) { |
201 | if( this.svg_element.parent(filter).size() != 0 ) { |
202 | this.svg_element.attr('stroke', '#000000'); |
203 | this.svg_element.siblings('text').attr('fill', '#000000'); |
204 | } |
205 | } |
206 | } |
207 | |
208 | function node_elements_for( ellipse ) { |
209 | node_elements = get_edge_elements_for( ellipse ); |
210 | node_elements.push( new svgshape( ellipse.siblings('text') ) ); |
211 | node_elements.push( new svgshape( ellipse ) ); |
212 | return node_elements; |
213 | } |
214 | |
215 | function get_edge_elements_for( ellipse ) { |
216 | edge_elements = new Array(); |
217 | node_id = ellipse.siblings('title').text(); |
218 | edge_in_pattern = new RegExp( node_id + '$' ); |
219 | edge_out_pattern = new RegExp( '^' + node_id ); |
220 | $.each( $('#svgenlargement .edge,#svgenlargement .relation').children('title'), function(index) { |
221 | title = $(this).text(); |
222 | if( edge_in_pattern.test(title) ) { |
223 | polygon = $(this).siblings('polygon'); |
224 | if( polygon.size() > 0 ) { |
225 | edge_elements.push( new svgshape( polygon ) ); |
226 | } |
227 | path_segments = $(this).siblings('path')[0].pathSegList; |
228 | edge_elements.push( new svgpath( path_segments.getItem(path_segments.numberOfItems - 1), $(this).siblings('path') ) ); |
229 | } |
230 | if( edge_out_pattern.test(title) ) { |
231 | path_segments = $(this).siblings('path')[0].pathSegList; |
232 | edge_elements.push( new svgpath( path_segments.getItem(0), $(this).siblings('path') ) ); |
233 | } |
234 | }); |
235 | return edge_elements; |
236 | } |
237 | |
238 | function relation_factory() { |
239 | var self = this; |
240 | this.color_memo = null; |
241 | //TODO: colors hard coded for now |
242 | this.temp_color = '#FFA14F'; |
243 | this.relation_colors = [ "#5CCCCC", "#67E667", "#F9FE72", "#6B90D4", "#FF7673", "#E467B3", "#AA67D5", "#8370D8", "#FFC173" ]; |
244 | |
245 | this.create_temporary = function( source_node_id, target_node_id ) { |
246 | var relation = $('#svgenlargement .relation').filter( function(index) { |
247 | var relation_id = $(this).children('title').text(); |
248 | if( ( relation_id == ( source_node_id + '->' + target_node_id ) ) || ( relation_id == ( target_node_id + '->' + source_node_id ) ) ) { |
249 | return true; |
250 | } |
251 | } ); |
252 | if( relation.size() == 0 ) { |
253 | draw_relation( source_node_id, target_node_id, self.temp_color ); |
254 | } else { |
255 | self.color_memo = relation.children('path').attr( 'stroke' ); |
256 | relation.children('path').attr( 'stroke', self.temp_color ); |
257 | } |
258 | } |
259 | this.remove_temporary = function() { |
260 | var path_element = $('#svgenlargement .relation').children('path[stroke="' + self.temp_color + '"]'); |
261 | if( self.color_memo != null ) { |
262 | path_element.attr( 'stroke', self.color_memo ); |
263 | self.color_memo = null; |
264 | } else { |
265 | path_element.parent('g').remove(); |
266 | } |
267 | } |
268 | this.create = function( source_node_id, target_node_id, color_index ) { |
269 | //TODO: Protect from (color_)index out of bound.. |
270 | var relation_color = self.relation_colors[ color_index ]; |
271 | draw_relation( source_node_id, target_node_id, relation_color ); |
272 | get_node_obj( source_node_id ).update_elements(); |
273 | get_node_obj( target_node_id ).update_elements(); |
274 | } |
275 | this.remove = function( source_node_id, target_id ) { |
276 | //TODO (When needed) |
277 | console.log( "Unsupported function node_obj.remove()." ); |
278 | } |
279 | } |
280 | |
281 | function draw_relation( source_id, target_id, relation_color ) { |
282 | var source_ellipse = get_ellipse( source_id ); |
283 | var target_ellipse = get_ellipse( target_id ); |
284 | var svg = $('#svgenlargement').children('svg').svg().svg('get'); |
285 | var path = svg.createPath(); |
286 | var sx = parseInt( source_ellipse.attr('cx') ); |
287 | var rx = parseInt( source_ellipse.attr('rx') ); |
288 | var sy = parseInt( source_ellipse.attr('cy') ); |
289 | var ex = parseInt( target_ellipse.attr('cx') ); |
290 | var ey = parseInt( target_ellipse.attr('cy') ); |
291 | var relation = svg.group( $("#svgenlargement svg g"), {'class':'relation'} ); |
292 | svg.title( relation, source_id + '->' + target_id ); |
293 | 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}); |
294 | var relation_element = $('#svgenlargement .relation').filter( ':last' ); |
295 | relation_element.insertBefore( $('#svgenlargement g g').filter(':first') ); |
296 | } |
297 | |
298 | $(document).ready(function () { |
299 | |
300 | relation_manager = new relation_factory(); |
301 | |
302 | scroll_ratio = $('#enlargement').height() / $('#graph').height(); |
303 | |
304 | $('#graph').mousedown(function (event) { |
305 | $(this) |
306 | .data('down', true) |
307 | .data('x', event.clientX) |
308 | .data('scrollLeft', this.scrollLeft); |
309 | return false; |
310 | }).mouseup(function (event) { |
311 | $(this).data('down', false); |
312 | }).mousemove(function (event) { |
313 | if ($(this).data('down') == true ) { |
314 | if ( $('#update_workspace_button').data('locked') != true ) { |
315 | var scroll_left = $(this).data('scrollLeft') + $(this).data('x') - event.clientX; |
316 | this.scrollLeft = scroll_left; |
317 | var enlarged_scroll_left = scroll_left * scroll_ratio; |
318 | $('#enlargement').scrollLeft( enlarged_scroll_left ); |
319 | color_enlarged(); |
320 | } |
321 | } |
322 | }).mousewheel(function (event, delta) { |
323 | if ( $('#update_workspace_button').data('locked') != true ) { |
324 | var scroll_left = delta * 30; |
325 | this.scrollLeft -= scroll_left; |
326 | var enlarged_scroll_left = $('#enlargement').scrollLeft(); |
327 | enlarged_scroll_left -= (scroll_left * scroll_ratio); |
328 | $('#enlargement').scrollLeft( enlarged_scroll_left ); |
329 | color_enlarged(); |
330 | } |
331 | }).css({ |
332 | 'overflow' : 'hidden', |
333 | 'cursor' : '-moz-grab' |
334 | }); |
335 | |
336 | |
337 | $( "#dialog-form" ).dialog({ |
338 | autoOpen: false, |
339 | height: 270, |
340 | width: 290, |
341 | modal: true, |
342 | buttons: { |
343 | "Ok": function() { |
344 | $('#status').empty(); |
345 | form_values = $('#collapse_node_form').serialize() |
346 | ncpath = window.location.pathname + '/relationship'; |
347 | var jqjson = $.post( ncpath, form_values, function(data) { |
348 | $.each( data, function(item, source_target) { |
349 | relation_manager.create( source_target[0], source_target[1], $('#rel_type').attr('selectedIndex') ); |
350 | }); |
351 | relation_manager.remove_temporary(); |
352 | $( "#dialog-form" ).dialog( "close" ); |
353 | }, 'json'); |
354 | }, |
355 | Cancel: function() { |
356 | relation_manager.remove_temporary(); |
357 | $( this ).dialog( "close" ); |
358 | } |
359 | }, |
360 | create: function(event, ui) { |
361 | $(this).data( 'relation_drawn', false ); |
362 | //TODO? Err handling? |
363 | var jqjson = $.getJSON( 'relationship_definition', function(data) { |
364 | var types = data.types.sort(); |
365 | $.each( types, function(index, value) { |
366 | $('#rel_type').append( $('<option>').attr( "value", value ).text(value) ); |
367 | $('#keymaplist').append( $('<li>').css( "border-color", relation_manager.relation_colors[index] ).text(value) ); |
368 | }); |
369 | var scopes = data.scopes; |
370 | $.each( scopes, function(index, value) { |
371 | $('#scope').append( $('<option>').attr( "value", value ).text(value) ); |
372 | }); |
373 | }); |
374 | }, |
375 | open: function() { |
376 | relation_manager.create_temporary( $('#source_node_id').val(), $('#target_node_id').val() ); |
377 | $(".ui-widget-overlay").css("background", "none"); |
378 | $("#dialog_overlay").show(); |
379 | $("#dialog_overlay").height( $("#enlargement_container").height() ); |
380 | $("#dialog_overlay").width( $("#enlargement_container").width() ); |
381 | $("#dialog_overlay").offset( $("#enlargement_container").offset() ); |
382 | }, |
383 | close: function() { |
384 | $( '#status' ).empty(); |
385 | $("#dialog_overlay").hide(); |
386 | } |
387 | }).ajaxError( function(event, jqXHR, ajaxSettings, thrownError) { |
388 | if( ( ajaxSettings.url.split("?")[0] == 'set_relationship' ) && jqXHR.status == 403 ) { |
389 | $('#status').append( '<p class="error">The relationship can not be made in this way between these nodes.</p>' ); |
390 | } |
391 | } ); |
392 | |
393 | $('#update_workspace_button').click( function() { |
394 | var svg_enlargement = $('#svgenlargement').svg().svg('get').root(); |
395 | if( $(this).data('locked')==true) { |
396 | $.each( ellipses_in_magnifier, function( index, ellipse ) { |
397 | ellipse.data( 'node_obj' ).ungreyout_edges(); |
398 | ellipse.data( 'node_obj' ).set_draggable( false ); |
399 | ellipse.data( 'node_obj', null ); |
400 | }) |
401 | svg_enlargement.children[0].setAttribute( 'transform', $(this).data('transform_memo') ); |
402 | $('#enlargement').scrollLeft( $(this).data('scrollleft_memo') ); |
403 | $(this).data('locked', false); |
404 | $(this).css('background-position', '0px 0px'); |
405 | } else { |
406 | $(this).css('background-position', '0px 17px'); |
407 | var y_min = parseInt( ellipses_in_magnifier[0].attr('cy') ) - parseInt( ellipses_in_magnifier[0].attr('ry') ); |
408 | var y_max = parseInt( ellipses_in_magnifier[0].attr('cy') ) + parseInt( ellipses_in_magnifier[0].attr('ry') ); |
409 | $.each( ellipses_in_magnifier, function( index, ellipse ) { |
410 | var ny_min = parseInt( ellipse.attr('cy') ) - parseInt( ellipse.attr('ry') ); |
411 | var ny_max = parseInt( ellipse.attr('cy') ) + parseInt( ellipse.attr('ry') ); |
412 | if( ny_min < y_min ) { y_min = ny_min }; |
413 | if( ny_max > y_max ) { y_max = ny_max }; |
414 | if( ellipse.data( 'node_obj' ) == null ) { |
415 | ellipse.data( 'node_obj', new node_obj( ellipse ) ); |
416 | } else { |
417 | ellipse.data( 'node_obj' ).set_draggable( true ); |
418 | } |
419 | ellipse.data( 'node_obj' ).greyout_edges(); |
420 | }) |
421 | var graph_frag_height = y_max - y_min ; |
422 | var svg_enlargement_vbheight = svg_enlargement.viewBox.baseVal.height; |
423 | var svg_enlargement_vbwidth = svg_enlargement.viewBox.baseVal.width; |
424 | var scale = svg_enlargement_vbheight / graph_frag_height; |
425 | mousemove_enlargement_ratio = scroll_enlargement_ratio * scale; |
426 | var scroll_padding = $('#enlargement_container').width(); |
427 | var scroll_scale = svg_enlargement_vbwidth / ( parseFloat( $('#svgenlargement svg').attr('width') ) - scroll_padding ); |
428 | var vbx_of_scroll = ( $('#enlargement').scrollLeft() ) * scroll_scale; |
429 | var translate_x = vbx_of_scroll; |
430 | var transform = svg_enlargement.children[0].getAttribute('transform'); |
431 | $(this).data('transform_memo', transform ); |
432 | $(this).data('scrollleft_memo', $('#enlargement').scrollLeft() ); |
433 | $(this).data('locked', true ); |
434 | $('#enlargement').scrollLeft(0); |
435 | transform = 'scale(' + scale + ') translate(' + (-1 * translate_x) + ',' + (-1 * y_min) + ')'; |
436 | svg_enlargement.children[0].setAttribute( 'transform', transform ); |
437 | } |
438 | }); |
439 | |
440 | }); |
441 | |
442 | $(window).mouseout(function (event) { |
443 | if ($('#graph').data('down')) { |
444 | try { |
445 | if (event.originalTarget.nodeName == 'BODY' || event.originalTarget.nodeName == 'HTML') { |
446 | $('#graph').data('down', false); |
447 | } |
448 | } catch (e) {} |
449 | } |
450 | }); |
451 | |
452 | function color_enlarged() { |
453 | ellipses_in_magnifier = []; |
454 | var scroll_offset = parseInt( $('#enlargement').scrollLeft() ); |
455 | var scroll_padding = $('#enlargement_container').width()/2; |
456 | $('#svgenlargement ellipse,#svgbasics ellipse' ).each( function( index ) { |
457 | var cpos_inscrollcoor = parseInt( $(this).attr('cx') ) * scroll_enlargement_ratio; |
458 | if ( ( cpos_inscrollcoor > (scroll_offset - scroll_padding) ) && ( cpos_inscrollcoor < ( scroll_offset + scroll_padding ) ) ) { |
459 | $(this).attr( {stroke:'green', fill:'#b3f36d'} ); |
460 | if( $(this).parents('#svgenlargement').size() == 1 ) { ellipses_in_magnifier.push( $(this) ) }; |
461 | } else { |
462 | $(this).attr( {stroke:'black', fill:'#fff'} ); |
463 | } |
464 | }); |
465 | } |
466 | |
467 | |
468 | |
469 | |