Reusable Accessible Mapping Platform

API Docs for: 5.0.0
Show:

File: src\js\RAMP\Modules\maptips.js

  1. /*global define, $, window, Modernizr, tmpl */
  2. /*jslint white: true */
  3.  
  4. /**
  5. *
  6. *
  7. * @module Map
  8. * @submodule Maptips
  9. */
  10.  
  11. /**
  12. * Maptips class.
  13. *
  14. * The map tip module provides functions to create a small popup window as the mouse hovers over a feature on the map (point, polygon, line, etc.).
  15. * NOTE: This module uses global config object. featureLayers->mapTipSettings
  16. *
  17. * @class Maptips
  18. * @static
  19. * @uses dojo/topic
  20. * @uses RAMP
  21. * @uses EventManager
  22. * @uses TmplHelper
  23. * @uses templates/feature_hovertip_template.json
  24. * @uses templates/feature_anchortip_template.json
  25. */
  26.  
  27. define([
  28. /* Dojo */
  29. "dojo/topic",
  30.  
  31. /* Ramp */
  32. "ramp/ramp", "ramp/eventManager",
  33.  
  34. /*tmplHelper */
  35. "utils/tmplHelper",
  36.  
  37. /* json hover template file */
  38. "dojo/text!./templates/feature_hovertip_template.json",
  39. /* json archor template file*/
  40. "dojo/text!./templates/feature_anchortip_template.json"
  41. ],
  42.  
  43. function (
  44. /* Dojo */
  45. topic,
  46. /* Ramp */
  47. Ramp, EventManager,
  48.  
  49. /*tmplHelper */
  50. TmplHelper, hovertips_template, anchortips_template
  51. ) {
  52. "use strict";
  53.  
  54. var hovertips_template_json = JSON.parse(TmplHelper.stringifyTemplate(hovertips_template)),
  55. anchortips_template_json = JSON.parse(TmplHelper.stringifyTemplate(anchortips_template)),
  56. maptipPrototype = {
  57. node: null,
  58. handle: null,
  59. graphic: null
  60. },
  61.  
  62. speed = 150,
  63. tolerance = 0,
  64.  
  65. highTooltip = Object.create(maptipPrototype),
  66.  
  67. subPanelOffset;
  68.  
  69. /**
  70. * Returns the position of the sub-panel relative to the leftmost edge of the screen.
  71. *
  72. * @method getSubPanelLeftOffset
  73. * @private
  74. * @return {Number} position of hte sub-panel relative to the leftmost edge of the screen
  75. */
  76. function getSubPanelLeftOffset() {
  77. return $(window).width() - subPanelOffset;
  78. }
  79.  
  80. /**
  81. * Returns the position of the maptip relative to the leftmost edge of the screen.
  82. *
  83. * @method getToolTipOffset
  84. * @private
  85. * @return {Number} the position of the maptip relative to the leftmost edge of the screen
  86. */
  87. function getToolTipOffset() {
  88. var offset = 0;
  89.  
  90. if (highTooltip.handle !== null && highTooltip.node !== null) {
  91. offset = parseInt(highTooltip.node.css("left"), 10) + highTooltip.node.width() / 2 - 20;
  92. }
  93.  
  94. return offset;
  95. }
  96.  
  97. /**
  98. * Checks if the maptip is hidden by the sub-panel and publishes a center-at event to pan the map, moving maptip into view.
  99. *
  100. * @method checkMaptipPosition
  101. * @private
  102. * @param {jObject} target a node to which the tooltip will be attached
  103. * @param {Object} graphic [description]
  104. */
  105. function checkMaptipPosition(target, graphic) {
  106. graphic = graphic || highTooltip.graphic || null;
  107. target = target || highTooltip.handle || null;
  108.  
  109. if (target && graphic &&
  110. target.offset().left > getSubPanelLeftOffset()) {
  111. //console.log("offsets", target.offset().left, getSubPanelLeftOffset());
  112. topic.publish(EventManager.Map.CENTER_AT, {
  113. point: graphic._extent.getCenter()
  114. });
  115.  
  116. topic.publish(EventManager.Maptips.EXTENT_CHANGE, {
  117. scroll: false
  118. });
  119. } else {
  120. topic.publish(EventManager.Maptips.EXTENT_CHANGE, {
  121. scroll: true
  122. });
  123. }
  124. }
  125.  
  126. /**
  127. * Generates content for a maptip.
  128. *
  129. * @method getMaptipContent
  130. * @private
  131. * @param {Object} graphic map graphic the tip is describing
  132. * @param {String} interactive indicates whether the maptip should have a close button
  133. */
  134. function getMaptipContent(graphic, interactive) {
  135. //the graphic might be in a highlight layer, if so we need the source layer id
  136. var layerId = graphic.getLayer().sourceLayerId;
  137. if (!layerId) {
  138. //graphic was not in a highlight layer
  139. layerId = graphic.getLayer().id;
  140. }
  141.  
  142. var layerConfig = Ramp.getLayerConfigWithId(layerId),
  143. templateKey = "",
  144. datawrapper,
  145. maptipContent;
  146.  
  147. tmpl.cache = {};
  148.  
  149. if (interactive === true) {
  150. templateKey = layerConfig.templates.anchor;
  151. tmpl.templates = anchortips_template_json;
  152. } else {
  153. templateKey = layerConfig.templates.hover;
  154. tmpl.templates = hovertips_template_json;
  155. }
  156.  
  157. datawrapper = TmplHelper.dataBuilder(graphic, layerConfig);
  158. maptipContent = tmpl(templateKey, datawrapper);
  159.  
  160. return maptipContent;
  161. }
  162.  
  163. /**
  164. * Creates a maptip on the map.
  165. *
  166. * @method showMapTip
  167. * @private
  168. * @param {jObject} target a node the user hovered over
  169. * @param {Object} graphic the graphic belonging to the target
  170. * @param {Boolean} interactive indicates whether the maptip should have a close button
  171. */
  172. function showMapTip(target, graphic, interactive) {
  173. var maptipContent = getMaptipContent(graphic, interactive);
  174.  
  175. if (maptipContent == null) {
  176. return;
  177. }
  178. target.tooltipster({
  179. offsetX: $(target)[0].getBBox().width / 2,
  180. content: $(maptipContent),
  181. interactive: true,
  182. arrow: true,
  183. updateAnimation: Modernizr.csstransitions, // known bug in tooltipster when browsers not supporting CSS animation don't display tooltips at all
  184. autoClose: interactive !== true,
  185. onlyOne: true,
  186. interactiveTolerance: tolerance,
  187. speed: speed,
  188. theme: (interactive === true) ? '.tooltipster-noir' : '.tooltipster-shadow'
  189. });
  190.  
  191. if (!interactive) {
  192. target
  193. .tooltipster("offsetX", $(target)[0].getBBox().width / 2) // ?
  194. .mouseover();
  195. } else {
  196. // add a close button
  197. target
  198. .tooltipster("show")
  199. .tooltipster("content", $(maptipContent).append('<button class="button-none button-close"><span class="wb-invisible">Close</span></button>'));
  200.  
  201. // set a listener to that close button
  202. $(target.tooltipster("elementTooltip"))
  203. .find(".button-close")
  204. .on("click", function () {
  205. topic.publish(EventManager.GUI.SUBPANEL_CLOSE, { origin: "all" });
  206. });
  207.  
  208. // keep pointers to the tooltip parts
  209. highTooltip.node = $(target.tooltipster("elementTooltip"));
  210. highTooltip.handle = target.tooltipster();
  211. highTooltip.graphic = graphic;
  212. }
  213. }
  214.  
  215. /**
  216. * Initialize event listeners for the maptip events
  217. *
  218. * @method initListeners
  219. * @private
  220. *
  221. */
  222. function initListeners() {
  223. topic.subscribe(EventManager.Maptips.SHOW, function (event) {
  224. //console.log(EventManager.Maptips.SHOW);
  225. showMapTip($(event.target), event.graphic);
  226. });
  227.  
  228. topic.subscribe(EventManager.Maptips.SHOW_INTERACTIVE, function (obj) {
  229. //console.log(EventManager.Maptips.SHOW_INTERACTIVE);
  230. checkMaptipPosition(obj.target, obj.graphic);
  231. showMapTip(obj.target, obj.graphic, true);
  232. });
  233.  
  234. topic.subscribe(EventManager.Maptips.REPOSITION_INTERACTIVE, function (obj) {
  235. //console.log(EventManager.Maptips.REPOSITION_INTERACTIVE);
  236.  
  237. if (highTooltip.handle !== null && highTooltip.node !== null) {
  238. var localOffset = obj.offset || 0;
  239.  
  240. highTooltip.handle
  241. .tooltipster("offsetX", localOffset)
  242. .tooltipster("reposition");
  243.  
  244. // check if the tooltip is "hidden" under the sub-panel; if so, hide it for real;
  245. window.setTimeout(function () {
  246. if (getToolTipOffset() > getSubPanelLeftOffset()) {
  247. highTooltip.node.hide();
  248. } else {
  249. highTooltip.node.show();
  250. }
  251. }, speed + 10);
  252. }
  253. });
  254.  
  255. topic.subscribe(EventManager.GUI.SUBPANEL_CHANGE, function (obj) {
  256. //console.log("subPanelChange", obj);
  257. if (obj.isComplete) {
  258. if (obj.visible) {
  259. subPanelOffset = obj.offsetLeft;
  260. checkMaptipPosition();
  261. } else {
  262. subPanelOffset = 0;
  263. }
  264. }
  265. });
  266. }
  267.  
  268. return {
  269. /**
  270. * Calls the event handling initialization function
  271. * @method init
  272. * @constructor
  273. *
  274. */
  275. init: function () {
  276. initListeners();
  277. }
  278. };
  279. });