Reusable Accessible Mapping Platform

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