site.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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 ispc=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([ispc['lat'], ispc['lng']]);
  125. isp['marker'].openPopup();
  126. if(matching !== null) {
  127. bnds.extend(matching['layer'].getBounds());
  128. matching['layer'].addTo(map);
  129. }
  130. });
  131. bnds.extend(c);
  132. bnds=bnds.pad(0.3);
  133. map.fitBounds(bnds, {paddingTopLeft: [20, 20]});
  134. });
  135. } else {
  136. var r=$.map(data[1], function(match, k) {
  137. var m=window.isp_list[match['isp_id']]['marker'];
  138. var ispc=m.getLatLng();
  139. if(k == 0) {
  140. map.closePopup();
  141. m.openPopup();
  142. }
  143. return [[ispc.lat, ispc.lng]];
  144. });
  145. r.push([c.lat, c.lng])
  146. bnds=new L.LatLngBounds(r);
  147. bnds=bnds.pad(0.3);
  148. map.fitBounds(bnds, {paddingTopLeft: [20, 20]});
  149. }
  150. });
  151. }
  152. })
  153. function init_map() {
  154. var mapquest=L.tileLayer('http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpg', {
  155. attribution: '&copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, '+
  156. 'Tiles courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a>',
  157. subdomains: '1234'
  158. });
  159. var mapquestsat=L.tileLayer('http://otile{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg', {
  160. attribution: '&copy; Tiles courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a>, '+
  161. 'Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency',
  162. subdomains: '1234',
  163. maxZoom: 11
  164. });
  165. var osm=L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  166. attribution: '&copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors',
  167. subdomains: 'ab'
  168. });
  169. var hyb=L.tileLayer('http://otile{s}.mqcdn.com/tiles/1.0.0/hyb/{z}/{x}/{y}.jpg', {
  170. subdomains: '1234',
  171. maxZoom: 11
  172. });
  173. if(!$('#map').length)
  174. return;
  175. var map = L.map('map', {
  176. center: new L.LatLng(46.603354, 10),
  177. zoom: 4,
  178. minZoom: 2,
  179. layers: [mapquest],
  180. worldCopyJump: true
  181. });
  182. map.attributionControl.setPrefix('');
  183. map.addControl(new L.Control.Pinpoint);
  184. L.control.layers({'MapQuest': mapquest, 'OSM Mapnik': osm, 'MapQuest Aerial': mapquestsat}).addTo(map);
  185. map.on('baselayerchange', function(a) {
  186. if(a.name == 'MapQuest Aerial') {
  187. map.addLayer(hyb);
  188. hyb.bringToFront();
  189. } else {
  190. map.removeLayer(hyb);
  191. }
  192. });
  193. var icon = L.icon({
  194. iconUrl: 'static/img/marker.png',
  195. iconSize: [14, 20], // size of the icon
  196. iconAnchor: [7, 20], // point of the icon which will correspond to marker's location
  197. popupAnchor: [0, -20] // point from which the popup should open relative to the iconAnchor
  198. });
  199. var icon_ffdn = $.extend(true, {}, icon);
  200. icon_ffdn['options']['iconUrl'] = 'static/img/marker_ffdn.png';
  201. window.isp_list={};
  202. $.getJSON('/isp/map_data.json', function(data) {
  203. $.each(data, function(k, isp) {
  204. window.isp_list[isp.id]=isp;
  205. if(!('coordinates' in isp))
  206. return; // cannot display an ISP without coordinates
  207. var marker = L.marker([isp['coordinates']['latitude'], isp['coordinates']['longitude']],
  208. {'icon': isp.ffdn_member ? icon_ffdn : icon});
  209. marker.bindPopup(isp.popup);
  210. marker.getPopup().on('open', function() {
  211. get_covered_areas(isp.id, function(items) {
  212. $.each(items, function(k, ca) {
  213. ca['layer'].addTo(map);
  214. });
  215. });
  216. });
  217. marker.getPopup().on('close', function() {
  218. $.each(window.isp_list[isp.id]['areas'], function(k, ca) {
  219. map.removeLayer(ca['layer']);
  220. });
  221. });
  222. marker.addTo(map);
  223. window.isp_list[isp.id]['marker']=marker;
  224. });
  225. });
  226. }
  227. function change_input_num(li, new_num, reset) {
  228. li.find('input,select').each(function() {
  229. var id = $(this).attr('id').replace(/^(.*)-\d{1,4}/, '$1-'+new_num);
  230. $(this).attr({'name': id, 'id': id});
  231. if(!!reset)
  232. $(this).val('').removeAttr('checked');
  233. });
  234. }
  235. function append_remove_button(li) {
  236. li.children(':first').after(' <button class="btn btn-mini" type="button"><i class="icon-minus"></i></button>');
  237. li.children('button').click(function() {
  238. var ul=li.parent();
  239. li.remove();
  240. var i=0;
  241. ul.children('li').each(function() {
  242. change_input_num($(this), i);
  243. i++;
  244. });
  245. });
  246. };
  247. function clone_fieldlist(el) {
  248. var new_element = el.clone(true);
  249. var elem_id = new_element.find(':input')[0].id;
  250. var elem_num = parseInt(elem_id.replace(/^.*-(\d{1,4})/, '$1')) + 1;
  251. change_input_num(new_element, elem_num, true);
  252. new_element.children('button').remove();
  253. new_element.children('.help-inline.error-list').remove();
  254. new_element.find('.bootstrap-select').remove();
  255. append_remove_button(new_element);
  256. new_element.find('.selectpicker').data('selectpicker', null).selectpicker();
  257. el.after(new_element);
  258. }