Commit | Line | Data |
76f05423 |
1 | var MARGIN=30; |
2 | var svg_root = null; |
3 | var svg_root_element = null; |
4 | var start_element_height = 0; |
5 | var reltypes = {}; |
5f15640c |
6 | var readingdata = {}; |
76f05423 |
7 | |
a471cb0f |
8 | jQuery.removeFromArray = function(value, arr) { |
9 | return jQuery.grep(arr, function(elem, index) { |
10 | return elem !== value; |
11 | }); |
12 | }; |
13 | |
a84ca4de |
14 | function arrayUnique(array) { |
15 | var a = array.concat(); |
16 | for(var i=0; i<a.length; ++i) { |
17 | for(var j=i+1; j<a.length; ++j) { |
18 | if(a[i] === a[j]) |
19 | a.splice(j--, 1); |
20 | } |
21 | } |
22 | return a; |
23 | }; |
24 | |
5f15640c |
25 | function getTextURL( which ) { |
3f9d7ae5 |
26 | return basepath + textid + '/' + which; |
5f15640c |
27 | } |
28 | |
29 | function getReadingURL( reading_id ) { |
3f9d7ae5 |
30 | return basepath + textid + '/reading/' + reading_id; |
b28e606e |
31 | } |
32 | |
45ee3b96 |
33 | // Make an XML ID into a valid selector |
34 | function jq(myid) { |
35 | return '#' + myid.replace(/(:|\.)/g,'\\$1'); |
36 | } |
37 | |
065c7cf2 |
38 | // Actions for opening the reading panel |
39 | function node_dblclick_listener( evt ) { |
40 | // Open the reading dialogue for the given node. |
41 | // First get the reading info |
42 | var reading_id = $(this).attr('id'); |
43 | var reading_info = readingdata[reading_id]; |
44 | // and then populate the dialog box with it. |
45 | // Set the easy properties first |
46 | $('#reading-form').dialog( 'option', 'title', 'Reading information for "' + reading_info['text'] + '"' ); |
47 | $('#reading_id').val( reading_id ); |
798fa939 |
48 | toggle_checkbox( $('#reading_is_nonsense'), reading_info['is_nonsense'] ); |
49 | toggle_checkbox( $('#reading_grammar_invalid'), reading_info['grammar_invalid'] ); |
065c7cf2 |
50 | // Use .text as a backup for .normal_form |
51 | var normal_form = reading_info['normal_form']; |
52 | if( !normal_form ) { |
53 | normal_form = reading_info['text']; |
54 | } |
55 | var nfboxsize = 10; |
56 | if( normal_form.length > 9 ) { |
57 | nfboxsize = normal_form.length + 1; |
58 | } |
59 | $('#reading_normal_form').attr( 'size', nfboxsize ) |
60 | $('#reading_normal_form').val( normal_form ); |
61 | // Now do the morphological properties. |
0dcdd5ec |
62 | morphology_form( reading_info['lexemes'] ); |
065c7cf2 |
63 | // and then open the dialog. |
0dcdd5ec |
64 | $('#reading-form').dialog("open"); |
65 | } |
66 | |
798fa939 |
67 | function toggle_checkbox( box, value ) { |
68 | if( value == null ) { |
69 | value = false; |
70 | } |
71 | box.attr('checked', value ); |
72 | } |
73 | |
0dcdd5ec |
74 | function morphology_form ( lexlist ) { |
487674b9 |
75 | if( lexlist.length ) { |
76 | $('#morph_outer').show(); |
77 | $('#morphology').empty(); |
78 | $.each( lexlist, function( idx, lex ) { |
79 | var morphoptions = []; |
80 | if( 'wordform_matchlist' in lex ) { |
81 | $.each( lex['wordform_matchlist'], function( tdx, tag ) { |
82 | var tagstr = stringify_wordform( tag ); |
83 | morphoptions.push( tagstr ); |
84 | }); |
85 | } |
86 | var formtag = 'morphology_' + idx; |
87 | var formstr = ''; |
88 | if( 'form' in lex ) { |
89 | formstr = stringify_wordform( lex['form'] ); |
90 | } |
91 | var form_morph_elements = morph_elements( |
92 | formtag, lex['string'], formstr, morphoptions ); |
93 | $.each( form_morph_elements, function( idx, el ) { |
94 | $('#morphology').append( el ); |
08f8443a |
95 | }); |
065c7cf2 |
96 | }); |
487674b9 |
97 | } else { |
98 | $('#morph_outer').hide(); |
99 | } |
065c7cf2 |
100 | } |
101 | |
102 | function stringify_wordform ( tag ) { |
08f8443a |
103 | if( tag ) { |
104 | var elements = tag.split(' // '); |
105 | return elements[1] + ' // ' + elements[2]; |
106 | } |
107 | return '' |
065c7cf2 |
108 | } |
109 | |
d1132306 |
110 | function morph_elements ( formtag, formtxt, currform, morphoptions ) { |
111 | var clicktag = '(Click to select)'; |
112 | if ( !currform ) { |
113 | currform = clicktag; |
114 | } |
065c7cf2 |
115 | var formlabel = $('<label/>').attr( 'id', 'label_' + formtag ).attr( |
d1132306 |
116 | 'for', 'reading_' + formtag ).text( formtxt + ': ' ); |
065c7cf2 |
117 | var forminput = $('<input/>').attr( 'id', 'reading_' + formtag ).attr( |
0dcdd5ec |
118 | 'name', 'reading_' + formtag ).attr( 'size', '50' ).attr( |
119 | 'class', 'reading_morphology' ).val( currform ); |
d1132306 |
120 | forminput.autocomplete({ source: morphoptions, minLength: 0 }); |
121 | forminput.focus( function() { |
122 | if( $(this).val() == clicktag ) { |
123 | $(this).val(''); |
124 | } |
125 | $(this).autocomplete('search', '') |
126 | }); |
065c7cf2 |
127 | var morphel = [ formlabel, forminput, $('<br/>') ]; |
128 | return morphel; |
129 | } |
130 | |
4c41c02c |
131 | function color_inactive ( el ) { |
132 | var reading_id = $(el).parent().attr('id'); |
133 | var reading_info = readingdata[reading_id]; |
134 | // If the reading info has any non-disambiguated lexemes, color it yellow; |
135 | // otherwise color it green. |
136 | $(el).attr( {stroke:'green', fill:'#b3f36d'} ); |
bb3230b1 |
137 | if( reading_info ) { |
138 | $.each( reading_info['lexemes'], function ( idx, lex ) { |
139 | if( !lex['is_disambiguated'] || lex['is_disambiguated'] == 0 ) { |
140 | $(el).attr( {stroke:'orange', fill:'#fee233'} ); |
141 | } |
142 | }); |
143 | } |
4c41c02c |
144 | } |
145 | |
997ebe92 |
146 | function relemmatize () { |
147 | // Send the reading for a new lemmatization and reopen the form. |
a0a66634 |
148 | $('#relemmatize_pending').show(); |
997ebe92 |
149 | var reading_id = $('#reading_id').val() |
150 | ncpath = getReadingURL( reading_id ); |
151 | form_values = { |
152 | 'normal_form': $('#reading_normal_form').val(), |
153 | 'relemmatize': 1 }; |
154 | var jqjson = $.post( ncpath, form_values, function( data ) { |
155 | // Update the form with the return |
156 | if( 'id' in data ) { |
157 | // We got back a good answer. Stash it |
158 | readingdata[reading_id] = data; |
159 | // and regenerate the morphology form. |
160 | morphology_form( data['lexemes'] ); |
161 | } else { |
162 | alert("Could not relemmatize as requested: " + data['error']); |
163 | } |
a0a66634 |
164 | $('#relemmatize_pending').hide(); |
997ebe92 |
165 | }); |
166 | } |
167 | |
065c7cf2 |
168 | // Initialize the SVG once it exists |
b28e606e |
169 | function svgEnlargementLoaded() { |
fc018906 |
170 | //Give some visual evidence that we are working |
171 | $('#loading_overlay').show(); |
172 | lo_height = $("#enlargement_container").outerHeight(); |
173 | lo_width = $("#enlargement_container").outerWidth(); |
174 | $("#loading_overlay").height( lo_height ); |
175 | $("#loading_overlay").width( lo_width ); |
176 | $("#loading_overlay").offset( $("#enlargement_container").offset() ); |
177 | $("#loading_message").offset( |
178 | { 'top': lo_height / 2 - $("#loading_message").height() / 2, |
179 | 'left': lo_width / 2 - $("#loading_message").width() / 2 }); |
30d0ba1e |
180 | if( editable ) { |
181 | // Show the update toggle button. |
182 | $('#update_workspace_button').data('locked', false); |
183 | $('#update_workspace_button').css('background-position', '0px 44px'); |
184 | } |
065c7cf2 |
185 | $('#svgenlargement ellipse').parent().dblclick( node_dblclick_listener ); |
9529f69c |
186 | var graph_svg = $('#svgenlargement svg'); |
187 | var svg_g = $('#svgenlargement svg g')[0]; |
76f05423 |
188 | if (!svg_g) return; |
9529f69c |
189 | svg_root = graph_svg.svg().svg('get').root(); |
76f05423 |
190 | |
191 | // Find the real root and ignore any text nodes |
192 | for (i = 0; i < svg_root.childNodes.length; ++i) { |
193 | if (svg_root.childNodes[i].nodeName != '#text') { |
194 | svg_root_element = svg_root.childNodes[i]; |
195 | break; |
196 | } |
197 | } |
198 | |
30d0ba1e |
199 | //Set viewbox width and height to width and height of $('#svgenlargement svg'). |
200 | //This is essential to make sure zooming and panning works properly. |
9529f69c |
201 | svg_root.viewBox.baseVal.width = graph_svg.attr( 'width' ); |
202 | svg_root.viewBox.baseVal.height = graph_svg.attr( 'height' ); |
203 | //Now set scale and translate so svg height is about 150px and vertically centered in viewbox. |
204 | //This is just to create a nice starting enlargement. |
205 | var initial_svg_height = 250; |
206 | var scale = initial_svg_height/graph_svg.attr( 'height' ); |
207 | var additional_translate = (graph_svg.attr( 'height' ) - initial_svg_height)/(2*scale); |
208 | var transform = svg_g.getAttribute('transform'); |
209 | var translate = parseFloat( transform.match( /translate\([^\)]*\)/ )[0].split('(')[1].split(' ')[1].split(')')[0] ); |
210 | translate += additional_translate; |
211 | var transform = 'rotate(0) scale(' + scale + ') translate(4 ' + translate + ')'; |
212 | svg_g.setAttribute('transform', transform); |
213 | //used to calculate min and max zoom level: |
4c41c02c |
214 | start_element_height = $('#__START__').children('ellipse')[0].getBBox().height; |
e538eccb |
215 | //some use of call backs to ensure succesive execution |
216 | add_relations( function() { |
217 | var rdgpath = getTextURL( 'readings' ); |
218 | $.getJSON( rdgpath, function( data ) { |
219 | readingdata = data; |
220 | $('#svgenlargement ellipse').each( function( i, el ) { color_inactive( el ) }); |
9231663d |
221 | $('#loading_overlay').hide(); |
e538eccb |
222 | }); |
e538eccb |
223 | }); |
c1add777 |
224 | |
225 | //initialize marquee |
226 | marquee = new Marquee(); |
89aae3ee |
227 | |
228 | if (text_direction == 'RL') { |
229 | scrollToEnd(); |
230 | } |
6afcd813 |
231 | } |
232 | |
fc018906 |
233 | function add_relations( callback_fn ) { |
56e3972e |
234 | // Add the relationship types to the keymap list |
56e3972e |
235 | $.each( relationship_types, function(index, typedef) { |
671c04b1 |
236 | li_elm = $('<li class="key">').css( "border-color", |
237 | relation_manager.relation_colors[index] ).text(typedef.name); |
238 | li_elm.append( $('<div>').attr('class', 'key_tip_container').append( |
239 | $('<div>').attr('class', 'key_tip').text(typedef.description) ) ); |
cfefd283 |
240 | $('#keymaplist').append( li_elm ); |
56e3972e |
241 | }); |
242 | // Now fetch the relationships themselves and add them to the graph |
243 | var rel_types = $.map( relationship_types, function(t) { return t.name }); |
244 | // Save this list of names to the outer element data so that the relationship |
245 | // factory can access it |
246 | $('#keymap').data('relations', rel_types); |
5f15640c |
247 | var textrelpath = getTextURL( 'relationships' ); |
56e3972e |
248 | $.getJSON( textrelpath, function(data) { |
249 | $.each(data, function( index, rel_info ) { |
250 | var type_index = $.inArray(rel_info.type, rel_types); |
51ca18ee |
251 | var source_found = get_ellipse( rel_info.source_id ); |
252 | var target_found = get_ellipse( rel_info.target_id ); |
cfa6ff76 |
253 | var emphasis = rel_info.is_significant; |
56e3972e |
254 | if( type_index != -1 && source_found.size() && target_found.size() ) { |
48a371e5 |
255 | var relation = relation_manager.create( rel_info.source_id, rel_info.target_id, type_index, emphasis ); |
51ca18ee |
256 | // Save the relationship data too. |
257 | $.each( rel_info, function( k, v ) { |
258 | relation.data( k, v ); |
259 | }); |
30d0ba1e |
260 | if( editable ) { |
51ca18ee |
261 | var node_obj = get_node_obj(rel_info.source_id); |
e538eccb |
262 | node_obj.set_selectable( false ); |
30d0ba1e |
263 | node_obj.ellipse.data( 'node_obj', null ); |
51ca18ee |
264 | node_obj = get_node_obj(rel_info.target_id); |
e538eccb |
265 | node_obj.set_selectable( false ); |
30d0ba1e |
266 | node_obj.ellipse.data( 'node_obj', null ); |
267 | } |
56e3972e |
268 | } |
269 | }); |
270 | callback_fn.call(); |
271 | }); |
b28e606e |
272 | } |
273 | |
274 | function get_ellipse( node_id ) { |
45ee3b96 |
275 | return $( jq( node_id ) + ' ellipse'); |
b28e606e |
276 | } |
277 | |
278 | function get_node_obj( node_id ) { |
9529f69c |
279 | var node_ellipse = get_ellipse( node_id ); |
280 | if( node_ellipse.data( 'node_obj' ) == null ) { |
281 | node_ellipse.data( 'node_obj', new node_obj(node_ellipse) ); |
282 | }; |
283 | return node_ellipse.data( 'node_obj' ); |
b28e606e |
284 | } |
285 | |
b28e606e |
286 | function node_obj(ellipse) { |
287 | this.ellipse = ellipse; |
288 | var self = this; |
289 | |
290 | this.x = 0; |
291 | this.y = 0; |
292 | this.dx = 0; |
293 | this.dy = 0; |
294 | this.node_elements = node_elements_for(self.ellipse); |
22a70299 |
295 | |
b28e606e |
296 | this.get_id = function() { |
45ee3b96 |
297 | return $(self.ellipse).parent().attr('id') |
b28e606e |
298 | } |
299 | |
e538eccb |
300 | this.set_selectable = function( clickable ) { |
301 | if( clickable && editable ) { |
302 | $(self.ellipse).attr( {stroke:'black', fill:'#fff'} ); |
303 | $(self.ellipse).parent().hover( this.enter_node, this.leave_node ); |
304 | $(self.ellipse).parent().mousedown( function(evt) { evt.stopPropagation() } ); |
305 | $(self.ellipse).parent().click( function(evt) { |
306 | evt.stopPropagation(); |
307 | if( $('ellipse[fill="#9999ff"]').size() > 0 ) { |
308 | $('ellipse[fill="#9999ff"]').each( function() { |
309 | $(this).data( 'node_obj' ).set_draggable( false ); |
310 | } ); |
311 | } |
312 | self.set_draggable( true ) |
313 | }); |
314 | } else { |
315 | $(self.ellipse).attr( {stroke:'black', fill:'#fff'} ); |
316 | self.ellipse.siblings('text').attr('class', ''); |
317 | $(self.ellipse).parent().unbind(); |
318 | $('body').unbind('mousemove'); |
319 | $('body').unbind('mouseup'); |
320 | } |
321 | } |
322 | |
b28e606e |
323 | this.set_draggable = function( draggable ) { |
30d0ba1e |
324 | if( draggable && editable ) { |
e538eccb |
325 | $(self.ellipse).attr( {stroke:'black', fill:'#9999ff'} ); |
05485bfd |
326 | $(self.ellipse).parent().mousedown( this.mousedown_listener ); |
e538eccb |
327 | $(self.ellipse).parent().unbind( 'mouseenter' ).unbind( 'mouseleave' ); |
05485bfd |
328 | self.ellipse.siblings('text').attr('class', 'noselect draggable'); |
b28e606e |
329 | } else { |
e538eccb |
330 | $(self.ellipse).attr( {stroke:'black', fill:'#fff'} ); |
05485bfd |
331 | self.ellipse.siblings('text').attr('class', ''); |
e538eccb |
332 | $(self.ellipse).parent().unbind( 'mousedown '); |
333 | $(self.ellipse).parent().mousedown( function(evt) { evt.stopPropagation() } ); |
334 | $(self.ellipse).parent().hover( this.enter_node, this.leave_node ); |
b28e606e |
335 | } |
336 | } |
337 | |
338 | this.mousedown_listener = function(evt) { |
339 | evt.stopPropagation(); |
340 | self.x = evt.clientX; |
341 | self.y = evt.clientY; |
342 | $('body').mousemove( self.mousemove_listener ); |
343 | $('body').mouseup( self.mouseup_listener ); |
05485bfd |
344 | $(self.ellipse).parent().unbind('mouseenter').unbind('mouseleave') |
e538eccb |
345 | self.ellipse.attr( 'fill', '#6b6bb2' ); |
b28e606e |
346 | first_node_g_element = $("#svgenlargement g .node" ).filter( ":first" ); |
347 | if( first_node_g_element.attr('id') !== self.get_g().attr('id') ) { self.get_g().insertBefore( first_node_g_element ) }; |
348 | } |
349 | |
350 | this.mousemove_listener = function(evt) { |
9529f69c |
351 | self.dx = (evt.clientX - self.x) / mouse_scale; |
352 | self.dy = (evt.clientY - self.y) / mouse_scale; |
b28e606e |
353 | self.move_elements(); |
05485bfd |
354 | evt.returnValue = false; |
355 | evt.preventDefault(); |
356 | return false; |
b28e606e |
357 | } |
358 | |
359 | this.mouseup_listener = function(evt) { |
360 | if( $('ellipse[fill="#ffccff"]').size() > 0 ) { |
45ee3b96 |
361 | var source_node_id = $(self.ellipse).parent().attr('id'); |
05485bfd |
362 | var source_node_text = self.ellipse.siblings('text').text(); |
45ee3b96 |
363 | var target_node_id = $('ellipse[fill="#ffccff"]').parent().attr('id'); |
05485bfd |
364 | var target_node_text = $('ellipse[fill="#ffccff"]').siblings("text").text(); |
b28e606e |
365 | $('#source_node_id').val( source_node_id ); |
05485bfd |
366 | $('#source_node_text').val( source_node_text ); |
51ca18ee |
367 | $('.rel_rdg_a').text( "'" + source_node_text + "'" ); |
b28e606e |
368 | $('#target_node_id').val( target_node_id ); |
05485bfd |
369 | $('#target_node_text').val( target_node_text ); |
51ca18ee |
370 | $('.rel_rdg_b').text( "'" + target_node_text + "'" ); |
b28e606e |
371 | $('#dialog-form').dialog( 'open' ); |
372 | }; |
373 | $('body').unbind('mousemove'); |
374 | $('body').unbind('mouseup'); |
e538eccb |
375 | self.ellipse.attr( 'fill', '#9999ff' ); |
9529f69c |
376 | self.reset_elements(); |
b28e606e |
377 | } |
f2fb96fc |
378 | |
b28e606e |
379 | this.cpos = function() { |
380 | return { x: self.ellipse.attr('cx'), y: self.ellipse.attr('cy') }; |
381 | } |
382 | |
383 | this.get_g = function() { |
384 | return self.ellipse.parent('g'); |
385 | } |
386 | |
387 | this.enter_node = function(evt) { |
388 | self.ellipse.attr( 'fill', '#ffccff' ); |
389 | } |
390 | |
391 | this.leave_node = function(evt) { |
392 | self.ellipse.attr( 'fill', '#fff' ); |
393 | } |
394 | |
395 | this.greyout_edges = function() { |
396 | $.each( self.node_elements, function(index, value) { |
397 | value.grey_out('.edge'); |
398 | }); |
399 | } |
400 | |
401 | this.ungreyout_edges = function() { |
402 | $.each( self.node_elements, function(index, value) { |
403 | value.un_grey_out('.edge'); |
404 | }); |
405 | } |
406 | |
6c8d1880 |
407 | this.reposition = function( dx, dy ) { |
408 | $.each( self.node_elements, function(index, value) { |
409 | value.reposition( dx, dy ); |
410 | } ); |
411 | } |
412 | |
b28e606e |
413 | this.move_elements = function() { |
414 | $.each( self.node_elements, function(index, value) { |
6c8d1880 |
415 | value.move( self.dx, self.dy ); |
22a70299 |
416 | } ); |
b28e606e |
417 | } |
418 | |
419 | this.reset_elements = function() { |
420 | $.each( self.node_elements, function(index, value) { |
6c8d1880 |
421 | value.reset(); |
22a70299 |
422 | } ); |
b28e606e |
423 | } |
424 | |
425 | this.update_elements = function() { |
426 | self.node_elements = node_elements_for(self.ellipse); |
427 | } |
428 | |
a84ca4de |
429 | this.get_witnesses = function() { |
430 | return readingdata[self.get_id()].witnesses |
431 | } |
6c8d1880 |
432 | |
e538eccb |
433 | self.set_selectable( true ); |
b28e606e |
434 | } |
435 | |
436 | function svgshape( shape_element ) { |
437 | this.shape = shape_element; |
6c8d1880 |
438 | this.reposx = 0; |
439 | this.reposy = 0; |
440 | this.repositioned = this.shape.parent().data( 'repositioned' ); |
441 | if( this.repositioned != null ) { |
442 | this.reposx = this.repositioned[0]; |
443 | this.reposy = this.repositioned[1]; |
444 | } |
445 | this.reposition = function (dx, dy) { |
446 | this.move( dx, dy ); |
447 | this.reposx = this.reposx + dx; |
448 | this.reposy = this.reposy + dy; |
449 | this.shape.parent().data( 'repositioned', [this.reposx,this.reposy] ); |
450 | } |
b28e606e |
451 | this.move = function(dx,dy) { |
6c8d1880 |
452 | this.shape.attr( "transform", "translate( " + (this.reposx + dx) + " " + (this.reposy + dy) + " )" ); |
b28e606e |
453 | } |
454 | this.reset = function() { |
6c8d1880 |
455 | this.shape.attr( "transform", "translate( " + this.reposx + " " + this.reposy + " )" ); |
b28e606e |
456 | } |
457 | this.grey_out = function(filter) { |
458 | if( this.shape.parent(filter).size() != 0 ) { |
459 | this.shape.attr({'stroke':'#e5e5e5', 'fill':'#e5e5e5'}); |
460 | } |
461 | } |
462 | this.un_grey_out = function(filter) { |
463 | if( this.shape.parent(filter).size() != 0 ) { |
464 | this.shape.attr({'stroke':'#000000', 'fill':'#000000'}); |
465 | } |
466 | } |
467 | } |
468 | |
469 | function svgpath( path_element, svg_element ) { |
470 | this.svg_element = svg_element; |
471 | this.path = path_element; |
472 | this.x = this.path.x; |
473 | this.y = this.path.y; |
6c8d1880 |
474 | |
475 | this.reposition = function (dx, dy) { |
476 | this.x = this.x + dx; |
477 | this.y = this.y + dy; |
478 | this.path.x = this.x; |
479 | this.path.y = this.y; |
480 | } |
481 | |
b28e606e |
482 | this.move = function(dx,dy) { |
483 | this.path.x = this.x + dx; |
484 | this.path.y = this.y + dy; |
485 | } |
6c8d1880 |
486 | |
b28e606e |
487 | this.reset = function() { |
488 | this.path.x = this.x; |
489 | this.path.y = this.y; |
490 | } |
6c8d1880 |
491 | |
b28e606e |
492 | this.grey_out = function(filter) { |
493 | if( this.svg_element.parent(filter).size() != 0 ) { |
494 | this.svg_element.attr('stroke', '#e5e5e5'); |
495 | this.svg_element.siblings('text').attr('fill', '#e5e5e5'); |
05485bfd |
496 | this.svg_element.siblings('text').attr('class', 'noselect'); |
b28e606e |
497 | } |
498 | } |
499 | this.un_grey_out = function(filter) { |
500 | if( this.svg_element.parent(filter).size() != 0 ) { |
501 | this.svg_element.attr('stroke', '#000000'); |
502 | this.svg_element.siblings('text').attr('fill', '#000000'); |
05485bfd |
503 | this.svg_element.siblings('text').attr('class', ''); |
b28e606e |
504 | } |
505 | } |
506 | } |
507 | |
508 | function node_elements_for( ellipse ) { |
509 | node_elements = get_edge_elements_for( ellipse ); |
510 | node_elements.push( new svgshape( ellipse.siblings('text') ) ); |
511 | node_elements.push( new svgshape( ellipse ) ); |
512 | return node_elements; |
513 | } |
514 | |
515 | function get_edge_elements_for( ellipse ) { |
516 | edge_elements = new Array(); |
45ee3b96 |
517 | node_id = ellipse.parent().attr('id'); |
b28e606e |
518 | edge_in_pattern = new RegExp( node_id + '$' ); |
22a70299 |
519 | edge_out_pattern = new RegExp( '^' + node_id + '-' ); |
b28e606e |
520 | $.each( $('#svgenlargement .edge,#svgenlargement .relation').children('title'), function(index) { |
521 | title = $(this).text(); |
522 | if( edge_in_pattern.test(title) ) { |
523 | polygon = $(this).siblings('polygon'); |
524 | if( polygon.size() > 0 ) { |
525 | edge_elements.push( new svgshape( polygon ) ); |
526 | } |
527 | path_segments = $(this).siblings('path')[0].pathSegList; |
528 | edge_elements.push( new svgpath( path_segments.getItem(path_segments.numberOfItems - 1), $(this).siblings('path') ) ); |
529 | } |
530 | if( edge_out_pattern.test(title) ) { |
531 | path_segments = $(this).siblings('path')[0].pathSegList; |
532 | edge_elements.push( new svgpath( path_segments.getItem(0), $(this).siblings('path') ) ); |
533 | } |
534 | }); |
535 | return edge_elements; |
536 | } |
537 | |
538 | function relation_factory() { |
539 | var self = this; |
540 | this.color_memo = null; |
541 | //TODO: colors hard coded for now |
542 | this.temp_color = '#FFA14F'; |
543 | this.relation_colors = [ "#5CCCCC", "#67E667", "#F9FE72", "#6B90D4", "#FF7673", "#E467B3", "#AA67D5", "#8370D8", "#FFC173" ]; |
544 | |
545 | this.create_temporary = function( source_node_id, target_node_id ) { |
45ee3b96 |
546 | var relation_id = get_relation_id( source_node_id, target_node_id ); |
547 | var relation = $( jq( relation_id ) ); |
9529f69c |
548 | if( relation.size() == 0 ) { |
b28e606e |
549 | draw_relation( source_node_id, target_node_id, self.temp_color ); |
550 | } else { |
551 | self.color_memo = relation.children('path').attr( 'stroke' ); |
552 | relation.children('path').attr( 'stroke', self.temp_color ); |
553 | } |
554 | } |
555 | this.remove_temporary = function() { |
556 | var path_element = $('#svgenlargement .relation').children('path[stroke="' + self.temp_color + '"]'); |
557 | if( self.color_memo != null ) { |
558 | path_element.attr( 'stroke', self.color_memo ); |
559 | self.color_memo = null; |
560 | } else { |
9529f69c |
561 | var temporary = path_element.parent('g').remove(); |
562 | temporary.empty(); |
563 | temporary = null; |
b28e606e |
564 | } |
565 | } |
48a371e5 |
566 | this.create = function( source_node_id, target_node_id, color_index, emphasis ) { |
b28e606e |
567 | //TODO: Protect from (color_)index out of bound.. |
568 | var relation_color = self.relation_colors[ color_index ]; |
48a371e5 |
569 | var relation = draw_relation( source_node_id, target_node_id, relation_color, emphasis ); |
9529f69c |
570 | get_node_obj( source_node_id ).update_elements(); |
571 | get_node_obj( target_node_id ).update_elements(); |
572 | return relation; |
b28e606e |
573 | } |
9529f69c |
574 | this.toggle_active = function( relation_id ) { |
45ee3b96 |
575 | var relation = $( jq( relation_id ) ); |
9529f69c |
576 | var relation_path = relation.children('path'); |
577 | if( !relation.data( 'active' ) ) { |
578 | relation_path.css( {'cursor':'pointer'} ); |
579 | relation_path.mouseenter( function(event) { |
580 | outerTimer = setTimeout( function() { |
581 | timer = setTimeout( function() { |
45ee3b96 |
582 | var related_nodes = get_related_nodes( relation_id ); |
583 | var source_node_id = related_nodes[0]; |
584 | var target_node_id = related_nodes[1]; |
9529f69c |
585 | $('#delete_source_node_id').val( source_node_id ); |
586 | $('#delete_target_node_id').val( target_node_id ); |
587 | self.showinfo(relation); |
588 | }, 500 ) |
589 | }, 1000 ); |
590 | }); |
591 | relation_path.mouseleave( function(event) { |
592 | clearTimeout(outerTimer); |
593 | if( timer != null ) { clearTimeout(timer); } |
594 | }); |
595 | relation.data( 'active', true ); |
596 | } else { |
597 | relation_path.unbind( 'mouseenter' ); |
598 | relation_path.unbind( 'mouseleave' ); |
599 | relation_path.css( {'cursor':'inherit'} ); |
600 | relation.data( 'active', false ); |
601 | } |
602 | } |
603 | this.showinfo = function(relation) { |
088a14af |
604 | $('#delete_relation_type').text( relation.data('type') ); |
605 | $('#delete_relation_scope').text( relation.data('scope') ); |
51ca18ee |
606 | $('#delete_relation_attributes').empty(); |
e4bdf660 |
607 | var significance = ' is not '; |
608 | if( relation.data( 'is_significant' ) === 'yes') { |
609 | significance = ' is '; |
610 | } else if ( relation.data( 'is_significant' ) === 'maybe' ) { |
611 | significance = ' might be '; |
612 | } |
613 | $('#delete_relation_attributes').append( |
614 | "This relationship" + significance + "stemmatically significant<br/>"); |
51ca18ee |
615 | if( relation.data( 'a_derivable_from_b' ) ) { |
616 | $('#delete_relation_attributes').append( |
617 | "'" + relation.data('source_text') + "' derivable from '" + relation.data('target_text') + "'<br/>"); |
618 | } |
619 | if( relation.data( 'b_derivable_from_a' ) ) { |
620 | $('#delete_relation_attributes').append( |
621 | "'" + relation.data('target_text') + "' derivable from '" + relation.data('source_text') + "'<br/>"); |
622 | } |
623 | if( relation.data( 'non_independent' ) ) { |
624 | $('#delete_relation_attributes').append( |
625 | "Variance unlikely to arise coincidentally<br/>"); |
626 | } |
69a19c91 |
627 | if( relation.data( 'note' ) ) { |
088a14af |
628 | $('#delete_relation_note').text('note: ' + relation.data( 'note' ) ); |
69a19c91 |
629 | } |
9529f69c |
630 | var points = relation.children('path').attr('d').slice(1).replace('C',' ').split(' '); |
631 | var xs = parseFloat( points[0].split(',')[0] ); |
632 | var xe = parseFloat( points[1].split(',')[0] ); |
633 | var ys = parseFloat( points[0].split(',')[1] ); |
634 | var ye = parseFloat( points[3].split(',')[1] ); |
635 | var p = svg_root.createSVGPoint(); |
636 | p.x = xs + ((xe-xs)*1.1); |
637 | p.y = ye - ((ye-ys)/2); |
76f05423 |
638 | var ctm = svg_root_element.getScreenCTM(); |
9529f69c |
639 | var nx = p.matrixTransform(ctm).x; |
640 | var ny = p.matrixTransform(ctm).y; |
641 | var dialog_aria = $ ("div[aria-labelledby='ui-dialog-title-delete-form']"); |
642 | $('#delete-form').dialog( 'open' ); |
643 | dialog_aria.offset({ left: nx, top: ny }); |
644 | } |
645 | this.remove = function( relation_id ) { |
30d0ba1e |
646 | if( !editable ) { |
647 | return; |
648 | } |
45ee3b96 |
649 | var relation = $( jq( relation_id ) ); |
9529f69c |
650 | relation.remove(); |
b28e606e |
651 | } |
652 | } |
653 | |
45ee3b96 |
654 | // Utility function to create/return the ID of a relation link between |
655 | // a source and target. |
656 | function get_relation_id( source_id, target_id ) { |
657 | var idlist = [ source_id, target_id ]; |
658 | idlist.sort(); |
659 | return 'relation-' + idlist[0] + '-...-' + idlist[1]; |
660 | } |
661 | |
662 | function get_related_nodes( relation_id ) { |
663 | var srctotarg = relation_id.substr( 9 ); |
664 | return srctotarg.split('-...-'); |
665 | } |
666 | |
48a371e5 |
667 | function draw_relation( source_id, target_id, relation_color, emphasis ) { |
9529f69c |
668 | var source_ellipse = get_ellipse( source_id ); |
669 | var target_ellipse = get_ellipse( target_id ); |
45ee3b96 |
670 | var relation_id = get_relation_id( source_id, target_id ); |
9529f69c |
671 | var svg = $('#svgenlargement').children('svg').svg().svg('get'); |
672 | var path = svg.createPath(); |
673 | var sx = parseInt( source_ellipse.attr('cx') ); |
674 | var rx = parseInt( source_ellipse.attr('rx') ); |
675 | var sy = parseInt( source_ellipse.attr('cy') ); |
676 | var ex = parseInt( target_ellipse.attr('cx') ); |
677 | var ey = parseInt( target_ellipse.attr('cy') ); |
9231663d |
678 | var relation = svg.group( $("#svgenlargement svg g"), { 'class':'relation', 'id':relation_id } ); |
9529f69c |
679 | svg.title( relation, source_id + '->' + target_id ); |
cfa6ff76 |
680 | var stroke_width = emphasis === "yes" ? 6 : emphasis === "maybe" ? 4 : 2; |
48a371e5 |
681 | svg.path( relation, path.move( sx, sy ).curveC( sx + (2*rx), sy, ex + (2*rx), ey, ex, ey ), {fill: 'none', stroke: relation_color, strokeWidth: stroke_width }); |
b28e606e |
682 | var relation_element = $('#svgenlargement .relation').filter( ':last' ); |
683 | relation_element.insertBefore( $('#svgenlargement g g').filter(':first') ); |
9529f69c |
684 | return relation_element; |
b28e606e |
685 | } |
686 | |
5fe117bc |
687 | function detach_node( readings ) { |
217f5e64 |
688 | // separate out the deleted relationships, discard for now |
b6f3476b |
689 | if( 'DELETED' in readings ) { |
690 | // Remove each of the deleted relationship links. |
691 | $.each( readings['DELETED'], function( idx, pair ) { |
692 | var relation_id = get_relation_id( pair[0], pair[1] ); |
693 | var relation = $( jq( relation_id ) ); |
694 | if( relation.size() == 0 ) { |
695 | relation_id = get_relation_id( pair[1], pair[0] ); |
696 | } |
697 | relation_manager.remove( relation_id ); |
698 | }); |
699 | delete readings['DELETED']; |
700 | } |
a471cb0f |
701 | // add new node(s) |
702 | $.extend( readingdata, readings ); |
703 | // remove from existing readings the witnesses for the new nodes/readings |
704 | $.each( readings, function( node_id, reading ) { |
705 | $.each( reading.witnesses, function( index, witness ) { |
706 | var witnesses = readingdata[ reading.orig_rdg ].witnesses; |
707 | readingdata[ reading.orig_rdg ].witnesses = $.removeFromArray( witness, witnesses ); |
708 | } ); |
709 | } ); |
710 | |
a471cb0f |
711 | detached_edges = []; |
8cd2e785 |
712 | |
713 | // here we detach witnesses from the existing edges accoring to what's being relayed by readings |
a471cb0f |
714 | $.each( readings, function( node_id, reading ) { |
715 | var edges = edges_of( get_ellipse( reading.orig_rdg ) ); |
716 | incoming_remaining = []; |
717 | outgoing_remaining = []; |
718 | $.each( reading.witnesses, function( index, witness ) { |
719 | incoming_remaining.push( witness ); |
720 | outgoing_remaining.push( witness ); |
721 | } ); |
722 | $.each( edges, function( index, edge ) { |
723 | detached_edge = edge.detach_witnesses( reading.witnesses ); |
724 | if( detached_edge != null ) { |
725 | detached_edges.push( detached_edge ); |
726 | $.each( detached_edge.witnesses, function( index, witness ) { |
727 | if( detached_edge.is_incoming == true ) { |
728 | incoming_remaining = $.removeFromArray( witness, incoming_remaining ); |
729 | } else { |
730 | outgoing_remaining = $.removeFromArray( witness, outgoing_remaining ); |
731 | } |
732 | } ); |
733 | } |
734 | } ); |
8cd2e785 |
735 | |
60c66cd2 |
736 | // After detaching we still need to check if for *all* readings |
8cd2e785 |
737 | // an edge was detached. It may be that a witness was not |
738 | // explicitly named on an edge but was part of a 'majority' edge |
739 | // in which case we need to duplicate and name that edge after those |
740 | // remaining witnesses. |
a471cb0f |
741 | if( outgoing_remaining.length > 0 ) { |
a471cb0f |
742 | $.each( edges, function( index, edge ) { |
a471cb0f |
743 | if( edge.get_label() == 'majority' && !edge.is_incoming ) { |
744 | detached_edges.push( edge.clone_for( outgoing_remaining ) ); |
745 | } |
746 | } ); |
747 | } |
748 | if( incoming_remaining.length > 0 ) { |
a471cb0f |
749 | $.each( edges, function( index, edge ) { |
750 | if( edge.get_label() == 'majority' && edge.is_incoming ) { |
dc8a13bd |
751 | detached_edges.push( edge.clone_for( incoming_remaining ) ); |
a471cb0f |
752 | } |
753 | } ); |
754 | } |
60c66cd2 |
755 | |
22a70299 |
756 | // Finally multiple selected nodes may share edges |
757 | var copy_array = []; |
758 | $.each( detached_edges, function( index, edge ) { |
759 | var do_copy = true; |
760 | $.each( copy_array, function( index, copy_edge ) { |
761 | if( copy_edge.g_elem.attr( 'id' ) == edge.g_elem.attr( 'id' ) ) { do_copy = false } |
762 | } ); |
763 | if( do_copy == true ) { |
764 | copy_array.push( edge ); |
765 | } |
766 | } ); |
767 | detached_edges = copy_array; |
768 | |
60c66cd2 |
769 | // Lots of unabstracted knowledge down here :/ |
770 | // Clone original node/reading, rename/id it.. |
771 | duplicate_node = get_ellipse( reading.orig_rdg ).parent().clone(); |
772 | duplicate_node.attr( 'id', node_id ); |
773 | duplicate_node.children( 'title' ).text( node_id ); |
6c8d1880 |
774 | |
775 | // This needs somehow to move to node or even to shapes! #repositioned |
776 | duplicate_node_data = get_ellipse( reading.orig_rdg ).parent().data( 'repositioned' ); |
22a70299 |
777 | if( duplicate_node_data != null ) { |
6c8d1880 |
778 | duplicate_node.children( 'ellipse' ).parent().data( 'repositioned', duplicate_node_data ); |
22a70299 |
779 | } |
60c66cd2 |
780 | |
781 | // Add the node and all new edges into the graph |
931ed236 |
782 | var graph_root = $('#svgenlargement svg g.graph'); |
60c66cd2 |
783 | graph_root.append( duplicate_node ); |
784 | $.each( detached_edges, function( index, edge ) { |
dc8a13bd |
785 | id_suffix = node_id.slice( node_id.indexOf( '_' ) ); |
786 | edge.g_elem.attr( 'id', ( edge.g_elem.attr( 'id' ) + id_suffix ) ); |
60c66cd2 |
787 | edge_title = edge.g_elem.children( 'title' ).text(); |
22a70299 |
788 | edge_weight = 0.8 + ( 0.2 * edge.witnesses.length ); |
60c66cd2 |
789 | edge_title = edge_title.replace( reading.orig_rdg, node_id ); |
790 | edge.g_elem.children( 'title' ).text( edge_title ); |
22a70299 |
791 | edge.g_elem.children( 'path').attr( 'stroke-width', edge_weight ); |
60c66cd2 |
792 | // Reg unabstracted knowledge: isn't it more elegant to make |
793 | // it edge.append_to( graph_root )? |
794 | graph_root.append( edge.g_elem ); |
795 | } ); |
22a70299 |
796 | |
797 | // Make the detached node a real node_obj |
798 | var ellipse_elem = get_ellipse( node_id ); |
799 | var new_node = new node_obj( ellipse_elem ); |
800 | ellipse_elem.data( 'node_obj', new_node ); |
801 | |
60c66cd2 |
802 | // Move the node somewhat up for 'dramatic effect' :-p |
9231663d |
803 | new_node.reposition( 0, -70 ); |
60c66cd2 |
804 | |
a471cb0f |
805 | } ); |
60c66cd2 |
806 | |
9231663d |
807 | } |
a471cb0f |
808 | |
9231663d |
809 | function merge_nodes( source_node_id, target_node_id, consequences ) { |
810 | if( consequences.status != null && consequences.status == 'ok' ) { |
811 | merge_node( source_node_id, target_node_id ); |
812 | if( consequences.checkalign != null ) { |
813 | $.each( consequences.checkalign, function( index, node_ids ) { |
0c4354f6 |
814 | var temp_relation = draw_relation( node_ids[0], node_ids[1], "#89a02c" ); |
9231663d |
815 | var sy = parseInt( temp_relation.children('path').attr('d').split('C')[0].split(',')[1] ); |
816 | var ey = parseInt( temp_relation.children('path').attr('d').split(' ')[2].split(',')[1] ); |
817 | var yC = ey + (( sy - ey )/2); |
818 | // TODO: compute xC to be always the same distance to the amplitude of the curve |
819 | var xC = parseInt( temp_relation.children('path').attr('d').split(' ')[1].split(',')[0] ); |
820 | var svg = $('#svgenlargement').children('svg').svg('get'); |
821 | parent_g = svg.group( $('#svgenlargement svg g') ); |
822 | var ids_text = node_ids[0] + '-' + node_ids[1]; |
823 | var merge_id = 'merge-' + ids_text; |
5a80f535 |
824 | var yes = svg.image( parent_g, xC, (yC-8), 16, 16, merge_button_yes, { id: merge_id } ); |
825 | var no = svg.image( parent_g, (xC+20), (yC-8), 16, 16, merge_button_no, { id: 'no' + merge_id } ); |
826 | $(yes).hover( function(){ $(this).addClass( 'draggable' ) }, function(){ $(this).removeClass( 'draggable' ) } ); |
827 | $(no).hover( function(){ $(this).addClass( 'draggable' ) }, function(){ $(this).removeClass( 'draggable' ) } ); |
828 | $(yes).click( function( evt ){ |
9231663d |
829 | merge_node( node_ids[0], node_ids[1] ); |
830 | temp_relation.remove(); |
5a80f535 |
831 | $(evt.target).parent().remove(); |
759f1868 |
832 | //notify backend |
833 | var ncpath = getTextURL( 'merge' ); |
aaf27b2e |
834 | var form_values = "source_id=" + node_ids[0] + "&target_id=" + node_ids[1] + "&single=true"; |
759f1868 |
835 | $.post( ncpath, form_values ); |
9231663d |
836 | } ); |
5a80f535 |
837 | $(no).click( function( evt ) { |
9231663d |
838 | temp_relation.remove(); |
5a80f535 |
839 | $(evt.target).parent().remove(); |
9231663d |
840 | } ); |
841 | } ); |
842 | } |
843 | } |
844 | } |
845 | |
846 | function merge_node( source_node_id, target_node_id ) { |
847 | $.each( edges_of( get_ellipse( source_node_id ) ), function( index, edge ) { |
848 | if( edge.is_incoming == true ) { |
849 | edge.attach_endpoint( target_node_id ); |
850 | } else { |
851 | edge.attach_startpoint( target_node_id ); |
852 | } |
853 | } ); |
854 | $( jq( source_node_id ) ).remove(); |
a471cb0f |
855 | } |
856 | |
a51e34c5 |
857 | function compress_nodes(readings) { |
858 | //add text of other readings to 1st reading |
a51e34c5 |
859 | |
2d34519e |
860 | var first = get_ellipse(readings[0]); |
861 | var first_title = first.parent().find('text')[0]; |
862 | |
863 | for (var i = 1; i < readings.length; i++) { |
864 | var cur = get_ellipse(readings[i]); |
a51e34c5 |
865 | var cur_title = cur.parent().find('text')[0]; |
866 | |
867 | first_title.textContent += " " + cur_title.textContent; |
868 | }; |
869 | |
870 | //delete all others |
871 | for (var i = 1; i < readings.length; i++) { |
872 | var node = get_ellipse(readings[i]); |
873 | var rid = readings[i-1] + '->' + readings[i]; |
874 | |
875 | //[].slice.call(s.getElementsByTagName('title')).find(function(elem){return elem.textContent=='r64.2->r66.2'}).parentNode.remove() |
876 | |
2a65f5c9 |
877 | var titles = svg_root.getElementsByTagName('title'); |
878 | var titlesArray = [].slice.call(titles); |
a51e34c5 |
879 | |
2a65f5c9 |
880 | if (titlesArray.length > 0) { |
881 | var title = titlesArray.find(function(elem){ |
882 | return elem.textContent === rid; |
883 | }); |
884 | |
885 | if (title && title.parentNode) { |
886 | title.parentNode.remove(); |
887 | } |
888 | } |
a51e34c5 |
889 | |
2a65f5c9 |
890 | var x = parseInt(first[0].getAttribute('cx'), 10); |
891 | |
892 | first[0].setAttribute('rx', 4.5 * first_title.textContent.length); |
893 | |
894 | if (text_direction !== "BI") { |
895 | first[0].setAttribute('cx', x + first_title.textContent.length + 20); |
896 | first_title.setAttribute('x', first[0].getAttribute('cx')); |
897 | } |
a51e34c5 |
898 | |
2a65f5c9 |
899 | merge_node(readings[i], readings[0]); |
900 | //node.parent().remove(); |
a51e34c5 |
901 | } |
902 | } |
903 | |
c1add777 |
904 | function Marquee() { |
905 | |
906 | var self = this; |
907 | |
f6516f22 |
908 | this.x = 0; |
909 | this.y = 0; |
910 | this.dx = 0; |
911 | this.dy = 0; |
c1add777 |
912 | this.enlargementOffset = $('#svgenlargement').offset(); |
913 | this.svg_rect = $('#svgenlargement svg').svg('get'); |
914 | |
915 | this.show = function( event ) { |
f6516f22 |
916 | self.x = event.clientX; |
917 | self.y = event.clientY; |
c1add777 |
918 | p = svg_root.createSVGPoint(); |
919 | p.x = event.clientX - self.enlargementOffset.left; |
920 | p.y = event.clientY - self.enlargementOffset.top; |
c1add777 |
921 | self.svg_rect.rect( p.x, p.y, 0, 0, { fill: 'black', 'fill-opacity': '0.1', stroke: 'black', 'stroke-dasharray': '4,2', strokeWidth: '0.02em', id: 'marquee' } ); |
922 | }; |
923 | |
924 | this.expand = function( event ) { |
f6516f22 |
925 | self.dx = (event.clientX - self.x); |
926 | self.dy = (event.clientY - self.y); |
c1add777 |
927 | var rect = $('#marquee'); |
f6516f22 |
928 | if( rect.length != 0 ) { |
929 | var rect_w = Math.abs( self.dx ); |
930 | var rect_h = Math.abs( self.dy ); |
931 | var rect_x = self.x - self.enlargementOffset.left; |
932 | var rect_y = self.y - self.enlargementOffset.top; |
933 | if( self.dx < 0 ) { rect_x = rect_x - rect_w } |
934 | if( self.dy < 0 ) { rect_y = rect_y - rect_h } |
935 | rect.attr("x", rect_x).attr("y", rect_y).attr("width", rect_w).attr("height", rect_h); |
c1add777 |
936 | } |
937 | }; |
938 | |
a84ca4de |
939 | this.select = function() { |
c1add777 |
940 | var rect = $('#marquee'); |
941 | if( rect.length != 0 ) { |
e538eccb |
942 | //unselect any possible selected first |
22a70299 |
943 | //TODO: unless SHIFT? |
e538eccb |
944 | if( $('ellipse[fill="#9999ff"]').size() > 0 ) { |
945 | $('ellipse[fill="#9999ff"]').each( function() { |
946 | $(this).data( 'node_obj' ).set_draggable( false ); |
947 | } ); |
948 | } |
949 | //compute dimension of marquee |
c1add777 |
950 | var left = $('#marquee').offset().left; |
951 | var top = $('#marquee').offset().top; |
952 | var right = left + parseInt( $('#marquee').attr( 'width' ) ); |
953 | var bottom = top + parseInt( $('#marquee').attr( 'height' ) ); |
954 | var tf = svg_root_element.getScreenCTM().inverse(); |
955 | var p = svg_root.createSVGPoint(); |
956 | p.x=left; |
957 | p.y=top; |
958 | var cx_min = p.matrixTransform(tf).x; |
959 | var cy_min = p.matrixTransform(tf).y; |
960 | p.x=right; |
961 | p.y=bottom; |
962 | var cx_max = p.matrixTransform(tf).x; |
963 | var cy_max = p.matrixTransform(tf).y; |
e538eccb |
964 | //select any node with its center inside the marquee |
5fe117bc |
965 | var readings = []; |
e538eccb |
966 | //also merge witness sets from nodes |
a84ca4de |
967 | var witnesses = []; |
c1add777 |
968 | $('#svgenlargement ellipse').each( function( index ) { |
969 | var cx = parseInt( $(this).attr('cx') ); |
970 | var cy = parseInt( $(this).attr('cy') ); |
6c8d1880 |
971 | |
972 | // This needs somehow to move to node or even to shapes! #repositioned |
973 | // We should ask something more aling the lines of: nodes.each { |item| node.selected? } |
974 | var org_translate = $(this).parent().data( 'repositioned' ); |
22a70299 |
975 | if( org_translate != null ) { |
976 | cx = cx + org_translate[0]; |
977 | cy = cy + org_translate[1]; |
978 | } |
6c8d1880 |
979 | |
c1add777 |
980 | if( cx > cx_min && cx < cx_max) { |
981 | if( cy > cy_min && cy < cy_max) { |
982 | // we actually heve no real 'selected' state for nodes, except coloring |
e538eccb |
983 | $(this).attr( 'fill', '#9999ff' ); |
5fe117bc |
984 | // Take note of the selected reading(s) and applicable witness(es) |
985 | // so we can populate the multipleselect-form |
986 | readings.push( $(this).parent().attr('id') ); |
a84ca4de |
987 | var this_witnesses = $(this).data( 'node_obj' ).get_witnesses(); |
988 | witnesses = arrayUnique( witnesses.concat( this_witnesses ) ); |
c1add777 |
989 | } |
990 | } |
991 | }); |
e538eccb |
992 | if( $('ellipse[fill="#9999ff"]').size() > 0 ) { |
5fe117bc |
993 | //add intersection of witnesses sets to the multi select form and open it |
994 | $('#detach_collated_form').empty(); |
a51e34c5 |
995 | |
5fe117bc |
996 | $.each( readings, function( index, value ) { |
997 | $('#detach_collated_form').append( $('<input>').attr( |
998 | "type", "hidden").attr("name", "readings[]").attr( |
999 | "value", value ) ); |
a51e34c5 |
1000 | }); |
1001 | $.each( witnesses, function( index, value ) { |
5fe117bc |
1002 | $('#detach_collated_form').append( |
1003 | '<input type="checkbox" name="witnesses[]" value="' + value |
1004 | + '">' + value + '<br>' ); |
a84ca4de |
1005 | }); |
5fe117bc |
1006 | $('#multiple_selected_readings').attr('value', readings.join(',') ); |
a51e34c5 |
1007 | |
1008 | if ($('#action-merge')[0].checked) { |
1009 | $('#detach_collated_form').hide(); |
1010 | $('#multipleselect-form-text').hide(); |
1011 | |
1012 | $('#detach_btn').hide(); |
1013 | $('#merge_btn').show(); |
1014 | } else { |
1015 | $('#detach_collated_form').show(); |
1016 | $('#multipleselect-form-text').show(); |
1017 | |
1018 | $('#detach_btn').show(); |
1019 | $('#merge_btn').hide(); |
1020 | } |
1021 | |
1022 | $('#action-detach').change(function() { |
1023 | if ($('#action-detach')[0].checked) { |
1024 | $('#detach_collated_form').show(); |
2d34519e |
1025 | $('#multipleselect-form-text').show(); |
a51e34c5 |
1026 | |
1027 | $('#detach_btn').show(); |
1028 | $('#merge_btn').hide(); |
1029 | } |
1030 | }); |
1031 | |
1032 | $('#action-merge').change(function() { |
1033 | if ($('#action-merge')[0].checked) { |
1034 | $('#detach_collated_form').hide(); |
2d34519e |
1035 | $('#multipleselect-form-text').hide(); |
a51e34c5 |
1036 | |
1037 | $('#detach_btn').hide(); |
1038 | $('#merge_btn').show(); |
1039 | } |
1040 | }); |
1041 | |
a84ca4de |
1042 | $('#multipleselect-form').dialog( 'open' ); |
1043 | } |
c1add777 |
1044 | self.svg_rect.remove( $('#marquee') ); |
1045 | } |
1046 | }; |
1047 | |
f6516f22 |
1048 | this.unselect = function() { |
e538eccb |
1049 | $('ellipse[fill="#9999ff"]').attr( 'fill', '#fff' ); |
f6516f22 |
1050 | } |
1051 | |
c1add777 |
1052 | } |
1053 | |
b001c73d |
1054 | function readings_equivalent( source, target ) { |
1055 | var sourcetext = readingdata[source].text; |
1056 | var targettext = readingdata[target].text; |
1057 | if( sourcetext === targettext ) { |
1058 | return true; |
1059 | } |
1060 | // Lowercase and strip punctuation from both and compare again |
f069bb5c |
1061 | var nonwc = XRegExp('[^\\p{L}\\s]|_'); |
1062 | var stlc = XRegExp.replace( sourcetext.toLocaleLowerCase(), nonwc, "", 'all' ); |
1063 | var ttlc = XRegExp.replace( targettext.toLocaleLowerCase(), nonwc, "", 'all' ); |
b001c73d |
1064 | if( stlc === ttlc ) { |
1065 | return true; |
1066 | } |
1067 | return false; |
1068 | } |
1069 | |
89aae3ee |
1070 | function scrollToEnd() { |
1071 | var stateTf = svg_root_element.getCTM().inverse(); |
1072 | |
1073 | var vbdim = svg_root.viewBox.baseVal; |
1074 | var width = Math.floor(svg_root_element.getBoundingClientRect().width) - vbdim.width; |
1075 | |
1076 | var p = svg_root.createSVGPoint(); |
1077 | p.x = width; |
1078 | p.y = 0; |
1079 | p = p.matrixTransform(stateTf); |
1080 | |
1081 | var matrix = stateTf.inverse().translate(-p.x, -100); |
1082 | var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")"; |
1083 | svg_root_element.setAttribute("transform", s); |
1084 | } |
9529f69c |
1085 | |
b28e606e |
1086 | $(document).ready(function () { |
9529f69c |
1087 | |
1088 | timer = null; |
b28e606e |
1089 | relation_manager = new relation_factory(); |
1090 | |
c1add777 |
1091 | $('#update_workspace_button').data('locked', false); |
b001c73d |
1092 | |
1093 | // Set up the mouse events on the SVG enlargement |
9529f69c |
1094 | $('#enlargement').mousedown(function (event) { |
b28e606e |
1095 | $(this) |
9529f69c |
1096 | .data('down', true) |
1097 | .data('x', event.clientX) |
1098 | .data('y', event.clientY) |
1099 | .data('scrollLeft', this.scrollLeft) |
c1add777 |
1100 | stateTf = svg_root_element.getCTM().inverse(); |
1101 | var p = svg_root.createSVGPoint(); |
1102 | p.x = event.clientX; |
1103 | p.y = event.clientY; |
1104 | stateOrigin = p.matrixTransform(stateTf); |
1105 | |
1106 | // Activate marquee if in interaction mode |
1107 | if( $('#update_workspace_button').data('locked') == true ) { marquee.show( event ) }; |
1108 | |
1109 | event.returnValue = false; |
1110 | event.preventDefault(); |
1111 | return false; |
b28e606e |
1112 | }).mouseup(function (event) { |
a84ca4de |
1113 | marquee.select(); |
c1add777 |
1114 | $(this).data('down', false); |
b28e606e |
1115 | }).mousemove(function (event) { |
9529f69c |
1116 | if( timer != null ) { clearTimeout(timer); } |
1117 | if ( ($(this).data('down') == true) && ($('#update_workspace_button').data('locked') == false) ) { |
1118 | var p = svg_root.createSVGPoint(); |
1119 | p.x = event.clientX; |
1120 | p.y = event.clientY; |
1121 | p = p.matrixTransform(stateTf); |
1122 | var matrix = stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y); |
1123 | var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")"; |
76f05423 |
1124 | svg_root_element.setAttribute("transform", s); |
b28e606e |
1125 | } |
c1add777 |
1126 | marquee.expand( event ); |
76f05423 |
1127 | event.returnValue = false; |
1128 | event.preventDefault(); |
b28e606e |
1129 | }).mousewheel(function (event, delta) { |
9529f69c |
1130 | event.returnValue = false; |
1131 | event.preventDefault(); |
1132 | if ( $('#update_workspace_button').data('locked') == false ) { |
76f05423 |
1133 | if (!delta || delta == null || delta == 0) delta = event.originalEvent.wheelDelta; |
1134 | if (!delta || delta == null || delta == 0) delta = -1 * event.originalEvent.detail; |
9529f69c |
1135 | if( delta < -9 ) { delta = -9 }; |
1136 | var z = 1 + delta/10; |
76f05423 |
1137 | z = delta > 0 ? 1 : -1; |
1138 | var g = svg_root_element; |
1139 | if (g && ((z<1 && (g.getScreenCTM().a * start_element_height) > 4.0) || (z>=1 && (g.getScreenCTM().a * start_element_height) < 100))) { |
9529f69c |
1140 | var root = svg_root; |
1141 | var p = root.createSVGPoint(); |
76f05423 |
1142 | p.x = event.originalEvent.clientX; |
1143 | p.y = event.originalEvent.clientY; |
9529f69c |
1144 | p = p.matrixTransform(g.getCTM().inverse()); |
76f05423 |
1145 | var scaleLevel = 1+(z/20); |
1146 | var k = root.createSVGMatrix().translate(p.x, p.y).scale(scaleLevel).translate(-p.x, -p.y); |
9529f69c |
1147 | var matrix = g.getCTM().multiply(k); |
1148 | var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")"; |
1149 | g.setAttribute("transform", s); |
1150 | } |
1151 | } |
b28e606e |
1152 | }).css({ |
1153 | 'overflow' : 'hidden', |
1154 | 'cursor' : '-moz-grab' |
1155 | }); |
1156 | |
c1add777 |
1157 | |
b001c73d |
1158 | // Set up the relationship creation dialog. This also functions as the reading |
1159 | // merge dialog where appropriate. |
b001c73d |
1160 | |
30d0ba1e |
1161 | if( editable ) { |
9231663d |
1162 | $( '#dialog-form' ).dialog( { |
30d0ba1e |
1163 | autoOpen: false, |
e4bdf660 |
1164 | height: 350, |
cfa6ff76 |
1165 | width: 340, |
30d0ba1e |
1166 | modal: true, |
1167 | buttons: { |
9231663d |
1168 | 'Merge readings': function( evt ) { |
932277e1 |
1169 | var mybuttons = $(evt.target).closest('button').parent().find('button'); |
1170 | mybuttons.button( 'disable' ); |
9231663d |
1171 | $( '#status' ).empty(); |
1172 | form_values = $( '#collapse_node_form' ).serialize(); |
b001c73d |
1173 | ncpath = getTextURL( 'merge' ); |
9231663d |
1174 | var jqjson = $.post( ncpath, form_values, function( data ) { |
1175 | merge_nodes( $( '#source_node_id' ).val(), $( '#target_node_id' ).val(), data ); |
932277e1 |
1176 | mybuttons.button( 'enable' ); |
9231663d |
1177 | $( '#dialog-form' ).dialog( 'close' ); |
1178 | } ); |
b001c73d |
1179 | }, |
1180 | OK: function( evt ) { |
932277e1 |
1181 | var mybuttons = $(evt.target).closest('button').parent().find('button'); |
1182 | mybuttons.button( 'disable' ); |
9231663d |
1183 | $( '#status' ).empty(); |
1184 | form_values = $( '#collapse_node_form' ).serialize(); |
30d0ba1e |
1185 | ncpath = getTextURL( 'relationships' ); |
9231663d |
1186 | var jqjson = $.post( ncpath, form_values, function( data ) { |
1187 | $.each( data, function( item, source_target ) { |
30d0ba1e |
1188 | var source_found = get_ellipse( source_target[0] ); |
1189 | var target_found = get_ellipse( source_target[1] ); |
9231663d |
1190 | var relation_found = $.inArray( source_target[2], $( '#keymap' ).data( 'relations' ) ); |
30d0ba1e |
1191 | if( source_found.size() && target_found.size() && relation_found > -1 ) { |
cfa6ff76 |
1192 | var emphasis = $('#is_significant option:selected').attr('value'); |
48a371e5 |
1193 | var relation = relation_manager.create( source_target[0], source_target[1], relation_found, emphasis ); |
45ee3b96 |
1194 | relation_manager.toggle_active( relation.attr('id') ); |
51ca18ee |
1195 | $.each( $('#collapse_node_form').serializeArray(), function( i, k ) { |
1196 | relation.data( k.name, k.value ); |
1197 | }); |
7b54e481 |
1198 | } |
932277e1 |
1199 | mybuttons.button( 'enable' ); |
30d0ba1e |
1200 | }); |
9231663d |
1201 | $( '#dialog-form' ).dialog( 'close' ); |
30d0ba1e |
1202 | }, 'json' ); |
1203 | }, |
1204 | Cancel: function() { |
9231663d |
1205 | $( this ).dialog( 'close' ); |
30d0ba1e |
1206 | } |
1207 | }, |
1208 | create: function(event, ui) { |
1209 | $(this).data( 'relation_drawn', false ); |
a166dca8 |
1210 | $('#rel_type').data( 'changed_after_open', false ); |
56e3972e |
1211 | $.each( relationship_types, function(index, typedef) { |
1212 | $('#rel_type').append( $('<option />').attr( "value", typedef.name ).text(typedef.name) ); |
1213 | }); |
1214 | $.each( relationship_scopes, function(index, value) { |
1215 | $('#scope').append( $('<option />').attr( "value", value ).text(value) ); |
a166dca8 |
1216 | }); |
e4bdf660 |
1217 | $.each( ternary_values, function( index, value ) { |
1218 | $('#is_significant').append( $('<option />').attr( "value", value ).text(value) ); |
1219 | }); |
1220 | // Handler to reset fields to default, the first time the relationship |
1221 | // is changed after opening the form. |
a166dca8 |
1222 | $('#rel_type').change( function () { |
1223 | if( !$(this).data( 'changed_after_open' ) ) { |
1224 | $('#note').val(''); |
e4bdf660 |
1225 | $(this).find(':checked').removeAttr('checked'); |
a166dca8 |
1226 | } |
1227 | $(this).data( 'changed_after_open', true ); |
1228 | }); |
30d0ba1e |
1229 | }, |
1230 | open: function() { |
b001c73d |
1231 | relation_manager.create_temporary( |
1232 | $('#source_node_id').val(), $('#target_node_id').val() ); |
1233 | var buttonset = $(this).parent().find( '.ui-dialog-buttonset' ) |
1234 | if( readings_equivalent( $('#source_node_id').val(), |
1235 | $('#target_node_id').val() ) ) { |
1236 | buttonset.find( "button:contains('Merge readings')" ).show(); |
1237 | } else { |
1238 | buttonset.find( "button:contains('Merge readings')" ).hide(); |
1239 | } |
30d0ba1e |
1240 | $(".ui-widget-overlay").css("background", "none"); |
1241 | $("#dialog_overlay").show(); |
1242 | $("#dialog_overlay").height( $("#enlargement_container").height() ); |
1243 | $("#dialog_overlay").width( $("#enlargement_container").innerWidth() ); |
1244 | $("#dialog_overlay").offset( $("#enlargement_container").offset() ); |
a166dca8 |
1245 | $('#rel_type').data( 'changed_after_open', false ); |
30d0ba1e |
1246 | }, |
1247 | close: function() { |
1248 | relation_manager.remove_temporary(); |
1249 | $( '#status' ).empty(); |
1250 | $("#dialog_overlay").hide(); |
1251 | } |
1252 | }).ajaxError( function(event, jqXHR, ajaxSettings, thrownError) { |
e4bdf660 |
1253 | if( ( ajaxSettings.url == getTextURL('relationships') |
1254 | || ajaxSettings.url == getTextURL('merge') ) |
21e6ebc7 |
1255 | && ajaxSettings.type == 'POST' && jqXHR.status == 403 ) { |
1256 | var error; |
1257 | if( jqXHR.responseText.indexOf('do not have permission to modify') > -1 ) { |
1258 | error = 'You are not authorized to modify this tradition. (Try logging in again?)'; |
1259 | } else { |
1260 | try { |
1261 | var errobj = jQuery.parseJSON( jqXHR.responseText ); |
1262 | error = errobj.error + '</br>The relationship cannot be made.</p>'; |
1263 | } catch(e) { |
1264 | error = jqXHR.responseText; |
1265 | } |
1266 | } |
1267 | $('#status').append( '<p class="error">Error: ' + error ); |
1268 | } |
1269 | $(event.target).parent().find('.ui-button').button("enable"); |
30d0ba1e |
1270 | } ); |
1271 | } |
b28e606e |
1272 | |
b001c73d |
1273 | // Set up the relationship info display and deletion dialog. |
9529f69c |
1274 | $( "#delete-form" ).dialog({ |
1275 | autoOpen: false, |
69a19c91 |
1276 | height: 135, |
d5b3c010 |
1277 | width: 300, |
9529f69c |
1278 | modal: false, |
b001c73d |
1279 | buttons: { |
1280 | OK: function() { $( this ).dialog( "close" ); }, |
1281 | "Delete all": function () { delete_relation( true ); }, |
1282 | Delete: function() { delete_relation( false ); } |
1283 | }, |
9529f69c |
1284 | create: function(event, ui) { |
30d0ba1e |
1285 | // TODO What is this logic doing? |
a84ca4de |
1286 | // This scales the buttons in the dialog and makes it look proper |
1287 | // Not sure how essential it is, does anything break if it's not here? |
9529f69c |
1288 | var buttonset = $(this).parent().find( '.ui-dialog-buttonset' ).css( 'width', '100%' ); |
b001c73d |
1289 | buttonset.find( "button:contains('OK')" ).css( 'float', 'right' ); |
a84ca4de |
1290 | // A: This makes sure that the pop up delete relation dialogue for a hovered over |
1291 | // relation auto closes if the user doesn't engage (mouseover) with it. |
9529f69c |
1292 | var dialog_aria = $("div[aria-labelledby='ui-dialog-title-delete-form']"); |
1293 | dialog_aria.mouseenter( function() { |
1294 | if( mouseWait != null ) { clearTimeout(mouseWait) }; |
1295 | }) |
1296 | dialog_aria.mouseleave( function() { |
1297 | mouseWait = setTimeout( function() { $("#delete-form").dialog( "close" ) }, 2000 ); |
1298 | }) |
1299 | }, |
1300 | open: function() { |
b001c73d |
1301 | // Show the appropriate buttons... |
1302 | var buttonset = $(this).parent().find( '.ui-dialog-buttonset' ) |
1303 | // If the user can't edit, show only the OK button |
088a14af |
1304 | if( !editable ) { |
b001c73d |
1305 | buttonset.find( "button:contains('Delete')" ).hide(); |
1306 | // If the relationship scope is local, show only OK and Delete |
088a14af |
1307 | } else if( $('#delete_relation_scope').text() === 'local' ) { |
1308 | $( this ).dialog( "option", "width", 160 ); |
b001c73d |
1309 | buttonset.find( "button:contains('Delete')" ).show(); |
1310 | buttonset.find( "button:contains('Delete all')" ).hide(); |
1311 | // Otherwise, show all three |
088a14af |
1312 | } else { |
1313 | $( this ).dialog( "option", "width", 200 ); |
b001c73d |
1314 | buttonset.find( "button:contains('Delete')" ).show(); |
088a14af |
1315 | } |
9529f69c |
1316 | mouseWait = setTimeout( function() { $("#delete-form").dialog( "close" ) }, 2000 ); |
1317 | }, |
088a14af |
1318 | close: function() {} |
9529f69c |
1319 | }); |
1320 | |
a84ca4de |
1321 | $( "#multipleselect-form" ).dialog({ |
1322 | autoOpen: false, |
1323 | height: 150, |
1324 | width: 250, |
1325 | modal: true, |
5fe117bc |
1326 | buttons: { |
32f13891 |
1327 | Cancel: function() { |
1328 | document.getElementById('duplicate-merge-error').innerHTML = ""; |
1329 | $( this ).dialog( "close" ); |
1330 | }, |
a51e34c5 |
1331 | Detach: function ( evt ) { |
1332 | evt.target.id = 'detach_btn'; |
1333 | |
22a70299 |
1334 | var self = $(this); |
a51e34c5 |
1335 | var mybuttons = $(evt.target).closest('button').parent().find('button'); |
1336 | mybuttons.button( 'disable' ); |
22a70299 |
1337 | var form_values = $('#detach_collated_form').serialize(); |
1338 | ncpath = getTextURL( 'duplicate' ); |
1339 | var jqjson = $.post( ncpath, form_values, function(data) { |
1340 | detach_node( data ); |
932277e1 |
1341 | mybuttons.button("enable"); |
22a70299 |
1342 | self.dialog( "close" ); |
1343 | } ); |
a51e34c5 |
1344 | }, |
1345 | Merge: function (evt) { |
1346 | evt.target.id = 'merge_btn'; |
1347 | |
1348 | var self = $(this); |
1349 | var mybuttons = $(evt.target).closest('button').parent().find('button'); |
1350 | mybuttons.button('disable'); |
1351 | |
1352 | var ncpath = getTextURL('compress'); |
1353 | var form_values = $('#detach_collated_form').serialize(); |
1354 | |
1355 | var jqjson = $.post(ncpath, form_values, function(data) { |
2d34519e |
1356 | if (data.success) { |
32f13891 |
1357 | document.getElementById('duplicate-merge-error').innerHTML = ""; |
1358 | |
2d34519e |
1359 | if (data.nodes) { |
1360 | compress_nodes(data.nodes); |
1361 | } |
1362 | |
1363 | mybuttons.button('enable'); |
1364 | self.dialog('close'); |
1365 | } else if (data.error_msg) { |
1366 | document.getElementById('duplicate-merge-error').innerHTML = data.error_msg; |
1367 | mybuttons.button('enable'); |
a51e34c5 |
1368 | |
2d34519e |
1369 | } |
a51e34c5 |
1370 | }); |
22a70299 |
1371 | } |
7ef4a584 |
1372 | }, |
1373 | create: function(event, ui) { |
a84ca4de |
1374 | var buttonset = $(this).parent().find( '.ui-dialog-buttonset' ).css( 'width', '100%' ); |
1375 | buttonset.find( "button:contains('Cancel')" ).css( 'float', 'right' ); |
1376 | }, |
1377 | open: function() { |
1378 | $( this ).dialog( "option", "width", 200 ); |
e538eccb |
1379 | $(".ui-widget-overlay").css("background", "none"); |
5fe117bc |
1380 | $('#multipleselect-form-status').empty(); |
e538eccb |
1381 | $("#dialog_overlay").show(); |
1382 | $("#dialog_overlay").height( $("#enlargement_container").height() ); |
1383 | $("#dialog_overlay").width( $("#enlargement_container").innerWidth() ); |
1384 | $("#dialog_overlay").offset( $("#enlargement_container").offset() ); |
a51e34c5 |
1385 | |
1386 | var mybuttons = $(this).parent().find('button'); |
1387 | |
1388 | mybuttons[1].id = 'detach_btn'; |
1389 | mybuttons[2].id = 'merge_btn'; |
a84ca4de |
1390 | }, |
e538eccb |
1391 | close: function() { |
1392 | marquee.unselect(); |
1393 | $("#dialog_overlay").hide(); |
1394 | } |
5fe117bc |
1395 | }).ajaxError( function(event, jqXHR, ajaxSettings, thrownError) { |
1396 | if( ajaxSettings.url == getTextURL('duplicate') |
1397 | && ajaxSettings.type == 'POST' && jqXHR.status == 403 ) { |
1398 | var error; |
1399 | if( jqXHR.responseText.indexOf('do not have permission to modify') > -1 ) { |
1400 | error = 'You are not authorized to modify this tradition. (Try logging in again?)'; |
1401 | } else { |
1402 | try { |
1403 | var errobj = jQuery.parseJSON( jqXHR.responseText ); |
1404 | error = errobj.error + '</br>The relationship cannot be made.</p>'; |
1405 | } catch(e) { |
1406 | error = jqXHR.responseText; |
1407 | } |
1408 | } |
1409 | $('#multipleselect-form-status').append( '<p class="error">Error: ' + error ); |
1410 | } |
1411 | $(event.target).parent().find('.ui-button').button("enable"); |
1412 | }); |
1413 | |
a84ca4de |
1414 | |
088a14af |
1415 | // Helpers for relationship deletion |
1416 | |
1417 | function delete_relation( scopewide ) { |
1418 | form_values = $('#delete_relation_form').serialize(); |
1419 | if( scopewide ) { |
1420 | form_values += "&scopewide=true"; |
1421 | } |
1422 | ncpath = getTextURL( 'relationships' ); |
1423 | var jqjson = $.ajax({ url: ncpath, data: form_values, success: function(data) { |
1424 | $.each( data, function(item, source_target) { |
1425 | relation_manager.remove( get_relation_id( source_target[0], source_target[1] ) ); |
1426 | }); |
1427 | $( "#delete-form" ).dialog( "close" ); |
1428 | }, dataType: 'json', type: 'DELETE' }); |
1429 | } |
1430 | |
1431 | function toggle_relation_active( node_id ) { |
1432 | $('#svgenlargement .relation').find( "title:contains('" + node_id + "')" ).each( function(index) { |
1433 | matchid = new RegExp( "^" + node_id ); |
1434 | if( $(this).text().match( matchid ) != null ) { |
1435 | var relation_id = $(this).parent().attr('id'); |
1436 | relation_manager.toggle_active( relation_id ); |
1437 | }; |
1438 | }); |
1439 | } |
1440 | |
487674b9 |
1441 | // function for reading form dialog should go here; |
1442 | // just hide the element for now if we don't have morphology |
1443 | if( can_morphologize ) { |
1444 | $('#reading-form').dialog({ |
1445 | autoOpen: false, |
1446 | // height: 400, |
1447 | width: 450, |
1448 | modal: true, |
1449 | buttons: { |
1450 | Cancel: function() { |
1451 | $( this ).dialog( "close" ); |
1452 | }, |
1453 | Update: function( evt ) { |
1454 | // Disable the button |
932277e1 |
1455 | var mybuttons = $(evt.target).closest('button').parent().find('button'); |
1456 | mybuttons.button( 'disable' ); |
487674b9 |
1457 | $('#reading_status').empty(); |
1458 | var reading_id = $('#reading_id').val() |
1459 | form_values = { |
1460 | 'id' : reading_id, |
1461 | 'is_nonsense': $('#reading_is_nonsense').is(':checked'), |
1462 | 'grammar_invalid': $('#reading_grammar_invalid').is(':checked'), |
1463 | 'normal_form': $('#reading_normal_form').val() }; |
1464 | // Add the morphology values |
1465 | $('.reading_morphology').each( function() { |
1466 | if( $(this).val() != '(Click to select)' ) { |
1467 | var rmid = $(this).attr('id'); |
1468 | rmid = rmid.substring(8); |
1469 | form_values[rmid] = $(this).val(); |
1470 | } |
45ee3b96 |
1471 | }); |
487674b9 |
1472 | // Make the JSON call |
1473 | ncpath = getReadingURL( reading_id ); |
1474 | var reading_element = readingdata[reading_id]; |
1475 | // $(':button :contains("Update")').attr("disabled", true); |
1476 | var jqjson = $.post( ncpath, form_values, function(data) { |
1477 | $.each( data, function(key, value) { |
1478 | reading_element[key] = value; |
1479 | }); |
1480 | if( $('#update_workspace_button').data('locked') == false ) { |
1481 | color_inactive( get_ellipse( reading_id ) ); |
1482 | } |
932277e1 |
1483 | mybuttons.button("enable"); |
487674b9 |
1484 | $( "#reading-form" ).dialog( "close" ); |
1485 | }); |
1486 | // Re-color the node if necessary |
1487 | return false; |
1488 | } |
1489 | }, |
1490 | create: function() { |
30d0ba1e |
1491 | if( !editable ) { |
1492 | // Get rid of the disallowed editing UI bits |
1493 | $( this ).dialog( "option", "buttons", |
1494 | [{ text: "OK", click: function() { $( this ).dialog( "close" ); }}] ); |
1495 | $('#reading_relemmatize').hide(); |
1496 | } |
487674b9 |
1497 | }, |
1498 | open: function() { |
1499 | $(".ui-widget-overlay").css("background", "none"); |
1500 | $("#dialog_overlay").show(); |
1501 | $('#reading_status').empty(); |
1502 | $("#dialog_overlay").height( $("#enlargement_container").height() ); |
1503 | $("#dialog_overlay").width( $("#enlargement_container").innerWidth() ); |
1504 | $("#dialog_overlay").offset( $("#enlargement_container").offset() ); |
1505 | $("#reading-form").parent().find('.ui-button').button("enable"); |
1506 | }, |
1507 | close: function() { |
1508 | $("#dialog_overlay").hide(); |
1509 | } |
1510 | }).ajaxError( function(event, jqXHR, ajaxSettings, thrownError) { |
21e6ebc7 |
1511 | if( ajaxSettings.url.lastIndexOf( getReadingURL('') ) > -1 |
487674b9 |
1512 | && ajaxSettings.type == 'POST' && jqXHR.status == 403 ) { |
21e6ebc7 |
1513 | var error; |
1514 | if( jqXHR.responseText.indexOf('do not have permission to modify') > -1 ) { |
1515 | error = 'You are not authorized to modify this tradition. (Try logging in again?)'; |
1516 | } else { |
1517 | try { |
1518 | var errobj = jQuery.parseJSON( jqXHR.responseText ); |
1519 | error = errobj.error + '</br>The relationship cannot be made.</p>'; |
1520 | } catch(e) { |
1521 | error = jqXHR.responseText; |
1522 | } |
1523 | } |
1524 | $('#status').append( '<p class="error">Error: ' + error ); |
1525 | } |
1526 | $(event.target).parent().find('.ui-button').button("enable"); |
487674b9 |
1527 | }); |
1528 | } else { |
1529 | $('#reading-form').hide(); |
45ee3b96 |
1530 | } |
4c41c02c |
1531 | |
76f05423 |
1532 | |
b28e606e |
1533 | $('#update_workspace_button').click( function() { |
30d0ba1e |
1534 | if( !editable ) { |
1535 | return; |
1536 | } |
b28e606e |
1537 | var svg_enlargement = $('#svgenlargement').svg().svg('get').root(); |
76f05423 |
1538 | mouse_scale = svg_root_element.getScreenCTM().a; |
9529f69c |
1539 | if( $(this).data('locked') == true ) { |
1540 | $('#svgenlargement ellipse' ).each( function( index ) { |
1541 | if( $(this).data( 'node_obj' ) != null ) { |
1542 | $(this).data( 'node_obj' ).ungreyout_edges(); |
e538eccb |
1543 | $(this).data( 'node_obj' ).set_selectable( false ); |
1544 | color_inactive( $(this) ); |
9529f69c |
1545 | var node_id = $(this).data( 'node_obj' ).get_id(); |
1546 | toggle_relation_active( node_id ); |
1547 | $(this).data( 'node_obj', null ); |
1548 | } |
b28e606e |
1549 | }) |
b28e606e |
1550 | $(this).data('locked', false); |
9529f69c |
1551 | $(this).css('background-position', '0px 44px'); |
b28e606e |
1552 | } else { |
9529f69c |
1553 | var left = $('#enlargement').offset().left; |
1554 | var right = left + $('#enlargement').width(); |
76f05423 |
1555 | var tf = svg_root_element.getScreenCTM().inverse(); |
9529f69c |
1556 | var p = svg_root.createSVGPoint(); |
1557 | p.x=left; |
1558 | p.y=100; |
1559 | var cx_min = p.matrixTransform(tf).x; |
1560 | p.x=right; |
1561 | var cx_max = p.matrixTransform(tf).x; |
1562 | $('#svgenlargement ellipse').each( function( index ) { |
1563 | var cx = parseInt( $(this).attr('cx') ); |
1564 | if( cx > cx_min && cx < cx_max) { |
1565 | if( $(this).data( 'node_obj' ) == null ) { |
1566 | $(this).data( 'node_obj', new node_obj( $(this) ) ); |
1567 | } else { |
e538eccb |
1568 | $(this).data( 'node_obj' ).set_selectable( true ); |
9529f69c |
1569 | } |
1570 | $(this).data( 'node_obj' ).greyout_edges(); |
1571 | var node_id = $(this).data( 'node_obj' ).get_id(); |
1572 | toggle_relation_active( node_id ); |
b28e606e |
1573 | } |
9529f69c |
1574 | }); |
1575 | $(this).css('background-position', '0px 0px'); |
b28e606e |
1576 | $(this).data('locked', true ); |
b28e606e |
1577 | } |
1578 | }); |
30d0ba1e |
1579 | |
1580 | if( !editable ) { |
1581 | // Hide the unused elements |
1582 | $('#dialog-form').hide(); |
1583 | $('#update_workspace_button').hide(); |
1584 | } |
1585 | |
b28e606e |
1586 | |
e847b186 |
1587 | $('.helptag').popupWindow({ |
1588 | height:500, |
1589 | width:800, |
1590 | top:50, |
1591 | left:50, |
1592 | scrollbars:1 |
1593 | }); |
1594 | |
76f05423 |
1595 | expandFillPageClients(); |
1596 | $(window).resize(function() { |
1597 | expandFillPageClients(); |
1598 | }); |
1599 | |
9529f69c |
1600 | }); |
b28e606e |
1601 | |
1602 | |
76f05423 |
1603 | function expandFillPageClients() { |
1604 | $('.fillPage').each(function () { |
1605 | $(this).height($(window).height() - $(this).offset().top - MARGIN); |
1606 | }); |
1607 | } |
1608 | |
aeb47ed3 |
1609 | function loadSVG(svgData) { |
76f05423 |
1610 | var svgElement = $('#svgenlargement'); |
1611 | |
1612 | $(svgElement).svg('destroy'); |
1613 | |
1614 | $(svgElement).svg({ |
1615 | loadURL: svgData, |
1616 | onLoad : svgEnlargementLoaded |
1617 | }); |
1618 | } |
1619 | |
1620 | |
c1add777 |
1621 | |
76f05423 |
1622 | /* OS Gadget stuff |
1623 | |
1624 | function svg_select_callback(topic, data, subscriberData) { |
1625 | svgData = data; |
1626 | loadSVG(svgData); |
1627 | } |
1628 | |
1629 | function loaded() { |
1630 | var prefs = new gadgets.Prefs(); |
1631 | var preferredHeight = parseInt(prefs.getString('height')); |
1632 | if (gadgets.util.hasFeature('dynamic-height')) gadgets.window.adjustHeight(preferredHeight); |
1633 | expandFillPageClients(); |
1634 | } |
1635 | |
1636 | if (gadgets.util.hasFeature('pubsub-2')) { |
1637 | gadgets.HubSettings.onConnect = function(hum, suc, err) { |
1638 | subId = gadgets.Hub.subscribe("interedition.svg.selected", svg_select_callback); |
1639 | loaded(); |
1640 | }; |
1641 | } |
1642 | else gadgets.util.registerOnLoadHandler(loaded); |
1643 | */ |