gis_data_editor.js 13 KB

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