Merge remote-tracking branch 'origin/QA_4_7' into QA_4_7
[phpmyadmin.git] / js / gis_data_editor.js
blob35238db7ed3a5e7575c0a06a9301f08f37f30d7f
1 /* vim: set expandtab sw=4 ts=4 sts=4: */
2 /**
3  * @fileoverview    functions used in GIS data editor
4  *
5  * @requires    jQuery
6  *
7  */
9 var gisEditorLoaded = false;
11 /**
12  * Closes the GIS data editor and perform necessary clean up work.
13  */
14 function closeGISEditor() {
15     $("#popup_background").fadeOut("fast");
16     $("#gis_editor").fadeOut("fast", function () {
17         $(this).empty();
18     });
21 /**
22  * Prepares the HTML received via AJAX.
23  */
24 function prepareJSVersion() {
25     // Change the text on the submit button
26     $("#gis_editor").find("input[name='gis_data[save]']")
27         .val(PMA_messages.strCopy)
28         .insertAfter($('#gis_data_textarea'))
29         .before('<br/><br/>');
31     // Add close and cancel links
32     $('#gis_data_editor').prepend('<a class="close_gis_editor" href="#">' + PMA_messages.strClose + '</a>');
33     $('<a class="cancel_gis_editor" href="#"> ' + PMA_messages.strCancel + '</a>')
34         .insertAfter($("input[name='gis_data[save]']"));
36     // Remove the unnecessary text
37     $('div#gis_data_output p').remove();
39     // Remove 'add' buttons and add links
40     $('#gis_editor').find('input.add').each(function (e) {
41         var $button = $(this);
42         $button.addClass('addJs').removeClass('add');
43         var classes = $button.attr('class');
44         $button.replaceWith(
45             '<a class="' + classes +
46             '" name="' + $button.attr('name') +
47             '" href="#">+ ' + $button.val() + '</a>'
48         );
49     });
52 /**
53  * Returns the HTML for a data point.
54  *
55  * @param pointNumber point number
56  * @param prefix      prefix of the name
57  * @returns the HTML for a data point
58  */
59 function addDataPoint(pointNumber, prefix) {
60     return '<br/>' +
61         PMA_sprintf(PMA_messages.strPointN, (pointNumber + 1)) + ': ' +
62         '<label for="x">' + PMA_messages.strX + '</label>' +
63         '<input type="text" name="' + prefix + '[' + pointNumber + '][x]" value=""/>' +
64         '<label for="y">' + PMA_messages.strY + '</label>' +
65         '<input type="text" name="' + prefix + '[' + pointNumber + '][y]" value=""/>';
68 /**
69  * Initialize the visualization in the GIS data editor.
70  */
71 function initGISEditorVisualization() {
72     // Loads either SVG or OSM visualization based on the choice
73     selectVisualization();
74     // Adds necessary styles to the div that coontains the openStreetMap
75     styleOSM();
76     // Loads the SVG element and make a reference to it
77     loadSVG();
78     // Adds controllers for zooming and panning
79     addZoomPanControllers();
80     zoomAndPan();
83 /**
84  * Loads JavaScript files and the GIS editor.
85  *
86  * @param value      current value of the geometry field
87  * @param field      field name
88  * @param type       geometry type
89  * @param input_name name of the input field
90  * @param token      token
91  */
92 function loadJSAndGISEditor(value, field, type, input_name, token) {
93     var head = document.getElementsByTagName('head')[0];
94     var script;
96     // Loads a set of small JS file needed for the GIS editor
97     var smallScripts = [ 'js/jquery/jquery.svg.js',
98                      'js/jquery/jquery.mousewheel.js',
99                      'js/jquery/jquery.event.drag-2.2.js',
100                      'js/tbl_gis_visualization.js' ];
102     for (var i = 0; i < smallScripts.length; i++) {
103         script = document.createElement('script');
104         script.type = 'text/javascript';
105         script.src = smallScripts[i];
106         head.appendChild(script);
107     }
109     // OpenLayers.js is BIG and takes time. So asynchronous loading would not work.
110     // Load the JS and do a callback to load the content for the GIS Editor.
111     script = document.createElement('script');
112     script.type = 'text/javascript';
114     script.onreadystatechange = function () {
115         if (this.readyState == 'complete') {
116             loadGISEditor(value, field, type, input_name, token);
117         }
118     };
119     script.onload = function () {
120         loadGISEditor(value, field, type, input_name, token);
121     };
122     script.onerror = function() {
123         loadGISEditor(value, field, type, input_name, token);
124     }
126     script.src = 'js/openlayers/OpenLayers.js';
127     head.appendChild(script);
129     gisEditorLoaded = true;
133  * Loads the GIS editor via AJAX
135  * @param value      current value of the geometry field
136  * @param field      field name
137  * @param type       geometry type
138  * @param input_name name of the input field
139  * @param token      token
140  */
141 function loadGISEditor(value, field, type, input_name, token) {
143     var $gis_editor = $("#gis_editor");
144     $.post('gis_data_editor.php', {
145         'field' : field,
146         'value' : value,
147         'type' : type,
148         'input_name' : input_name,
149         'get_gis_editor' : true,
150         'token' : token,
151         'ajax_request': true
152     }, function (data) {
153         if (typeof data !== 'undefined' && data.success === true) {
154             $gis_editor.html(data.gis_editor);
155             initGISEditorVisualization();
156             prepareJSVersion();
157         } else {
158             PMA_ajaxShowMessage(data.error, false);
159         }
160     }, 'json');
164  * Opens up the dialog for the GIS data editor.
165  */
166 function openGISEditor() {
168     // Center the popup
169     var windowWidth = document.documentElement.clientWidth;
170     var windowHeight = document.documentElement.clientHeight;
171     var popupWidth = windowWidth * 0.9;
172     var popupHeight = windowHeight * 0.9;
173     var popupOffsetTop = windowHeight / 2 - popupHeight / 2;
174     var popupOffsetLeft = windowWidth / 2 - popupWidth / 2;
176     var $gis_editor = $("#gis_editor");
177     var $backgrouond = $("#popup_background");
179     $gis_editor.css({"top": popupOffsetTop, "left": popupOffsetLeft, "width": popupWidth, "height": popupHeight});
180     $backgrouond.css({"opacity" : "0.7"});
182     $gis_editor.append(
183         '<div id="gis_data_editor">' +
184         '<img class="ajaxIcon" id="loadingMonitorIcon" src="' +
185         pmaThemeImage + 'ajax_clock_small.gif" alt=""/>' +
186         '</div>'
187     );
189     // Make it appear
190     $backgrouond.fadeIn("fast");
191     $gis_editor.fadeIn("fast");
195  * Prepare and insert the GIS data in Well Known Text format
196  * to the input field.
197  */
198 function insertDataAndClose() {
199     var $form = $('form#gis_data_editor_form');
200     var input_name = $form.find("input[name='input_name']").val();
202     $.post('gis_data_editor.php', $form.serialize() + "&generate=true&ajax_request=true", function (data) {
203         if (typeof data !== 'undefined' && data.success === true) {
204             $("input[name='" + input_name + "']").val(data.result);
205         } else {
206             PMA_ajaxShowMessage(data.error, false);
207         }
208     }, 'json');
209     closeGISEditor();
213  * Unbind all event handlers before tearing down a page
214  */
215 AJAX.registerTeardown('gis_data_editor.js', function () {
216     $(document).off('click', "#gis_editor input[name='gis_data[save]']");
217     $(document).off('submit', '#gis_editor');
218     $(document).off('change', "#gis_editor input[type='text']");
219     $(document).off('change', "#gis_editor select.gis_type");
220     $(document).off('click', '#gis_editor a.close_gis_editor, #gis_editor a.cancel_gis_editor');
221     $(document).off('click', '#gis_editor a.addJs.addPoint');
222     $(document).off('click', '#gis_editor a.addLine.addJs');
223     $(document).off('click', '#gis_editor a.addJs.addPolygon');
224     $(document).off('click', '#gis_editor a.addJs.addGeom');
227 AJAX.registerOnload('gis_data_editor.js', function () {
229     // Remove the class that is added due to the URL being too long.
230     $('span.open_gis_editor a').removeClass('formLinkSubmit');
232     /**
233      * Prepares and insert the GIS data to the input field on clicking 'copy'.
234      */
235     $(document).on('click', "#gis_editor input[name='gis_data[save]']", function (event) {
236         event.preventDefault();
237         insertDataAndClose();
238     });
240     /**
241      * Prepares and insert the GIS data to the input field on pressing 'enter'.
242      */
243     $(document).on('submit', '#gis_editor', function (event) {
244         event.preventDefault();
245         insertDataAndClose();
246     });
248     /**
249      * Trigger asynchronous calls on data change and update the output.
250      */
251     $(document).on('change', "#gis_editor input[type='text']", function () {
252         var $form = $('form#gis_data_editor_form');
253         $.post('gis_data_editor.php', $form.serialize() + "&generate=true&ajax_request=true", function (data) {
254             if (typeof data !== 'undefined' && data.success === true) {
255                 $('#gis_data_textarea').val(data.result);
256                 $('#placeholder').empty().removeClass('hasSVG').html(data.visualization);
257                 $('#openlayersmap').empty();
258                 /* TODO: the gis_data_editor should rather return JSON than JS code to eval */
259                 eval(data.openLayers);
260                 initGISEditorVisualization();
261             } else {
262                 PMA_ajaxShowMessage(data.error, false);
263             }
264         }, 'json');
265     });
267     /**
268      * Update the form on change of the GIS type.
269      */
270     $(document).on('change', "#gis_editor select.gis_type", function (event) {
271         var $gis_editor = $("#gis_editor");
272         var $form = $('form#gis_data_editor_form');
274         $.post('gis_data_editor.php', $form.serialize() + "&get_gis_editor=true&ajax_request=true", function (data) {
275             if (typeof data !== 'undefined' && data.success === true) {
276                 $gis_editor.html(data.gis_editor);
277                 initGISEditorVisualization();
278                 prepareJSVersion();
279             } else {
280                 PMA_ajaxShowMessage(data.error, false);
281             }
282         }, 'json');
283     });
285     /**
286      * Handles closing of the GIS data editor.
287      */
288     $(document).on('click', '#gis_editor a.close_gis_editor, #gis_editor a.cancel_gis_editor', function () {
289         closeGISEditor();
290     });
292     /**
293      * Handles adding data points
294      */
295     $(document).on('click', '#gis_editor a.addJs.addPoint', function () {
296         var $a = $(this);
297         var name = $a.attr('name');
298         // Eg. name = gis_data[0][MULTIPOINT][add_point] => prefix = gis_data[0][MULTIPOINT]
299         var prefix = name.substr(0, name.length - 11);
300         // Find the number of points
301         var $noOfPointsInput = $("input[name='" + prefix + "[no_of_points]" + "']");
302         var noOfPoints = parseInt($noOfPointsInput.val(), 10);
303         // Add the new data point
304         var html = addDataPoint(noOfPoints, prefix);
305         $a.before(html);
306         $noOfPointsInput.val(noOfPoints + 1);
307     });
309     /**
310      * Handles adding linestrings and inner rings
311      */
312     $(document).on('click', '#gis_editor a.addLine.addJs', function () {
313         var $a = $(this);
314         var name = $a.attr('name');
316         // Eg. name = gis_data[0][MULTILINESTRING][add_line] => prefix = gis_data[0][MULTILINESTRING]
317         var prefix = name.substr(0, name.length - 10);
318         var type = prefix.slice(prefix.lastIndexOf('[') + 1, prefix.lastIndexOf(']'));
320         // Find the number of lines
321         var $noOfLinesInput = $("input[name='" + prefix + "[no_of_lines]" + "']");
322         var noOfLines = parseInt($noOfLinesInput.val(), 10);
324         // Add the new linesting of inner ring based on the type
325         var html = '<br/>';
326         var noOfPoints;
327         if (type == 'MULTILINESTRING') {
328             html += PMA_messages.strLineString + ' ' + (noOfLines + 1) + ':';
329             noOfPoints = 2;
330         } else {
331             html += PMA_messages.strInnerRing + ' ' + noOfLines + ':';
332             noOfPoints = 4;
333         }
334         html += '<input type="hidden" name="' + prefix + '[' + noOfLines + '][no_of_points]" value="' + noOfPoints + '"/>';
335         for (var i = 0; i < noOfPoints; i++) {
336             html += addDataPoint(i, (prefix + '[' + noOfLines + ']'));
337         }
338         html += '<a class="addPoint addJs" name="' + prefix + '[' + noOfLines + '][add_point]" href="#">+ ' +
339             PMA_messages.strAddPoint + '</a><br/>';
341         $a.before(html);
342         $noOfLinesInput.val(noOfLines + 1);
343     });
345     /**
346      * Handles adding polygons
347      */
348     $(document).on('click', '#gis_editor a.addJs.addPolygon', function () {
349         var $a = $(this);
350         var name = $a.attr('name');
351         // Eg. name = gis_data[0][MULTIPOLYGON][add_polygon] => prefix = gis_data[0][MULTIPOLYGON]
352         var prefix = name.substr(0, name.length - 13);
353         // Find the number of polygons
354         var $noOfPolygonsInput = $("input[name='" + prefix + "[no_of_polygons]" + "']");
355         var noOfPolygons = parseInt($noOfPolygonsInput.val(), 10);
357         // Add the new polygon
358         var html = PMA_messages.strPolygon + ' ' + (noOfPolygons + 1) + ':<br/>';
359         html += '<input type="hidden" name="' + prefix + '[' + noOfPolygons + '][no_of_lines]" value="1"/>' +
360             '<br/>' + PMA_messages.strOuterRing + ':' +
361             '<input type="hidden" name="' + prefix + '[' + noOfPolygons + '][0][no_of_points]" value="4"/>';
362         for (var i = 0; i < 4; i++) {
363             html += addDataPoint(i, (prefix + '[' + noOfPolygons + '][0]'));
364         }
365         html += '<a class="addPoint addJs" name="' + prefix + '[' + noOfPolygons + '][0][add_point]" href="#">+ ' +
366             PMA_messages.strAddPoint + '</a><br/>' +
367             '<a class="addLine addJs" name="' + prefix + '[' + noOfPolygons + '][add_line]" href="#">+ ' +
368             PMA_messages.strAddInnerRing + '</a><br/><br/>';
370         $a.before(html);
371         $noOfPolygonsInput.val(noOfPolygons + 1);
372     });
374     /**
375      * Handles adding geoms
376      */
377     $(document).on('click', '#gis_editor a.addJs.addGeom', function () {
378         var $a = $(this);
379         var prefix = 'gis_data[GEOMETRYCOLLECTION]';
380         // Find the number of geoms
381         var $noOfGeomsInput = $("input[name='" + prefix + "[geom_count]" + "']");
382         var noOfGeoms = parseInt($noOfGeomsInput.val(), 10);
384         var html1 = PMA_messages.strGeometry + ' ' + (noOfGeoms + 1) + ':<br/>';
385         var $geomType = $("select[name='gis_data[" + (noOfGeoms - 1) + "][gis_type]']").clone();
386         $geomType.attr('name', 'gis_data[' + noOfGeoms + '][gis_type]').val('POINT');
387         var html2 = '<br/>' + PMA_messages.strPoint + ' :' +
388             '<label for="x"> ' + PMA_messages.strX + ' </label>' +
389             '<input type="text" name="gis_data[' + noOfGeoms + '][POINT][x]" value=""/>' +
390             '<label for="y"> ' + PMA_messages.strY + ' </label>' +
391             '<input type="text" name="gis_data[' + noOfGeoms + '][POINT][y]" value=""/>' +
392             '<br/><br/>';
394         $a.before(html1);
395         $geomType.insertBefore($a);
396         $a.before(html2);
397         $noOfGeomsInput.val(noOfGeoms + 1);
398     });