UPDATE 4.4.0.0
[phpmyadmin.git] / js / gis_data_editor.js
blob0fb39d7a759eb5c7075ba7102c3e2c98e81846c2
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 recieved via AJAX.
23  */
24 function prepareJSVersion() {
25     // Change the text on the submit button
26     $("#gis_editor 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 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     };
123     script.src = 'js/openlayers/OpenLayers.js';
124     head.appendChild(script);
126     gisEditorLoaded = true;
130  * Loads the GIS editor via AJAX
132  * @param value      current value of the geometry field
133  * @param field      field name
134  * @param type       geometry type
135  * @param input_name name of the input field
136  * @param token      token
137  */
138 function loadGISEditor(value, field, type, input_name, token) {
140     var $gis_editor = $("#gis_editor");
141     $.post('gis_data_editor.php', {
142         'field' : field,
143         'value' : value,
144         'type' : type,
145         'input_name' : input_name,
146         'get_gis_editor' : true,
147         'token' : token,
148         'ajax_request': true
149     }, function (data) {
150         if (typeof data !== 'undefined' && data.success === true) {
151             $gis_editor.html(data.gis_editor);
152             initGISEditorVisualization();
153             prepareJSVersion();
154         } else {
155             PMA_ajaxShowMessage(data.error, false);
156         }
157     }, 'json');
161  * Opens up the dialog for the GIS data editor.
162  */
163 function openGISEditor() {
165     // Center the popup
166     var windowWidth = document.documentElement.clientWidth;
167     var windowHeight = document.documentElement.clientHeight;
168     var popupWidth = windowWidth * 0.9;
169     var popupHeight = windowHeight * 0.9;
170     var popupOffsetTop = windowHeight / 2 - popupHeight / 2;
171     var popupOffsetLeft = windowWidth / 2 - popupWidth / 2;
173     var $gis_editor = $("#gis_editor");
174     var $backgrouond = $("#popup_background");
176     $gis_editor.css({"top": popupOffsetTop, "left": popupOffsetLeft, "width": popupWidth, "height": popupHeight});
177     $backgrouond.css({"opacity" : "0.7"});
179     $gis_editor.append(
180         '<div id="gis_data_editor">' +
181         '<img class="ajaxIcon" id="loadingMonitorIcon" src="' +
182         pmaThemeImage + 'ajax_clock_small.gif" alt=""/>' +
183         '</div>'
184     );
186     // Make it appear
187     $backgrouond.fadeIn("fast");
188     $gis_editor.fadeIn("fast");
192  * Prepare and insert the GIS data in Well Known Text format
193  * to the input field.
194  */
195 function insertDataAndClose() {
196     var $form = $('form#gis_data_editor_form');
197     var input_name = $form.find("input[name='input_name']").val();
199     $.post('gis_data_editor.php', $form.serialize() + "&generate=true&ajax_request=true", function (data) {
200         if (typeof data !== 'undefined' && data.success === true) {
201             $("input[name='" + input_name + "']").val(data.result);
202         } else {
203             PMA_ajaxShowMessage(data.error, false);
204         }
205     }, 'json');
206     closeGISEditor();
210  * Unbind all event handlers before tearing down a page
211  */
212 AJAX.registerTeardown('gis_data_editor.js', function () {
213     $(document).off('click', "#gis_editor input[name='gis_data[save]']");
214     $(document).off('submit', '#gis_editor');
215     $(document).off('change', "#gis_editor input[type='text']");
216     $(document).off('change', "#gis_editor select.gis_type");
217     $(document).off('click', '#gis_editor a.close_gis_editor, #gis_editor a.cancel_gis_editor');
218     $(document).off('click', '#gis_editor a.addJs.addPoint');
219     $(document).off('click', '#gis_editor a.addLine.addJs');
220     $(document).off('click', '#gis_editor a.addJs.addPolygon');
221     $(document).off('click', '#gis_editor a.addJs.addGeom');
224 AJAX.registerOnload('gis_data_editor.js', function () {
226     // Remove the class that is added due to the URL being too long.
227     $('span.open_gis_editor a').removeClass('formLinkSubmit');
229     /**
230      * Prepares and insert the GIS data to the input field on clicking 'copy'.
231      */
232     $(document).on('click', "#gis_editor input[name='gis_data[save]']", function (event) {
233         event.preventDefault();
234         insertDataAndClose();
235     });
237     /**
238      * Prepares and insert the GIS data to the input field on pressing 'enter'.
239      */
240     $(document).on('submit', '#gis_editor', function (event) {
241         event.preventDefault();
242         insertDataAndClose();
243     });
245     /**
246      * Trigger asynchronous calls on data change and update the output.
247      */
248     $(document).on('change', "#gis_editor input[type='text']", function () {
249         var $form = $('form#gis_data_editor_form');
250         $.post('gis_data_editor.php', $form.serialize() + "&generate=true&ajax_request=true", function (data) {
251             if (typeof data !== 'undefined' && data.success === true) {
252                 $('#gis_data_textarea').val(data.result);
253                 $('#placeholder').empty().removeClass('hasSVG').html(data.visualization);
254                 $('#openlayersmap').empty();
255                 /* TODO: the gis_data_editor should rather return JSON than JS code to eval */
256                 eval(data.openLayers);
257                 initGISEditorVisualization();
258             } else {
259                 PMA_ajaxShowMessage(data.error, false);
260             }
261         }, 'json');
262     });
264     /**
265      * Update the form on change of the GIS type.
266      */
267     $(document).on('change', "#gis_editor select.gis_type", function (event) {
268         var $gis_editor = $("#gis_editor");
269         var $form = $('form#gis_data_editor_form');
271         $.post('gis_data_editor.php', $form.serialize() + "&get_gis_editor=true&ajax_request=true", function (data) {
272             if (typeof data !== 'undefined' && data.success === true) {
273                 $gis_editor.html(data.gis_editor);
274                 initGISEditorVisualization();
275                 prepareJSVersion();
276             } else {
277                 PMA_ajaxShowMessage(data.error, false);
278             }
279         }, 'json');
280     });
282     /**
283      * Handles closing of the GIS data editor.
284      */
285     $(document).on('click', '#gis_editor a.close_gis_editor, #gis_editor a.cancel_gis_editor', function () {
286         closeGISEditor();
287     });
289     /**
290      * Handles adding data points
291      */
292     $(document).on('click', '#gis_editor a.addJs.addPoint', function () {
293         var $a = $(this);
294         var name = $a.attr('name');
295         // Eg. name = gis_data[0][MULTIPOINT][add_point] => prefix = gis_data[0][MULTIPOINT]
296         var prefix = name.substr(0, name.length - 11);
297         // Find the number of points
298         var $noOfPointsInput = $("input[name='" + prefix + "[no_of_points]" + "']");
299         var noOfPoints = parseInt($noOfPointsInput.val(), 10);
300         // Add the new data point
301         var html = addDataPoint(noOfPoints, prefix);
302         $a.before(html);
303         $noOfPointsInput.val(noOfPoints + 1);
304     });
306     /**
307      * Handles adding linestrings and inner rings
308      */
309     $(document).on('click', '#gis_editor a.addLine.addJs', function () {
310         var $a = $(this);
311         var name = $a.attr('name');
313         // Eg. name = gis_data[0][MULTILINESTRING][add_line] => prefix = gis_data[0][MULTILINESTRING]
314         var prefix = name.substr(0, name.length - 10);
315         var type = prefix.slice(prefix.lastIndexOf('[') + 1, prefix.lastIndexOf(']'));
317         // Find the number of lines
318         var $noOfLinesInput = $("input[name='" + prefix + "[no_of_lines]" + "']");
319         var noOfLines = parseInt($noOfLinesInput.val(), 10);
321         // Add the new linesting of inner ring based on the type
322         var html = '<br/>';
323         var noOfPoints;
324         if (type == 'MULTILINESTRING') {
325             html += PMA_messages.strLineString + ' ' + (noOfLines + 1) + ':';
326             noOfPoints = 2;
327         } else {
328             html += PMA_messages.strInnerRing + ' ' + noOfLines + ':';
329             noOfPoints = 4;
330         }
331         html += '<input type="hidden" name="' + prefix + '[' + noOfLines + '][no_of_points]" value="' + noOfPoints + '"/>';
332         for (var i = 0; i < noOfPoints; i++) {
333             html += addDataPoint(i, (prefix + '[' + noOfLines + ']'));
334         }
335         html += '<a class="addPoint addJs" name="' + prefix + '[' + noOfLines + '][add_point]" href="#">+ ' +
336             PMA_messages.strAddPoint + '</a><br/>';
338         $a.before(html);
339         $noOfLinesInput.val(noOfLines + 1);
340     });
342     /**
343      * Handles adding polygons
344      */
345     $(document).on('click', '#gis_editor a.addJs.addPolygon', function () {
346         var $a = $(this);
347         var name = $a.attr('name');
348         // Eg. name = gis_data[0][MULTIPOLYGON][add_polygon] => prefix = gis_data[0][MULTIPOLYGON]
349         var prefix = name.substr(0, name.length - 13);
350         // Find the number of polygons
351         var $noOfPolygonsInput = $("input[name='" + prefix + "[no_of_polygons]" + "']");
352         var noOfPolygons = parseInt($noOfPolygonsInput.val(), 10);
354         // Add the new polygon
355         var html = PMA_messages.strPolygon + ' ' + (noOfPolygons + 1) + ':<br/>';
356         html += '<input type="hidden" name="' + prefix + '[' + noOfPolygons + '][no_of_lines]" value="1"/>' +
357             '<br/>' + PMA_messages.strOuterRing + ':' +
358             '<input type="hidden" name="' + prefix + '[' + noOfPolygons + '][0][no_of_points]" value="4"/>';
359         for (var i = 0; i < 4; i++) {
360             html += addDataPoint(i, (prefix + '[' + noOfPolygons + '][0]'));
361         }
362         html += '<a class="addPoint addJs" name="' + prefix + '[' + noOfPolygons + '][0][add_point]" href="#">+ ' +
363             PMA_messages.strAddPoint + '</a><br/>' +
364             '<a class="addLine addJs" name="' + prefix + '[' + noOfPolygons + '][add_line]" href="#">+ ' +
365             PMA_messages.strAddInnerRing + '</a><br/><br/>';
367         $a.before(html);
368         $noOfPolygonsInput.val(noOfPolygons + 1);
369     });
371     /**
372      * Handles adding geoms
373      */
374     $(document).on('click', '#gis_editor a.addJs.addGeom', function () {
375         var $a = $(this);
376         var prefix = 'gis_data[GEOMETRYCOLLECTION]';
377         // Find the number of geoms
378         var $noOfGeomsInput = $("input[name='" + prefix + "[geom_count]" + "']");
379         var noOfGeoms = parseInt($noOfGeomsInput.val(), 10);
381         var html1 = PMA_messages.strGeometry + ' ' + (noOfGeoms + 1) + ':<br/>';
382         var $geomType = $("select[name='gis_data[" + (noOfGeoms - 1) + "][gis_type]']").clone();
383         $geomType.attr('name', 'gis_data[' + noOfGeoms + '][gis_type]').val('POINT');
384         var html2 = '<br/>' + PMA_messages.strPoint + ' :' +
385             '<label for="x"> ' + PMA_messages.strX + ' </label>' +
386             '<input type="text" name="gis_data[' + noOfGeoms + '][POINT][x]" value=""/>' +
387             '<label for="y"> ' + PMA_messages.strY + ' </label>' +
388             '<input type="text" name="gis_data[' + noOfGeoms + '][POINT][y]" value=""/>' +
389             '<br/><br/>';
391         $a.before(html1);
392         $geomType.insertBefore($a);
393         $a.before(html2);
394         $noOfGeomsInput.val(noOfGeoms + 1);
395     });