site.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. "use strict";
  2. $(function () {
  3. $('.fieldlist').each(function() {
  4. var $this=$(this);
  5. var lis=$this.children('li');
  6. lis.first().children(':first').after(' <button class="btn btn-mini" type="button"><i class="icon-plus"></i></button>');
  7. lis.first().children('button').click(function() {
  8. clone_fieldlist($this.children('li:last'));
  9. });
  10. lis=lis.slice(1);
  11. lis.each(function() {
  12. append_remove_button($(this));
  13. });
  14. });
  15. $('.selectpicker').selectpicker();
  16. $("[rel=tooltip]").tooltip();
  17. init_map();
  18. });
  19. function layer_from_covered_area(ca) {
  20. return L.geoJson(ca['area'], {
  21. style: {
  22. "color": "#ff7800",
  23. "weight": 5,
  24. "opacity": 0.65
  25. }
  26. });
  27. }
  28. function get_covered_areas(isp_id, cb) {
  29. if('areas' in window.isp_list[isp_id]) {
  30. cb(window.isp_list[isp_id]['areas']);
  31. return;
  32. } else {
  33. window.isp_list[isp_id]['areas']=[];
  34. }
  35. return $.getJSON('/isp/'+isp_id+'/covered_areas.json', function done(data) {
  36. $.each(data, function(k, covered_area) {
  37. if(!covered_area['area'])
  38. return;
  39. covered_area['layer']=layer_from_covered_area(covered_area);
  40. window.isp_list[isp_id]['areas'].push(
  41. covered_area
  42. );
  43. });
  44. cb(window.isp_list[isp_id]['areas']);
  45. });
  46. }
  47. L.Control.Pinpoint = L.Control.extend({
  48. options: {
  49. position: 'topleft'
  50. },
  51. onAdd: function(map) {
  52. this._map = map;
  53. this.select_mode = false;
  54. this._container = L.DomUtil.create('div', 'leaflet-control-pinpoint leaflet-bar');
  55. this._button = L.DomUtil.create('a', 'leaflet-control-pinpoint-button', this._container);
  56. this._button.href = '#';
  57. this._button.innerHTML = '<i class="icon-hand-down"></i>';
  58. this._button.style = 'cursor: pointer';
  59. this._button.title = 'Find ISPs near you';
  60. L.DomEvent
  61. .addListener(this._button, 'click', L.DomEvent.stop)
  62. .addListener(this._button, 'click', L.DomEvent.stopPropagation)
  63. .addListener(this._button, 'click', function() {
  64. if(this.select_mode) {
  65. this._map.removeLayer(this._marker);
  66. this._disableSelect();
  67. } else {
  68. this._enableSelect();
  69. }
  70. }, this);
  71. this._icon = L.icon({
  72. iconUrl: 'static/img/marker_selector.png',
  73. iconSize: [18, 28],
  74. iconAnchor: [9, 26],
  75. });
  76. this._marker = L.marker([0, 0], {icon: this._icon, draggable: true});
  77. this._marker.on('dragend', this.findNearISP, this);
  78. return this._container;
  79. },
  80. _enableSelect: function() {
  81. this._marker.addTo(this._map);
  82. this._map.on('mousemove', this._mouseMove, this);
  83. this._map.on('click', this._setMarker, this);
  84. this._map._container.style.cursor = 'crosshair';
  85. this._marker._icon.style.cursor = 'crosshair';
  86. this.select_mode = true;
  87. },
  88. _disableSelect: function() {
  89. this._map.off('mousemove', this._mouseMove, this);
  90. this._map.off('click', this._setMarker, this);
  91. this._map._container.style.cursor = 'default';
  92. if(!!this._marker._icon)
  93. this._marker._icon.style.cursor = 'default';
  94. this.select_mode = false;
  95. },
  96. _mouseMove: function(e) {
  97. this._marker.setLatLng(e.latlng);
  98. },
  99. _setMarker: function(e) {
  100. this._disableSelect();
  101. this.findNearISP();
  102. },
  103. findNearISP: function() {
  104. var c=this._marker.getLatLng();
  105. var map=this._map;
  106. $.getJSON('/isp/find_near.json?lon='+c.lng+'&lat='+c.lat, function(data) {
  107. var bnds;
  108. if(data[0].length) {
  109. var bnds=new L.LatLngBounds;
  110. var defered=[];
  111. $.each(data[0], function(k, match) {
  112. var isp=window.isp_list[match['isp_id']];
  113. defered.push(get_covered_areas(match['isp_id'], $.noop));
  114. });
  115. $.when.apply(this, defered).done(function() {
  116. $.each(data[0], function(k, match) {
  117. var isp=window.isp_list[match['isp_id']];
  118. var c=isp['marker'].getLatLng();
  119. var matching=null;
  120. $.each(isp['areas'], function(j, a) {
  121. if(a['id'] == match['area']['id'])
  122. matching = a;
  123. });
  124. bnds.extend([c['lat'], c['lng']]);
  125. isp['marker'].openPopup();
  126. if(matching !== null) {
  127. bnds.extend(matching['layer'].getBounds());
  128. matching['layer'].addTo(map);
  129. }
  130. });
  131. bnds=bnds.pad(0.3);
  132. map.fitBounds(bnds, {paddingTopLeft: [20, 20]});
  133. });
  134. } else {
  135. var r=$.map(data[1], function(match, k) {
  136. var m=window.isp_list[match['isp_id']]['marker'];
  137. var c=m.getLatLng();
  138. if(k == 0) {
  139. map.closePopup();
  140. m.openPopup();
  141. }
  142. return [[c['lat'], c['lng']]];
  143. });
  144. bnds=new L.LatLngBounds(r);
  145. bnds=bnds.pad(0.3);
  146. map.fitBounds(bnds, {paddingTopLeft: [20, 20]});
  147. }
  148. });
  149. }
  150. })
  151. function init_map() {
  152. var mapquest=L.tileLayer('http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpg', {
  153. attribution: '&copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, '+
  154. 'Tiles courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a>',
  155. subdomains: '1234'
  156. });
  157. var mapquestsat=L.tileLayer('http://otile{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg', {
  158. attribution: '&copy; Tiles courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a>, '+
  159. 'Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency',
  160. subdomains: '1234',
  161. maxZoom: 11
  162. });
  163. var osm=L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  164. attribution: '&copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors',
  165. subdomains: 'ab'
  166. });
  167. var hyb=L.tileLayer('http://otile{s}.mqcdn.com/tiles/1.0.0/hyb/{z}/{x}/{y}.jpg', {
  168. subdomains: '1234',
  169. maxZoom: 11
  170. });
  171. if(!$('#map').length)
  172. return;
  173. var map = L.map('map', {
  174. center: new L.LatLng(46.603354, 10),
  175. zoom: 4,
  176. minZoom: 2,
  177. layers: [mapquest],
  178. worldCopyJump: true
  179. });
  180. map.attributionControl.setPrefix('');
  181. map.addControl(new L.Control.Pinpoint);
  182. L.control.layers({'MapQuest': mapquest, 'OSM Mapnik': osm, 'MapQuest Aerial': mapquestsat}).addTo(map);
  183. map.on('baselayerchange', function(a) {
  184. if(a.name == 'MapQuest Aerial') {
  185. map.addLayer(hyb);
  186. hyb.bringToFront();
  187. } else {
  188. map.removeLayer(hyb);
  189. }
  190. });
  191. var icon = L.icon({
  192. iconUrl: 'static/img/marker.png',
  193. iconSize: [14, 20], // size of the icon
  194. iconAnchor: [7, 20], // point of the icon which will correspond to marker's location
  195. popupAnchor: [0, -20] // point from which the popup should open relative to the iconAnchor
  196. });
  197. var icon_ffdn = $.extend(true, {}, icon);
  198. icon_ffdn['options']['iconUrl'] = 'static/img/marker_ffdn.png';
  199. window.isp_list={};
  200. $.getJSON('/isp/map_data.json', function(data) {
  201. $.each(data, function(k, isp) {
  202. window.isp_list[isp.id]=isp;
  203. if(!('coordinates' in isp))
  204. return; // cannot display an ISP without coordinates
  205. var marker = L.marker([isp['coordinates']['latitude'], isp['coordinates']['longitude']],
  206. {'icon': isp.ffdn_member ? icon_ffdn : icon});
  207. marker.bindPopup(isp.popup);
  208. marker.getPopup().on('open', function() {
  209. get_covered_areas(isp.id, function(items) {
  210. $.each(items, function(k, ca) {
  211. ca['layer'].addTo(map);
  212. });
  213. });
  214. });
  215. marker.getPopup().on('close', function() {
  216. $.each(window.isp_list[isp.id]['areas'], function(k, ca) {
  217. map.removeLayer(ca['layer']);
  218. });
  219. });
  220. marker.addTo(map);
  221. window.isp_list[isp.id]['marker']=marker;
  222. });
  223. });
  224. }
  225. function change_input_num(li, new_num, reset) {
  226. li.find('input,select').each(function() {
  227. var id = $(this).attr('id').replace(/^(.*)-\d{1,4}/, '$1-'+new_num);
  228. $(this).attr({'name': id, 'id': id});
  229. if(!!reset)
  230. $(this).val('').removeAttr('checked');
  231. });
  232. }
  233. function append_remove_button(li) {
  234. li.children(':first').after(' <button class="btn btn-mini" type="button"><i class="icon-minus"></i></button>');
  235. li.children('button').click(function() {
  236. var ul=li.parent();
  237. li.remove();
  238. var i=0;
  239. ul.children('li').each(function() {
  240. change_input_num($(this), i);
  241. i++;
  242. });
  243. });
  244. };
  245. function clone_fieldlist(el) {
  246. var new_element = el.clone(true);
  247. var elem_id = new_element.find(':input')[0].id;
  248. var elem_num = parseInt(elem_id.replace(/^.*-(\d{1,4})/, '$1')) + 1;
  249. change_input_num(new_element, elem_num, true);
  250. new_element.children('button').remove();
  251. new_element.children('.help-inline.error-list').remove();
  252. new_element.find('.bootstrap-select').remove();
  253. append_remove_button(new_element);
  254. new_element.find('.selectpicker').data('selectpicker', null).selectpicker();
  255. el.after(new_element);
  256. }