gis_data_editor.js 14 KB

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