tbl_gis_visualization.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /* vim: set expandtab sw=4 ts=4 sts=4: */
  2. /**
  3. * @fileoverview functions used for visualizing GIS data
  4. *
  5. * @requires jquery
  6. * @requires vendor/jquery/jquery.svg.js
  7. * @requires vendor/jquery/jquery.mousewheel.js
  8. * @requires vendor/jquery/jquery.event.drag-2.2.js
  9. */
  10. // Constants
  11. var zoomFactor = 1.5;
  12. var defaultX = 0;
  13. var defaultY = 0;
  14. // Variables
  15. var x = 0;
  16. var y = 0;
  17. var scale = 1;
  18. var svg;
  19. /**
  20. * Zooms and pans the visualization.
  21. */
  22. function zoomAndPan () {
  23. var g = svg.getElementById('groupPanel');
  24. if (!g) {
  25. return;
  26. }
  27. g.setAttribute('transform', 'translate(' + x + ', ' + y + ') scale(' + scale + ')');
  28. var id;
  29. var circle;
  30. $('circle.vector').each(function () {
  31. id = $(this).attr('id');
  32. circle = svg.getElementById(id);
  33. $(svg).change(circle, {
  34. r : (3 / scale),
  35. 'stroke-width' : (2 / scale)
  36. });
  37. });
  38. var line;
  39. $('polyline.vector').each(function () {
  40. id = $(this).attr('id');
  41. line = svg.getElementById(id);
  42. $(svg).change(line, {
  43. 'stroke-width' : (2 / scale)
  44. });
  45. });
  46. var polygon;
  47. $('path.vector').each(function () {
  48. id = $(this).attr('id');
  49. polygon = svg.getElementById(id);
  50. $(svg).change(polygon, {
  51. 'stroke-width' : (0.5 / scale)
  52. });
  53. });
  54. }
  55. /**
  56. * Initially loads either SVG or OSM visualization based on the choice.
  57. */
  58. function selectVisualization () {
  59. if ($('#choice').prop('checked') !== true) {
  60. $('#openlayersmap').hide();
  61. } else {
  62. $('#placeholder').hide();
  63. }
  64. }
  65. /**
  66. * Adds necessary styles to the div that coontains the openStreetMap.
  67. */
  68. function styleOSM () {
  69. var $placeholder = $('#placeholder');
  70. var cssObj = {
  71. 'border' : '1px solid #aaa',
  72. 'width' : $placeholder.width(),
  73. 'height' : $placeholder.height(),
  74. 'float' : 'right'
  75. };
  76. $('#openlayersmap').css(cssObj);
  77. }
  78. /**
  79. * Loads the SVG element and make a reference to it.
  80. */
  81. function loadSVG () {
  82. var $placeholder = $('#placeholder');
  83. $placeholder.svg({
  84. onLoad: function (svg_ref) {
  85. svg = svg_ref;
  86. }
  87. });
  88. // Removes the second SVG element unnecessarily added due to the above command
  89. $placeholder.find('svg:nth-child(2)').remove();
  90. }
  91. /**
  92. * Adds controllers for zooming and panning.
  93. */
  94. function addZoomPanControllers () {
  95. var $placeholder = $('#placeholder');
  96. if ($('#placeholder').find('svg').length > 0) {
  97. var pmaThemeImage = $('#pmaThemeImage').val();
  98. // add panning arrows
  99. $('<img class="button" id="left_arrow" src="' + pmaThemeImage + 'west-mini.png">').appendTo($placeholder);
  100. $('<img class="button" id="right_arrow" src="' + pmaThemeImage + 'east-mini.png">').appendTo($placeholder);
  101. $('<img class="button" id="up_arrow" src="' + pmaThemeImage + 'north-mini.png">').appendTo($placeholder);
  102. $('<img class="button" id="down_arrow" src="' + pmaThemeImage + 'south-mini.png">').appendTo($placeholder);
  103. // add zooming controls
  104. $('<img class="button" id="zoom_in" src="' + pmaThemeImage + 'zoom-plus-mini.png">').appendTo($placeholder);
  105. $('<img class="button" id="zoom_world" src="' + pmaThemeImage + 'zoom-world-mini.png">').appendTo($placeholder);
  106. $('<img class="button" id="zoom_out" src="' + pmaThemeImage + 'zoom-minus-mini.png">').appendTo($placeholder);
  107. }
  108. }
  109. /**
  110. * Resizes the GIS visualization to fit into the space available.
  111. */
  112. function resizeGISVisualization () {
  113. var $placeholder = $('#placeholder');
  114. var old_width = $placeholder.width();
  115. var visWidth = $('#div_view_options').width() - 48;
  116. // Assign new value for width
  117. $placeholder.width(visWidth);
  118. $('svg').attr('width', visWidth);
  119. // Assign the offset created due to resizing to defaultX and center the svg.
  120. defaultX = (visWidth - old_width) / 2;
  121. x = defaultX;
  122. y = 0;
  123. scale = 1;
  124. }
  125. /**
  126. * Initialize the GIS visualization.
  127. */
  128. function initGISVisualization () {
  129. // Loads either SVG or OSM visualization based on the choice
  130. selectVisualization();
  131. // Resizes the GIS visualization to fit into the space available
  132. resizeGISVisualization();
  133. if (typeof OpenLayers !== 'undefined') {
  134. // Configure OpenLayers
  135. OpenLayers._getScriptLocation = function () {
  136. return './js/vendor/openlayers/';
  137. };
  138. // Adds necessary styles to the div that coontains the openStreetMap
  139. styleOSM();
  140. // Draws openStreetMap with openLayers
  141. drawOpenLayers();
  142. }
  143. // Loads the SVG element and make a reference to it
  144. loadSVG();
  145. // Adds controllers for zooming and panning
  146. addZoomPanControllers();
  147. zoomAndPan();
  148. }
  149. function getRelativeCoords (e) {
  150. var position = $('#placeholder').offset();
  151. return {
  152. x : e.pageX - position.left,
  153. y : e.pageY - position.top
  154. };
  155. }
  156. /**
  157. * Ajax handlers for GIS visualization page
  158. *
  159. * Actions Ajaxified here:
  160. *
  161. * Zooming in and zooming out on mousewheel movement.
  162. * Panning the visualization on dragging.
  163. * Zooming in on double clicking.
  164. * Zooming out on clicking the zoom out button.
  165. * Panning on clicking the arrow buttons.
  166. * Displaying tooltips for GIS objects.
  167. */
  168. /**
  169. * Unbind all event handlers before tearing down a page
  170. */
  171. AJAX.registerTeardown('tbl_gis_visualization.js', function () {
  172. $(document).off('click', '#choice');
  173. $(document).off('mousewheel', '#placeholder');
  174. $(document).off('dragstart', 'svg');
  175. $(document).off('mouseup', 'svg');
  176. $(document).off('drag', 'svg');
  177. $(document).off('dblclick', '#placeholder');
  178. $(document).off('click', '#zoom_in');
  179. $(document).off('click', '#zoom_world');
  180. $(document).off('click', '#zoom_out');
  181. $(document).off('click', '#left_arrow');
  182. $(document).off('click', '#right_arrow');
  183. $(document).off('click', '#up_arrow');
  184. $(document).off('click', '#down_arrow');
  185. $('.vector').off('mousemove').off('mouseout');
  186. });
  187. AJAX.registerOnload('tbl_gis_visualization.js', function () {
  188. // If we are in GIS visualization, initialize it
  189. if ($('#gis_div').length > 0) {
  190. initGISVisualization();
  191. }
  192. if (typeof OpenLayers === 'undefined') {
  193. $('#choice, #labelChoice').hide();
  194. }
  195. $(document).on('click', '#choice', function () {
  196. if ($(this).prop('checked') === false) {
  197. $('#placeholder').show();
  198. $('#openlayersmap').hide();
  199. } else {
  200. $('#placeholder').hide();
  201. $('#openlayersmap').show();
  202. }
  203. });
  204. $(document).on('mousewheel', '#placeholder', function (event, delta) {
  205. event.preventDefault();
  206. var relCoords = getRelativeCoords(event);
  207. if (delta > 0) {
  208. // zoom in
  209. scale *= zoomFactor;
  210. // zooming in keeping the position under mouse pointer unmoved.
  211. x = relCoords.x - (relCoords.x - x) * zoomFactor;
  212. y = relCoords.y - (relCoords.y - y) * zoomFactor;
  213. zoomAndPan();
  214. } else {
  215. // zoom out
  216. scale /= zoomFactor;
  217. // zooming out keeping the position under mouse pointer unmoved.
  218. x = relCoords.x - (relCoords.x - x) / zoomFactor;
  219. y = relCoords.y - (relCoords.y - y) / zoomFactor;
  220. zoomAndPan();
  221. }
  222. return true;
  223. });
  224. var dragX = 0;
  225. var dragY = 0;
  226. $(document).on('dragstart', 'svg', function (event, dd) {
  227. $('#placeholder').addClass('placeholderDrag');
  228. dragX = Math.round(dd.offsetX);
  229. dragY = Math.round(dd.offsetY);
  230. });
  231. $(document).on('mouseup', 'svg', function (event) {
  232. $('#placeholder').removeClass('placeholderDrag');
  233. });
  234. $(document).on('drag', 'svg', function (event, dd) {
  235. var newX = Math.round(dd.offsetX);
  236. x += newX - dragX;
  237. dragX = newX;
  238. var newY = Math.round(dd.offsetY);
  239. y += newY - dragY;
  240. dragY = newY;
  241. zoomAndPan();
  242. });
  243. $(document).on('dblclick', '#placeholder', function (event) {
  244. scale *= zoomFactor;
  245. // zooming in keeping the position under mouse pointer unmoved.
  246. var relCoords = getRelativeCoords(event);
  247. x = relCoords.x - (relCoords.x - x) * zoomFactor;
  248. y = relCoords.y - (relCoords.y - y) * zoomFactor;
  249. zoomAndPan();
  250. });
  251. $(document).on('click', '#zoom_in', function (e) {
  252. e.preventDefault();
  253. // zoom in
  254. scale *= zoomFactor;
  255. var $placeholder = $('#placeholder').find('svg');
  256. width = $placeholder.attr('width');
  257. height = $placeholder.attr('height');
  258. // zooming in keeping the center unmoved.
  259. x = width / 2 - (width / 2 - x) * zoomFactor;
  260. y = height / 2 - (height / 2 - y) * zoomFactor;
  261. zoomAndPan();
  262. });
  263. $(document).on('click', '#zoom_world', function (e) {
  264. e.preventDefault();
  265. scale = 1;
  266. x = defaultX;
  267. y = defaultY;
  268. zoomAndPan();
  269. });
  270. $(document).on('click', '#zoom_out', function (e) {
  271. e.preventDefault();
  272. // zoom out
  273. scale /= zoomFactor;
  274. var $placeholder = $('#placeholder').find('svg');
  275. width = $placeholder.attr('width');
  276. height = $placeholder.attr('height');
  277. // zooming out keeping the center unmoved.
  278. x = width / 2 - (width / 2 - x) / zoomFactor;
  279. y = height / 2 - (height / 2 - y) / zoomFactor;
  280. zoomAndPan();
  281. });
  282. $(document).on('click', '#left_arrow', function (e) {
  283. e.preventDefault();
  284. x += 100;
  285. zoomAndPan();
  286. });
  287. $(document).on('click', '#right_arrow', function (e) {
  288. e.preventDefault();
  289. x -= 100;
  290. zoomAndPan();
  291. });
  292. $(document).on('click', '#up_arrow', function (e) {
  293. e.preventDefault();
  294. y += 100;
  295. zoomAndPan();
  296. });
  297. $(document).on('click', '#down_arrow', function (e) {
  298. e.preventDefault();
  299. y -= 100;
  300. zoomAndPan();
  301. });
  302. /**
  303. * Detect the mousemove event and show tooltips.
  304. */
  305. $('.vector').on('mousemove', function (event) {
  306. var contents = $.trim(escapeHtml($(this).attr('name')));
  307. $('#tooltip').remove();
  308. if (contents !== '') {
  309. $('<div id="tooltip">' + contents + '</div>').css({
  310. position : 'absolute',
  311. top : event.pageY + 10,
  312. left : event.pageX + 10,
  313. border : '1px solid #fdd',
  314. padding : '2px',
  315. 'background-color' : '#fee',
  316. opacity : 0.90
  317. }).appendTo('body').fadeIn(200);
  318. }
  319. });
  320. /**
  321. * Detect the mouseout event and hide tooltips.
  322. */
  323. $('.vector').on('mouseout', function (event) {
  324. $('#tooltip').remove();
  325. });
  326. });