leaflet.module 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. <?php
  2. /**
  3. * @file
  4. * Provide Leaflet API integration and field formatters.
  5. */
  6. module_load_include('inc', 'leaflet', 'leaflet.formatters');
  7. /**
  8. * Implements hook_help().
  9. */
  10. function leaflet_help($path, $arg) {
  11. switch ($path) {
  12. case 'admin/help#leaflet':
  13. $output = '';
  14. $output .= '<h3>' . t('About') . '</h3>';
  15. $output .= '<p>' . t('The Leaflet module provides integration with Leaflet, the modern open-source JavaScript library for mobile-friendly interactive maps.') . '</p>';
  16. $output .= '<p>' . t('The module provides a field formatter that can show a map for fields that contain geospatial data. It includes Views integration that plots data on a map (using the sub module Leaflet Views) and an API for displaying data on a map. For more information, see the online documentation for the <a href="@leaflet">Leaflet module</a>.', array('@leaflet' => 'http://drupal.org/node/1645460')) . '</p>';
  17. $output .= '<h3>' . t('Uses') . '</h3>';
  18. $output .= '<dl>';
  19. $output .= '<dt>' . t('Field Formatter') . '</dt>';
  20. $output .= '<dd>' . t('Leaflet includes a field formatter that makes it possible to show geospatial data (for example longitude and latitude) on a map. You can use tokens instead of static text for Popups that use the Leaflet field formatter.') . '</dd>';
  21. $output .= '<dt>' . t('Views Integration') . '</dt>';
  22. $output .= '<dd>' . t('You can have maps on node displays and maps on views displays, thanks to Views integration. The process is very similar to adding and setting up a plugin on Views. To render a map using Views, enable the included module Leaflet_views.') . '</dd>';
  23. $output .= '<dt>' . t('Leaflet API') . '</dt>';
  24. $output .= '<dd>' . t('Rendering a map is as simple as calling a single method, leaflet_render_map(), which takes 3 parameters $map, $features, and $height.') . '</dd>';
  25. return $output;
  26. }
  27. }
  28. /**
  29. * Implements hook_theme().
  30. */
  31. function leaflet_theme($existing, $type, $theme, $path) {
  32. return array(
  33. 'leaflet_map' => array(
  34. 'arguments' => array('map_id' => NULL, 'height' => '400px'),
  35. 'template' => 'leaflet_map',
  36. ),
  37. );
  38. }
  39. /**
  40. * Implements hook_libraries_info().
  41. */
  42. function leaflet_libraries_info() {
  43. $libraries['leaflet'] = array(
  44. // Only used in administrative UI of Libraries API.
  45. 'name' => 'Leaflet JavaScript Library',
  46. 'vendor url' => 'http://leafletjs.com/',
  47. 'download url' => 'http://cdn.leafletjs.com/leaflet/v1.0.2/leaflet.zip',
  48. 'version arguments' => array(
  49. 'file' => 'leaflet.js',
  50. // Handle patterns like version: "1.0.2+4bbb16c"
  51. 'pattern' => '/version[=: ]*[\'"]([\d+\.]+[\-a-z\.\d]*)[\'"]/',
  52. ),
  53. 'files' => array(
  54. 'js' => array(
  55. // This setting is needed in order to properly render market images.
  56. 'leaflet_root_url' => array(
  57. 'type' => 'inline',
  58. 'data' => 'L_ROOT_URL = "' . base_path() . libraries_get_path('leaflet') . '/";',
  59. 'group' => JS_LIBRARY,
  60. ),
  61. 'leaflet.js' => array(
  62. 'type' => 'file',
  63. 'group' => JS_LIBRARY,
  64. ),
  65. // For AdvAgg module. See [#2294639] This runs after leaflet.js.
  66. 'leaflet_imagepath' => array(
  67. 'type' => 'inline',
  68. // Note: ends with "/"
  69. 'data' => 'L.Icon.Default.imagePath = "' . base_path() . libraries_get_path('leaflet') . '/images/";',
  70. ),
  71. ),
  72. 'css' => array(
  73. 'leaflet.css' => array(
  74. 'type' => 'file',
  75. 'media' => 'all',
  76. ),
  77. 'leaflet.ie.css' => array(
  78. 'browsers' => array(
  79. 'IE' => 'lte IE 8',
  80. '!IE' => FALSE,
  81. ),
  82. ),
  83. ),
  84. ),
  85. 'integration files' => array(
  86. 'leaflet' => array(
  87. 'js' => array('leaflet.drupal.js'),
  88. ),
  89. ),
  90. );
  91. return $libraries;
  92. }
  93. /**
  94. * Attach Leaflet-required client files and return renderable array for a map.
  95. *
  96. * @param array $map
  97. * Map definition as returned my leaflet_map_get_info();
  98. * @param array $features
  99. * Associative array of map features.
  100. * @param string $height
  101. * The height of the map.
  102. *
  103. * @return array
  104. * A renderable array.
  105. */
  106. function leaflet_build_map($map, $features = array(), $height = '400px') {
  107. // [#2777321] With two maps on 1 page, drupal_html_id() sometimes fails to
  108. // return a unique id. Make it so.
  109. $map_id = drupal_html_id('leaflet_map') . '-' . rand();
  110. $build = array(
  111. '#theme' => 'html_tag',
  112. '#tag' => 'div',
  113. '#value' => '',
  114. '#attributes' => array(
  115. 'id' => $map_id,
  116. 'style' => 'height: ' . $height,
  117. ),
  118. );
  119. // Allow map definitions to provide a default icon:
  120. if (isset($map['icon']['iconUrl'])) {
  121. foreach ($features as &$feature) {
  122. if (!isset($feature['icon'])) {
  123. $feature['icon'] = $map['icon'];
  124. }
  125. }
  126. }
  127. $settings = array(
  128. 'mapId' => $map_id,
  129. 'map' => $map,
  130. 'features' => $features,
  131. );
  132. drupal_alter('leaflet_map_prebuild', $settings);
  133. $build['#attached']['js'][] = array(
  134. 'data' => array('leaflet' => array($settings)),
  135. 'type' => 'setting',
  136. );
  137. $build['#attached']['css'][] = array(
  138. 'data' => drupal_get_path('module', 'leaflet') . '/leaflet_extras.css',
  139. );
  140. // Load the leaflet library, which includes integration files.
  141. // libraries_load('leaflet');
  142. // See [2460643]
  143. $build['#attached']['libraries_load'][] = array('leaflet');
  144. // Let other modules properly attach libraries as well [#2567387]
  145. drupal_alter('leaflet_build_map', $build);
  146. return $build;
  147. }
  148. /**
  149. * DEPRECATED. Use leaflet_build_map() instead.
  150. *
  151. * Load all Leaflet required client files and return markup for a map.
  152. *
  153. * @param array $map
  154. * Map definition as returned my leaflet_map_get_info();
  155. * @param array $features
  156. * Associative array of map features.
  157. * @param string $height
  158. * The height of the map.
  159. *
  160. * @return string
  161. * map markup
  162. */
  163. function leaflet_render_map($map, $features = array(), $height = '400px') {
  164. $build = leaflet_build_map($map, $features, $height);
  165. return render($build);
  166. }
  167. /**
  168. * Get all available Leaflet map definitions.
  169. *
  170. * @string $map
  171. * The name of the map defined in hook_leaflet_map_get_info().
  172. */
  173. function leaflet_map_get_info($map = NULL) {
  174. static $drupal_static_fast;
  175. if (!isset($drupal_static_fast)) {
  176. $drupal_static_fast['leaflet_map_info'] = &drupal_static(__FUNCTION__);
  177. }
  178. $map_info = &$drupal_static_fast['leaflet_map_info'];
  179. if (empty($map_info)) {
  180. if ($cache = cache_get("leaflet_map_info")) {
  181. $map_info = $cache->data;
  182. }
  183. else {
  184. $map_info = module_invoke_all('leaflet_map_info');
  185. // Let other modules alter the map info.
  186. drupal_alter('leaflet_map_info', $map_info);
  187. cache_set("leaflet_map_info", $map_info);
  188. }
  189. }
  190. if (empty($map)) {
  191. return $map_info;
  192. }
  193. elseif (isset($map_info[$map])) {
  194. return $map_info[$map];
  195. }
  196. }
  197. /**
  198. * Implements hook_leaflet_map_info().
  199. *
  200. * Return a default map for the module.
  201. */
  202. function leaflet_leaflet_map_info() {
  203. return array(
  204. 'OSM Mapnik' =>
  205. array(
  206. 'label' => 'OSM Mapnik',
  207. 'description' => t('Leaflet default map.'),
  208. // 'center' is used when map contains no features, or every time the map
  209. // is loaded if "force" is TRUE. Otherwise, the map will center itself
  210. // intelligently based on the features in the map.
  211. // RdB: bad things happen when 'center' is specified and Leaflet
  212. // MarkerCluster is used, see https://drupal.org/node/2144935
  213. // Also, a hard-coded center is not a great idea.
  214. //'center' => array(
  215. // 'lat' => 45.526513,
  216. // 'lon' => -122.674833,
  217. // 'force' => FALSE,
  218. //),
  219. 'settings' => array(
  220. // Setting "zoom" forces a zoom level on every map load.
  221. //'zoom' => 17,
  222. // The "zoomDefault" is only used when no features are present.
  223. 'zoomDefault' => 10,
  224. 'minZoom' => 0,
  225. 'maxZoom' => 18,
  226. 'dragging' => TRUE,
  227. 'touchZoom' => TRUE,
  228. 'scrollWheelZoom' => TRUE,
  229. 'doubleClickZoom' => TRUE,
  230. 'zoomControl' => TRUE,
  231. 'attributionControl' => TRUE,
  232. 'trackResize' => TRUE,
  233. 'fadeAnimation' => TRUE,
  234. 'zoomAnimation' => TRUE,
  235. 'closePopupOnClick' => TRUE,
  236. ),
  237. 'layers' => array(
  238. 'earth' => array(
  239. 'urlTemplate' => '//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
  240. 'options' => array(
  241. 'attribution' => 'OSM Mapnik',
  242. ),
  243. ),
  244. ),
  245. ),
  246. );
  247. }