Commit | Line | Data |
b8a92065 |
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 | $('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 | |
31 | function add_node_objs() { |
32 | $('ellipse[fill="#fff"]').each( function() { |
33 | $(this).data( 'node_obj', new node_obj( $(this) ) ); |
34 | } |
35 | ); |
36 | } |
37 | |
38 | function 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 | |
44 | function get_edge( edge_id ) { |
45 | return $('.edge').filter( function(index) { |
46 | return $(this).children( 'title' ).text() == $('<div/>').html(edge_id).text() ; |
47 | }); |
48 | } |
49 | |
50 | function 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() + ' ' ); |
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( ' … ' ); |
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 | |
200 | function 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 | |
210 | function 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 | |
224 | function 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 | |
231 | function 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 | |