Reusable Accessible Mapping Platform

API Docs for: 3.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. var layerUrl = graphic.getLayer().url,
  136. templateKey = "",
  137. datawrapper,
  138. maptipContent;
  139.  
  140. tmpl.cache = {};
  141.  
  142. if (interactive === true) {
  143. templateKey = Ramp.getLayerConfig(layerUrl).mapTipSettings.anchorTemplate;
  144. tmpl.templates = anchortips_template_json;
  145. } else {
  146. templateKey = Ramp.getLayerConfig(layerUrl).mapTipSettings.hoverTemplate;
  147. tmpl.templates = hovertips_template_json;
  148. }
  149.  
  150. datawrapper = TmplHelper.dataBuilder(graphic, layerUrl);
  151. maptipContent = tmpl(templateKey, datawrapper);
  152.  
  153. return maptipContent;
  154. }
  155.  
  156. /**
  157. * Creates a maptip on the map.
  158. *
  159. * @method showMapTip
  160. * @private
  161. * @param {jObject} target a node the user hovered over
  162. * @param {Object} graphic the graphic belonging to the target
  163. * @param {Boolean} interactive indicates whether the maptip should have a close button
  164. */
  165. function showMapTip(target, graphic, interactive) {
  166. var maptipContent = getMaptipContent(graphic, interactive);
  167.  
  168. if (maptipContent == null) {
  169. return;
  170. }
  171. target.tooltipster({
  172. offsetX: $(target)[0].getBBox().width / 2,
  173. content: $(maptipContent),
  174. interactive: true,
  175. arrow: true,
  176. updateAnimation: Modernizr.csstransitions, // known bug in tooltipster when browsers not supporting CSS animation don't display tooltips at all
  177. autoClose: interactive !== true,
  178. onlyOne: true,
  179. interactiveTolerance: tolerance,
  180. speed: speed,
  181. theme: (interactive === true) ? '.tooltipster-noir' : '.tooltipster-shadow'
  182. });
  183.  
  184. if (!interactive) {
  185. target
  186. .tooltipster("offsetX", $(target)[0].getBBox().width / 2) // ?
  187. .mouseover();
  188. } else {
  189. // add a close button
  190. target
  191. .tooltipster("show")
  192. .tooltipster("content", $(maptipContent).append('<button class="button-none button-close"><span class="wb-invisible">Close</span></button>'));
  193.  
  194. // set a listener to that close button
  195. $(target.tooltipster("elementTooltip"))
  196. .find(".button-close")
  197. .on("click", function () {
  198. topic.publish(EventManager.GUI.SUBPANEL_CLOSE, { origin: "all" });
  199. });
  200.  
  201. // keep pointers to the tooltip parts
  202. highTooltip.node = $(target.tooltipster("elementTooltip"));
  203. highTooltip.handle = target.tooltipster();
  204. highTooltip.graphic = graphic;
  205. }
  206. }
  207.  
  208. /**
  209. * Initialize event listeners for the maptip events
  210. *
  211. * @method initListeners
  212. * @private
  213. *
  214. */
  215. function initListeners() {
  216. topic.subscribe(EventManager.Maptips.SHOW, function (event) {
  217. //console.log(EventManager.Maptips.SHOW);
  218. showMapTip($(event.target), event.graphic);
  219. });
  220.  
  221. topic.subscribe(EventManager.Maptips.SHOW_INTERACTIVE, function (obj) {
  222. //console.log(EventManager.Maptips.SHOW_INTERACTIVE);
  223. checkMaptipPosition(obj.target, obj.graphic);
  224. showMapTip(obj.target, obj.graphic, true);
  225. });
  226.  
  227. topic.subscribe(EventManager.Maptips.REPOSITION_INTERACTIVE, function (obj) {
  228. //console.log(EventManager.Maptips.REPOSITION_INTERACTIVE);
  229.  
  230. if (highTooltip.handle !== null && highTooltip.node !== null) {
  231. var localOffset = obj.offset || 0;
  232.  
  233. highTooltip.handle
  234. .tooltipster("offsetX", localOffset)
  235. .tooltipster("reposition");
  236.  
  237. // check if the tooltip is "hidden" under the sub-panel; if so, hide it for real;
  238. window.setTimeout(function () {
  239. if (getToolTipOffset() > getSubPanelLeftOffset()) {
  240. highTooltip.node.hide();
  241. } else {
  242. highTooltip.node.show();
  243. }
  244. }, speed + 10);
  245. }
  246. });
  247.  
  248. topic.subscribe(EventManager.GUI.SUBPANEL_CHANGE, function (obj) {
  249. //console.log("subPanelChange", obj);
  250. if (obj.isComplete) {
  251. if (obj.visible) {
  252. subPanelOffset = obj.offsetLeft;
  253. checkMaptipPosition();
  254. } else {
  255. subPanelOffset = 0;
  256. }
  257. }
  258. });
  259. }
  260.  
  261. return {
  262. /**
  263. * Calls the event handling initialization function
  264. * @method init
  265. * @constructor
  266. *
  267. */
  268. init: function () {
  269. initListeners();
  270. }
  271. };
  272. });