├── .gitignore
├── mapboxstyle
├── .thumb.png
├── ffcmap.tm2z
├── project.yml
├── style.mss
└── project.xml
├── images
├── contact_icons.png
├── location-icon.png
├── touch-icon-114.png
├── touch-icon-52.png
└── touch-icon-72.png
├── external
├── leaflet
│ ├── images
│ │ ├── layers.png
│ │ ├── layers-2x.png
│ │ ├── marker-icon.png
│ │ ├── marker-icon-2x.png
│ │ └── marker-shadow.png
│ ├── MarkerCluster.css
│ ├── MarkerCluster.Default.ie.css
│ ├── MarkerCluster.Default.css
│ ├── leaflet-button-control.css
│ ├── leaflet.ie.css
│ ├── leaflet-button-control.js
│ ├── leaflet.css
│ └── leaflet.markercluster.js
├── underscore
│ ├── underscore-min.js
│ └── underscore-min.map
└── jquery
│ └── jquery.min.js
├── index.html
├── config.json.sample
├── README.md
├── server.js
├── ffGeoJsonp.php
├── map.html
├── community_map.css
└── community_map.js
/.gitignore:
--------------------------------------------------------------------------------
1 | config.json
--------------------------------------------------------------------------------
/mapboxstyle/.thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fossasia/cmap.api.fossasia.net/master/mapboxstyle/.thumb.png
--------------------------------------------------------------------------------
/images/contact_icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fossasia/cmap.api.fossasia.net/master/images/contact_icons.png
--------------------------------------------------------------------------------
/images/location-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fossasia/cmap.api.fossasia.net/master/images/location-icon.png
--------------------------------------------------------------------------------
/images/touch-icon-114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fossasia/cmap.api.fossasia.net/master/images/touch-icon-114.png
--------------------------------------------------------------------------------
/images/touch-icon-52.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fossasia/cmap.api.fossasia.net/master/images/touch-icon-52.png
--------------------------------------------------------------------------------
/images/touch-icon-72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fossasia/cmap.api.fossasia.net/master/images/touch-icon-72.png
--------------------------------------------------------------------------------
/mapboxstyle/ffcmap.tm2z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fossasia/cmap.api.fossasia.net/master/mapboxstyle/ffcmap.tm2z
--------------------------------------------------------------------------------
/external/leaflet/images/layers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fossasia/cmap.api.fossasia.net/master/external/leaflet/images/layers.png
--------------------------------------------------------------------------------
/external/leaflet/images/layers-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fossasia/cmap.api.fossasia.net/master/external/leaflet/images/layers-2x.png
--------------------------------------------------------------------------------
/external/leaflet/images/marker-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fossasia/cmap.api.fossasia.net/master/external/leaflet/images/marker-icon.png
--------------------------------------------------------------------------------
/external/leaflet/images/marker-icon-2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fossasia/cmap.api.fossasia.net/master/external/leaflet/images/marker-icon-2x.png
--------------------------------------------------------------------------------
/external/leaflet/images/marker-shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fossasia/cmap.api.fossasia.net/master/external/leaflet/images/marker-shadow.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Freifunk Community Map
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/config.json.sample:
--------------------------------------------------------------------------------
1 | {
2 | "feedUrl": "//feed-fossasia-api.herokuapp.com/feed.php",
3 | "embedTimelineUrl": "//timeline-fossasia-api.herokuapp.com/embed.php",
4 | "geoJSONUrl": "http://api.fossasia.net/map/ffGeoJsonp.php",
5 | "postContenLimit": 30
6 | }
--------------------------------------------------------------------------------
/external/leaflet/MarkerCluster.css:
--------------------------------------------------------------------------------
1 | .leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow {
2 | -webkit-transition: -webkit-transform 0.2s ease-out, opacity 0.2s ease-in;
3 | -moz-transition: -moz-transform 0.2s ease-out, opacity 0.2s ease-in;
4 | -o-transition: -o-transform 0.2s ease-out, opacity 0.2s ease-in;
5 | transition: transform 0.2s ease-out, opacity 0.2s ease-in;
6 | }
--------------------------------------------------------------------------------
/external/leaflet/MarkerCluster.Default.ie.css:
--------------------------------------------------------------------------------
1 | /* IE 6-8 fallback colors */
2 | .marker-cluster-small {
3 | background-color: rgb(181, 226, 140);
4 | }
5 | .marker-cluster-small div {
6 | background-color: rgb(110, 204, 57);
7 | }
8 |
9 | .marker-cluster-medium {
10 | background-color: rgb(241, 211, 87);
11 | }
12 | .marker-cluster-medium div {
13 | background-color: rgb(240, 194, 12);
14 | }
15 |
16 | .marker-cluster-large {
17 | background-color: rgb(253, 156, 115);
18 | }
19 | .marker-cluster-large div {
20 | background-color: rgb(241, 128, 23);
21 | }
22 |
--------------------------------------------------------------------------------
/mapboxstyle/project.yml:
--------------------------------------------------------------------------------
1 | _prefs:
2 | baselayer: ''
3 | saveCenter: true
4 | _properties: {}
5 | attribution: Map data © OpenStreetMap contributors
6 | bounds:
7 | - -180
8 | - -85.0511
9 | - 180
10 | - 85.0511
11 | center:
12 | - 9.140625
13 | - 48.821332549646634
14 | - 6
15 | description: Map to display Freifunk and other free networks
16 | format: "png8:m=h:c=32"
17 | interactivity_layer: admin
18 | layers: null
19 | maxzoom: 22
20 | minzoom: 0
21 | mtime: 1398410448920
22 | name: Freifunk Community Map
23 | scale: 1
24 | source: "mapbox:///mapbox.mapbox-streets-v4"
25 | styles:
26 | - style.mss
27 | template: ''
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Community Map
2 | =============
3 |
4 | [](https://gitter.im/fossasia/api.fossasia.net?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
5 |
6 | ## Setup
7 | -----
8 |
9 | ```
10 | git clone https://github.com/fossasia/cmap.api.fossasia.net.git
11 | cd cmap.api.fossasia.net
12 | node server.js
13 | ```
14 |
15 | ## Dependencies
16 | (external folder)
17 |
18 | * jQuery v2.0.3
19 | * underscore.js v1.5.2
20 | * leaflet.js
21 |
22 | ## Contribute
23 |
24 | The community map is a fun & visual way to know more about open-source communities across Asia. If you think there are cool features that can be integrated in the map, you can let us know by opening an issue, or sending pull requests. Bug reports are equally welcomed.
25 |
26 | [FOSSASIA API repo](https://github.com/fossasia/api.fossasia.net)
27 |
--------------------------------------------------------------------------------
/external/leaflet/MarkerCluster.Default.css:
--------------------------------------------------------------------------------
1 | .marker-cluster-small {
2 | background-color: rgba(181, 226, 140, 0.6);
3 | }
4 | .marker-cluster-small div {
5 | background-color: rgba(110, 204, 57, 0.6);
6 | }
7 |
8 | .marker-cluster-medium {
9 | background-color: rgba(241, 211, 87, 0.6);
10 | }
11 | .marker-cluster-medium div {
12 | background-color: rgba(240, 194, 12, 0.6);
13 | }
14 |
15 | .marker-cluster-large {
16 | background-color: rgba(253, 156, 115, 0.6);
17 | }
18 | .marker-cluster-large div {
19 | background-color: rgba(241, 128, 23, 0.6);
20 | }
21 |
22 | .marker-cluster {
23 | background-clip: padding-box;
24 | border-radius: 20px;
25 | }
26 | .marker-cluster div {
27 | width: 30px;
28 | height: 30px;
29 | margin-left: 5px;
30 | margin-top: 5px;
31 |
32 | text-align: center;
33 | border-radius: 15px;
34 | font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif;
35 | }
36 | .marker-cluster span {
37 | line-height: 30px;
38 | }
--------------------------------------------------------------------------------
/external/leaflet/leaflet-button-control.css:
--------------------------------------------------------------------------------
1 | .leaflet-control-button {
2 | z-index: 1000;
3 | width: 26px;
4 | height: 26px;
5 | box-shadow: 0 1px 7px rgba(0,0,0,0.65);
6 | -webkit-border-radius: 4px;
7 | border-radius: 4px;
8 | }
9 |
10 | .leaflet-buttons-control-button {
11 | background: white;
12 | -webkit-border-radius: 4px;
13 | border-radius: 4px;
14 | }
15 |
16 | .leaflet-touch .leaflet-control-button {
17 | border: 4px solid rgba(0, 0, 0, 0.3);
18 | width: 30px;
19 | height: 30px;
20 | font-size: 28px;
21 | line-height: 30px;
22 | box-shadow: none;
23 | -webkit-border-radius: 10px;
24 | border-radius: 10px;
25 | }
26 |
27 | .leaflet-touch .leaflet-buttons-control-button {
28 | width: 100%;
29 | height: 100%;
30 | background: white;
31 | -webkit-border-radius: 7px;
32 | border-radius: 7px;
33 | }
34 |
35 | .leaflet-touch .leaflet-buttons-control-img {
36 | margin: 2px;
37 | }
38 |
39 | .leaflet-buttons-control-button.disabled {
40 | background: lightgray;
41 | opacity: 0.8;
42 | cursor: default;
43 | }
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | var http = require("http");
2 | var url = require("url");
3 | var fs = require("fs");
4 | var port = process.argv[2] || 8080;
5 |
6 | http.createServer(function(request, response) {
7 |
8 | var uri = url.parse(request.url).pathname;
9 | var filename = process.cwd() + uri;
10 |
11 | fs.exists(filename, function(exists) {
12 | if(!exists) {
13 | response.writeHead(404, {"Content-Type": "text/plain"});
14 | response.write("404 Not Found\n");
15 | response.end();
16 | return;
17 | }
18 |
19 | if (fs.statSync(filename).isDirectory()) filename += '/index.html';
20 |
21 | fs.readFile(filename, "binary", function(err, file) {
22 | if(err) {
23 | response.writeHead(500, {"Content-Type": "text/plain"});
24 | response.write(err + "\n");
25 | response.end();
26 | return;
27 | }
28 |
29 | response.writeHead(200);
30 | response.write(file, "binary");
31 | response.end();
32 | });
33 | });
34 | }).listen(parseInt(port, 10));
35 |
36 | console.log("Static file server running at => http://localhost:" + port + "/\nCTRL + C to shutdown");
--------------------------------------------------------------------------------
/external/leaflet/leaflet.ie.css:
--------------------------------------------------------------------------------
1 | .leaflet-vml-shape {
2 | width: 1px;
3 | height: 1px;
4 | }
5 | .lvml {
6 | behavior: url(#default#VML);
7 | display: inline-block;
8 | position: absolute;
9 | }
10 |
11 | .leaflet-control {
12 | display: inline;
13 | }
14 |
15 | .leaflet-popup-tip {
16 | width: 21px;
17 | _width: 27px;
18 | margin: 0 auto;
19 | _margin-top: -3px;
20 |
21 | filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
22 | -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
23 | }
24 | .leaflet-popup-tip-container {
25 | margin-top: -1px;
26 | }
27 | .leaflet-popup-content-wrapper, .leaflet-popup-tip {
28 | border: 1px solid #999;
29 | }
30 | .leaflet-popup-content-wrapper {
31 | zoom: 1;
32 | }
33 |
34 | .leaflet-control-zoom,
35 | .leaflet-control-layers {
36 | border: 3px solid #999;
37 | }
38 | .leaflet-control-layers-toggle {
39 | }
40 | .leaflet-control-attribution,
41 | .leaflet-control-layers,
42 | .leaflet-control-scale-line {
43 | background: white;
44 | }
45 | .leaflet-zoom-box {
46 | filter: alpha(opacity=50);
47 | }
48 | .leaflet-control-attribution {
49 | border-top: 1px solid #bbb;
50 | border-left: 1px solid #bbb;
51 | }
--------------------------------------------------------------------------------
/ffGeoJsonp.php:
--------------------------------------------------------------------------------
1 | =6] { line-width: 2; }
26 | [zoom>=8] { line-width: 4; }
27 | [disputed=1] { line-dasharray: 4,4; }
28 | }
29 | // States / Provices / Subregions
30 | [admin_level>=3] {
31 | line-width: 0.2;
32 | line-dasharray: 10,3,3,3;
33 | [zoom>=8] { line-width: 0.6; }
34 | [zoom>=12] { line-width: 3; }
35 | }
36 | }
37 |
38 | // Places //
39 |
40 | #country_label_line {
41 | line-color: #324;
42 | line-opacity: 0.05;
43 | }
44 |
45 | #place_label{
46 | [type='city'][zoom<=15] {
47 | text-name: @name;
48 | text-face-name: 'Open Sans Semibold';
49 | text-fill: #a5a1a1;
50 | text-halo-fill: #ffffff;
51 | text-halo-radius: 1.5;
52 | text-size: 16;
53 | text-wrap-width: 100;
54 | text-wrap-before: true;
55 | [zoom>=10] { text-size: 18; }
56 | [zoom>=12] { text-size: 24; }
57 | }
58 | [type='town'][zoom<=17] {
59 | text-name: @name;
60 | text-face-name: 'Open Sans Regular';
61 | text-fill: #a5a1a1;
62 | text-halo-fill: #ffffff;
63 | text-halo-radius: 1.5;
64 | text-size: 14;
65 | text-wrap-width: 100;
66 | text-wrap-before: true;
67 | [zoom>=10] { text-size: 16; }
68 | [zoom>=12] { text-size: 20; }
69 | }
70 | [type='village'] {
71 | text-name: @name;
72 | text-face-name: 'Open Sans Regular';
73 | text-fill: #a5a1a1;
74 | text-halo-fill: #ffffff;
75 | text-halo-radius: 1.5;
76 | text-size: 12;
77 | text-wrap-width: 100;
78 | text-wrap-before: true;
79 | [zoom>=12] { text-size: 14; }
80 | [zoom>=14] { text-size: 18; }
81 | }
82 | [type='hamlet'],
83 | [type='suburb'],
84 | [type='neighbourhood'] {
85 | text-name: @name;
86 | text-face-name: 'Open Sans Regular';
87 | text-fill: #a5a1a1;
88 | text-halo-fill: #ffffff;
89 | text-halo-radius: 1.5;
90 | text-size: 12;
91 | text-wrap-width: 100;
92 | text-wrap-before: true;
93 | [zoom>=14] { text-size: 14; }
94 | [zoom>=16] { text-size: 16; }
95 | }
96 | }
97 | // Water Features //
98 |
99 | #water {
100 | polygon-fill: @water;
101 | polygon-gamma: 0.6;
102 | }
103 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/external/leaflet/leaflet-button-control.js:
--------------------------------------------------------------------------------
1 | /**
2 | * https://gist.github.com/ejh/2935327
3 | */
4 |
5 | L.Control.Button = L.Control.extend({
6 | options: {
7 | position: 'topleft'
8 | },
9 | initialize: function (options) {
10 | this._button = {};
11 | this.setButton(options);
12 | },
13 |
14 | onAdd: function (map) {
15 | this._map = map;
16 | var container = L.DomUtil.create('div', 'leaflet-control-button');
17 |
18 | this._container = container;
19 |
20 | this._update();
21 | return this._container;
22 | },
23 |
24 | onRemove: function (map) {
25 | },
26 |
27 | setButton: function (options) {
28 | var button = {
29 | 'text': options.text || "", //string
30 | 'iconUrl': options.iconUrl, //string
31 | 'onClick': options.onClick, //callback function
32 | 'hideText': !!options.hideText, //forced bool
33 | 'maxWidth': options.maxWidth || 70, //number
34 | 'doToggle': options.toggle, //bool
35 | 'toggleStatus': false //bool
36 | };
37 |
38 | this._button = button;
39 | this._update();
40 | },
41 |
42 | getText: function () {
43 | return this._button.text;
44 | },
45 |
46 | getIconUrl: function () {
47 | return this._button.iconUrl;
48 | },
49 |
50 | destroy: function () {
51 | this._button = {};
52 | this._update();
53 | },
54 |
55 | toggle: function (e) {
56 | if(typeof e === 'boolean'){
57 | this._button.toggleStatus = e;
58 | }
59 | else{
60 | this._button.toggleStatus = !this._button.toggleStatus;
61 | }
62 | this._update();
63 | },
64 |
65 | _update: function () {
66 | if (!this._map) {
67 | return;
68 | }
69 |
70 | this._container.innerHTML = '';
71 | this._makeButton(this._button);
72 |
73 | },
74 |
75 | _makeButton: function (button) {
76 | var newButton = L.DomUtil.create('div', 'leaflet-buttons-control-button', this._container);
77 | if(button.toggleStatus)
78 | L.DomUtil.addClass(newButton,'leaflet-buttons-control-toggleon');
79 |
80 | var image = L.DomUtil.create('img', 'leaflet-buttons-control-img', newButton);
81 | image.setAttribute('src',button.iconUrl);
82 |
83 | if(button.text !== ''){
84 |
85 | L.DomUtil.create('br','',newButton); //there must be a better way
86 |
87 | var span = L.DomUtil.create('span', 'leaflet-buttons-control-text', newButton);
88 | var text = document.createTextNode(button.text); //is there an L.DomUtil for this?
89 | span.appendChild(text);
90 | if(button.hideText)
91 | L.DomUtil.addClass(span,'leaflet-buttons-control-text-hide');
92 | }
93 |
94 | L.DomEvent
95 | .addListener(newButton, 'click', L.DomEvent.stop)
96 | .addListener(newButton, 'click', button.onClick)
97 | .addListener(newButton, 'click', this._clicked, this);
98 | L.DomEvent.disableClickPropagation(newButton);
99 | return newButton;
100 |
101 | },
102 |
103 | _clicked: function() { //'this' refers to button
104 | if(this._button.doToggle){
105 | if(this._button.toggleStatus) { //currently true, remove class
106 | L.DomUtil.removeClass(this._container.childNodes[0],'leaflet-buttons-control-toggleon');
107 | }
108 | else{
109 | L.DomUtil.addClass(this._container.childNodes[0],'leaflet-buttons-control-toggleon');
110 | }
111 | this.toggle();
112 | }
113 | return;
114 | }
115 |
116 | });
--------------------------------------------------------------------------------
/map.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Fossasia Community Map
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/community_map.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 0;
3 | margin: 0;
4 | }
5 |
6 | html, body, #map {
7 | height: 100%;
8 | }
9 |
10 | /* Leaflet controls */
11 | .leaflet-bar a, .leaflet-bar a:hover {
12 | color: #DF3A6C;
13 | }
14 |
15 | .leaflet-buttons-control-button {
16 | height: 100%;
17 | width: 100%;
18 | }
19 | /* /Leaflet controls */
20 |
21 |
22 | /* MarkerCluster */
23 | .marker-cluster-small,
24 | .marker-cluster-medium {
25 | background-color: rgba(212, 0, 0, 0.3);
26 | }
27 | .marker-cluster-small div,
28 | .marker-cluster-medium div {
29 | background-color: rgba(212, 0, 0, 0.7);
30 | }
31 | /* /MarkerCluster */
32 |
33 | /* community-popup */
34 | .community-popup h2,
35 | .community-popup h3 {
36 | font-size: 12px;
37 | margin: 0px;
38 | color: #009ee0
39 | }
40 | .community-popup .leaflet-container a {
41 | color: #009ee0;
42 | }
43 | .community-popup .nodes {
44 | margin: 10px 0px;
45 | }
46 | .community-popup .state,
47 | .community-popup .state.unknown {
48 | display: inline-block;
49 | text-size: 0.5em;
50 | color: lightgray;
51 | }
52 | .community-popup .state.up-to-date {
53 | color: green;
54 | }
55 | .community-popup .state.valid {
56 | color: orange;
57 | }
58 | .community-popup .state.outdated {
59 | color: red;
60 | }
61 |
62 | .community-popup ul.contacts {
63 | list-style: none;
64 | margin: 10px 0px 0px 0px;
65 | padding: 0px;
66 | }
67 | .community-popup ul.contacts li.contact {
68 | float: left;
69 | margin: 5px 5px 0px 0px;
70 | }
71 | .community-popup ul.contacts li.contact a {
72 | display: block;
73 | width: 30px;
74 | height: 30px;
75 | border-radius: 4px;
76 | background: url(images/contact_icons.png);
77 | background-repeat:no-repeat;
78 | background-position:right top;
79 | background-size: 30px 390px;
80 | }
81 | .community-popup ul.contacts li.contact a.button.www {
82 | background-position: 0px 0px;
83 | }
84 | .community-popup ul.contacts li.contact a.button.email {
85 | background-position: 0px -30px;
86 | }
87 | .community-popup ul.contacts li.contact a.button.phone {
88 | background-position: 0px -60px;
89 | }
90 | .community-popup ul.contacts li.contact a.button.twitter {
91 | background-position: 0px -90px;
92 | }
93 | .community-popup ul.contacts li.contact a.button.irc {
94 | background-position: 0px -120px;
95 | }
96 | .community-popup ul.contacts li.contact a.button.jabber {
97 | background-position: 0px -150px;
98 | }
99 | .community-popup ul.contacts li.contact a.button.rss {
100 | background-position: 0px -180px;
101 | }
102 | .community-popup ul.contacts li.contact a.button.facebook {
103 | background-position: 0px -210px;
104 | }
105 | .community-popup ul.contacts li.contact a.button.flickr {
106 | background-position: 0px -240x;
107 | }
108 | .community-popup ul.contacts li.contact a.button.googleplus {
109 | background-position: 0px -270px;
110 | }
111 | .community-popup ul.contacts li.contact a.button.identica {
112 | background-position: 0px -300px;
113 | }
114 | .community-popup ul.contacts li.contact a.button.vimeo {
115 | background-position: 0px -330px;
116 | }
117 | .community-popup ul.contacts li.contact a.button.youtube {
118 | background-position: 0px -360px;
119 | }
120 |
121 | .community-popup img.logo {
122 | height: 64px;
123 |
124 | }
125 |
126 | .leaflet-popup-content {
127 | width: 272px !important;
128 | }
129 | /* /community-popup */
130 |
131 |
132 | .info {
133 | padding: 6px 8px;
134 | background: white;
135 | background: rgba(255,255,255,0.8);
136 | box-shadow: 0 0 15px rgba(0,0,0,0.2);
137 | border-radius: 5px;
138 | }
139 | .info hr {
140 | margin: 5px 0 5px;
141 | color: #777;
142 | }
143 | @media only screen and (max-width: 768px) {
144 | .info {
145 | bottom: 30px;
146 | }
147 | }
148 |
149 | iframe.embed-timeline {
150 | margin: 0;
151 | padding: 0;
152 | border: none;
153 | width: 272px;
154 | height: 112px;
155 | display: block;
156 | }
157 | .rssfeed {
158 | margin: 8px;
159 | }
160 | .rssfeed .title {
161 | color: #47a3da;
162 | font-size: 16px;
163 | }
164 | .rssfeed .description {
165 | margin-left: 16px;
166 | }
167 |
168 | .rssfeed .bloglink {
169 | display: block;
170 | }
171 | .rssfeed ul {
172 | padding-left: 15px;
173 | }
174 | .hidden {
175 | display: none;
176 | }
--------------------------------------------------------------------------------
/community_map.js:
--------------------------------------------------------------------------------
1 | var FFCommunityMapWidget = function(settings, map_options, link) {
2 |
3 | var renderPopup = function (props, configs) {
4 | //console.log(props);
5 | //clean up values before rendering
6 | if (props.url && !props.url.match(/^http([s]?):\/\/.*/)) {
7 | props.url = "http://" + props.url;
8 | }
9 | if (props.email && !props.email.match(/^mailto:.*/)) {
10 | props.email = "mailto:" + props.email;
11 | }
12 | if (props.twitter && !props.twitter.match(/^http([s]?):\/\/.*/)) {
13 | props.twitter = "https://twitter.com/" + props.twitter;
14 | }
15 | if (props.irc && !props.irc.match(/^irc:.*/)) {
16 | props.irc = "irc:" + props.irc;
17 | }
18 | if (props.jabber && !props.jabber.match(/^jabber:.*/)) {
19 | props.jabber = "xmpp:" + props.jabber;
20 | }
21 | if (props.identica && !props.identica.match(/^identica:.*/)) {
22 | props.identica = "identica:" + props.identica;
23 | }
24 |
25 | function getAgeFromProperties(props) {
26 | var ageindays = -1;
27 | if (props.mtime) {
28 | ageindays = Math.round((Math.round(+new Date()/1000) - props.mtime) / (3600*24));
29 | }
30 | return ageindays;
31 | };
32 |
33 | function getStateFromProperties(props) {
34 | var state = 'unknown';
35 | if (props.mtime) {
36 | var ageindays = getAgeFromProperties(props);
37 | if (ageindays < 0 || isNaN(ageindays)) {
38 | state = 'unknown';
39 | } else if (ageindays < 2) {
40 | state = 'up-to-date';
41 | } else if (ageindays < 7) {
42 | state = 'valid';
43 | } else {
44 | state = 'outdated';
45 | }
46 | }
47 | return state;
48 | };
49 | props.age = getAgeFromProperties(props);
50 | props.state = getStateFromProperties(props);
51 |
52 | props.contacts = [];
53 | if (props.url) {
54 | props.contacts.push({
55 | type: 'www',
56 | url : props.url
57 | });
58 | }
59 |
60 | if (props.email) {
61 | props.contacts.push({
62 | type: 'email',
63 | url : props.email
64 | });
65 | }
66 |
67 | if (props.facebook) {
68 | props.contacts.push({
69 | type: 'facebook',
70 | url : props.facebook
71 | });
72 | }
73 |
74 | if (props.twitter) {
75 | props.contacts.push({
76 | type: 'twitter',
77 | url : props.twitter
78 | });
79 | }
80 |
81 | if (props.irc) {
82 | props.contacts.push({
83 | type: 'irc',
84 | url : props.irc
85 | });
86 | }
87 |
88 | if (props.jabber) {
89 | props.contacts.push({
90 | type: 'jabber',
91 | url : props.jabber
92 | });
93 | }
94 |
95 | if (props.identica) {
96 | props.contacts.push({
97 | type: 'identica',
98 | url : props.identicy
99 | });
100 | }
101 |
102 | if (props.googleplus) {
103 | props.contacts.push({
104 | type: 'googleplus',
105 | url : props.googleplus
106 | });
107 | }
108 |
109 | props.embedTimelineUrl = configs.embedTimelineUrl;
110 | //render html and return
111 | return widget.communityTemplate(props);
112 | };
113 |
114 | var options = L.extend({
115 | divId: 'map',
116 | geoJSONUrl: settings.geoJson || "/map/ffGeoJson.json",
117 | getPopupHTML: renderPopup,
118 | zoom: 3,
119 | maxZoom: 8,
120 | center: [46.2830,86.6700]
121 | }, options);
122 |
123 | var widget = {};
124 | widget.map = L.map(options.divId, map_options);
125 | widget.map.setView(
126 | options.center,
127 | options.zoom
128 | );
129 |
130 | var mapboxLayer = L.tileLayer('https://{s}.tiles.mapbox.com/v3/andibraeu.kd6ccoce/{z}/{x}/{y}.png', {
131 | attribution: '© Mapbox © OpenStreetMap Improve this map'
132 | });
133 |
134 | var osmlayer = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
135 | attribution: '© OpenStreetMap contributors'
136 | });
137 |
138 | //set default layer
139 | widget.map.addLayer(osmlayer);
140 |
141 | var clusters = L.markerClusterGroup({
142 | spiderfyOnMaxZoom: true,
143 | showCoverageOnHover: false,
144 | maxClusterRadius: 40
145 | }).addTo(widget.map);
146 |
147 | //disable srolling
148 | if (!settings.scrollByMousewheel) {
149 | widget.map.scrollWheelZoom.disable();
150 | }
151 | if (!settings.hideLocationButton) {
152 | var locationButton = new L.Control.Button({
153 | iconUrl: "/map/images/location-icon.png",
154 | hideText: true,
155 | doToggle: false,
156 | onClick: function(e) {
157 | var btn = $(this);
158 | /* disable the location button visually if location permission is not granted */
159 | widget.map.on('locationerror', function(e) {
160 | if (e.code == 1 /*PERMISSION_DENIED*/) {
161 | btn.addClass('disabled');
162 | console.log(btn);
163 | }
164 | });
165 | /* try to read the user location and center map there */
166 | widget.map.locate({
167 | setView: true,
168 | maxZoom: 8,
169 | timeout: 30000
170 | });
171 | }
172 | });
173 | widget.map.addControl(locationButton);
174 | }
175 |
176 | if (!settings.hideLayerControl) {
177 | var controls = L.control.layers({
178 | "Gray": mapboxLayer,
179 | "OSM": osmlayer
180 | }).addTo(widget.map);
181 | }
182 |
183 | $.getJSON('config.json', function(configs) {
184 | $.getJSON(options.geoJSONUrl, function(geojson) {
185 | var geoJsonLayer = L.geoJson(geojson, {
186 | onEachFeature: function(feature, layer) {
187 | layer.bindPopup(options.getPopupHTML(feature.properties, configs), { minWidth: 210 });
188 | },
189 | filter: function(feature, layer) {
190 | if (feature.geometry.coordinates[0] && feature.geometry.coordinates[1]) {
191 | return true;
192 | } else {
193 | return false;
194 | }
195 | },
196 | pointToLayer: function(feature, latlng) {
197 | var marker = L.circleMarker(latlng, {
198 | //title: feature.properties.name,
199 | //riseOnHover: true
200 | stroke: true,
201 | weight: 10,
202 | opacity: 0.3,
203 | color: '#d40000',
204 | fill: true,
205 | fillColor: '#d40000',
206 | fillOpacity: 0.7
207 | });
208 | return marker;
209 | }
210 | }).addTo(clusters);
211 |
212 | //add stats info box
213 | if (!settings.hideInfoBox) {
214 | var legend = L.control({position: 'bottomleft'});
215 | legend.onAdd = function(data) {
216 | var div = L.DomUtil.create('div', 'info');
217 | var nodes = 0;
218 | _.each(geojson.features, function(item, key, list) {
219 | if (item.properties.nodes) { nodes += parseInt(item.properties.nodes); }
220 | });
221 | div.innerHTML = '' + geojson.features.length + ' Orte';
222 | div.innerHTML += '
';
223 | div.innerHTML += '' + nodes + ' Zugänge';
224 | return div;
225 | };
226 | legend.addTo(widget.map);
227 | }
228 | });
229 |
230 | //initialize underscore templating
231 | _.templateSettings.variable = "props";
232 | widget.communityTemplate = _.template(
233 | $( "script.template#community-popup" ).html()
234 | );
235 |
236 | widget.map.on('popupopen', function(e){
237 | var url = configs.feedUrl
238 | + '?limit=3&source='
239 | + e.popup._contentNode.getElementsByClassName('community-popup')[0].getAttribute('data-id');
240 | console.log(url);
241 | $.ajax({
242 | url: url,
243 | error: function(err) {
244 | console.log(err);
245 | },
246 | dataType: "jsonp",
247 | success: function(data) {
248 | $data = $($.parseXML(data));
249 | items = $data.find('item');
250 | if (items.length > 0) {
251 | console.log('There are some items');
252 | var rssfeed = $(e.popup._container).find('.community-popup').append('