gis_data_editor.js 13 KB

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