leaflet.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. CKEDITOR.dialog.add('leaflet', function(editor) {
  2. // Dialog's function callback for the Leaflet Map Widget.
  3. return {
  4. title: 'Create/Edit Leaflet Map',
  5. minWidth: 320,
  6. minHeight: 125,
  7. contents: [{
  8. // Create a Location tab.
  9. id: 'location_tab',
  10. label: 'Location',
  11. elements: [
  12. {
  13. id: 'map_geocode',
  14. className: 'geocode',
  15. type: 'text',
  16. label: 'Auto-Search of Coordinates.',
  17. style: 'margin-top: -7px;',
  18. setup: function(widget) {
  19. this.setValue("");
  20. },
  21. onShow: function (widget) {
  22. // Get the DOM reference for the Search field.
  23. var input = jQuery(".geocode input")[0];
  24. // Bind the Search field to the Autocomplete widget.
  25. var autocomplete = new google.maps.places.Autocomplete(input);
  26. // Fix for the Google's type-ahead search displaying behind
  27. // the widgets dialog window.
  28. // Basically, we want to override the z-index of the
  29. // Seach Autocomplete list, in which the styling is being set
  30. // in real-time by Google.
  31. // Make a new DOM element.
  32. var stylesheet = jQuery('<style type="text/css" />');
  33. // Set the inner HTML. Include also the vertical alignment
  34. // adjustment for the MiniMap checkbox.
  35. stylesheet.html('.pac-container { z-index: 100000 !important;} input.minimap { margin-top: 18px !important; }');
  36. // Append to the main document's Head section.
  37. jQuery('head').append(stylesheet);
  38. },
  39. },
  40. { // Dummy element serving as label/text container only.
  41. type: 'html',
  42. id: 'map_label',
  43. className: 'label',
  44. style: 'margin-bottom: -10px;',
  45. html: '<p>Manual Input of Coordinates:</p>'
  46. },
  47. {
  48. // Create a new horizontal group.
  49. type: 'hbox',
  50. // Set the relative widths of Latitude, Longitude and Zoom fields.
  51. widths: [ '50%', '50%' ],
  52. children: [
  53. {
  54. id: 'map_latitude',
  55. className: 'latitude',
  56. type: 'text',
  57. label: 'Latitude',
  58. setup: function(widget) {
  59. // Set the Lat values if widget has previous value.
  60. if (widget.element.data('lat') != "") {
  61. this.setValue(widget.element.data('lat'));
  62. }
  63. },
  64. },
  65. {
  66. id: 'map_longitude',
  67. className: 'longitude',
  68. type: 'text',
  69. label: 'Longitude',
  70. setup: function(widget) {
  71. // Set the Lat values if widget has previous value.
  72. if (widget.element.data('lon') != "") {
  73. this.setValue(widget.element.data('lon'));
  74. }
  75. },
  76. },
  77. ]
  78. },
  79. {
  80. id: 'popup_text',
  81. className: 'popup-text',
  82. type: 'text',
  83. label: 'Pop-up Text (Optional)',
  84. style: 'margin-bottom: 8px;',
  85. setup: function(widget) {
  86. // Set the Lat values if widget has previous value.
  87. if (widget.element.data('popup-text') != "") {
  88. this.setValue(widget.element.data('popup-text'));
  89. }
  90. else {
  91. // Set a diffused/default text for better user experience.
  92. jQuery(".popup-text input").attr("placeholder", "Enter the marker's text.")
  93. }
  94. },
  95. },
  96. ]
  97. },
  98. {
  99. // Create an Options tab.
  100. id: 'options_tab',
  101. label: 'Options',
  102. elements: [
  103. {
  104. // Create a new horizontal group.
  105. type: 'hbox',
  106. style: 'margin-top: -7px;',
  107. // Set the relative widths of Latitude, Longitude and Zoom fields.
  108. widths: [ '38%', '38%', '24%' ],
  109. children: [
  110. {
  111. id: 'width',
  112. className: 'map_width',
  113. type: 'text',
  114. label: 'Map Width',
  115. setup: function(widget) {
  116. // Set a diffused/default text for better user experience.
  117. jQuery(".map_width input").attr("placeholder", "400")
  118. // Set the map width value if widget has a previous value.
  119. if (widget.element.data('width') != "") {
  120. this.setValue(widget.element.data('width'));
  121. }
  122. },
  123. },
  124. {
  125. id: 'height',
  126. className: 'map_height',
  127. type: 'text',
  128. label: 'Map Height',
  129. setup: function(widget) {
  130. // Set a diffused/default text for better user experience.
  131. jQuery(".map_height input").attr("placeholder", "400")
  132. // Set the map height value if widget has a previous value.
  133. if (widget.element.data('height') != "") {
  134. this.setValue(widget.element.data('height'));
  135. }
  136. },
  137. },
  138. {
  139. // Create a select list for Zoom Levels.
  140. // 'className' attribute is used for targeting this element in jQuery.
  141. id: 'map_zoom',
  142. className: 'zoom',
  143. type: 'select',
  144. label: 'Zoom Level',
  145. width: '70px',
  146. items: [['1'], ['2'], ['3'], ['4'],['5'], ['6'], ['7'], ['8'], ['9'], ['10'], ['11'], ['12'], ['13'], ['14'], ['15'], ['16'], ['17'], ['18'], ['19'], ['20']],
  147. // This will execute also every time you edit/double-click the widget.
  148. setup: function(widget) {
  149. // Set this Zoom Level's select list when
  150. // the current location has been initialized and set previously.
  151. if (widget.element.data('zoom') != "") {
  152. // Get the previously saved zoom value data attribute.
  153. // It will be compared to the current value in the map view.
  154. var zoomSaved = widget.element.data('zoom');
  155. // Get the zoom level's snapshot because the current user
  156. // might have changed it via mouse events or via the zoom bar.
  157. var zoomIframe = widget.element.getChild(0).$.contentDocument.getElementById("map_container").getAttribute("data-zoom");
  158. if (zoomIframe != zoomSaved) {
  159. // Update the saved zoom value in data attribute.
  160. zoomSaved = zoomIframe;
  161. }
  162. this.setValue(zoomSaved);
  163. }
  164. // Set the Default Zoom Level value.
  165. else {
  166. this.setValue("10");
  167. }
  168. },
  169. }
  170. ]
  171. },
  172. {
  173. // Create a new horizontal group.
  174. type: 'hbox',
  175. // Set the relative widths the tile and overview map fields.
  176. widths: [ '50%', '50%' ],
  177. children: [
  178. {
  179. // Create a select list for map tiles.
  180. // 'className' attribute is used for targeting this element in jQuery.
  181. type: 'select',
  182. id: 'map_tile',
  183. className: 'tile',
  184. label: 'Base Map Tile',
  185. items: [['MapQuestOpen.OSM'], ['MapQuestOpen.Aerial'], ['OpenStreetMap.Mapnik'], ['OpenStreetMap.DE'], ['OpenStreetMap.HOT'], ['Esri.DeLorme'], ['Esri.NatGeoWorldMap'], ['Esri.WorldPhysical'], ['Esri.WorldTopoMap'], ['Thunderforest.OpenCycleMap'], ['Thunderforest.Landscape'], ['Stamen.Watercolor']],
  186. // This will execute also every time you edit/double-click the widget.
  187. setup: function(widget) {
  188. // Set the Tile data attribute.
  189. if (widget.element.data('tile') != "") {
  190. this.setValue(widget.element.data('tile'));
  191. }
  192. else {
  193. // Set the default value.
  194. this.setValue('MapQuestOpen.OSM');
  195. }
  196. },
  197. // This will execute every time you click the Dialog's OK button.
  198. // It will inject a map iframe in the CKEditor page.
  199. commit: function(widget) {
  200. // Remove the iframe if it has one.
  201. widget.element.setHtml('');
  202. // Retrieve the value in the Search field.
  203. var geocode = jQuery('.geocode input').val();
  204. var latitude, longitude;
  205. if (geocode != "") {
  206. // No need to call the encodeURIComponent().
  207. var geocodingRequest = "https://maps.googleapis.com/maps/api/geocode/json?address=" + geocode + "&sensor=false";
  208. // Disable the asynchoronous behavior temporarily so that
  209. // waiting for results will happen before proceeding
  210. // to the next statements.
  211. jQuery.ajaxSetup({
  212. async: false
  213. });
  214. // Geocode the retrieved place name.
  215. jQuery.getJSON(geocodingRequest, function(data) {
  216. if (data["status"] != "ZERO_RESULTS") {
  217. // Get the Latitude and Longitude object in the
  218. // returned JSON object.
  219. latitude = data.results[0].geometry.location.lat;
  220. longitude = data.results[0].geometry.location.lng;
  221. }
  222. // Handle queries with no results or have some
  223. // malformed parameters.
  224. else {
  225. alert("The Place could not be Geocoded properly. Kindly choose another one.")
  226. }
  227. });
  228. }
  229. // Get the Lat/Lon values from the corresponding fields.
  230. var latInput = jQuery('.latitude input').val();
  231. var lonInput = jQuery('.longitude input').val();
  232. // Get the data-lat and data-lon values.
  233. // It is empty for yet to be created widgets.
  234. var latSaved = widget.element.data('lat');
  235. var lonSaved = widget.element.data('lon');
  236. // Used the inputted values if it's not empty or
  237. // not equal to the previously saved values.
  238. // latSaved and lonSaved are initially empty also
  239. // for widgets that are yet to be created.
  240. // Or if the user edited an existing map, and did not edit
  241. // the lat/lon fields, and the Search field is empty.
  242. if ((latInput != "" && lonInput != "") && ((latInput != latSaved && lonInput != lonSaved) || geocode == "")) {
  243. latitude = latInput;
  244. longitude = lonInput;
  245. }
  246. var width = jQuery(".map_width input").val() || "400";
  247. var height = jQuery(".map_height input").val() || "400";
  248. var zoom = jQuery('select.zoom').val();
  249. var popUpText = jQuery(".popup-text input").val();
  250. var tile = jQuery('select.tile').val();
  251. var alignment = jQuery('select.alignment').val();
  252. // Returns 'on' or 'undefined'.
  253. var minimap = jQuery('.minimap input:checked').val();
  254. // Use 'off' if the MiniMap checkbox is unchecked.
  255. if (minimap == undefined) {
  256. minimap = 'off';
  257. }
  258. // Get a unique timestamp:
  259. var milliseconds = new Date().getTime();
  260. // Set/Update the widget's data attributes.
  261. widget.element.setAttribute('id', 'leaflet_div-' + milliseconds);
  262. widget.element.data('lat', latitude);
  263. widget.element.data('lon', longitude);
  264. widget.element.data('width', width);
  265. widget.element.data('height', height);
  266. widget.element.data('zoom', zoom);
  267. widget.element.data('popup-text', popUpText);
  268. widget.element.data('tile', tile);
  269. widget.element.data('minimap', minimap);
  270. widget.element.data('alignment', alignment);
  271. // Remove the previously set alignment class.
  272. // Only one alignment class is set per map.
  273. widget.element.removeClass('align-left');
  274. widget.element.removeClass('align-right');
  275. widget.element.removeClass('align-center');
  276. // Set the alignment for this map.
  277. widget.element.addClass('align-' + alignment);
  278. // Build the full path to the map renderer.
  279. mapParserPathFull = mapParserPath + "?lat=" + latitude + "&lon=" + longitude + "&width=" + width + "&height=" + height + "&zoom=" + zoom + "&text=" + popUpText + "&tile=" + tile + "&minimap=" + minimap;
  280. // Create a new CKEditor DOM's iFrame.
  281. var iframe = new CKEDITOR.dom.element('iframe');
  282. // Setup the iframe characteristics.
  283. iframe.setAttributes({
  284. 'scrolling': 'no',
  285. 'id': 'leaflet_iframe-' + milliseconds,
  286. 'class': 'leaflet_iframe',
  287. 'width': width + 'px',
  288. 'height': height + 'px',
  289. 'frameborder': 0,
  290. 'allowTransparency': true,
  291. 'src': mapParserPathFull,
  292. 'data-cke-saved-src': mapParserPathFull
  293. });
  294. // Insert the iframe to the widget's DIV element.
  295. widget.element.append(iframe);
  296. },
  297. },
  298. {
  299. type: 'checkbox',
  300. id: 'map_mini',
  301. className: 'minimap',
  302. label: 'Include MiniMap',
  303. // This will execute also every time you edit/double-click the widget.
  304. setup: function(widget) {
  305. // Set the MiniMap check button.
  306. if (widget.element.data('minimap') != "" && widget.element.data('minimap') != "on") {
  307. this.setValue('');
  308. }
  309. else {
  310. // Set the default value.
  311. this.setValue('true');
  312. }
  313. },
  314. }
  315. ]
  316. },
  317. {
  318. // Create a select list for Map Alignment.
  319. // 'className' attribute is used for targeting this element in jQuery.
  320. id: 'map_alignment',
  321. className: 'alignment',
  322. type: 'select',
  323. label: 'Alignment',
  324. items: [['Left', 'left'], ['Right', 'right'], ['Center', 'center']],
  325. style: 'margin-bottom: 4px;',
  326. // This will execute also every time you edit/double-click the widget.
  327. setup: function(widget) {
  328. // Set this map alignment's select list when
  329. // the current map has been initialized and set previously.
  330. if (widget.element.data('alignment') != "") {
  331. // Set the alignment.
  332. this.setValue(widget.element.data('alignment'));
  333. }
  334. // Set the Default alignment value.
  335. else {
  336. this.setValue("left");
  337. }
  338. },
  339. }
  340. ]
  341. }]
  342. };
  343. });