├── .couchappignore ├── .couchapprc ├── .gitignore ├── CNAME ├── README.md ├── external ├── icanhaz │ └── ICanHaz.js ├── leaflet-markercluster │ ├── MarkerCluster.Default.css │ ├── MarkerCluster.css │ ├── leaflet.markercluster-src.js │ └── leaflet.markercluster.js └── leaflet │ └── Bing.js ├── images ├── favicon.ico ├── node_circle.svg └── wifi_icon60.png ├── index.html ├── map.html ├── rewrites.json ├── script ├── owm_app.js └── owm_widget.js └── style ├── owm_app.css └── owm_widget.css /.couchappignore: -------------------------------------------------------------------------------- 1 | [ 2 | // filenames matching these regexps will not be pushed to the database 3 | // uncomment to activate; separate entries with "," 4 | ".*~$", 5 | ".*\\.swp$", 6 | ".*\\.bak$", 7 | ".git" 8 | ] 9 | -------------------------------------------------------------------------------- /.couchapprc: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | openwifimap.net 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # openwifimap-html5 2 | 3 | OpenWiFiMap is a database and map for free network WiFi routers (freifunk and others, too!). 4 | 5 | This is a HTML5 map app with data from a [OpenWiFiMap database](http://github.com/freifunk/openwifimap-api/). 6 | 7 | ## HTML5 app installations 8 | 9 | Visit the main installation at [openwifimap.net](http://openwifimap.net/) or the stripped down version at [openwifimap.net/map.html](http://openwifimap.net/map.html) (e.g. for inclusion in other sites via iframe). 10 | 11 | Of course, you can easily set up your own map! Here is a (possibly incomplete) list of installations: 12 | * [openwifimap.net](http://openwifimap.net/) 13 | * [map.pberg.freifunk.net](http://map.pberg.freifunk.net/) 14 | * [map.weimarnetz.de](http://map.weimarnetz.de/) 15 | 16 | If your installation is missing, feel free to add it or tell us by opening an issue. 17 | 18 | ## Submitting and querying data 19 | 20 | If you want to submit nodes to the database or if you want to query the database, please take a look at the [OpenWiFiMap API documentation](https://github.com/freifunk/openwifimap-api/blob/master/API.md). 21 | 22 | ## License 23 | 24 | openwifimap-html5 is licensed under the [MIT license](http://opensource.org/licenses/MIT). 25 | -------------------------------------------------------------------------------- /external/icanhaz/ICanHaz.js: -------------------------------------------------------------------------------- 1 | /*! 2 | ICanHaz.js version 0.10 -- by @HenrikJoreteg 3 | More info at: http://icanhazjs.com 4 | */ 5 | (function () { 6 | /* 7 | mustache.js — Logic-less templates in JavaScript 8 | 9 | See http://mustache.github.com/ for more info. 10 | */ 11 | 12 | var Mustache = function () { 13 | var _toString = Object.prototype.toString; 14 | 15 | Array.isArray = Array.isArray || function (obj) { 16 | return _toString.call(obj) == "[object Array]"; 17 | } 18 | 19 | var _trim = String.prototype.trim, trim; 20 | 21 | if (_trim) { 22 | trim = function (text) { 23 | return text == null ? "" : _trim.call(text); 24 | } 25 | } else { 26 | var trimLeft, trimRight; 27 | 28 | // IE doesn't match non-breaking spaces with \s. 29 | if ((/\S/).test("\xA0")) { 30 | trimLeft = /^[\s\xA0]+/; 31 | trimRight = /[\s\xA0]+$/; 32 | } else { 33 | trimLeft = /^\s+/; 34 | trimRight = /\s+$/; 35 | } 36 | 37 | trim = function (text) { 38 | return text == null ? "" : 39 | text.toString().replace(trimLeft, "").replace(trimRight, ""); 40 | } 41 | } 42 | 43 | var escapeMap = { 44 | "&": "&", 45 | "<": "<", 46 | ">": ">", 47 | '"': '"', 48 | "'": ''' 49 | }; 50 | 51 | function escapeHTML(string) { 52 | return String(string).replace(/&(?!\w+;)|[<>"']/g, function (s) { 53 | return escapeMap[s] || s; 54 | }); 55 | } 56 | 57 | var regexCache = {}; 58 | var Renderer = function () {}; 59 | 60 | Renderer.prototype = { 61 | otag: "{{", 62 | ctag: "}}", 63 | pragmas: {}, 64 | buffer: [], 65 | pragmas_implemented: { 66 | "IMPLICIT-ITERATOR": true 67 | }, 68 | context: {}, 69 | 70 | render: function (template, context, partials, in_recursion) { 71 | // reset buffer & set context 72 | if (!in_recursion) { 73 | this.context = context; 74 | this.buffer = []; // TODO: make this non-lazy 75 | } 76 | 77 | // fail fast 78 | if (!this.includes("", template)) { 79 | if (in_recursion) { 80 | return template; 81 | } else { 82 | this.send(template); 83 | return; 84 | } 85 | } 86 | 87 | // get the pragmas together 88 | template = this.render_pragmas(template); 89 | 90 | // render the template 91 | var html = this.render_section(template, context, partials); 92 | 93 | // render_section did not find any sections, we still need to render the tags 94 | if (html === false) { 95 | html = this.render_tags(template, context, partials, in_recursion); 96 | } 97 | 98 | if (in_recursion) { 99 | return html; 100 | } else { 101 | this.sendLines(html); 102 | } 103 | }, 104 | 105 | /* 106 | Sends parsed lines 107 | */ 108 | send: function (line) { 109 | if (line !== "") { 110 | this.buffer.push(line); 111 | } 112 | }, 113 | 114 | sendLines: function (text) { 115 | if (text) { 116 | var lines = text.split("\n"); 117 | for (var i = 0; i < lines.length; i++) { 118 | this.send(lines[i]); 119 | } 120 | } 121 | }, 122 | 123 | /* 124 | Looks for %PRAGMAS 125 | */ 126 | render_pragmas: function (template) { 127 | // no pragmas 128 | if (!this.includes("%", template)) { 129 | return template; 130 | } 131 | 132 | var that = this; 133 | var regex = this.getCachedRegex("render_pragmas", function (otag, ctag) { 134 | return new RegExp(otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + ctag, "g"); 135 | }); 136 | 137 | return template.replace(regex, function (match, pragma, options) { 138 | if (!that.pragmas_implemented[pragma]) { 139 | throw({message: 140 | "This implementation of mustache doesn't understand the '" + 141 | pragma + "' pragma"}); 142 | } 143 | that.pragmas[pragma] = {}; 144 | if (options) { 145 | var opts = options.split("="); 146 | that.pragmas[pragma][opts[0]] = opts[1]; 147 | } 148 | return ""; 149 | // ignore unknown pragmas silently 150 | }); 151 | }, 152 | 153 | /* 154 | Tries to find a partial in the curent scope and render it 155 | */ 156 | render_partial: function (name, context, partials) { 157 | name = trim(name); 158 | if (!partials || partials[name] === undefined) { 159 | throw({message: "unknown_partial '" + name + "'"}); 160 | } 161 | if (!context || typeof context[name] != "object") { 162 | return this.render(partials[name], context, partials, true); 163 | } 164 | return this.render(partials[name], context[name], partials, true); 165 | }, 166 | 167 | /* 168 | Renders inverted (^) and normal (#) sections 169 | */ 170 | render_section: function (template, context, partials) { 171 | if (!this.includes("#", template) && !this.includes("^", template)) { 172 | // did not render anything, there were no sections 173 | return false; 174 | } 175 | 176 | var that = this; 177 | 178 | var regex = this.getCachedRegex("render_section", function (otag, ctag) { 179 | // This regex matches _the first_ section ({{#foo}}{{/foo}}), and captures the remainder 180 | return new RegExp( 181 | "^([\\s\\S]*?)" + // all the crap at the beginning that is not {{*}} ($1) 182 | 183 | otag + // {{ 184 | "(\\^|\\#)\\s*(.+)\\s*" + // #foo (# == $2, foo == $3) 185 | ctag + // }} 186 | 187 | "\n*([\\s\\S]*?)" + // between the tag ($2). leading newlines are dropped 188 | 189 | otag + // {{ 190 | "\\/\\s*\\3\\s*" + // /foo (backreference to the opening tag). 191 | ctag + // }} 192 | 193 | "\\s*([\\s\\S]*)$", // everything else in the string ($4). leading whitespace is dropped. 194 | 195 | "g"); 196 | }); 197 | 198 | 199 | // for each {{#foo}}{{/foo}} section do... 200 | return template.replace(regex, function (match, before, type, name, content, after) { 201 | // before contains only tags, no sections 202 | var renderedBefore = before ? that.render_tags(before, context, partials, true) : "", 203 | 204 | // after may contain both sections and tags, so use full rendering function 205 | renderedAfter = after ? that.render(after, context, partials, true) : "", 206 | 207 | // will be computed below 208 | renderedContent, 209 | 210 | value = that.find(name, context); 211 | 212 | if (type === "^") { // inverted section 213 | if (!value || Array.isArray(value) && value.length === 0) { 214 | // false or empty list, render it 215 | renderedContent = that.render(content, context, partials, true); 216 | } else { 217 | renderedContent = ""; 218 | } 219 | } else if (type === "#") { // normal section 220 | if (Array.isArray(value)) { // Enumerable, Let's loop! 221 | renderedContent = that.map(value, function (row) { 222 | return that.render(content, that.create_context(row), partials, true); 223 | }).join(""); 224 | } else if (that.is_object(value)) { // Object, Use it as subcontext! 225 | renderedContent = that.render(content, that.create_context(value), 226 | partials, true); 227 | } else if (typeof value == "function") { 228 | // higher order section 229 | renderedContent = value.call(context, content, function (text) { 230 | return that.render(text, context, partials, true); 231 | }); 232 | } else if (value) { // boolean section 233 | renderedContent = that.render(content, context, partials, true); 234 | } else { 235 | renderedContent = ""; 236 | } 237 | } 238 | 239 | return renderedBefore + renderedContent + renderedAfter; 240 | }); 241 | }, 242 | 243 | /* 244 | Replace {{foo}} and friends with values from our view 245 | */ 246 | render_tags: function (template, context, partials, in_recursion) { 247 | // tit for tat 248 | var that = this; 249 | 250 | var new_regex = function () { 251 | return that.getCachedRegex("render_tags", function (otag, ctag) { 252 | return new RegExp(otag + "(=|!|>|&|\\{|%)?([^#\\^]+?)\\1?" + ctag + "+", "g"); 253 | }); 254 | }; 255 | 256 | var regex = new_regex(); 257 | var tag_replace_callback = function (match, operator, name) { 258 | switch(operator) { 259 | case "!": // ignore comments 260 | return ""; 261 | case "=": // set new delimiters, rebuild the replace regexp 262 | that.set_delimiters(name); 263 | regex = new_regex(); 264 | return ""; 265 | case ">": // render partial 266 | return that.render_partial(name, context, partials); 267 | case "{": // the triple mustache is unescaped 268 | case "&": // & operator is an alternative unescape method 269 | return that.find(name, context); 270 | default: // escape the value 271 | return escapeHTML(that.find(name, context)); 272 | } 273 | }; 274 | var lines = template.split("\n"); 275 | for(var i = 0; i < lines.length; i++) { 276 | lines[i] = lines[i].replace(regex, tag_replace_callback, this); 277 | if (!in_recursion) { 278 | this.send(lines[i]); 279 | } 280 | } 281 | 282 | if (in_recursion) { 283 | return lines.join("\n"); 284 | } 285 | }, 286 | 287 | set_delimiters: function (delimiters) { 288 | var dels = delimiters.split(" "); 289 | this.otag = this.escape_regex(dels[0]); 290 | this.ctag = this.escape_regex(dels[1]); 291 | }, 292 | 293 | escape_regex: function (text) { 294 | // thank you Simon Willison 295 | if (!arguments.callee.sRE) { 296 | var specials = [ 297 | '/', '.', '*', '+', '?', '|', 298 | '(', ')', '[', ']', '{', '}', '\\' 299 | ]; 300 | arguments.callee.sRE = new RegExp( 301 | '(\\' + specials.join('|\\') + ')', 'g' 302 | ); 303 | } 304 | return text.replace(arguments.callee.sRE, '\\$1'); 305 | }, 306 | 307 | /* 308 | find `name` in current `context`. That is find me a value 309 | from the view object 310 | */ 311 | find: function (name, context) { 312 | name = trim(name); 313 | 314 | // Checks whether a value is thruthy or false or 0 315 | function is_kinda_truthy(bool) { 316 | return bool === false || bool === 0 || bool; 317 | } 318 | 319 | var value; 320 | 321 | // check for dot notation eg. foo.bar 322 | if (name.match(/([a-z_]+)\./ig)) { 323 | var childValue = this.walk_context(name, context); 324 | if (is_kinda_truthy(childValue)) { 325 | value = childValue; 326 | } 327 | } else { 328 | if (is_kinda_truthy(context[name])) { 329 | value = context[name]; 330 | } else if (is_kinda_truthy(this.context[name])) { 331 | value = this.context[name]; 332 | } 333 | } 334 | 335 | if (typeof value == "function") { 336 | return value.apply(context); 337 | } 338 | if (value !== undefined) { 339 | return value; 340 | } 341 | // silently ignore unkown variables 342 | return ""; 343 | }, 344 | 345 | walk_context: function (name, context) { 346 | var path = name.split('.'); 347 | // if the var doesn't exist in current context, check the top level context 348 | var value_context = (context[path[0]] != undefined) ? context : this.context; 349 | var value = value_context[path.shift()]; 350 | while (value != undefined && path.length > 0) { 351 | value_context = value; 352 | value = value[path.shift()]; 353 | } 354 | // if the value is a function, call it, binding the correct context 355 | if (typeof value == "function") { 356 | return value.apply(value_context); 357 | } 358 | return value; 359 | }, 360 | 361 | // Utility methods 362 | 363 | /* includes tag */ 364 | includes: function (needle, haystack) { 365 | return haystack.indexOf(this.otag + needle) != -1; 366 | }, 367 | 368 | // by @langalex, support for arrays of strings 369 | create_context: function (_context) { 370 | if (this.is_object(_context)) { 371 | return _context; 372 | } else { 373 | var iterator = "."; 374 | if (this.pragmas["IMPLICIT-ITERATOR"]) { 375 | iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator; 376 | } 377 | var ctx = {}; 378 | ctx[iterator] = _context; 379 | return ctx; 380 | } 381 | }, 382 | 383 | is_object: function (a) { 384 | return a && typeof a == "object"; 385 | }, 386 | 387 | /* 388 | Why, why, why? Because IE. Cry, cry cry. 389 | */ 390 | map: function (array, fn) { 391 | if (typeof array.map == "function") { 392 | return array.map(fn); 393 | } else { 394 | var r = []; 395 | var l = array.length; 396 | for(var i = 0; i < l; i++) { 397 | r.push(fn(array[i])); 398 | } 399 | return r; 400 | } 401 | }, 402 | 403 | getCachedRegex: function (name, generator) { 404 | var byOtag = regexCache[this.otag]; 405 | if (!byOtag) { 406 | byOtag = regexCache[this.otag] = {}; 407 | } 408 | 409 | var byCtag = byOtag[this.ctag]; 410 | if (!byCtag) { 411 | byCtag = byOtag[this.ctag] = {}; 412 | } 413 | 414 | var regex = byCtag[name]; 415 | if (!regex) { 416 | regex = byCtag[name] = generator(this.otag, this.ctag); 417 | } 418 | 419 | return regex; 420 | } 421 | }; 422 | 423 | return({ 424 | name: "mustache.js", 425 | version: "0.4.0", 426 | 427 | /* 428 | Turns a template and view into HTML 429 | */ 430 | to_html: function (template, view, partials, send_fun) { 431 | var renderer = new Renderer(); 432 | if (send_fun) { 433 | renderer.send = send_fun; 434 | } 435 | renderer.render(template, view || {}, partials); 436 | if (!send_fun) { 437 | return renderer.buffer.join("\n"); 438 | } 439 | } 440 | }); 441 | }(); 442 | /*! 443 | ICanHaz.js -- by @HenrikJoreteg 444 | */ 445 | /*global */ 446 | (function () { 447 | function trim(stuff) { 448 | if (''.trim) return stuff.trim(); 449 | else return stuff.replace(/^\s+/, '').replace(/\s+$/, ''); 450 | } 451 | var ich = { 452 | VERSION: "0.10", 453 | templates: {}, 454 | 455 | // grab jquery or zepto if it's there 456 | $: (typeof window !== 'undefined') ? window.jQuery || window.Zepto || null : null, 457 | 458 | // public function for adding templates 459 | // can take a name and template string arguments 460 | // or can take an object with name/template pairs 461 | // We're enforcing uniqueness to avoid accidental template overwrites. 462 | // If you want a different template, it should have a different name. 463 | addTemplate: function (name, templateString) { 464 | if (typeof name === 'object') { 465 | for (var template in name) { 466 | this.addTemplate(template, name[template]); 467 | } 468 | return; 469 | } 470 | if (ich[name]) { 471 | console.error("Invalid name: " + name + "."); 472 | } else if (ich.templates[name]) { 473 | console.error("Template \"" + name + " \" exists"); 474 | } else { 475 | ich.templates[name] = templateString; 476 | ich[name] = function (data, raw) { 477 | data = data || {}; 478 | var result = Mustache.to_html(ich.templates[name], data, ich.templates); 479 | return (ich.$ && !raw) ? ich.$(result) : result; 480 | }; 481 | } 482 | }, 483 | 484 | // clears all retrieval functions and empties cache 485 | clearAll: function () { 486 | for (var key in ich.templates) { 487 | delete ich[key]; 488 | } 489 | ich.templates = {}; 490 | }, 491 | 492 | // clears/grabs 493 | refresh: function () { 494 | ich.clearAll(); 495 | ich.grabTemplates(); 496 | }, 497 | 498 | // grabs templates from the DOM and caches them. 499 | // Loop through and add templates. 500 | // Whitespace at beginning and end of all templates inside 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 29 | 30 | 31 | 32 | 33 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 59 | 66 | 96 | 109 | 289 | 290 | 291 | 292 |
293 |OpenWiFiMap is 312 |
327 | Donate with flattr: 328 |
333 | 329 | 332 | Close 334 |