Browse Source

Initial commit

master
Chimo 6 years ago
commit
af4215af04
10 changed files with 391 additions and 0 deletions
  1. +9
    -0
      .jscsrc
  2. +13
    -0
      .jshintrc
  3. +17
    -0
      README
  4. +7
    -0
      build.sh
  5. +1
    -0
      dist/chiq.map.js
  6. +2
    -0
      dist/chiq.min.js
  7. +123
    -0
      src/map.js
  8. +28
    -0
      src/nominatim.js
  9. +164
    -0
      src/poi.js
  10. +27
    -0
      src/utils.js

+ 9
- 0
.jscsrc View File

@ -0,0 +1,9 @@
{
"preset": "jquery",
"validateLineBreaks": null,
"requireCamelCaseOrUpperCaseIdentifiers": null,
"maximumLineLength": 500,
"requireBlocksOnNewline": true,
"requireSpaceBeforeBlockStatements": true,
"disallowMixedSpacesAndTabs": true
}

+ 13
- 0
.jshintrc View File

@ -0,0 +1,13 @@
{
"boss": true,
"curly": true,
"eqeqeq": true,
"eqnull": true,
"expr": true,
"immed": true,
"noarg": true,
"undef": true,
"unused": true,
"jquery": true,
"browser": true
}

+ 17
- 0
README View File

@ -0,0 +1,17 @@
# Chiq
A small, modular JavaScript library to work with
[Overpass](https://wiki.openstreetmap.org/wiki/Overpass_API),
[Nominatim](http://wiki.openstreetmap.org/wiki/Nominatim) and
[OpenLayers](http://openlayers.org/).
Mainly developed for [Pullet](https://github.com/chimo/Pullet) and [GNU social
Checkin Plugin](https://github.com/chimo/gs-checkin)
## Dependencies
* [jQuery](http://jquery.com/)
* [OpenLayers](http://openlayers.org/download/) (if you want maps)
* [es6-promise polyfill](https://github.com/jakearchibald/es6-promise/) for
[browsers without native Promises](http://caniuse.com/#search=promise)

+ 7
- 0
build.sh View File

@ -0,0 +1,7 @@
#!/usr/bin/bash
DIR=dist
mkdir -p "${DIR}"
uglifyjs --source-map "${DIR}"/chiq.map.js --screw-ie8 --mangle --compress --lint src/* > "${DIR}"/chiq.min.js

+ 1
- 0
dist/chiq.map.js View File

@ -0,0 +1 @@
{"version":3,"sources":["src/map.js","src/nominatim.js","src/poi.js","src/utils.js"],"names":["createStyle","createMarkers","_Pullet","window","Pullet","map","create","container","places","markers","tiles","ol","layer","Tile","source","OSM","layers","extent","getSource","getExtent","Map","target","view","View","center","zoom","getView","fit","getSize","maxZoom","points","i","lat","lon","point","poiName","len","length","tags","name","parseFloat","isNaN","push","Feature","geometry","geom","Point","proj","transform","Vector","features","style","src","Style","image","Icon","anchor","anchorXUnits","anchorYUnits","opacity","$","each","$this","this","$container","data","pois","find","$poi","text","get","nominatim","lookup","osm_ids","query","endpoint","Array","isArray","join","then","Promise","resolve","sortAlpha","nearby","getLocation","position","coords","near","longitude","latitude","catch","err","reject","xml","overpass","radius","around","post","elements","sort","a","b","nameA","nameB","toLowerCase","navigator","geolocation","getCurrentPosition"],"mappings":"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"}

+ 2
- 0
dist/chiq.min.js View File

@ -0,0 +1,2 @@
!function(){"use strict";var e,t,n=window.Pullet||{};n.map={create:function(e,n){var o,r=t(n),a=new ol.layer.Tile({source:new ol.source.OSM}),u=[a,r],i=r.getSource().getExtent();return o=new ol.Map({target:e,layers:u,view:new ol.View({center:[0,0],zoom:1})}),o.getView().fit(i,o.getSize(),{maxZoom:18}),o}},t=function(t){var n,o,r,a,u,i=t.length,s=[];for(n=0;i>n;n+=1)a=t[n],u=a.tags.name,o=parseFloat(a.lat),r=parseFloat(a.lon),isNaN(o)||isNaN(r)||s.push(new ol.Feature({geometry:new ol.geom.Point(ol.proj.transform([r,o],"EPSG:4326","EPSG:3857"))}));return new ol.layer.Vector({source:new ol.source.Vector({features:s}),style:e("/images/marker-green.png")})},e=function(e){return new ol.style.Style({image:new ol.style.Icon({anchor:[.5,46],anchorXUnits:"fraction",anchorYUnits:"pixels",opacity:.75,src:e})})},$("[data-mapcontainer]").each(function(){var e=$(this),t=$(e.data("mapcontainer")),o=[];e.find(".poi").each(function(){var e=$(this);o.push({tags:{name:e.find(".poi__name").text()},lat:e.find(".poi__lat").text(),lon:e.find(".poi__lon").text()})}),n.map.create(t.get(0),o)}),window.Pullet=n}(),function(){"use strict";var e=window.Pullet||{};e.nominatim={lookup:function(e){var t,n=window.Pullet.endpoint.nominatim+"/lookup";return Array.isArray(e)&&0!==e.length?(t="format=json&osm_ids="+e.join(),$.get(n,t).then(function(e){return e})):Promise.resolve([])}},window.Pullet=e}(),function(){"use strict";var e,t=window.Pullet||{};t.places={nearby:function(){return Pullet.getLocation().then(function(e){var t=e.coords;return Pullet.places.near(t.longitude,t.latitude)}).catch(function(e){return Promise.reject(e)})},near:function(e,t){var n,o=Pullet.endpoint.overpass,r=300,a="<around lon='"+e+"' lat='"+t+"' radius='"+r+"'/>";return n="<osm-script output='json' timeout='25'><union><query type='node'><has-kv k='amenity'/>"+a+"</query><query type='way'><has-kv k='amenity'/>"+a+"</query><query type='node'><has-kv k='shop'/>"+a+"</query><query type='way'><has-kv k='shop'/>"+a+"</query><query type='node'><has-kv k='office'/>"+a+"</query><query type='way'><has-kv k='office'/>"+a+"</query><query type='node'><has-kv k='craft'/>"+a+"</query><query type='way'><has-kv k='craft'/>"+a+"</query><query type='node'><has-kv k='leisure'/>"+a+"</query><query type='way'><has-kv k='leisure'/>"+a+"</query><query type='node'><has-kv k='public_transport' v='platform'/>"+a+"</query><query type='way'><has-kv k='public_transport' v='platform'/>"+a+"</query><query type='node'><has-kv k='highway' v='bus_stop'/>"+a+"</query><query type='way'><has-kv k='highway' v='bus_stop'/>"+a+"</query></union><print mode='body' order='quadtile'/></osm-script>",$.post(o,n).then(function(e){return e.elements})},sort:function(t){return t.sort(e)}},e=function(e,t){var n=e.tags.name||"",o=t.tags.name||"";return n=n.toLowerCase(),o=o.toLowerCase(),o>n?-1:n>o?1:0},window.Pullet=t}(),function(){"use strict";var e=window.Pullet||{};e.getLocation=function(){return new Promise(function(e,t){navigator.geolocation.getCurrentPosition(function(t){e(t)},function(e){t(e)})})},window.Pullet=e}();
//# sourceMappingURL=dist/chiq.map.js

+ 123
- 0
src/map.js View File

@ -0,0 +1,123 @@
( function() {
/*global ol: false*/
"use strict";
var _Pullet = window.Pullet || {},
createStyle,
createMarkers;
/**
* Namespace for 'map' related methods
*/
_Pullet.map = {
/**
* Create map with markers
*/
create: function( container, places ) {
var markers = createMarkers( places ),
tiles = new ol.layer.Tile( { source: new ol.source.OSM() } ),
layers = [ tiles, markers ],
extent = markers.getSource().getExtent(),
map;
map = new ol.Map( {
target: container,
layers: layers,
view: new ol.View( {
center: [ 0, 0 ],
zoom: 1
} )
} );
map.getView().fit( extent, map.getSize(), { maxZoom: 18 } );
return map;
}
};
/**
* Create markers
*/
createMarkers = function( points ) {
var len = points.length,
i,
lat,
lon,
point,
poiName,
markers = [];
for ( i = 0; i < len; i += 1 ) {
point = points[ i ];
poiName = point.tags.name;
lat = parseFloat( point.lat );
lon = parseFloat( point.lon );
// Skip points with invalid/no lat/lon
if ( isNaN( lat ) || isNaN( lon ) ) {
continue;
}
// create markers
markers.push(
new ol.Feature( {
geometry: new ol.geom.Point( ol.proj.transform( [ lon, lat ], "EPSG:4326", "EPSG:3857" ) )
} )
);
}
// create and return layer
return new ol.layer.Vector( {
source: new ol.source.Vector( { features: markers } ),
style: createStyle( "/images/marker-green.png" )
} );
};
/**
* Create map marker style
*
* @param src String URL to image
*/
createStyle = function( src ) {
return new ol.style.Style(
{
image: new ol.style.Icon(
{
anchor: [ 0.5, 46 ],
anchorXUnits: "fraction",
anchorYUnits: "pixels",
opacity: 0.75,
src: src
}
)
}
);
};
/**
* Build map in all .map containers
*/
$( "[data-mapcontainer]" ).each( function() {
var $this = $( this ),
$container = $( $this.data( "mapcontainer" ) ),
pois = [];
$this.find( ".poi" ).each( function() {
var $poi = $( this );
pois.push( {
tags: {
name: $poi.find( ".poi__name" ).text()
},
lat: $poi.find( ".poi__lat" ).text(),
lon: $poi.find( ".poi__lon" ).text()
} );
} );
_Pullet.map.create( $container.get( 0 ), pois );
} );
window.Pullet = _Pullet;
}() );

+ 28
- 0
src/nominatim.js View File

@ -0,0 +1,28 @@
( function() {
/*global Promise: false*/
"use strict";
var _Pullet = window.Pullet || {};
_Pullet.nominatim = {
lookup: function( osm_ids ) {
var endpoint = window.Pullet.endpoint.nominatim + "/lookup",
query;
// Don't contact endpoint if we have no data or bad param
if ( !Array.isArray( osm_ids ) || osm_ids.length === 0 ) {
return Promise.resolve( [] );
}
query = "format=json&osm_ids=" + osm_ids.join();
// TODO: Error handling
return $.get( endpoint, query )
.then( function( data ) {
return data;
} );
}
};
window.Pullet = _Pullet;
}() );

+ 164
- 0
src/poi.js View File

@ -0,0 +1,164 @@
( function() {
/*global Promise: false, Pullet: false*/
"use strict";
var _Pullet = window.Pullet || {},
sortAlpha;
/**
* Namespace for point-of-interest (POIs)
* related methods
*/
_Pullet.places = {
/**
* Pullet.places.nearby
*
* Gets POIs near current location
*/
nearby: function() {
return Pullet
.getLocation()
.then( function( position ) {
var coords = position.coords;
return Pullet.places.near( coords.longitude, coords.latitude );
} )
.catch( function( err ) {
return Promise.reject( err );
} );
},
/**
* Pullet.places.near
*
* Gets POIs near a specific location
*/
near: function( lon, lat ) {
var endpoint = Pullet.endpoint.overpass,
radius = 300, // TODO: configurable
around = "<around lon='" + lon + "' lat='" + lat + "' radius='" + radius + "'/>",
xml;
xml = "<osm-script output='json' timeout='25'>" +
"<union>" +
// Amenities
"<query type='node'>" +
"<has-kv k='amenity'/>" +
around +
"</query>" +
"<query type='way'>" +
"<has-kv k='amenity'/>" +
around +
"</query>" +
// Shops
"<query type='node'>" +
"<has-kv k='shop'/>" +
around +
"</query>" +
"<query type='way'>" +
"<has-kv k='shop'/>" +
around +
"</query>" +
// Offices
"<query type='node'>" +
"<has-kv k='office'/>" +
around +
"</query>" +
"<query type='way'>" +
"<has-kv k='office'/>" +
around +
"</query>" +
// Crafts
"<query type='node'>" +
"<has-kv k='craft'/>" +
around +
"</query>" +
"<query type='way'>" +
"<has-kv k='craft'/>" +
around +
"</query>" +
// Leisure (parks, etc.)
/*
This one has significant 'relation' usage.
TODO: Look into it: https://wiki.openstreetmap.org/wiki/Key:leisure
*/
"<query type='node'>" +
"<has-kv k='leisure'/>" +
around +
"</query>" +
"<query type='way'>" +
"<has-kv k='leisure'/>" +
around +
"</query>" +
// Public transport platforms (waiting areas)
"<query type='node'>" +
"<has-kv k='public_transport' v='platform'/>" +
around +
"</query>" +
"<query type='way'>" +
"<has-kv k='public_transport' v='platform'/>" +
around +
"</query>" +
// Bus stops (seems more popular than public_transport=platform)
"<query type='node'>" +
"<has-kv k='highway' v='bus_stop'/>" +
around +
"</query>" +
"<query type='way'>" +
"<has-kv k='highway' v='bus_stop'/>" +
around +
"</query>" +
"</union>" +
"<print mode='body' order='quadtile'/>" +
"</osm-script>";
// Fetch POIs
return $.post( endpoint, xml )
.then( function( data ) {
return data.elements;
} );
},
/**
* Pullet.places.sort
*
* Sort POIs
* Only A-Z sorting is supported right now
*/
sort: function( pois ) {
return pois.sort( sortAlpha );
}
};
sortAlpha = function( a, b ) {
/* Undefined names converted to empty string
I don't like this, but empty strings evaluate to false, at least */
var nameA = a.tags.name || "",
nameB = b.tags.name || "";
// Case insensitive sort
nameA = nameA.toLowerCase();
nameB = nameB.toLowerCase();
if ( nameA < nameB ) {
return -1;
}
if ( nameA > nameB ) {
return 1;
}
return 0;
};
window.Pullet = _Pullet;
}() );

+ 27
- 0
src/utils.js View File

@ -0,0 +1,27 @@
( function() {
/*global Promise: false*/
"use strict";
var _Pullet = window.Pullet || {};
/**
* Get current location
*/
_Pullet.getLocation = function() {
return new Promise( function( resolve, reject ) {
navigator.geolocation.getCurrentPosition(
/* Success */
function( position ) {
resolve( position );
},
/* Error */
function( err ) {
reject( err );
}
);
} );
};
window.Pullet = _Pullet;
}() );

Loading…
Cancel
Save