diff --git a/Makefile b/Makefile index 1e0fb7e..9366294 100644 --- a/Makefile +++ b/Makefile @@ -2,97 +2,134 @@ ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) NOW := $(shell date --iso=seconds) SRC_DIR := $(ROOT_DIR)/src BUILD_DIR := $(ROOT_DIR)/build -JS_DEBUG := $(BUILD_DIR)/ol3-geocoder-debug.js -JS_FINAL := $(BUILD_DIR)/ol3-geocoder.js + +define GetFromPkg +$(shell node -p "require('./package.json').$(1)") +endef + +LAST_VERSION := $(call GetFromPkg,version) +DESCRIPTION := $(call GetFromPkg,description) +PROJECT_URL := $(call GetFromPkg,homepage) + +JS_DEBUG := $(ROOT_DIR)/$(call GetFromPkg,rollup.dest) +JS_FINAL := $(ROOT_DIR)/$(call GetFromPkg,main) + + CSS_COMBINED := $(BUILD_DIR)/ol3-geocoder.css CSS_FINAL := $(BUILD_DIR)/ol3-geocoder.min.css TMPFILE := $(BUILD_DIR)/tmp -PACKAGE_JSON := $(ROOT_DIR)/package.json -LAST_VERSION := $(shell node -p "require('./package.json').version") -JS_FILES := $(SRC_DIR)/wrapper-head.js \ - $(SRC_DIR)/utils.js \ - $(SRC_DIR)/base.js \ - $(SRC_DIR)/nominatim.js \ - $(SRC_DIR)/wrapper-tail.js +JS_SRC := $(SRC_DIR)/js +SASS_SRC := $(SRC_DIR)/sass +SASS_VENDOR_SRC := $(SASS_SRC)/vendor -CSS_FILES := $(SRC_DIR)/ol3-geocoder.css +SASS_MAIN_FILE := $(SASS_SRC)/main.scss NODE_MODULES := ./node_modules/.bin + CLEANCSS := $(NODE_MODULES)/cleancss CLEANCSSFLAGS := --skip-restructuring + POSTCSS := $(NODE_MODULES)/postcss -POSTCSSFLAGS := --use autoprefixer -b "last 2 versions" +POSTCSSFLAGS := --use autoprefixer -b "last 3 versions, ie >= 9" --replace + ESLINT := $(NODE_MODULES)/eslint UGLIFYJS := $(NODE_MODULES)/uglifyjs UGLIFYJSFLAGS := --mangle --mangle-regex --screw-ie8 -c warnings=false -JS_BEAUTIFY := $(NODE_MODULES)/js-beautify -BEAUTIFYFLAGS := -f - --indent-size 2 --preserve-newlines + NODEMON := $(NODE_MODULES)/nodemon PARALLELSHELL := $(NODE_MODULES)/parallelshell +SASS := $(NODE_MODULES)/node-sass +SASSFLAGS := --importer node_modules/node-sass-json-importer/dist/node-sass-json-importer.js -# just to create variables like NODEMON_JS_FLAGS when called -define NodemonFlags - UP_LANG = $(shell echo $(1) | tr '[:lower:]' '[:upper:]') - NODEMON_$$(UP_LANG)_FLAGS := --on-change-only --watch "$(SRC_DIR)" --ext "$(1)" --exec "make build-$(1)" -endef +ROLLUP := $(NODE_MODULES)/rollup +ROLLUPFLAGS := -c config/rollup.config.js define HEADER -// Geocoder Nominatim for OpenLayers 3. -// https://github.com/jonataswalker/ol3-geocoder -// Version: v$(LAST_VERSION) -// Built: $(NOW) +/** + * $(DESCRIPTION) + * $(PROJECT_URL) + * Version: v$(LAST_VERSION) + * Built: $(NOW) + */ endef export HEADER # targets - .PHONY: ci ci: build +.PHONY: build-watch build-watch: build watch +.PHONY: watch watch: - $(PARALLELSHELL) "make watch-js" "make watch-css" + $(PARALLELSHELL) "make watch-js" "make watch-sass" +.PHONY: build build: build-js build-css -build-js: combine-js lint uglifyjs addheader - @echo `date +'%H:%M:%S'` " - build JS ... OK" +.PHONY: build-js +build-js: bundle-js lint uglifyjs add-js-header + @echo `date +'%H:%M:%S'` "Build JS ... OK" -build-css: combine-css cleancss - @echo `date +'%H:%M:%S'` " - build CSS ... OK" +.PHONY: build-css +build-css: compile-sass prefix-css cleancss add-css-header + @echo `date +'%H:%M:%S'` "Build CSS ... OK" -uglifyjs: $(JS_DEBUG) - @$(UGLIFYJS) $^ $(UGLIFYJSFLAGS) > $(JS_FINAL) +.PHONY: compile-sass +compile-sass: $(SASS_MAIN_FILE) + @$(SASS) $(SASSFLAGS) $^ $(CSS_COMBINED) + +.PHONY: prefix-css +prefix-css: $(CSS_COMBINED) + @$(POSTCSS) $(POSTCSSFLAGS) $^ +.PHONY: build +cleancss: $(CSS_COMBINED) + @cat $^ | $(CLEANCSS) $(CLEANCSSFLAGS) > $(CSS_FINAL) + +.PHONY: bundle-js +bundle-js: + @$(ROLLUP) $(ROLLUPFLAGS) + +.PHONY: lint lint: $(JS_DEBUG) @$(ESLINT) $^ -addheader-debug: $(JS_DEBUG) +.PHONY: uglifyjs +uglifyjs: $(JS_DEBUG) + @$(UGLIFYJS) $^ $(UGLIFYJSFLAGS) > $(JS_FINAL) + +.PHONY: add-js-header-debug +add-js-header-debug: $(JS_DEBUG) @echo "$$HEADER" | cat - $^ > $(TMPFILE) && mv $(TMPFILE) $^ -addheader-min: $(JS_FINAL) +.PHONY: add-js-header-min +add-js-header-min: $(JS_FINAL) @echo "$$HEADER" | cat - $^ > $(TMPFILE) && mv $(TMPFILE) $^ -addheader: addheader-debug addheader-min +.PHONY: add-js-header +add-js-header: add-js-header-debug add-js-header-min -cleancss: $(CSS_COMBINED) - @cat $^ | $(CLEANCSS) $(CLEANCSSFLAGS) > $(CSS_FINAL) +.PHONY: add-css-header-debug +add-css-header-debug: $(CSS_COMBINED) + @echo "$$HEADER" | cat - $^ > $(TMPFILE) && mv $(TMPFILE) $^ -combine-js: $(JS_FILES) - @cat $^ | $(JS_BEAUTIFY) $(BEAUTIFYFLAGS) > $(JS_DEBUG) +.PHONY: add-css-header-min +add-css-header-min: $(CSS_FINAL) + @echo "$$HEADER" | cat - $^ > $(TMPFILE) && mv $(TMPFILE) $^ -combine-css: $(CSS_FILES) - @cat $^ | $(POSTCSS) $(POSTCSSFLAGS) > $(CSS_COMBINED) +.PHONY: add-css-header +add-css-header: add-css-header-debug add-css-header-min -watch-js: $(JS_FILES) - $(eval $(call NodemonFlags,js)) - @$(NODEMON) $(NODEMON_JS_FLAGS) +.PHONY: watch-js +watch-js: $(JS_SRC) + @$(NODEMON) --on-change-only --watch $^ --ext js --exec "make build-js" -watch-css: $(CSS_FILES) - $(eval $(call NodemonFlags,css)) - @$(NODEMON) $(NODEMON_CSS_FLAGS) +.PHONY: watch-sass +watch-sass: $(SASS_SRC) + @$(NODEMON) --on-change-only --watch $^ --ext scss --ignore $(SASS_VENDOR_SRC) --exec "make build-css" .DEFAULT_GOAL := build diff --git a/build/ol3-geocoder-debug.js b/build/ol3-geocoder-debug.js index 6d0b702..1608052 100644 --- a/build/ol3-geocoder-debug.js +++ b/build/ol3-geocoder-debug.js @@ -1,945 +1,1056 @@ -// Geocoder Nominatim for OpenLayers 3. -// https://github.com/jonataswalker/ol3-geocoder -// Version: v1.7.0 -// Built: 2016-04-01T08:24:58-0300 - -'use strict'; - -(function(root, factory) { - if (typeof exports === 'object') { - module.exports = factory(); - } else if (typeof define === 'function' && define.amd) { - define([], factory); - } else { - root.Geocoder = factory(); - } -}(this, function() { - - var G = {}; - /** - * Helper - */ - var utils = { - whiteSpaceRegex: /\s+/, - toQueryString: function(obj) { - return Object.keys(obj).reduce(function(a, k) { - a.push((typeof obj[k] === 'object') ? - utils.toQueryString(obj[k]) : - encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]) - ); - return a; - }, []).join('&'); - }, - encodeUrlXhr: function(url, data) { - if (data && typeof(data) === 'object') { - var str_data = utils.toQueryString(data); - url += (/\?/.test(url) ? '&' : '?') + str_data; - } - return url; - }, - json: function(url, data) { - var xhr = new XMLHttpRequest(), - when = {}, - onload = function() { - if (xhr.status === 200) { - when.ready.call(undefined, JSON.parse(xhr.response)); - } - }, - onerror = function() { - console.info('Cannot XHR ' + JSON.stringify(url)); - }; - url = utils.encodeUrlXhr(url, data); - xhr.open('GET', url, true); - xhr.setRequestHeader('Accept', 'application/json'); - xhr.onload = onload; - xhr.onerror = onerror; - xhr.send(null); - - return { - when: function(obj) { - when.ready = obj.ready; - } - }; - }, - randomId: function(prefix) { - var id = (new Date().getTime()).toString(36); - return (prefix) ? prefix + id : id; - }, - to3857: function(coord) { - return ol.proj.transform( - [parseFloat(coord[0]), parseFloat(coord[1])], - 'EPSG:4326', 'EPSG:3857' - ); - }, - to4326: function(coord) { - return ol.proj.transform( - [parseFloat(coord[0]), parseFloat(coord[1])], - 'EPSG:3857', 'EPSG:4326' - ); - }, - isNumeric: function(str) { - return /^\d+$/.test(str); - }, - classRegex: function(classname) { - return new RegExp('(^|\\s+)' + classname + '(\\s+|$)'); - }, - /** - * @param {Element|Array} element DOM node or array of nodes. - * @param {String|Array} classname Class or array of classes. - * For example: 'class1 class2' or ['class1', 'class2'] - * @param {Number|undefined} timeout Timeout to remove a class. - */ - addClass: function(element, classname, timeout) { - if (Array.isArray(element)) { - element.forEach(function(each) { - utils.addClass(each, classname); - }); - return; - } - - var - array = (Array.isArray(classname)) ? classname : classname.split(/\s+/), - i = array.length; - while (i--) { - if (!utils.hasClass(element, array[i])) { - utils._addClass(element, array[i], timeout); - } - } - }, - _addClass: function(el, c, timeout) { - // use native if available - if (el.classList) { - el.classList.add(c); - } else { - el.className = (el.className + ' ' + c).trim(); - } - - if (timeout && utils.isNumeric(timeout)) { - window.setTimeout(function() { - utils._removeClass(el, c); - }, timeout); - } - }, - /** - * @param {Element|Array} element DOM node or array of nodes. - * @param {String|Array} classname Class or array of classes. - * For example: 'class1 class2' or ['class1', 'class2'] - * @param {Number|undefined} timeout Timeout to add a class. - */ - removeClass: function(element, classname, timeout) { - if (Array.isArray(element)) { - element.forEach(function(each) { - utils.removeClass(each, classname, timeout); - }); - return; - } - - var - array = (Array.isArray(classname)) ? classname : classname.split(/\s+/), - i = array.length; - while (i--) { - if (utils.hasClass(element, array[i])) { - utils._removeClass(element, array[i], timeout); - } - } - }, - _removeClass: function(el, c, timeout) { - if (el.classList) { - el.classList.remove(c); - } else { - el.className = (el.className.replace(utils.classRegex(c), ' ')).trim(); - } - if (timeout && utils.isNumeric(timeout)) { - window.setTimeout(function() { - utils._addClass(el, c); - }, timeout); - } - }, - /** - * @param {Element} element DOM node. - * @param {String} classname Classname. - * @return {Boolean} - */ - hasClass: function(element, c) { - // use native if available - return (element.classList) ? - element.classList.contains(c) : utils.classRegex(c).test(element.className); - }, - /** - * @param {Element|Array} element DOM node or array of nodes. - * @param {String} classname Classe. - */ - toggleClass: function(element, classname) { - if (Array.isArray(element)) { - element.forEach(function(each) { - utils.toggleClass(each, classname); - }); - return; - } - - // use native if available - if (element.classList) { - element.classList.toggle(classname); - } else { - if (utils.hasClass(element, classname)) { - utils._removeClass(element, classname); - } else { - utils._addClass(element, classname); - } - } - }, - $: function(id) { - id = (id[0] === '#') ? id.substr(1, id.length) : id; - return document.getElementById(id); - }, - isElement: function(obj) { - // DOM, Level2 - if ('HTMLElement' in window) { - return (!!obj && obj instanceof HTMLElement); - } - // Older browsers - return (!!obj && typeof obj === 'object' && - obj.nodeType === 1 && !!obj.nodeName); - }, - getAllChildren: function(node, tag) { - return [].slice.call(node.getElementsByTagName(tag)); - }, - isEmpty: function(str) { - return (!str || 0 === str.length); - }, - emptyArray: function(array) { - while (array.length) array.pop(); - }, - anyMatchInArray: function(source, target) { - return source.some(function(each) { - return target.indexOf(each) >= 0; - }); - }, - everyMatchInArray: function(arr1, arr2) { - return arr2.every(function(each) { - return arr1.indexOf(each) >= 0; - }); - }, - anyItemHasValue: function(obj) { - var has = false; - for (var key in obj) { - if (!utils.isEmpty(obj[key])) { - has = true; - } - } - return has; - }, - removeAllChildren: function(node) { - while (node.firstChild) { - node.removeChild(node.firstChild); - } - }, - removeAll: function(collection) { - var node; - while ((node = collection[0])) { - node.parentNode.removeChild(node); - } - }, - getChildren: function(node, tag) { - return [].filter.call(node.childNodes, function(el) { - return (tag) ? - el.nodeType == 1 && el.tagName.toLowerCase() == tag : - el.nodeType == 1; - }); - }, - template: function(html, row) { - var this_ = this; - - return html.replace(/\{ *([\w_-]+) *\}/g, function(html, key) { - var value = (row[key] === undefined) ? '' : row[key]; - return this_.htmlEscape(value); - }); - }, - htmlEscape: function(str) { - return String(str) - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); - }, - /** - * Overwrites obj1's values with obj2's and adds - * obj2's if non existent in obj1 - * @returns obj3 a new object based on obj1 and obj2 - */ - mergeOptions: function(obj1, obj2) { - var obj3 = {}; - for (var attr1 in obj1) { - obj3[attr1] = obj1[attr1]; - } - for (var attr2 in obj2) { - obj3[attr2] = obj2[attr2]; - } - return obj3; - }, - createElement: function(node, html) { - var elem; - if (Array.isArray(node)) { - elem = document.createElement(node[0]); - - if (node[1].id) { - elem.id = node[1].id; - } - if (node[1].classname) { - elem.className = node[1].classname; - } - - if (node[1].attr) { - var attr = node[1].attr; - if (Array.isArray(attr)) { - var i = -1; - while (++i < attr.length) { - elem.setAttribute(attr[i].name, attr[i].value); - } - } else { - elem.setAttribute(attr.name, attr.value); - } - } - } else { - elem = document.createElement(node); - } - elem.innerHTML = html; - var frag = document.createDocumentFragment(); - - while (elem.childNodes[0]) { - frag.appendChild(elem.childNodes[0]); - } - elem.appendChild(frag); - return elem; - }, - assert: function(condition, message) { - if (!condition) { - message = message || 'Assertion failed'; - if (typeof Error !== 'undefined') { - throw new Error(message); - } - throw message; // Fallback - } - }, - assertEqual: function(a, b, message) { - if (a != b) { - throw new Error(message + ' mismatch: ' + a + ' != ' + b); - } - } - }; - /** - * @constructor - * @extends {ol.control.Control} - * @fires {G.EventType} - * @param {string} control_type Nominatim|Reverse. - * @param {object|undefined} opt_options Options. - */ - G.Base = function(control_type, opt_options) { - utils.assert(typeof control_type === 'string', '@param `control_type`' + - ' should be string type!' - ); - utils.assert(typeof opt_options === 'object' || typeof opt_options === 'undefined', - '@param `opt_options` should be object|undefined type!' - ); - - control_type = control_type || 'nominatim'; - - G.$base = this; - G.$nominatim = new G.Nominatim(opt_options); - - ol.control.Control.call(this, { - element: G.$nominatim.container - }); - }; - ol.inherits(G.Base, ol.control.Control); - - /** - * @return {ol.source.Vector} Returns the source created by this control - */ - G.Base.prototype.getSource = function() { - return this.getLayer().getSource(); - }; - - /** - * @return {ol.layer.Vector} Returns the layer created by this control - */ - G.Base.prototype.getLayer = function() { - return G.$nominatim.layer; - }; - /** - * @constructor - */ - G.Nominatim = function(opt_options) { - this.layer_name = utils.randomId('geocoder-layer-'); - this.layer = new ol.layer.Vector({ - name: this.layer_name, - source: new ol.source.Vector() - }); - var defaults = { - provider: 'osm', - placeholder: 'Search for an address', - featureStyle: G.Nominatim.featureStyle, - lang: 'en-US', - limit: 5, - keepOpen: false, - debug: false - }; - - this.options = utils.mergeOptions(defaults, opt_options); - this.options.provider = this.options.provider.toLowerCase(); - this.constants = { - road: 'ol-geocoder-road', - city: 'ol-geocoder-city', - country: 'ol-geocoder-country', - class_container: 'ol-geocoder', - expanded_class: 'ol-geocoder-search-expanded' - }; - - this.container = this.createControl(); - this.els = G.Nominatim.elements; - this.registered_listeners = { - map_click: false - }; - this.setListeners(); - return this; - }; - - G.Nominatim.prototype = { - createControl: function() { - var container = utils.createElement([ - 'div', { - classname: this.constants.class_container - } - ], G.Nominatim.html); - - G.Nominatim.elements = { - container: container, - control: container.querySelector('.ol-geocoder-search'), - btn_search: container.querySelector('.ol-geocoder-btn-search'), - input_search: container.querySelector('.ol-geocoder-input-search'), - result_container: container.querySelector('.ol-geocoder-result') - }; - //set placeholder from options - G.Nominatim.elements.input_search.placeholder = this.options.placeholder; - - return container; - }, - setListeners: function() { - var - this_ = this, - openSearch = function() { - if (utils.hasClass(this_.els.control, this_.constants.expanded_class)) { - this_.collapse(); - } else { - this_.expand(); - } - }, - query = function(evt) { - if (evt.keyCode == 13) { //enter key - var q = utils.htmlEscape(this_.els.input_search.value); - this_.query(q); - } - }; - this_.els.input_search.addEventListener('keydown', query, false); - this_.els.btn_search.addEventListener('click', openSearch, false); - }, - listenMapClick: function() { - if (this.registered_listeners.map_click) { - // already registered - return; - } - - var this_ = this; - var map_element = G.$base.getMap().getTargetElement(); - this.registered_listeners.map_click = true; - - //one-time fire click - map_element.addEventListener('click', { - handleEvent: function(evt) { - this_.clearResults(true); - map_element.removeEventListener(evt.type, this, false); - this_.registered_listeners.map_click = false; - } - }, false); - }, - expand: function() { - utils.removeClass(this.els.input_search, 'ol-geocoder-loading'); - utils.addClass(this.els.control, this.constants.expanded_class); - var input = this.els.input_search; - window.setTimeout(function() { - input.focus(); - }, 100); - this.listenMapClick(); - }, - collapse: function() { - this.els.input_search.value = ''; - this.els.input_search.blur(); - utils.removeClass(this.els.control, this.constants.expanded_class); - this.clearResults(); - }, - clearResults: function(collapse) { - if (collapse) { - this.collapse(); - } else { - utils.removeAllChildren(this.els.result_container); - } - }, - query: function(query) { - var this_ = this, - options = this.options, - input = this.els.input_search, - providers_names = G.Nominatim.providers.names, - provider = this.getProvider({ - provider: options.provider, - key: options.key, - query: query, - lang: options.lang, - countrycodes: options.countrycodes, - limit: options.limit - }); - - this.clearResults(); - utils.addClass(input, 'ol-geocoder-loading'); - - utils.json(provider.url, provider.params).when({ - ready: function(response) { - if (options.debug) { - console.info(response); - } - - utils.removeClass(input, 'ol-geocoder-loading'); - - //will be fullfiled according to provider - var response__; - - switch (this_.options.provider) { - case providers_names.OSM: - case providers_names.MAPQUEST: - response__ = response.length > 0 ? - this_.mapquestResponse(response) : undefined; - break; - case providers_names.PELIAS: - response__ = response.features.length > 0 ? - this_.peliasResponse(response.features) : undefined; - break; - case providers_names.PHOTON: - response__ = response.features.length > 0 ? - this_.photonResponse(response.features) : undefined; - break; - case providers_names.GOOGLE: - response__ = response.results.length > 0 ? - this_.googleResponse(response.results) : undefined; - break; - } - if (response__) { - this_.createList(response__); - this_.listenMapClick(); - } - }, - error: function() { - utils.removeClass(input, 'ol-geocoder-loading'); - var li = utils.createElement('li', - '
Error! No internet connection?
'); - this_.els.result_container.appendChild(li); - } - }); - }, - createList: function(response) { - var this_ = this; - var ul = this.els.result_container; - response.forEach(function(row) { - var - address_html = this_.addressTemplate(row), - html = '' + address_html + '', - li = utils.createElement('li', html); - li.addEventListener('click', function(evt) { - evt.preventDefault(); - this_.chosen(row, address_html, row.address, row.original); - }, false); - - ul.appendChild(li); - }); - }, - addressTemplate: function(r) { - var row = r.address, - html = []; - if (row.name) { - html.push( - '{name}' - ); - } - if (row.road || row.building || row.house_number) { - html.push( - '{building} {road} {house_number}' - ); - } - if (row.city || row.town || row.village) { - html.push( - '{postcode} {city} {town} {village}' - ); - } - if (row.state || row.country) { - html.push( - '{state} {country}' - ); - } - return utils.template(html.join('
'), row); - }, - chosen: function(place, address_html, address_obj, address_original) { - if (this.options.keepOpen === false) { - this.clearResults(true); - } - - var map = G.$base.getMap(), - view = map.getView(), - projection = view.getProjection(), - coord = ol.proj.transform( - [parseFloat(place.lon), parseFloat(place.lat)], - 'EPSG:4326', projection - ), - resolution = 2.388657133911758, - duration = 500, - obj = { - coord: coord, - address_html: address_html, - address_obj: address_obj, - address_original: address_original - }, - pan = ol.animation.pan({ - duration: duration, - source: view.getCenter() - }), - zoom = ol.animation.zoom({ - duration: duration, - resolution: view.getResolution() - }); - - map.beforeRender(pan, zoom); - view.setCenter(coord); - view.setResolution(resolution); - this.createFeature(obj); - }, - createFeature: function(obj) { - var feature = new ol.Feature({ - address_html: obj.address_html, - address_obj: obj.address_obj, - address_original: obj.address_original, - geometry: new ol.geom.Point(obj.coord) - }), - feature_id = utils.randomId('geocoder-ft-'), - feature_style = this.options.featureStyle || G.Nominatim.featureStyle; - - this.addLayer(); - feature.setStyle(feature_style); - feature.setId(feature_id); - this.getSource().addFeature(feature); - G.$base.dispatchEvent({ - type: G.EventType.ADDRESSCHOSEN, - feature: feature, - coordinate: obj.coord, - }); - }, - mapquestResponse: function(results) { - var array = results.map(function(result) { - return { - lon: result.lon, - lat: result.lat, - address: { - name: result.address.neighbourhood || '', - road: result.address.road || '', - postcode: result.address.postcode, - city: result.address.city || result.address.town, - state: result.address.state, - country: result.address.country - }, - original: { - formatted: result.display_name, - details: result.address - } - }; - }); - return array; - }, - photonResponse: function(features) { - var array = features.map(function(feature) { - return { - lon: feature.geometry.coordinates[0], - lat: feature.geometry.coordinates[1], - address: { - name: feature.properties.name, - postcode: feature.properties.postcode, - city: feature.properties.city, - state: feature.properties.state, - country: feature.properties.country - }, - original: { - formatted: feature.properties.name, - details: feature.properties - } - }; - }); - return array; - }, - peliasResponse: function(features) { - var array = features.map(function(feature) { - return { - lon: feature.geometry.coordinates[0], - lat: feature.geometry.coordinates[1], - address: { - name: feature.properties.name, - house_number: feature.properties.housenumber, - postcode: feature.properties.postalcode, - road: feature.properties.street, - city: feature.properties.city, - state: feature.properties.region, - country: feature.properties.country - }, - original: { - formatted: feature.properties.label, - details: feature.properties - } - }; - }); - return array; - }, - googleResponse: function(results) { - var - name = [ - 'point_of_interest', - 'establishment', - 'natural_feature', - 'airport' - ], - road = [ - 'street_address', - 'route', - 'sublocality_level_5', - 'intersection' - ], - postcode = ['postal_code'], - city = ['locality'], - state = ['administrative_area_level_1'], - country = ['country']; - - /* - * @param {Array} details - address_components - */ - var getDetails = function(details) { - var parts = { - name: '', - road: '', - postcode: '', - city: '', - state: '', - country: '' - }; - details.forEach(function(detail) { - if (utils.anyMatchInArray(detail.types, name)) { - parts.name = detail.long_name; - } else if (utils.anyMatchInArray(detail.types, road)) { - parts.road = detail.long_name; - } else if (utils.anyMatchInArray(detail.types, postcode)) { - parts.postcode = detail.long_name; - } else if (utils.anyMatchInArray(detail.types, city)) { - parts.city = detail.long_name; - } else if (utils.anyMatchInArray(detail.types, state)) { - parts.state = detail.long_name; - } else if (utils.anyMatchInArray(detail.types, country)) { - parts.country = detail.long_name; - } - }); - return parts; - }; - - var array = []; - results.forEach(function(result) { - var details = getDetails(result.address_components); - if (utils.anyItemHasValue(details)) { - array.push({ - lon: result.geometry.location.lng, - lat: result.geometry.location.lat, - address: { - name: details.name, - postcode: details.postcode, - road: details.road, - city: details.city, - state: details.state, - country: details.country - }, - original: { - formatted: result.formatted_address, - details: result.address_components - } - }); - } - }); - return array; - }, - getSource: function() { - return this.layer.getSource(); - }, - addLayer: function() { - var this_ = this, - found = false; - var map = G.$base.getMap(); - - map.getLayers().forEach(function(layer) { - if (layer === this_.layer) found = true; - }); - if (!found) { - map.addLayer(this.layer); - } - }, - getProvider: function(options) { - var params, - provider = G.Nominatim.providers[options.provider], - providers_names = G.Nominatim.providers.names, - requires_key = [ - providers_names.MAPQUEST, - providers_names.PELIAS, - providers_names.GOOGLE - ], - langs_photon = ['de', 'it', 'fr', 'en']; - switch (options.provider) { - case providers_names.OSM: - case providers_names.MAPQUEST: - params = { - q: options.query, - limit: options.limit, - countrycodes: options.countrycodes, - 'accept-language': options.lang - }; - provider.params = utils.mergeOptions(provider.params, params); - break; - case providers_names.PHOTON: - options.lang = options.lang.toLowerCase(); - params = { - q: options.query, - limit: options.limit || provider.params.limit, - lang: (langs_photon.indexOf(options.lang) > -1) ? - options.lang : provider.params.lang - }; - provider.params = utils.mergeOptions(provider.params, params); - break; - case providers_names.GOOGLE: - params = { - address: options.query, - language: options.lang - }; - provider.params = utils.mergeOptions(provider.params, params); - break; - case providers_names.PELIAS: - params = { - text: options.query, - size: options.limit - }; - provider.params = utils.mergeOptions(provider.params, params); - break; - } - if (requires_key.indexOf(options.provider) > -1) { - provider.params.key = options.key; - } - return provider; - } - }; - G.EventType = { - /** - * Triggered when an address is chosen. - */ - ADDRESSCHOSEN: 'addresschosen' - }; - - G.Nominatim.elements = {}; - G.Nominatim.providers = { - names: { - OSM: 'osm', - MAPQUEST: 'mapquest', - GOOGLE: 'google', - PHOTON: 'photon', - PELIAS: 'pelias' - }, - osm: { - url: 'http://nominatim.openstreetmap.org/search/', - params: { - format: 'json', - q: '', - addressdetails: 1, - limit: 10, - countrycodes: '', - 'accept-language': 'en-US' - } - }, - mapquest: { - url: 'http://open.mapquestapi.com/nominatim/v1/search.php', - params: { - key: '', - format: 'json', - q: '', - addressdetails: 1, - limit: 10, - countrycodes: '', - 'accept-language': 'en-US' - } - }, - google: { - url: 'https://maps.googleapis.com/maps/api/geocode/json', - params: { - key: '', - address: '', - language: 'en-US' - } - }, - pelias: { - url: 'https://search.mapzen.com/v1/search', - params: { - key: '', - text: '', - size: 10 - } - }, - photon: { - url: 'http://photon.komoot.de/api/', - params: { - q: '', - limit: 10, - lang: 'en' - } - } - }; - G.Nominatim.featureStyle = [ - new ol.style.Style({ - image: new ol.style.Icon({ - scale: 0.7, - anchor: [0.5, 1], - src: '//cdn.rawgit.com/jonataswalker/' + 'map-utils/master/images/marker.png' - }), - zIndex: 5 - }), - new ol.style.Style({ - image: new ol.style.Circle({ - fill: new ol.style.Fill({ - color: [235, 235, 235, 1] - }), - stroke: new ol.style.Stroke({ - color: [0, 0, 0, 1] - }), - radius: 5 - }), - zIndex: 4 - }) - ]; - G.Nominatim.html = [ - '', - '
    ' - ].join(''); - return G.Base; +/** + * A geocoder extension for OpenLayers 3. + * https://github.com/jonataswalker/ol3-geocoder + * Version: v2.0.0 + * Built: 2016-04-22T16:55:20-0300 + */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.Geocoder = factory()); +}(this, function () { 'use strict'; + + var namespace = "ol3-geocoder"; + var container_class = "-container"; + var control_class = "-search"; + var btn_search_class = "-btn-search"; + var loading_class = "-loading"; + var input_search_class = "-input-search"; + var result_class = "-result"; + var expanded_class = "-search-expanded"; + var country_class = "-country"; + var city_class = "-city"; + var road_class = "-road"; + var OL3_control_class = "ol-control"; + + var eventType = { + ADDRESSCHOSEN: 'addresschosen' + }; + + var featureStyle = [ + new ol.style.Style({ + image: new ol.style.Icon({ + anchor: [0.5, 1], + src: [ + 'data:image/png;base64,', + 'iVBORw0KGgoAAAANSUhEUgAAAC0AAAAtCAYAAAA6GuKaAAAABmJLR0QA/wD/AP+gvaeT', + 'AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AQWCiErd9Z21AAABAJJREFUWMPVm', + 'U1oXFUUx3/3zatJx04SDOgiVUMSgrXJwpqIKy26SrKoLjQgCkIFW7otuCvdllbo1q6Epg', + 'vNQvtx710lEFdihwpSjdikJLGJWEhrM9MyX7nPxbypwzBv5n3cqXpgmOHOuff/mzPn3Pf', + 'ueWDBpqZnrPq1M5EUVitZ+9wPvA0cAgaALqAIbAI3gAWt5HbjvCcGXROdmp4RwDDwBfBW', + 'iKmLwKfAqlbSiwvvJAAeAeaBWyGB8f1uAfNT0zMj/jqdjXQd8Ds+sJsguyrAe1rJb6NGX', + 'MQAPgJ8k7QefPOAd7WSl6OAi4jAk8D3cdKqhRngda3k9bDgUSL9NLAO9GPftoEXtZIPrR', + 'WiXyzHwwAbA8WyoFAUFMsCY0JB9wPHwxalGyH3T4RxHByo8MZEgf4+w/ZfDt9lu9n4I5T', + 'MCeBzP8+tQL8KDAZuA7swOljh4yM5JsaKGAPGA0fABzN5sje7+PJyht/WXNxU8O/1dbK2', + '9ulPWn05tL/CqWP3GR8tUSgKSmVBpVJ9LxQF46MlTh27z9D+SiKdqNCBFw/jwexUnr4eg', + 'xfwx3oe9PUYZqfyGC+eThzo4SCYTNpweLLQtuCMgcOTBTLp4B8XpBMXuqnfroGxkTIi5M', + 'YpRNV/1yTjCQv9oHmkBXu7vRD1/s/1b2+3h+eJSDpxoa83G0w5HisbLqRCrpKClQ2XlON', + 'F0okL/XXTyQ6sbe1h/Y7bNkWEgPU7Lmtbe3CcaDpxoS8CuaYbfcpj7mqmVXE9Ltq5qxnc', + 'VKBjztexBl0Azgd9uZTt4spimlJZkHKqUa29Ug6UyoIri2mWsl2tNM77OlZvmIaBn4B00', + '6tiRfDSUIk3JwocerlIzz7DTt7hxi9dLGW7+fX2U7huYJQfAeNayduduDX9Cni/3X5sPI', + 'HnVSPtCK9VDj/OZa3krPVbUx++J+y2FNF6tZI71s+IfhR2gNOWgU9rJXeinBUjnxGBF4A', + 'fgWcsAN8DXgE2OnJGbIC/CHxoAXpOK/lRx1sIvn1mKTVirRO377EFnE0IfFYrudXxvkdD', + 'bvcCvwOZGEvkgOeBB0+kwwTU9tIccClmlC8Bubj9vKQNyAPAzxHX8YCDWsnluLpOAmB84', + 'fmIU+e1kstJ2r42OkVH/S5R2G7S0aSCsaFrHU+tZB44F3LaOa1k/l/pTzfZSQ4APwD7Wr', + 'jmgdeA5STAttKjltsLbdwWkhSf1UjXRfxZ4M8WLs9pJe/a0HIsAeMDnQlwOaOVvPufeFD', + 'UJLcH/H27t6EtcBDYTJrLViNdl9ubwLWG4Wv+uDUTWDb/LLlSNzSilVy1qeFYBsYHvOAP', + 'XdBKrtrK5Y5A19lJqo8kTnZi8U6kRy0YY8BNwNgqwP+1/Q09w5giQWRk7AAAAABJRU5Er', + 'kJggg==' + ].join('') + }) + }) + ]; + + var providers = { + OSM: 'osm', + MAPQUEST: 'mapquest', + GOOGLE: 'google', + PHOTON: 'photon', + PELIAS: 'pelias' + }; + + var defaultOptions = { + provider: providers.OSM, + placeholder: 'Search for an address', + featureStyle: featureStyle, + lang: 'en-US', + limit: 5, + keepOpen: false, + debug: false + }; + + /** + * @module utils + * All the helper functions needed in this project + */ + var utils = { + toQueryString: function toQueryString(obj) { + var this$1 = this; + + return Object.keys(obj).reduce(function (a, k) { + a.push( + typeof obj[k] === 'object' ? + this$1.toQueryString(obj[k]) : + encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]) + ); + return a; + }, []).join('&'); + }, + encodeUrlXhr: function encodeUrlXhr(url, data) { + if(data && typeof(data) === 'object') { + var str_data = this.toQueryString(data); + url += (/\?/.test(url) ? '&' : '?') + str_data; + } + return url; + }, + json: function json(url, data) { + var xhr = new XMLHttpRequest(), + when = {}, + onload = function () { + if (xhr.status === 200) { + when.ready.call(undefined, JSON.parse(xhr.response)); + } + }, + onerror = function () { + console.info('Cannot XHR ' + JSON.stringify(url)); + }; + url = this.encodeUrlXhr(url, data); + xhr.open('GET', url, true); + xhr.setRequestHeader('Accept','application/json'); + xhr.onload = onload; + xhr.onerror = onerror; + xhr.send(null); + + return { + when: function ( obj ) { when.ready = obj.ready; } + }; + }, + randomId: function randomId(prefix) { + var id = window.performance.now().toString(36); + return prefix ? prefix + id : id; + }, + to3857: function to3857(coord) { + return ol.proj.transform( + [parseFloat(coord[0]), parseFloat(coord[1])], + 'EPSG:4326', 'EPSG:3857' + ); + }, + to4326: function to4326(coord) { + return ol.proj.transform( + [parseFloat(coord[0]), parseFloat(coord[1])], + 'EPSG:3857', 'EPSG:4326' + ); + }, + isNumeric: function isNumeric(str) { + return /^\d+$/.test(str); + }, + classRegex: function classRegex(classname) { + return new RegExp(("(^|\\s+) " + classname + " (\\s+|$)")); + }, + /** + * @param {Element|Array} element DOM node or array of nodes. + * @param {String|Array} classname Class or array of classes. + * For example: 'class1 class2' or ['class1', 'class2'] + * @param {Number|undefined} timeout Timeout to remove a class. + */ + addClass: function addClass(element, classname, timeout) { + var this$1 = this; + + if (Array.isArray(element)) { + element.forEach(function ( each ) { this$1.addClass(each, classname) }); + return; + } + + var array = (Array.isArray(classname)) ? classname : classname.split(/\s+/); + var i = array.length; + + while(i--) { + if (!this$1.hasClass(element, array[i])) { + this$1._addClass(element, array[i], timeout); + } + } + }, + _addClass: function _addClass(el, c, timeout) { + // use native if available + var this$1 = this; + + if (el.classList) { + el.classList.add(c); + } else { + el.className = (el.className +' '+ c).trim(); + } + + if (timeout && this.isNumeric(timeout)) { + window.setTimeout(function () { this$1._removeClass(el, c) }, timeout); + } + }, + /** + * @param {Element|Array} element DOM node or array of nodes. + * @param {String|Array} classname Class or array of classes. + * For example: 'class1 class2' or ['class1', 'class2'] + * @param {Number|undefined} timeout Timeout to add a class. + */ + removeClass: function removeClass(element, classname, timeout) { + var this$1 = this; + + if (Array.isArray(element)) { + element.forEach(function ( each ) { this$1.removeClass(each, classname, timeout) }); + return; + } + + var array = (Array.isArray(classname)) ? classname : classname.split(/\s+/); + var i = array.length; + + while(i--) { + if (this$1.hasClass(element, array[i])) { + this$1._removeClass(element, array[i], timeout); + } + } + }, + _removeClass: function _removeClass(el, c, timeout) { + var this$1 = this; + + if (el.classList) { + el.classList.remove(c); + } else { + el.className = (el.className.replace(this.classRegex(c), ' ')).trim(); + } + if (timeout && this.isNumeric(timeout)) { + window.setTimeout(function () { + this$1._addClass(el, c); + }, timeout); + } + }, + /** + * @param {Element} element DOM node. + * @param {String} classname Classname. + * @return {Boolean} + */ + hasClass: function hasClass(element, c) { + // use native if available + return (element.classList) ? + element.classList.contains(c) : this.classRegex(c).test(element.className); + }, + /** + * @param {Element|Array} element DOM node or array of nodes. + * @param {String} classname Classe. + */ + toggleClass: function toggleClass(element, classname) { + var this$1 = this; + + if (Array.isArray(element)) { + element.forEach(function ( each ) { this$1.toggleClass(each, classname) }); + return; + } + + // use native if available + if (element.classList) { + element.classList.toggle(classname); + } else { + if (this.hasClass(element, classname)) { + this._removeClass(element, classname); + } else { + this._addClass(element, classname); + } + } + }, + $: function $(id) { + id = (id[0] === '#') ? id.substr(1, id.length) : id; + return document.getElementById(id); + }, + isElement: function isElement(obj) { + // DOM, Level2 + if ('HTMLElement' in window) { + return (!!obj && obj instanceof HTMLElement); + } + // Older browsers + return (!!obj && typeof obj === 'object' && + obj.nodeType === 1 && !!obj.nodeName); + }, + getAllChildren: function getAllChildren(node, tag) { + return [].slice.call(node.getElementsByTagName(tag)); + }, + isEmpty: function isEmpty(str) { + return (!str || 0 === str.length); + }, + emptyArray: function emptyArray(array) { + while(array.length) array.pop(); + }, + anyMatchInArray: function anyMatchInArray(source, target) { + return source.some(function ( each ) { return target.indexOf(each) >= 0; }); + }, + everyMatchInArray: function everyMatchInArray(arr1, arr2) { + return arr2.every(function ( each ) { return arr1.indexOf(each) >= 0; }); + }, + anyItemHasValue: function anyItemHasValue(obj, has) { + if ( has === void 0 ) has = false; + + for(var key in obj) { + if(!this.isEmpty(obj[key])) { + has = true; + } + } + return has; + }, + removeAllChildren: function removeAllChildren(node) { + while (node.firstChild) { + node.removeChild(node.firstChild); + } + }, + removeAll: function removeAll(collection) { + var node; + while ((node = collection[0])) { + node.parentNode.removeChild(node); + } + }, + getChildren: function getChildren(node, tag) { + return [].filter.call(node.childNodes, function ( el ) { return tag ? + el.nodeType == 1 && el.tagName.toLowerCase() == tag : el.nodeType == 1; }); + }, + template: function template(html, row) { + var this$1 = this; + + return html.replace(/\{ *([\w_-]+) *\}/g, function (html, key) { + var value = (row[key] === undefined) ? '' : row[key]; + return this$1.htmlEscape(value); + }); + }, + htmlEscape: function htmlEscape(str) { + return String(str) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + }, + /** + * Overwrites obj1's values with obj2's and adds + * obj2's if non existent in obj1 + * @returns obj3 a new object based on obj1 and obj2 + */ + mergeOptions: function(obj1, obj2){ + var obj3 = {}; + for (var attr1 in obj1) { obj3[attr1] = obj1[attr1]; } + for (var attr2 in obj2) { obj3[attr2] = obj2[attr2]; } + return obj3; + }, + createElement: function createElement(node, html) { + var elem; + if (Array.isArray(node)) { + elem = document.createElement(node[0]); + + if (node[1].id) elem.id = node[1].id; + if (node[1].classname) elem.className = node[1].classname; + + if (node[1].attr) { + var attr = node[1].attr; + if (Array.isArray(attr)) { + var i = -1; + while(++i < attr.length) { + elem.setAttribute(attr[i].name, attr[i].value); + } + } else { + elem.setAttribute(attr.name, attr.value); + } + } + } else { + elem = document.createElement(node); + } + elem.innerHTML = html; + var frag = document.createDocumentFragment(); + + while (elem.childNodes[0]) { + frag.appendChild(elem.childNodes[0]); + } + elem.appendChild(frag); + return elem; + }, + assert: function assert(condition, message) { + if ( message === void 0 ) message = 'Assertion failed'; + + if (!condition) { + if (typeof Error !== 'undefined') { + throw new Error(message); + } + throw message; // Fallback + } + } + }; + + /** + * @class Photon + */ + var Photon = function Photon() { + + this.settings = { + url: 'http://photon.komoot.de/api/', + params: { + q: '', + limit: 10, + lang: 'en' + }, + langs: ['de', 'it', 'fr', 'en'] + }; + + }; + + Photon.prototype.getParameters = function getParameters(options) { + options.lang = options.lang.toLowerCase(); + + return { + url: this.settings.url, + params: { + q: options.query, + limit: options.limit || this.settings.params.limit, + lang: this.settings.langs.indexOf(options.lang) > -1 ? + options.lang : this.settings.params.lang + } + }; + }; + + Photon.prototype.handleResponse = function handleResponse(results) { + return results.map(function ( result ) { return ({ + lon: result.geometry.coordinates[0], + lat: result.geometry.coordinates[1], + address: { + name: result.properties.name, + postcode: result.properties.postcode, + city: result.properties.city, + state: result.properties.state, + country: result.properties.country + }, + original: { + formatted: result.properties.name, + details: result.properties + } + }); }); + }; + + /** + * @class OpenStreet + */ + var OpenStreet = function OpenStreet() { + + this.settings = { + url: 'http://nominatim.openstreetmap.org/search/', + params: { + q: '', + format: 'json', + addressdetails: 1, + limit: 10, + countrycodes: '', + 'accept-language': 'en-US' + } + }; + }; + + OpenStreet.prototype.getParameters = function getParameters(options) { + return { + url: this.settings.url, + params: { + q: options.query, + format: 'json', + addressdetails: 1, + limit: options.limit || this.settings.params.limit, + countrycodes: options.countrycodes || this.settings.params.countrycodes, + 'accept-language': options.lang || this.settings.params['accept-language'] + } + }; + }; + + OpenStreet.prototype.handleResponse = function handleResponse(results) { + return results.map(function ( result ) { return ({ + lon: result.lon, + lat: result.lat, + address: { + name: result.address.neighbourhood || '', + road: result.address.road || '', + postcode: result.address.postcode, + city: result.address.city || result.address.town, + state: result.address.state, + country: result.address.country + }, + original: { + formatted: result.display_name, + details: result.address + } + }); }); + }; + + /** + * @class MapQuest + */ + var MapQuest = function MapQuest() { + + this.settings = { + url: 'http://open.mapquestapi.com/nominatim/v1/search.php', + params: { + q: '', + key: '', + format: 'json', + addressdetails: 1, + limit: 10, + countrycodes: '', + 'accept-language': 'en-US' + } + }; + }; + + MapQuest.prototype.getParameters = function getParameters(options) { + return { + url: this.settings.url, + params: { + q: options.query, + key: options.key, + format: 'json', + addressdetails: 1, + limit: options.limit || this.settings.params.limit, + countrycodes: options.countrycodes || this.settings.params.countrycodes, + 'accept-language': options.lang || this.settings.params['accept-language'] + } + }; + }; + + MapQuest.prototype.handleResponse = function handleResponse(results) { + return results.map(function ( result ) { return ({ + lon: result.lon, + lat: result.lat, + address: { + name: result.address.neighbourhood || '', + road: result.address.road || '', + postcode: result.address.postcode, + city: result.address.city || result.address.town, + state: result.address.state, + country: result.address.country + }, + original: { + formatted: result.display_name, + details: result.address + } + }); }); + }; + + /** + * @class Pelias + */ + var Pelias = function Pelias() { + + this.settings = { + url: 'https://search.mapzen.com/v1/search', + params: { + text: '', + key: '', + size: 10 + } + }; + }; + + Pelias.prototype.getParameters = function getParameters(options) { + return { + url: this.settings.url, + params: { + text: options.query, + key: options.key, + size: options.limit || this.settings.params.size + } + }; + }; + + Pelias.prototype.handleResponse = function handleResponse(results) { + return results.map(function ( result ) { return ({ + lon: result.geometry.coordinates[0], + lat: result.geometry.coordinates[1], + address: { + name: result.properties.name, + house_number: result.properties.housenumber, + postcode: result.properties.postalcode, + road: result.properties.street, + city: result.properties.city, + state: result.properties.region, + country: result.properties.country + }, + original: { + formatted: result.properties.label, + details: result.properties + } + }); }); + }; + + /** + * @class Google + */ + var Google = function Google() { + + this.settings = { + url: 'https://maps.googleapis.com/maps/api/geocode/json', + params: { + address: '', + key: '', + language: 'en-US' + } + }; + }; + + Google.prototype.getParameters = function getParameters(options) { + return { + url: this.settings.url, + params: { + address: options.query, + key: options.key, + language: options.lang || this.settings.params.language + } + }; + }; + + Google.prototype.handleResponse = function handleResponse(results) { + var name = [ + 'point_of_interest', + 'establishment', + 'natural_feature', + 'airport' + ], + road = [ + 'street_address', + 'route', + 'sublocality_level_5', + 'intersection' + ], + postcode = [ 'postal_code' ], + city = [ 'locality' ], + state = [ 'administrative_area_level_1' ], + country = [ 'country' ]; + + /* + * @param {Array} details - address_components + */ + var getDetails = function ( details ) { + var parts = { + name: '', + road: '', + postcode: '', + city: '', + state: '', + country: '' + }; + details.forEach(function ( detail ) { + if(utils.anyMatchInArray(detail.types, name)){ + parts.name = detail.long_name; + } else if(utils.anyMatchInArray(detail.types, road)){ + parts.road = detail.long_name; + } else if(utils.anyMatchInArray(detail.types, postcode)){ + parts.postcode = detail.long_name; + } else if(utils.anyMatchInArray(detail.types, city)){ + parts.city = detail.long_name; + } else if(utils.anyMatchInArray(detail.types, state)){ + parts.state = detail.long_name; + } else if(utils.anyMatchInArray(detail.types, country)){ + parts.country = detail.long_name; + } + }); + return parts; + }; + + var array = []; + + results.forEach(function ( result ) { + var details = getDetails(result.address_components); + if(utils.anyItemHasValue(details)){ + array.push({ + lon: result.geometry.location.lng, + lat: result.geometry.location.lat, + address: { + name: details.name, + postcode: details.postcode, + road: details.road, + city: details.city, + state: details.state, + country: details.country + }, + original: { + formatted: result.formatted_address, + details: result.address_components + } + }); + } + }); + + return array; + }; + + /** + * @class Nominatim + */ + var Nominatim = function Nominatim(base) { + this.Base = base; + + this.layer_name = utils.randomId('geocoder-layer-'); + this.layer = new ol.layer.Vector({ + name: this.layer_name, + source: new ol.source.Vector() + }); + + this.options = base.options; + this.options.provider = this.options.provider.toLowerCase(); + + this.els = this.createControl(); + this.container = this.els.container; + this.registered_listeners = { + map_click: false + }; + this.setListeners(); + + // providers + this.Photon = new Photon(); + this.OpenStreet = new OpenStreet(); + this.MapQuest = new MapQuest(); + this.Pelias = new Pelias(); + this.Google = new Google(); + + return this; + }; + + Nominatim.prototype.createControl = function createControl() { + var container = utils.createElement([ + 'div', { classname: namespace + container_class } + ], Nominatim.html); + + var elements = { + container: container, + control: + container.querySelector(("." + (namespace + control_class))), + btn_search: + container.querySelector(("." + (namespace + btn_search_class))), + input_search: + container.querySelector(("." + (namespace + input_search_class))), + result_container: + container.querySelector(("." + (namespace + result_class))) + }; + //set placeholder from options + elements.input_search.placeholder = this.options.placeholder; + return elements; + }; + + Nominatim.prototype.setListeners = function setListeners() { + var this$1 = this; + + var openSearch = function () { + if(utils.hasClass(this$1.els.control, namespace + expanded_class)) { + this$1.collapse(); + } else { + this$1.expand(); + } + }, + query = function ( evt ) { + if (evt.keyCode == 13) { //enter key + var q = utils.htmlEscape(this$1.els.input_search.value); + this$1.query(q); + } + }; + this.els.input_search.addEventListener('keydown', query, false); + this.els.btn_search.addEventListener('click', openSearch, false); + }; + + Nominatim.prototype.query = function query(q) { + var this$1 = this; + + var this_ = this, + options = this.options, + input = this.els.input_search, + provider = this.getProvider({ + query: q, + provider: options.provider, + key: options.key, + lang: options.lang, + countrycodes: options.countrycodes, + limit: options.limit + }); + + this.clearResults(); + utils.addClass(input, namespace + loading_class); + + utils.json(provider.url, provider.params).when({ + ready: function ( response ) { + if (options.debug) { + console.info(response); + } + + utils.removeClass(input, namespace + loading_class); + + //will be fullfiled according to provider + var response__; + + switch (options.provider) { + case providers.OSM: + response__ = response.length > 0 ? + this$1.OpenStreet.handleResponse(response) : undefined; + break; + case providers.MAPQUEST: + response__ = response.length > 0 ? + this$1.MapQuest.handleResponse(response) : undefined; + break; + case providers.PELIAS: + response__ = response.features.length > 0 ? + this$1.Pelias.handleResponse(response.features) : undefined; + break; + case providers.PHOTON: + response__ = response.features.length > 0 ? + this$1.Photon.handleResponse(response.features) : undefined; + break; + case providers.GOOGLE: + response__ = response.results.length > 0 ? + this$1.Google.handleResponse(response.results) : undefined; + break; + } + if(response__){ + this$1.createList(response__); + this$1.listenMapClick(); + } + }, + error: function () { + utils.removeClass(input, namespace + loading_class); + var li = utils.createElement('li', + '
    Error! No internet connection?
    '); + this$1.els.result_container.appendChild(li); + } + }); + }; + + Nominatim.prototype.createList = function createList(response) { + var this$1 = this; + + var ul = this.els.result_container; + response.forEach(function ( row ) { + var address_html = this$1.addressTemplate(row.address), + html = '' + address_html + '', + li = utils.createElement('li', html); + + li.addEventListener('click', function ( evt ) { + evt.preventDefault(); + this$1.chosen(row, address_html, row.address, row.original); + }, false); + + ul.appendChild(li); + }); + }; + + Nominatim.prototype.chosen = function chosen(place, address_html, address_obj, address_original) { + if(this.options.keepOpen === false){ + this.clearResults(true); + } + + var map = this.Base.getMap(), + view = map.getView(), + projection = view.getProjection(), + coord = ol.proj.transform( + [parseFloat(place.lon), parseFloat(place.lat)], + 'EPSG:4326', projection + ), + resolution = 2.388657133911758, duration = 500, + obj = { + coord: coord, + address_html: address_html, + address_obj: address_obj, + address_original: address_original + }, + pan = ol.animation.pan({ + duration: duration, + source: view.getCenter() + }), + zoom = ol.animation.zoom({ + duration: duration, + resolution: view.getResolution() + }); + + map.beforeRender(pan, zoom); + view.setCenter(coord); + view.setResolution(resolution); + this.createFeature(obj); + }; + + Nominatim.prototype.createFeature = function createFeature(obj) { + var feature = new ol.Feature({ + address_html: obj.address_html, + address_obj: obj.address_obj, + address_original: obj.address_original, + geometry: new ol.geom.Point(obj.coord) + }); + + this.addLayer(); + feature.setStyle(this.options.featureStyle); + feature.setId(utils.randomId('geocoder-ft-')); + this.getSource().addFeature(feature); + this.Base.dispatchEvent({ + type: eventType.ADDRESSCHOSEN, + feature: feature, + coordinate: obj.coord, + }); + }; + + Nominatim.prototype.addressTemplate = function addressTemplate(address) { + var html = []; + if (address.name) { + html.push( + '{name}' + ); + } + if (address.road || address.building || address.house_number) { + html.push( + '{building} {road} {house_number}' + ); + } + if (address.city || address.town || address.village) { + html.push( + '{postcode} {city} {town} {village}' + ); + } + if (address.state || address.country) { + html.push( + '{state} {country}' + ); + } + return utils.template(html.join('
    '), address); + }; + + Nominatim.prototype.getProvider = function getProvider(options) { + var provider; + + switch(options.provider) { + case providers.OSM: + provider = this.OpenStreet.getParameters(options); + break; + case providers.MAPQUEST: + provider = this.MapQuest.getParameters(options); + break; + case providers.PHOTON: + provider = this.Photon.getParameters(options); + break; + case providers.GOOGLE: + provider = this.Google.getParameters(options); + break; + case providers.PELIAS: + provider = this.Pelias.getParameters(options); + break; + } + return provider; + }; + + Nominatim.prototype.expand = function expand() { + var this$1 = this; + + utils.removeClass(this.els.input_search, namespace + loading_class); + utils.addClass(this.els.control, namespace + expanded_class); + window.setTimeout(function () { + this$1.els.input_search.focus(); + }, 100); + this.listenMapClick(); + }; + + Nominatim.prototype.collapse = function collapse() { + this.els.input_search.value = ''; + this.els.input_search.blur(); + utils.removeClass(this.els.control, namespace + expanded_class); + this.clearResults(); + }; + + Nominatim.prototype.listenMapClick = function listenMapClick() { + if(this.registered_listeners.map_click) { + // already registered + return; + } + + var this_ = this; + var map_element = this.Base.getMap().getTargetElement(); + this.registered_listeners.map_click = true; + + //one-time fire click + map_element.addEventListener('click', { + handleEvent: function (evt) { + this_.clearResults(true); + map_element.removeEventListener(evt.type, this, false); + this_.registered_listeners.map_click = false; + } + }, false); + }; + + Nominatim.prototype.clearResults = function clearResults(collapse) { + if(collapse) { + this.collapse(); + } else { + utils.removeAllChildren(this.els.result_container); + } + }; + + Nominatim.prototype.getSource = function getSource() { + return this.layer.getSource(); + }; + + Nominatim.prototype.addLayer = function addLayer() { + var this$1 = this; + + var found = false; + var map = this.Base.getMap(); + + map.getLayers().forEach(function ( layer ) { + if (layer === this$1.layer) found = true; + }); + if (!found) { + map.addLayer(this.layer); + } + }; + + Nominatim.html = [ + ("
    "), + (""), + '"), + '
    ', + ("
      ") + ].join(''); + + /** + * @class Base + * @extends {ol.control.Control} + */ + var Base = function Base(control_type, opt_options) { + if ( control_type === void 0 ) control_type = 'nominatim'; + if ( opt_options === void 0 ) opt_options = {}; + + utils.assert(typeof control_type == 'string', + '@param `control_type` should be string type!' + ); + utils.assert(typeof opt_options == 'object', + '@param `opt_options` should be object type!' + ); + + this.options = utils.mergeOptions(defaultOptions, opt_options); + + Base.Nominatim = new Nominatim(this); + + ol.control.Control.call(this, { + element: Base.Nominatim.container + }); + }; + + /** + * @return {ol.layer.Vector} Returns the layer created by this control + */ + Base.prototype.getLayer = function getLayer() { + return Base.Nominatim.layer; + }; + + /** + * @return {ol.source.Vector} Returns the source created by this control + */ + Base.prototype.getSource = function getSource() { + return this.getLayer().getSource(); + }; + + ol.inherits(Base, ol.control.Control); + + return Base; + })); \ No newline at end of file diff --git a/build/ol3-geocoder.css b/build/ol3-geocoder.css index 6ca6e3f..c91159f 100644 --- a/build/ol3-geocoder.css +++ b/build/ol3-geocoder.css @@ -1,103 +1,104 @@ -.ol-geocoder { - position: absolute; - top: calc(.5em + 65px); - left: .5em; - box-sizing: border-box; -} -.ol-geocoder *, -.ol-geocoder *::before, -.ol-geocoder *::after { - box-sizing: inherit; -} -.ol-geocoder-search { - width: 31px; - height: 31px; - overflow: hidden; - -webkit-transition: width .2s, height .2s; - transition: width .2s, height .2s; -} -.ol-geocoder-search-expanded { - width: 220px; - height: 35px; -} -.ol-geocoder-input-search{ - position: absolute; - top: 2px; left: 32px; - width: 180px; - padding: 5px; - border: 1px solid #ccc; - font-family:inherit; - font-size: 14px; -} -.ol-geocoder-input-search:focus { - border-color: #35b5f4; -} -ul.ol-geocoder-result { - position: absolute; - top: 37px; left: 32px; - width: 260px; - max-height: 300px; - white-space: normal; - list-style: none; - padding: 0; - margin: 0; - border-top: none; - - background-color: white; - box-shadow: 0 1px 7px rgba(0, 0, 0, 0.8); - border-radius: 4px; - border-top-left-radius: 0; - border-top-right-radius: 0; - line-height: 1.2; - overflow-x: hidden; - overflow-y: auto; - - -webkit-transition: height 300ms ease-in; - - transition: height 300ms ease-in; -} -ul.ol-geocoder-result li { +/** + * A geocoder extension for OpenLayers 3. + * https://github.com/jonataswalker/ol3-geocoder + * Version: v2.0.0 + * Built: 2016-04-22T16:55:20-0300 + */ + +.ol3-geocoder-container { + position: absolute; + top: calc(.5em + 65px); + left: .5em; + box-sizing: border-box; } + .ol3-geocoder-container *, + .ol3-geocoder-container *::before, + .ol3-geocoder-container *::after { + box-sizing: inherit; } + +.ol3-geocoder-search { + width: 31px; + height: 31px; + overflow: hidden; + -webkit-transition: width 200ms, height 200ms; + transition: width 200ms, height 200ms; } + +.ol3-geocoder-search-expanded { + width: 220px; + height: 35px; } + +.ol3-geocoder-input-search { + position: absolute; + top: 2px; + left: 32px; + width: 180px; + padding: 5px; + border: 1px solid #ccc; + font-family: inherit; + font-size: 0.875rem; } + .ol3-geocoder-input-search:focus { + border-color: #35b5f4; } + +ul.ol3-geocoder-result { + position: absolute; + top: 37px; + left: 32px; + width: 260px; + max-height: 300px; + white-space: normal; + list-style: none; + padding: 0; + margin: 0; + background-color: white; + border-radius: 4px; + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; + overflow-x: hidden; + overflow-y: auto; + box-shadow: 0 1px 7px rgba(0, 0, 0, 0.8); + -webkit-transition: max-height 300ms ease-in; + transition: max-height 300ms ease-in; } + ul.ol3-geocoder-result > li { width: 100%; overflow: hidden; border-bottom: 1px solid #eee; padding: 0; -} -ul.ol-geocoder-result li:nth-child(odd) { - background-color: rgb(224, 255, 224); -} -ul.ol-geocoder-result li a { - display: block; - text-decoration: none; - padding: 3px 5px; -} -ul.ol-geocoder-result li a:hover { - background-color: rgb(212, 212, 212); -} -.ol-geocoder-road{ - font-size: 14px; - font-weight: bold; - color: #000; -} -.ol-geocoder-city{ - font-size: 12px; - font-weight: normal; - color: #000; -} -.ol-geocoder-country{ - font-size: 12px; - font-weight: lighter; - color: #444; -} -.ol-geocoder-btn-search{ - position: absolute; - width: 25px; height: 25px; - top: 2px; left: 2px; - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAABPUlEQVQoU41SwXHCQAzUHh58eoUOIBWEDkI6oAToIKkg7iAuwakgpAIowXRACcnrzp6BzchjMx4wE/S6kW5XK60gvQghzJIkmVoqSZI9gJ9+/fINS5Cc1HX9QXIlIr/tpwcRyb33b7cIGnAIYQdg4pxbjcfj0nJ1Xc+Px+PGObdN03Q9RIAQwgpAnqbp7FKmjQGgJLlU1d2V7BjjRkQO3vvXIXarkyxVNbsCm2QR2Q0V7XOMMReRmfd+OQQubN6hYgs22ZtbnRcAtiRfLueqqmpJ8ovko6oeBq0KIWQA3gFkzrlmMafTaUEyI/mpqmbhVTRWWbRdbClPbeobQNES5KPRqOxs7DBn8K1DsAOKMZYApiTXqlrcDe4d0XN7jWeCfzt351tVle2iGalTcBd4gGDvvZ/fDe4RmCOFLe8Pr7mvEP2N9PQAAAAASUVORK5CYII='); - background-repeat: no-repeat; - background-position: center center; -} -.ol-geocoder-loading { - background-image: url('data:image/gif;base64,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'); - background-repeat: no-repeat; - background-position: right center; -} \ No newline at end of file + line-height: 0.875rem; } + ul.ol3-geocoder-result > li > a { + display: block; + text-decoration: none; + padding: 3px 5px; } + ul.ol3-geocoder-result > li > a:hover { + background-color: #d4d4d4; } + ul.ol3-geocoder-result > li:nth-child(odd) { + background-color: #e0ffe0; } + +.ol3-geocoder-road { + font-size: 0.875rem; + font-weight: 700; + color: #000; } + +.ol3-geocoder-city { + font-size: 0.75rem; + font-weight: normal; + color: #000; } + +.ol3-geocoder-country { + font-size: 0.75rem; + font-weight: lighter; + color: #444; } + +.ol3-geocoder-btn-search { + position: absolute; + width: 25px; + height: 25px; + top: 2px; + left: 2px; + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAABPUlEQVQoU41SwXHCQAzUHh58eoUOIBWEDkI6oAToIKkg7iAuwakgpAIowXRACcnrzp6BzchjMx4wE/S6kW5XK60gvQghzJIkmVoqSZI9gJ9+/fINS5Cc1HX9QXIlIr/tpwcRyb33b7cIGnAIYQdg4pxbjcfj0nJ1Xc+Px+PGObdN03Q9RIAQwgpAnqbp7FKmjQGgJLlU1d2V7BjjRkQO3vvXIXarkyxVNbsCm2QR2Q0V7XOMMReRmfd+OQQubN6hYgs22ZtbnRcAtiRfLueqqmpJ8ovko6oeBq0KIWQA3gFkzrlmMafTaUEyI/mpqmbhVTRWWbRdbClPbeobQNES5KPRqOxs7DBn8K1DsAOKMZYApiTXqlrcDe4d0XN7jWeCfzt351tVle2iGalTcBd4gGDvvZ/fDe4RmCOFLe8Pr7mvEP2N9PQAAAAASUVORK5CYII="); + background-repeat: no-repeat; + background-position: center center; } + +.ol3-geocoder-loading { + background-image: url("data:image/gif;base64,R0lGODlhFAAUAKUAAAQCBISChMTCxERCRKSipOTi5GRiZJSSlNTS1LSytPTy9CQiJHRydExOTIyKjMzKzKyqrOzq7JyanNza3Ly6vPz6/CwuLHx6fBwaHExKTGxubFRWVAQGBISGhMTGxERGRKSmpOTm5GRmZJSWlNTW1LS2tPT29CQmJHR2dFRSVIyOjMzOzKyurOzu7JyenNze3Ly+vPz+/DQyNHx+fP7+/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCQA0ACwAAAAAFAAUAAAG80CaUKgw0RAAAIJWqQyftBjEAqIpOBwF7UUpxKBMDSbjPC2EAtbqO4w5TR8MiZbJ0FoJgTPGLqGMBRYzNAwMRyVGFQ8FVhkyG4wCKE8IEVYwCRQmJgkGMgMeYEIhJSUCL2xbBx2iRyRaQi+wrWAVLQ0pBjMjqVAxCB4UCSW4IgEuvU8VJA+YCQVGtLWwMQUgBK0rCC1sJgIBIgxzohHCMKgmFyIdlhMsUU4rliaYFE4PLk4RHRQ0HqEkKGipsCKEEDc0TIwIYLCUFRYCovWSMsOFEAhVaAhI8CBZFAQqVjCRIMHJCxheWjWhEUHCiBZMnDwJAgAh+QQJCQAwACwAAAAAFAAUAIUEAgSEgoTEwsRERkTk4uSkoqRsamzU0tT08vS0srQkIiSUlpRcWlyMiozMyszs6uysqqx0dnTc2tz8+vy8urw0MjQUFhRMTkycnpxkYmQ8OjyEhoTExsRMSkzk5uSkpqRsbmzU1tT09vS0trScmpxcXlyMjozMzszs7uysrqx8fnzc3tz8/vy8vrw0NjQcGhz+/v4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG90CYUIgQwUKvVwgmQgyfMFaik4IhXgrn4lVgQWETVaU0gWlcUReA4R2yvCJGRQIrlWAHQMX5FrYaTh4DJjABKjAgFitgDgRMGR0GHjAOG08GAlYtKS0TEyMRFwwnX0IeIwkcBGVCBBgLpXghTq1GsaUTKBkGESYQrF8sBxwUCQkGICoLEG3BBw4tCSMetrdQE7QspwmxJwcobRMcJAEbi6UPxS0rLCImAQtOBC1RXicPmiMUZQcpZSgYOMg6QsHJhBOOopSZAIEECkoCEaQQYKtZFAoLuMGgQEEIhwQOLAphseLDkgnGyqyg4EHkEE8wUKB6yAKYkCAAIfkECQkAMwAsAAAAABQAFACFBAIEhIKExMLEREZE5OLkpKKkZGZkLC4s1NLU9PL0tLK0dHZ0lJKUVFZUFBIUzMrM7OrsrKqsbG5sPDo83Nrc/Pr8vLq8jIqMTE5MfH58nJqcXF5cHBocxMbETEpM5ObkpKakbGpsNDI01NbU9Pb0tLa0fHp8lJaUXFpczM7M7O7srK6sdHJ0PD483N7c/P78vL68jI6MHB4c/v7+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABvnAmVBIIs0oIhFlRkoMn7OXZWOZJSYTZ0EEekGjMQ9LiMHMKgOOxDt8eUkSjGsmkcxGnIHxVRE+Tn0QKBozMTEzAQcEVg0FTAsGAR8zCAxPCwJHBwAcKhUCFwYsCF9CJQ4ALQVGQh8RIKUzIQsjQx+ssV8VKgEBMQUlfaUvCB0WCiUZviAWwl8vIw8wCgoQuLlPL05REB0wsSkIKmwVCCsaBZOlEMcwLnwgJytOHylRXikQVjAlzTMuMPokKFELQa0RFpxUSLEoSp8K05x0eDBDhYKAQthkfKAg0wwLVWYIUPBAY5sPFuZUKKGgD0ACJrP1sahAhUMoQQAAIfkECQkAMQAsAAAAABQAFACFBAYEhIaExMbEREZEpKak5ObkZGZk1NbUtLa0lJaUXFpc9Pb0LCosdHZ0zM7MTE5MrK6s7O7s3N7cvL68nJ6cHBocjI6MbG5sZGJk/P78REJEfH58jIqMzMrMTEpMrKqs7Ors3NrcvLq8nJqcXF5c/Pr8NDI01NLUVFJUtLK09PL05OLkxMLEpKKkHB4cdHJ0hIKE/v7+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABvbAmFC4WMRWnocktlANn7GMoMFioh5GiCeVgUZHBo4QY4iSTJvSM9MtwQyr2AYWC5kUxow6dvoYQS8fMSMjMRwDBTEqBoILHBsJIDEHBE8BHTESGhUmESUOFDABS14xEwwVDwR7MSAiKaUxDTAhQyBGsaURDoQECCxdpSUXAy4AAL0iAsFeJQ0oDMeeuaUqtUIqJw6xDicRwSUSLBAikqWuKRMSJSUiECx/22wxDpIqEwgiagUOaioIB/gEPIDASQYHcaK0mZDCiQBMKtLtYRalQzohE0QIYZGiA0UhGQqIiFMiRQo1EiYU+DiEXYwICFJEiMJKSBAAIfkECQkAMgAsAAAAABQAFACFBAIEhIaExMbEREJE5ObkrKqsZGJk1NbUdHJ0JCIklJaU9Pb0vLq8VFZUjI6MzM7M7O7stLK0bGps3N7cfHp8NDI0FBYUTEpMpKKk/P78xMLEXF5cPD48jIqMzMrM7OrsrK6sZGZk3NrcdHZ0nJqc/Pr8vL68XFpclJKU1NLU9PL0tLa0bG5s5OLkfH58NDY0HB4cTE5M/v7+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABvpAmVC4KMlaoVBLtlgMn7JMquNhSiROxoaRgUYLLpKQQokiLo7uMNMtKVwfGQolm1xYzoxRJmI4VR0rMgUFMgobcSojgiUYCgUQdRFPCil1JxUDRQcRJBhLXjICAxUGK05CEAIaoTIBDhNDEHutXhCcEQwCKWpeGRQNFTAwKysmHge9UCUBBhwJMCq0tU8qIkMqKQ+tGywPeyUTGiAMcaEaFgAVCkUMIBpOH9tsMg9xExUA0TIE3zIqKw7ISCHwwAoVTDYUitLGRASEAqqoiGDCiJ4nGTxQFGKCgRANETwoE5KBAIMlJSJEMDLBBIGRQ0oYgbAiQqSLT4IAACH5BAkJADYALAAAAAAUABQAhQQCBISChMTCxERGRKSipOTi5GRmZJSSlNTS1FRWVLSytPTy9CQiJHR2dIyKjMzKzExOTKyqrOzq7GxubJyanNza3FxeXLy6vPz6/DQ2NBQSFHx+fISGhMTGxExKTKSmpOTm5GxqbJSWlNTW1FxaXLS2tPT29CwuLHx6fIyOjMzOzFRSVKyurOzu7HRydJyenNze3GRiZLy+vPz+/Dw6PBwaHP7+/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbzQJtQiDHZJJsAyFYcOm2zCmFkMwUCRkGjM3tCLxSWMHUQcgyU7nDWxbAoEtuHYCsYAhhovv7ItwgdNiUXci5xJhwyTBcsAgs2IAJOU5AhHjEmGDAdCiVxXjYqJB4NMns2CyMIoDYHL0tCLaesT6kKChcdCGpeMw6WGRklJTIPI7xPGAcTKzQZC7O0QyYwQwsIKqwTKAh7mgIsF59eHSc1AwSZjAJGEtlsNhaEBQM1z5AqeQslVAhULhoqVAkhBkobGQoedXhgYwSAE49mzJrxQIEiGzII2aABIEE0KCAuFGByKw+FGhGQOcHgp4SCFlWMOAkCACH5BAkJAC4ALAAAAAAUABQAhQQGBIyKjMTGxERGROTm5KyqrGRmZNTW1CwqLPT29Ly6vJyanFxeXHR2dMzOzExOTOzu7LSytNze3ERCRBwaHJSWlDQyNPz+/MTCxKSmpHx+fIyOjMzKzExKTOzq7KyurHRydNza3Pz6/Ly+vJyenGRiZNTS1FRSVPTy9LS2tOTi5CQiJDQ2NISChP7+/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb1QJdQKBK5IIsKxCVKDJ+uiyqlciUWJCNn47hAo44IRpjJCBeaj3d48YpGEZQrlXJ5NAujaK3iGBMpBy4CAnMBHlYVhSIKHxhyHiZPERJ2GgYNRRICESmIXy4mIAYBAkZCKAeSoBkFBEMQp6CgKBIREQoCJmtfFxUaJQ8ndCMcB7xQIiQtBicPKLKzUAlVqCYOsxoBIaciEhgfCp9fDgMWDAUJjI5OHthFLiAjLgQMFh1OBA5GKIHxIC40IKiUQEOdKG7gyBnQwcUBChPkXIh2gUOEeS5WrBDygIKBaEIuEFBQBQUAAHIysIiA7Ak8ByclJXDyJAgAIfkECQkAMgAsAAAAABQAFACFBAIEhIKExMLEREJE5OLkpKKkZGJkJCIk1NLU9PL0tLK0lJKUVFZUdHJ0NDI0zMrM7OrsrKqs3Nrc/Pr8vLq8nJqcFBIUjIqMTEpMXF5cfH58PDo8xMbE5ObkpKakbGpsLC4s1NbU9Pb0tLa0lJaUXFpcdHZ0NDY0zM7M7O7srK6s3N7c/P78vL68nJ6cHB4cjI6MTE5M/v7+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABvNAmVA4mchSCkVKNhENnzIWYURgjkbGUEHCgkZRCoGQ0hKqKpTukNWdtBQJGechg5BURraQ8DCKRiEyCIEcBXEiEShMFCoCcRAITy0ddSQaMEUrHAojEF5CEhcaLihGQgkhkZ8qFJ5CKaafnyIESRQcCGpeLB4LJgYfVy0PIbpQExGWHx8JsbJQIpSnCIqfMBVcRCsCrK5eCCUxwSITjAJOIwZMRhocMh0NMQZOHaUyEhYNMhoaMgsDK5hcEBOlSwIQACJlKCFjhQMGTvSsYQDghJATG4QYcGDCGJEIL1zISHDgRRwVMdLIEuEkxIsDgZpACQIAIfkECQkAMQAsAAAAABQAFACFBAIEhIKExMLEREJE5OLkpKKkZGJkJCIk1NLU9PL0lJKUtLK0dHZ0XFpcNDI0zMrM7OrsbGps3Nrc/Pr8nJqcvLq8FBYUjI6MTEpMrKqsPDo8hIaExMbE5ObkpKakZGZkLCos1NbU9Pb0lJaUtLa0fHp8XF5cNDY0zM7M7O7sbG5s3N7c/P78nJ6cvL68HBocTE5M/v7+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABvnAmFA4mcRSi0UqxjIOnywCiRCbkEjGVYXAegpZqIVAWHEJBQtUd8jqTlyLRIzzOC5cxraQ8DCKSCExCIEIJCJVFRKId3IQCE8oSykZIwUiEyscCyQQXkMEBRQLIWsxCSGPnjEuHEtCKU6qqiIdSRUcCKVeLCQFFwElVy4PpLITFR4KAQEJsbJeIp1MCCoGsi0eXEIiIw4AFmOqIQwfGwIiCQcADisxAipVRhcoMRAbBiWHHiZyKyABMS5ciNGiQYcqLeowMZJggIVAKuARwBDh0ARdLD5YgCEEBgYhDDBs0EVkwQkPpjSckFPBgACSQ0QckqCynUwvQQAAIfkECQkALwAsAAAAABQAFACFBAYEjIqMxMbEREZE5ObkrKqsZGZkJCYk1NbU9Pb0vLq8dHZ0nJqcVFZUNDY0zM7M7O7stLK0fH58pKKkHBocTE5MbG5sLC4s3N7c/P78xMLEjI6MzMrM7OrsrK6s/Pr8vL68fHp8nJ6cZGJkREJE1NLU9PL0tLa0hIKEpKakHB4cVFJUdHJ0NDI05OLk/v7+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABvbAl1D4+bwgkQjklTEOnxnXyfX6nE5GjMKVeQozj4hGqAAJNZFHd5jpfkAR00vAOUZAxrbQxTEmTggvJYElJwlVHFQfCh4ach0lTw9LJnAKRRgCEScdXkMdJ2IYay8mCJGeLw8IckKTqbBVHQAAKgMWTp4ZGicpDAy0ByssuV4ZAgq+DKyxqR9LTCUSFrAeJwRrCRMDFBcCsC4BKAwCHyYOFANUAhJVRiKREAwhG0YeFnIuJBsvvy8eLDol8ICqyYsEDVpgeCEBxQsXBlAc0sNmQYsRQkZgfBHAAANSQxZViHCwwopDGhZwAPkkwSEXKypQSVDsRRAAIfkECQkAMgAsAAAAABQAFACFBAIEhIKExMLEREZEpKKk5OLkbGpslJKU1NLUtLK09PL0JCIkVFZUjIqMzMrMrKqs7OrsdHZ0nJqc3NrcvLq8/Pr8NDI0XF5cFBIUTE5MfH58hIaExMbETEpMpKak5ObklJaU1NbUtLa09Pb0LC4sXFpcjI6MzM7MrK6s7O7sfHp8nJ6c3N7cvL68/P78PD48ZGJkHB4c/v7+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABvlAmVBYqchSiURK5jIOn66CqCCriERGFqXgegpdp4RASGkJBYlTd9isthIKGcdxTLSMrjWBER+JQjIIgAgiI1UOVAoxACQTMhAnTwgQMgpvFBUjKy8AGCJeQxAiYixrMiERBqBCJyFxQghLq7MVKTExFgwaTqAuCBwUCSIxCy8XAaZevg4toxOvs6AVry4TDRqzLQIQayMPFxYDdKsfBCAoIZkdFiUfMicmVUYojgooEgRGFBqGHyUSMh48kEFhw5IKLRxV6TLCQAcqJkA80gDCSIVkLhp0iCBEhQohEjQ84DWkggAYnxoaMAQPQbInI4wUMGCASiYvQQAAIfkECQkALwAsAAAAABQAFACFBAIEhIKExMLEREJE5OLkpKKkZGJk1NLU9PL0LCostLK0lJKUdHJ0VFJUzMrM7Ors3Nrc/Pr8NDY0vLq8FBYUjIqMTEpMrKqsbGpsnJqcfHp8xMbE5ObkpKakZGZk1NbU9Pb0NDI0tLa0dHZ0XFpczM7M7O7s3N7c/P78PDo8vL68HBocjI6MTE5MnJ6c/v7+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABvLAl1CIQLxMCoXphYoMn8wCJfOKiETO04SAglZJAEl3MhEKFKXusPkChQCH18ZxVKicKPXFYzxRGC8HH4EiIFUOBC8IIRQDJy8qGE8lSwgqChMRIB0NFAkqXkIPIgoCJ2ovJwEjoYEfRkKvra0RJhIpFhgVqFAoBxsTSbctDCy8T74OKqQnhrNeEbAoEBksrSUHJmogIgwWJHGhD8EqpyAGFgwcLx8uVU4qiSCXmS8CFYYcDBcvImUbBZZEKLGOSRcQATysK1DgSIYLznihyOChghAW1l5cyDDhGBMHGgS0CRDAEIQOEDwKAeGEA8l1mqAEAQA7"); + background-repeat: no-repeat; + background-position: right center; } diff --git a/build/ol3-geocoder.js b/build/ol3-geocoder.js index 2a37de1..61e2268 100644 --- a/build/ol3-geocoder.js +++ b/build/ol3-geocoder.js @@ -1,6 +1,8 @@ -// Geocoder Nominatim for OpenLayers 3. -// https://github.com/jonataswalker/ol3-geocoder -// Version: v1.7.0 -// Built: 2016-04-01T08:24:58-0300 +/** + * A geocoder extension for OpenLayers 3. + * https://github.com/jonataswalker/ol3-geocoder + * Version: v2.0.0 + * Built: 2016-04-22T16:55:20-0300 + */ -"use strict";!function(e,t){"object"==typeof exports?module.exports=t():"function"==typeof define&&define.amd?define([],t):e.Geocoder=t()}(this,function(){var e={},t={whiteSpaceRegex:/\s+/,toQueryString:function(e){return Object.keys(e).reduce(function(r,n){return r.push("object"==typeof e[n]?t.toQueryString(e[n]):encodeURIComponent(n)+"="+encodeURIComponent(e[n])),r},[]).join("&")},encodeUrlXhr:function(e,r){if(r&&"object"==typeof r){var n=t.toQueryString(r);e+=(/\?/.test(e)?"&":"?")+n}return e},json:function(e,r){var n=new XMLHttpRequest,o={},s=function(){200===n.status&&o.ready.call(void 0,JSON.parse(n.response))},a=function(){console.info("Cannot XHR "+JSON.stringify(e))};return e=t.encodeUrlXhr(e,r),n.open("GET",e,!0),n.setRequestHeader("Accept","application/json"),n.onload=s,n.onerror=a,n.send(null),{when:function(e){o.ready=e.ready}}},randomId:function(e){var t=(new Date).getTime().toString(36);return e?e+t:t},to3857:function(e){return ol.proj.transform([parseFloat(e[0]),parseFloat(e[1])],"EPSG:4326","EPSG:3857")},to4326:function(e){return ol.proj.transform([parseFloat(e[0]),parseFloat(e[1])],"EPSG:3857","EPSG:4326")},isNumeric:function(e){return/^\d+$/.test(e)},classRegex:function(e){return new RegExp("(^|\\s+)"+e+"(\\s+|$)")},addClass:function(e,r,n){if(Array.isArray(e))return void e.forEach(function(e){t.addClass(e,r)});for(var o=Array.isArray(r)?r:r.split(/\s+/),s=o.length;s--;)t.hasClass(e,o[s])||t._addClass(e,o[s],n)},_addClass:function(e,r,n){e.classList?e.classList.add(r):e.className=(e.className+" "+r).trim(),n&&t.isNumeric(n)&&window.setTimeout(function(){t._removeClass(e,r)},n)},removeClass:function(e,r,n){if(Array.isArray(e))return void e.forEach(function(e){t.removeClass(e,r,n)});for(var o=Array.isArray(r)?r:r.split(/\s+/),s=o.length;s--;)t.hasClass(e,o[s])&&t._removeClass(e,o[s],n)},_removeClass:function(e,r,n){e.classList?e.classList.remove(r):e.className=e.className.replace(t.classRegex(r)," ").trim(),n&&t.isNumeric(n)&&window.setTimeout(function(){t._addClass(e,r)},n)},hasClass:function(e,r){return e.classList?e.classList.contains(r):t.classRegex(r).test(e.className)},toggleClass:function(e,r){return Array.isArray(e)?void e.forEach(function(e){t.toggleClass(e,r)}):void(e.classList?e.classList.toggle(r):t.hasClass(e,r)?t._removeClass(e,r):t._addClass(e,r))},$:function(e){return e="#"===e[0]?e.substr(1,e.length):e,document.getElementById(e)},isElement:function(e){return"HTMLElement"in window?!!e&&e instanceof HTMLElement:!!e&&"object"==typeof e&&1===e.nodeType&&!!e.nodeName},getAllChildren:function(e,t){return[].slice.call(e.getElementsByTagName(t))},isEmpty:function(e){return!e||0===e.length},emptyArray:function(e){for(;e.length;)e.pop()},anyMatchInArray:function(e,t){return e.some(function(e){return t.indexOf(e)>=0})},everyMatchInArray:function(e,t){return t.every(function(t){return e.indexOf(t)>=0})},anyItemHasValue:function(e){var r=!1;for(var n in e)t.isEmpty(e[n])||(r=!0);return r},removeAllChildren:function(e){for(;e.firstChild;)e.removeChild(e.firstChild)},removeAll:function(e){for(var t;t=e[0];)t.parentNode.removeChild(t)},getChildren:function(e,t){return[].filter.call(e.childNodes,function(e){return t?1==e.nodeType&&e.tagName.toLowerCase()==t:1==e.nodeType})},template:function(e,t){var r=this;return e.replace(/\{ *([\w_-]+) *\}/g,function(e,n){var o=void 0===t[n]?"":t[n];return r.htmlEscape(o)})},htmlEscape:function(e){return String(e).replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")},mergeOptions:function(e,t){var r={};for(var n in e)r[n]=e[n];for(var o in t)r[o]=t[o];return r},createElement:function(e,t){var r;if(Array.isArray(e)){if(r=document.createElement(e[0]),e[1].id&&(r.id=e[1].id),e[1].classname&&(r.className=e[1].classname),e[1].attr){var n=e[1].attr;if(Array.isArray(n))for(var o=-1;++o0?n.mapquestResponse(e):void 0;break;case a.PELIAS:r=e.features.length>0?n.peliasResponse(e.features):void 0;break;case a.PHOTON:r=e.features.length>0?n.photonResponse(e.features):void 0;break;case a.GOOGLE:r=e.results.length>0?n.googleResponse(e.results):void 0}r&&(n.createList(r),n.listenMapClick())},error:function(){t.removeClass(s,"ol-geocoder-loading");var e=t.createElement("li","
      Error! No internet connection?
      ");n.els.result_container.appendChild(e)}})},createList:function(e){var r=this,n=this.els.result_container;e.forEach(function(e){var o=r.addressTemplate(e),s=''+o+"",a=t.createElement("li",s);a.addEventListener("click",function(t){t.preventDefault(),r.chosen(e,o,e.address,e.original)},!1),n.appendChild(a)})},addressTemplate:function(e){var r=e.address,n=[];return r.name&&n.push('{name}'),(r.road||r.building||r.house_number)&&n.push('{building} {road} {house_number}'),(r.city||r.town||r.village)&&n.push('{postcode} {city} {town} {village}'),(r.state||r.country)&&n.push('{state} {country}'),t.template(n.join("
      "),r)},chosen:function(t,r,n,o){this.options.keepOpen===!1&&this.clearResults(!0);var s=e.$base.getMap(),a=s.getView(),i=a.getProjection(),l=ol.proj.transform([parseFloat(t.lon),parseFloat(t.lat)],"EPSG:4326",i),c=2.388657133911758,d=500,u={coord:l,address_html:r,address_obj:n,address_original:o},p=ol.animation.pan({duration:d,source:a.getCenter()}),m=ol.animation.zoom({duration:d,resolution:a.getResolution()});s.beforeRender(p,m),a.setCenter(l),a.setResolution(c),this.createFeature(u)},createFeature:function(r){var n=new ol.Feature({address_html:r.address_html,address_obj:r.address_obj,address_original:r.address_original,geometry:new ol.geom.Point(r.coord)}),o=t.randomId("geocoder-ft-"),s=this.options.featureStyle||e.Nominatim.featureStyle;this.addLayer(),n.setStyle(s),n.setId(o),this.getSource().addFeature(n),e.$base.dispatchEvent({type:e.EventType.ADDRESSCHOSEN,feature:n,coordinate:r.coord})},mapquestResponse:function(e){var t=e.map(function(e){return{lon:e.lon,lat:e.lat,address:{name:e.address.neighbourhood||"",road:e.address.road||"",postcode:e.address.postcode,city:e.address.city||e.address.town,state:e.address.state,country:e.address.country},original:{formatted:e.display_name,details:e.address}}});return t},photonResponse:function(e){var t=e.map(function(e){return{lon:e.geometry.coordinates[0],lat:e.geometry.coordinates[1],address:{name:e.properties.name,postcode:e.properties.postcode,city:e.properties.city,state:e.properties.state,country:e.properties.country},original:{formatted:e.properties.name,details:e.properties}}});return t},peliasResponse:function(e){var t=e.map(function(e){return{lon:e.geometry.coordinates[0],lat:e.geometry.coordinates[1],address:{name:e.properties.name,house_number:e.properties.housenumber,postcode:e.properties.postalcode,road:e.properties.street,city:e.properties.city,state:e.properties.region,country:e.properties.country},original:{formatted:e.properties.label,details:e.properties}}});return t},googleResponse:function(e){var r=["point_of_interest","establishment","natural_feature","airport"],n=["street_address","route","sublocality_level_5","intersection"],o=["postal_code"],s=["locality"],a=["administrative_area_level_1"],i=["country"],l=function(e){var l={name:"",road:"",postcode:"",city:"",state:"",country:""};return e.forEach(function(e){t.anyMatchInArray(e.types,r)?l.name=e.long_name:t.anyMatchInArray(e.types,n)?l.road=e.long_name:t.anyMatchInArray(e.types,o)?l.postcode=e.long_name:t.anyMatchInArray(e.types,s)?l.city=e.long_name:t.anyMatchInArray(e.types,a)?l.state=e.long_name:t.anyMatchInArray(e.types,i)&&(l.country=e.long_name)}),l},c=[];return e.forEach(function(e){var r=l(e.address_components);t.anyItemHasValue(r)&&c.push({lon:e.geometry.location.lng,lat:e.geometry.location.lat,address:{name:r.name,postcode:r.postcode,road:r.road,city:r.city,state:r.state,country:r.country},original:{formatted:e.formatted_address,details:e.address_components}})}),c},getSource:function(){return this.layer.getSource()},addLayer:function(){var t=this,r=!1,n=e.$base.getMap();n.getLayers().forEach(function(e){e===t.layer&&(r=!0)}),r||n.addLayer(this.layer)},getProvider:function(r){var n,o=e.Nominatim.providers[r.provider],s=e.Nominatim.providers.names,a=[s.MAPQUEST,s.PELIAS,s.GOOGLE],i=["de","it","fr","en"];switch(r.provider){case s.OSM:case s.MAPQUEST:n={q:r.query,limit:r.limit,countrycodes:r.countrycodes,"accept-language":r.lang},o.params=t.mergeOptions(o.params,n);break;case s.PHOTON:r.lang=r.lang.toLowerCase(),n={q:r.query,limit:r.limit||o.params.limit,lang:i.indexOf(r.lang)>-1?r.lang:o.params.lang},o.params=t.mergeOptions(o.params,n);break;case s.GOOGLE:n={address:r.query,language:r.lang},o.params=t.mergeOptions(o.params,n);break;case s.PELIAS:n={text:r.query,size:r.limit},o.params=t.mergeOptions(o.params,n)}return a.indexOf(r.provider)>-1&&(o.params.key=r.key),o}},e.EventType={ADDRESSCHOSEN:"addresschosen"},e.Nominatim.elements={},e.Nominatim.providers={names:{OSM:"osm",MAPQUEST:"mapquest",GOOGLE:"google",PHOTON:"photon",PELIAS:"pelias"},osm:{url:"http://nominatim.openstreetmap.org/search/",params:{format:"json",q:"",addressdetails:1,limit:10,countrycodes:"","accept-language":"en-US"}},mapquest:{url:"http://open.mapquestapi.com/nominatim/v1/search.php",params:{key:"",format:"json",q:"",addressdetails:1,limit:10,countrycodes:"","accept-language":"en-US"}},google:{url:"https://maps.googleapis.com/maps/api/geocode/json",params:{key:"",address:"",language:"en-US"}},pelias:{url:"https://search.mapzen.com/v1/search",params:{key:"",text:"",size:10}},photon:{url:"http://photon.komoot.de/api/",params:{q:"",limit:10,lang:"en"}}},e.Nominatim.featureStyle=[new ol.style.Style({image:new ol.style.Icon({scale:.7,anchor:[.5,1],src:"//cdn.rawgit.com/jonataswalker/map-utils/master/images/marker.png"}),zIndex:5}),new ol.style.Style({image:new ol.style.Circle({fill:new ol.style.Fill({color:[235,235,235,1]}),stroke:new ol.style.Stroke({color:[0,0,0,1]}),radius:5}),zIndex:4})],e.Nominatim.html=['",'
        '].join(""),e.Base}); +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Geocoder=t()}(this,function(){"use strict";var e="ol3-geocoder",t="-container",r="-search",s="-btn-search",n="-loading",a="-input-search",o="-result",i="-search-expanded",l="-country",c="-city",d="-road",u="ol-control",p={ADDRESSCHOSEN:"addresschosen"},h=[new ol.style.Style({image:new ol.style.Icon({anchor:[.5,1],src:["data:image/png;base64,","iVBORw0KGgoAAAANSUhEUgAAAC0AAAAtCAYAAAA6GuKaAAAABmJLR0QA/wD/AP+gvaeT","AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AQWCiErd9Z21AAABAJJREFUWMPVm","U1oXFUUx3/3zatJx04SDOgiVUMSgrXJwpqIKy26SrKoLjQgCkIFW7otuCvdllbo1q6Epg","vNQvtx710lEFdihwpSjdikJLGJWEhrM9MyX7nPxbypwzBv5n3cqXpgmOHOuff/mzPn3Pf","ueWDBpqZnrPq1M5EUVitZ+9wPvA0cAgaALqAIbAI3gAWt5HbjvCcGXROdmp4RwDDwBfBW","iKmLwKfAqlbSiwvvJAAeAeaBWyGB8f1uAfNT0zMj/jqdjXQd8Ds+sJsguyrAe1rJb6NGX","MQAPgJ8k7QefPOAd7WSl6OAi4jAk8D3cdKqhRngda3k9bDgUSL9NLAO9GPftoEXtZIPrR","WiXyzHwwAbA8WyoFAUFMsCY0JB9wPHwxalGyH3T4RxHByo8MZEgf4+w/ZfDt9lu9n4I5T","MCeBzP8+tQL8KDAZuA7swOljh4yM5JsaKGAPGA0fABzN5sje7+PJyht/WXNxU8O/1dbK2","9ulPWn05tL/CqWP3GR8tUSgKSmVBpVJ9LxQF46MlTh27z9D+SiKdqNCBFw/jwexUnr4eg","xfwx3oe9PUYZqfyGC+eThzo4SCYTNpweLLQtuCMgcOTBTLp4B8XpBMXuqnfroGxkTIi5M","YpRNV/1yTjCQv9oHmkBXu7vRD1/s/1b2+3h+eJSDpxoa83G0w5HisbLqRCrpKClQ2XlON","F0okL/XXTyQ6sbe1h/Y7bNkWEgPU7Lmtbe3CcaDpxoS8CuaYbfcpj7mqmVXE9Ltq5qxnc","VKBjztexBl0Azgd9uZTt4spimlJZkHKqUa29Ug6UyoIri2mWsl2tNM77OlZvmIaBn4B00","6tiRfDSUIk3JwocerlIzz7DTt7hxi9dLGW7+fX2U7huYJQfAeNayduduDX9Cni/3X5sPI","HnVSPtCK9VDj/OZa3krPVbUx++J+y2FNF6tZI71s+IfhR2gNOWgU9rJXeinBUjnxGBF4A","fgWcsAN8DXgE2OnJGbIC/CHxoAXpOK/lRx1sIvn1mKTVirRO377EFnE0IfFYrudXxvkdD","bvcCvwOZGEvkgOeBB0+kwwTU9tIccClmlC8Bubj9vKQNyAPAzxHX8YCDWsnluLpOAmB84","fmIU+e1kstJ2r42OkVH/S5R2G7S0aSCsaFrHU+tZB44F3LaOa1k/l/pTzfZSQ4APwD7Wr","jmgdeA5STAttKjltsLbdwWkhSf1UjXRfxZ4M8WLs9pJe/a0HIsAeMDnQlwOaOVvPufeFD","UJLcH/H27t6EtcBDYTJrLViNdl9ubwLWG4Wv+uDUTWDb/LLlSNzSilVy1qeFYBsYHvOAP","XdBKrtrK5Y5A19lJqo8kTnZi8U6kRy0YY8BNwNgqwP+1/Q09w5giQWRk7AAAAABJRU5Er","kJggg=="].join("")})})],m={OSM:"osm",MAPQUEST:"mapquest",GOOGLE:"google",PHOTON:"photon",PELIAS:"pelias"},y={provider:m.OSM,placeholder:"Search for an address",featureStyle:h,lang:"en-US",limit:5,keepOpen:!1,debug:!1},g={toQueryString:function(e){var t=this;return Object.keys(e).reduce(function(r,s){return r.push("object"==typeof e[s]?t.toQueryString(e[s]):encodeURIComponent(s)+"="+encodeURIComponent(e[s])),r},[]).join("&")},encodeUrlXhr:function(e,t){if(t&&"object"==typeof t){var r=this.toQueryString(t);e+=(/\?/.test(e)?"&":"?")+r}return e},json:function(e,t){var r=new XMLHttpRequest,s={},n=function(){200===r.status&&s.ready.call(void 0,JSON.parse(r.response))},a=function(){console.info("Cannot XHR "+JSON.stringify(e))};return e=this.encodeUrlXhr(e,t),r.open("GET",e,!0),r.setRequestHeader("Accept","application/json"),r.onload=n,r.onerror=a,r.send(null),{when:function(e){s.ready=e.ready}}},randomId:function(e){var t=window.performance.now().toString(36);return e?e+t:t},to3857:function(e){return ol.proj.transform([parseFloat(e[0]),parseFloat(e[1])],"EPSG:4326","EPSG:3857")},to4326:function(e){return ol.proj.transform([parseFloat(e[0]),parseFloat(e[1])],"EPSG:3857","EPSG:4326")},isNumeric:function(e){return/^\d+$/.test(e)},classRegex:function(e){return new RegExp("(^|\\s+) "+e+" (\\s+|$)")},addClass:function(e,t,r){var s=this;if(Array.isArray(e))return void e.forEach(function(e){s.addClass(e,t)});for(var n=Array.isArray(t)?t:t.split(/\s+/),a=n.length;a--;)s.hasClass(e,n[a])||s._addClass(e,n[a],r)},_addClass:function(e,t,r){var s=this;e.classList?e.classList.add(t):e.className=(e.className+" "+t).trim(),r&&this.isNumeric(r)&&window.setTimeout(function(){s._removeClass(e,t)},r)},removeClass:function(e,t,r){var s=this;if(Array.isArray(e))return void e.forEach(function(e){s.removeClass(e,t,r)});for(var n=Array.isArray(t)?t:t.split(/\s+/),a=n.length;a--;)s.hasClass(e,n[a])&&s._removeClass(e,n[a],r)},_removeClass:function(e,t,r){var s=this;e.classList?e.classList.remove(t):e.className=e.className.replace(this.classRegex(t)," ").trim(),r&&this.isNumeric(r)&&window.setTimeout(function(){s._addClass(e,t)},r)},hasClass:function(e,t){return e.classList?e.classList.contains(t):this.classRegex(t).test(e.className)},toggleClass:function(e,t){var r=this;return Array.isArray(e)?void e.forEach(function(e){r.toggleClass(e,t)}):void(e.classList?e.classList.toggle(t):this.hasClass(e,t)?this._removeClass(e,t):this._addClass(e,t))},$:function(e){return e="#"===e[0]?e.substr(1,e.length):e,document.getElementById(e)},isElement:function(e){return"HTMLElement"in window?!!e&&e instanceof HTMLElement:!!e&&"object"==typeof e&&1===e.nodeType&&!!e.nodeName},getAllChildren:function(e,t){return[].slice.call(e.getElementsByTagName(t))},isEmpty:function(e){return!e||0===e.length},emptyArray:function(e){for(;e.length;)e.pop()},anyMatchInArray:function(e,t){return e.some(function(e){return t.indexOf(e)>=0})},everyMatchInArray:function(e,t){return t.every(function(t){return e.indexOf(t)>=0})},anyItemHasValue:function(e,t){void 0===t&&(t=!1);for(var r in e)this.isEmpty(e[r])||(t=!0);return t},removeAllChildren:function(e){for(;e.firstChild;)e.removeChild(e.firstChild)},removeAll:function(e){for(var t;t=e[0];)t.parentNode.removeChild(t)},getChildren:function(e,t){return[].filter.call(e.childNodes,function(e){return t?1==e.nodeType&&e.tagName.toLowerCase()==t:1==e.nodeType})},template:function(e,t){var r=this;return e.replace(/\{ *([\w_-]+) *\}/g,function(e,s){var n=void 0===t[s]?"":t[s];return r.htmlEscape(n)})},htmlEscape:function(e){return String(e).replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")},mergeOptions:function(e,t){var r={};for(var s in e)r[s]=e[s];for(var n in t)r[n]=t[n];return r},createElement:function(e,t){var r;if(Array.isArray(e)){if(r=document.createElement(e[0]),e[1].id&&(r.id=e[1].id),e[1].classname&&(r.className=e[1].classname),e[1].attr){var s=e[1].attr;if(Array.isArray(s))for(var n=-1;++n-1?e.lang:this.settings.params.lang}}},f.prototype.handleResponse=function(e){return e.map(function(e){return{lon:e.geometry.coordinates[0],lat:e.geometry.coordinates[1],address:{name:e.properties.name,postcode:e.properties.postcode,city:e.properties.city,state:e.properties.state,country:e.properties.country},original:{formatted:e.properties.name,details:e.properties}}})};var v=function(){this.settings={url:"http://nominatim.openstreetmap.org/search/",params:{q:"",format:"json",addressdetails:1,limit:10,countrycodes:"","accept-language":"en-US"}}};v.prototype.getParameters=function(e){return{url:this.settings.url,params:{q:e.query,format:"json",addressdetails:1,limit:e.limit||this.settings.params.limit,countrycodes:e.countrycodes||this.settings.params.countrycodes,"accept-language":e.lang||this.settings.params["accept-language"]}}},v.prototype.handleResponse=function(e){return e.map(function(e){return{lon:e.lon,lat:e.lat,address:{name:e.address.neighbourhood||"",road:e.address.road||"",postcode:e.address.postcode,city:e.address.city||e.address.town,state:e.address.state,country:e.address.country},original:{formatted:e.display_name,details:e.address}}})};var A=function(){this.settings={url:"http://open.mapquestapi.com/nominatim/v1/search.php",params:{q:"",key:"",format:"json",addressdetails:1,limit:10,countrycodes:"","accept-language":"en-US"}}};A.prototype.getParameters=function(e){return{url:this.settings.url,params:{q:e.query,key:e.key,format:"json",addressdetails:1,limit:e.limit||this.settings.params.limit,countrycodes:e.countrycodes||this.settings.params.countrycodes,"accept-language":e.lang||this.settings.params["accept-language"]}}},A.prototype.handleResponse=function(e){return e.map(function(e){return{lon:e.lon,lat:e.lat,address:{name:e.address.neighbourhood||"",road:e.address.road||"",postcode:e.address.postcode,city:e.address.city||e.address.town,state:e.address.state,country:e.address.country},original:{formatted:e.display_name,details:e.address}}})};var C=function(){this.settings={url:"https://search.mapzen.com/v1/search",params:{text:"",key:"",size:10}}};C.prototype.getParameters=function(e){return{url:this.settings.url,params:{text:e.query,key:e.key,size:e.limit||this.settings.params.size}}},C.prototype.handleResponse=function(e){return e.map(function(e){return{lon:e.geometry.coordinates[0],lat:e.geometry.coordinates[1],address:{name:e.properties.name,house_number:e.properties.housenumber,postcode:e.properties.postalcode,road:e.properties.street,city:e.properties.city,state:e.properties.region,country:e.properties.country},original:{formatted:e.properties.label,details:e.properties}}})};var w=function(){this.settings={url:"https://maps.googleapis.com/maps/api/geocode/json",params:{address:"",key:"",language:"en-US"}}};w.prototype.getParameters=function(e){return{url:this.settings.url,params:{address:e.query,key:e.key,language:e.lang||this.settings.params.language}}},w.prototype.handleResponse=function(e){var t=["point_of_interest","establishment","natural_feature","airport"],r=["street_address","route","sublocality_level_5","intersection"],s=["postal_code"],n=["locality"],a=["administrative_area_level_1"],o=["country"],i=function(e){var i={name:"",road:"",postcode:"",city:"",state:"",country:""};return e.forEach(function(e){g.anyMatchInArray(e.types,t)?i.name=e.long_name:g.anyMatchInArray(e.types,r)?i.road=e.long_name:g.anyMatchInArray(e.types,s)?i.postcode=e.long_name:g.anyMatchInArray(e.types,n)?i.city=e.long_name:g.anyMatchInArray(e.types,a)?i.state=e.long_name:g.anyMatchInArray(e.types,o)&&(i.country=e.long_name)}),i},l=[];return e.forEach(function(e){var t=i(e.address_components);g.anyItemHasValue(t)&&l.push({lon:e.geometry.location.lng,lat:e.geometry.location.lat,address:{name:t.name,postcode:t.postcode,road:t.road,city:t.city,state:t.state,country:t.country},original:{formatted:e.formatted_address,details:e.address_components}})}),l};var S=function(e){return this.Base=e,this.layer_name=g.randomId("geocoder-layer-"),this.layer=new ol.layer.Vector({name:this.layer_name,source:new ol.source.Vector}),this.options=e.options,this.options.provider=this.options.provider.toLowerCase(),this.els=this.createControl(),this.container=this.els.container,this.registered_listeners={map_click:!1},this.setListeners(),this.Photon=new f,this.OpenStreet=new v,this.MapQuest=new A,this.Pelias=new C,this.Google=new w,this};S.prototype.createControl=function(){var n=g.createElement(["div",{classname:e+t}],S.html),i={container:n,control:n.querySelector("."+(e+r)),btn_search:n.querySelector("."+(e+s)),input_search:n.querySelector("."+(e+a)),result_container:n.querySelector("."+(e+o))};return i.input_search.placeholder=this.options.placeholder,i},S.prototype.setListeners=function(){var t=this,r=function(){g.hasClass(t.els.control,e+i)?t.collapse():t.expand()},s=function(e){if(13==e.keyCode){var r=g.htmlEscape(t.els.input_search.value);t.query(r)}};this.els.input_search.addEventListener("keydown",s,!1),this.els.btn_search.addEventListener("click",r,!1)},S.prototype.query=function(t){var r=this,s=this.options,a=this.els.input_search,o=this.getProvider({query:t,provider:s.provider,key:s.key,lang:s.lang,countrycodes:s.countrycodes,limit:s.limit});this.clearResults(),g.addClass(a,e+n),g.json(o.url,o.params).when({ready:function(t){s.debug&&console.info(t),g.removeClass(a,e+n);var o;switch(s.provider){case m.OSM:o=t.length>0?r.OpenStreet.handleResponse(t):void 0;break;case m.MAPQUEST:o=t.length>0?r.MapQuest.handleResponse(t):void 0;break;case m.PELIAS:o=t.features.length>0?r.Pelias.handleResponse(t.features):void 0;break;case m.PHOTON:o=t.features.length>0?r.Photon.handleResponse(t.features):void 0;break;case m.GOOGLE:o=t.results.length>0?r.Google.handleResponse(t.results):void 0}o&&(r.createList(o),r.listenMapClick())},error:function(){g.removeClass(a,e+n);var t=g.createElement("li","
        Error! No internet connection?
        ");r.els.result_container.appendChild(t)}})},S.prototype.createList=function(e){var t=this,r=this.els.result_container;e.forEach(function(e){var s=t.addressTemplate(e.address),n=''+s+"",a=g.createElement("li",n);a.addEventListener("click",function(r){r.preventDefault(),t.chosen(e,s,e.address,e.original)},!1),r.appendChild(a)})},S.prototype.chosen=function(e,t,r,s){this.options.keepOpen===!1&&this.clearResults(!0);var n=this.Base.getMap(),a=n.getView(),o=a.getProjection(),i=ol.proj.transform([parseFloat(e.lon),parseFloat(e.lat)],"EPSG:4326",o),l=2.388657133911758,c=500,d={coord:i,address_html:t,address_obj:r,address_original:s},u=ol.animation.pan({duration:c,source:a.getCenter()}),p=ol.animation.zoom({duration:c,resolution:a.getResolution()});n.beforeRender(u,p),a.setCenter(i),a.setResolution(l),this.createFeature(d)},S.prototype.createFeature=function(e){var t=new ol.Feature({address_html:e.address_html,address_obj:e.address_obj,address_original:e.address_original,geometry:new ol.geom.Point(e.coord)});this.addLayer(),t.setStyle(this.options.featureStyle),t.setId(g.randomId("geocoder-ft-")),this.getSource().addFeature(t),this.Base.dispatchEvent({type:p.ADDRESSCHOSEN,feature:t,coordinate:e.coord})},S.prototype.addressTemplate=function(t){var r=[];return t.name&&r.push('{name}'),(t.road||t.building||t.house_number)&&r.push('{building} {road} {house_number}'),(t.city||t.town||t.village)&&r.push('{postcode} {city} {town} {village}'),(t.state||t.country)&&r.push('{state} {country}'),g.template(r.join("
        "),t)},S.prototype.getProvider=function(e){var t;switch(e.provider){case m.OSM:t=this.OpenStreet.getParameters(e);break;case m.MAPQUEST:t=this.MapQuest.getParameters(e);break;case m.PHOTON:t=this.Photon.getParameters(e);break;case m.GOOGLE:t=this.Google.getParameters(e);break;case m.PELIAS:t=this.Pelias.getParameters(e)}return t},S.prototype.expand=function(){var t=this;g.removeClass(this.els.input_search,e+n),g.addClass(this.els.control,e+i),window.setTimeout(function(){t.els.input_search.focus()},100),this.listenMapClick()},S.prototype.collapse=function(){this.els.input_search.value="",this.els.input_search.blur(),g.removeClass(this.els.control,e+i),this.clearResults()},S.prototype.listenMapClick=function(){if(!this.registered_listeners.map_click){var e=this,t=this.Base.getMap().getTargetElement();this.registered_listeners.map_click=!0,t.addEventListener("click",{handleEvent:function(r){e.clearResults(!0),t.removeEventListener(r.type,this,!1),e.registered_listeners.map_click=!1}},!1)}},S.prototype.clearResults=function(e){e?this.collapse():g.removeAllChildren(this.els.result_container)},S.prototype.getSource=function(){return this.layer.getSource()},S.prototype.addLayer=function(){var e=this,t=!1,r=this.Base.getMap();r.getLayers().forEach(function(r){r===e.layer&&(t=!0)}),t||r.addLayer(this.layer)},S.html=['
        ','','',"
        ",'
          '].join("");var E=function e(t,r){void 0===t&&(t="nominatim"),void 0===r&&(r={}),g.assert("string"==typeof t,"@param `control_type` should be string type!"),g.assert("object"==typeof r,"@param `opt_options` should be object type!"),this.options=g.mergeOptions(y,r),e.Nominatim=new S(this),ol.control.Control.call(this,{element:e.Nominatim.container})};return E.prototype.getLayer=function(){return E.Nominatim.layer},E.prototype.getSource=function(){return this.getLayer().getSource()},ol.inherits(E,ol.control.Control),E}); diff --git a/build/ol3-geocoder.min.css b/build/ol3-geocoder.min.css index f7f6f2d..69c3d7f 100644 --- a/build/ol3-geocoder.min.css +++ b/build/ol3-geocoder.min.css @@ -1 +1,8 @@ -.ol-geocoder{position:absolute;top:calc(.5em + 65px);left:.5em;box-sizing:border-box}.ol-geocoder *,.ol-geocoder ::after,.ol-geocoder ::before{box-sizing:inherit}.ol-geocoder-search{width:31px;height:31px;overflow:hidden;-webkit-transition:width .2s,height .2s;transition:width .2s,height .2s}.ol-geocoder-search-expanded{width:220px;height:35px}.ol-geocoder-input-search{position:absolute;top:2px;left:32px;width:180px;padding:5px;border:1px solid #ccc;font-family:inherit;font-size:14px}.ol-geocoder-input-search:focus{border-color:#35b5f4}ul.ol-geocoder-result{position:absolute;top:37px;left:32px;width:260px;max-height:300px;white-space:normal;list-style:none;padding:0;margin:0;border-top:none;background-color:#fff;box-shadow:0 1px 7px rgba(0,0,0,.8);border-radius:0 0 4px 4px;line-height:1.2;overflow-x:hidden;overflow-y:auto;-webkit-transition:height .3s ease-in;transition:height .3s ease-in}ul.ol-geocoder-result li{width:100%;overflow:hidden;border-bottom:1px solid #eee;padding:0}ul.ol-geocoder-result li:nth-child(odd){background-color:#e0ffe0}ul.ol-geocoder-result li a{display:block;text-decoration:none;padding:3px 5px}ul.ol-geocoder-result li a:hover{background-color:#d4d4d4}.ol-geocoder-road{font-size:14px;font-weight:700;color:#000}.ol-geocoder-city{font-size:12px;font-weight:400;color:#000}.ol-geocoder-country{font-size:12px;font-weight:lighter;color:#444}.ol-geocoder-btn-search{position:absolute;width:25px;height:25px;top:2px;left:2px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAABPUlEQVQoU41SwXHCQAzUHh58eoUOIBWEDkI6oAToIKkg7iAuwakgpAIowXRACcnrzp6BzchjMx4wE/S6kW5XK60gvQghzJIkmVoqSZI9gJ9+/fINS5Cc1HX9QXIlIr/tpwcRyb33b7cIGnAIYQdg4pxbjcfj0nJ1Xc+Px+PGObdN03Q9RIAQwgpAnqbp7FKmjQGgJLlU1d2V7BjjRkQO3vvXIXarkyxVNbsCm2QR2Q0V7XOMMReRmfd+OQQubN6hYgs22ZtbnRcAtiRfLueqqmpJ8ovko6oeBq0KIWQA3gFkzrlmMafTaUEyI/mpqmbhVTRWWbRdbClPbeobQNES5KPRqOxs7DBn8K1DsAOKMZYApiTXqlrcDe4d0XN7jWeCfzt351tVle2iGalTcBd4gGDvvZ/fDe4RmCOFLe8Pr7mvEP2N9PQAAAAASUVORK5CYII=);background-repeat:no-repeat;background-position:center center}.ol-geocoder-loading{background-image:url(data:image/gif;base64,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);background-repeat:no-repeat;background-position:right center} \ No newline at end of file +/** + * A geocoder extension for OpenLayers 3. + * https://github.com/jonataswalker/ol3-geocoder + * Version: v2.0.0 + * Built: 2016-04-22T16:55:20-0300 + */ + +.ol3-geocoder-container{position:absolute;top:calc(.5em + 65px);left:.5em;box-sizing:border-box}.ol3-geocoder-container *,.ol3-geocoder-container ::after,.ol3-geocoder-container ::before{box-sizing:inherit}.ol3-geocoder-search{width:31px;height:31px;overflow:hidden;-webkit-transition:width .2s,height .2s;transition:width .2s,height .2s}.ol3-geocoder-search-expanded{width:220px;height:35px}.ol3-geocoder-input-search{position:absolute;top:2px;left:32px;width:180px;padding:5px;border:1px solid #ccc;font-family:inherit;font-size:.875rem}.ol3-geocoder-input-search:focus{border-color:#35b5f4}ul.ol3-geocoder-result{position:absolute;top:37px;left:32px;width:260px;max-height:300px;white-space:normal;list-style:none;padding:0;margin:0;background-color:#fff;border-radius:0 0 4px 4px;border-top:none;overflow-x:hidden;overflow-y:auto;box-shadow:0 1px 7px rgba(0,0,0,.8);-webkit-transition:max-height .3s ease-in;transition:max-height .3s ease-in}ul.ol3-geocoder-result>li{width:100%;overflow:hidden;border-bottom:1px solid #eee;padding:0;line-height:.875rem}ul.ol3-geocoder-result>li>a{display:block;text-decoration:none;padding:3px 5px}ul.ol3-geocoder-result>li>a:hover{background-color:#d4d4d4}ul.ol3-geocoder-result>li:nth-child(odd){background-color:#e0ffe0}.ol3-geocoder-road{font-size:.875rem;font-weight:700;color:#000}.ol3-geocoder-city{font-size:.75rem;font-weight:400;color:#000}.ol3-geocoder-country{font-size:.75rem;font-weight:lighter;color:#444}.ol3-geocoder-btn-search{position:absolute;width:25px;height:25px;top:2px;left:2px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAABPUlEQVQoU41SwXHCQAzUHh58eoUOIBWEDkI6oAToIKkg7iAuwakgpAIowXRACcnrzp6BzchjMx4wE/S6kW5XK60gvQghzJIkmVoqSZI9gJ9+/fINS5Cc1HX9QXIlIr/tpwcRyb33b7cIGnAIYQdg4pxbjcfj0nJ1Xc+Px+PGObdN03Q9RIAQwgpAnqbp7FKmjQGgJLlU1d2V7BjjRkQO3vvXIXarkyxVNbsCm2QR2Q0V7XOMMReRmfd+OQQubN6hYgs22ZtbnRcAtiRfLueqqmpJ8ovko6oeBq0KIWQA3gFkzrlmMafTaUEyI/mpqmbhVTRWWbRdbClPbeobQNES5KPRqOxs7DBn8K1DsAOKMZYApiTXqlrcDe4d0XN7jWeCfzt351tVle2iGalTcBd4gGDvvZ/fDe4RmCOFLe8Pr7mvEP2N9PQAAAAASUVORK5CYII=);background-repeat:no-repeat;background-position:center center}.ol3-geocoder-loading{background-image:url(data:image/gif;base64,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);background-repeat:no-repeat;background-position:right center} \ No newline at end of file diff --git a/config/rollup.config.js b/config/rollup.config.js new file mode 100644 index 0000000..fec0714 --- /dev/null +++ b/config/rollup.config.js @@ -0,0 +1,19 @@ +import json from 'rollup-plugin-json'; +import buble from 'rollup-plugin-buble'; + +var pkg = require('../package.json'); + +export default { + format: 'umd', + entry: pkg.rollup.entry, + dest: pkg.rollup.dest, + moduleName: pkg.rollup.moduleName, + plugins: [ + json({ + exclude: [ 'node_modules/**' ] + }), + buble({ + exclude: ['node_modules/**', '*.json'] + }) + ] +} \ No newline at end of file diff --git a/examples/control-nominatim.html b/examples/control-nominatim.html index 3156e0d..fbd8f2f 100644 --- a/examples/control-nominatim.html +++ b/examples/control-nominatim.html @@ -15,6 +15,7 @@ + diff --git a/examples/control-nominatim.js b/examples/control-nominatim.js index 0f3674a..d77db64 100644 --- a/examples/control-nominatim.js +++ b/examples/control-nominatim.js @@ -1,24 +1,22 @@ (function(win, doc){ 'use strict'; - var - olview = new ol.View({ - center: [0, 0], - zoom: 3, - minZoom: 2, - maxZoom: 20 - }), - baseLayer = new ol.layer.Tile({ - source: new ol.source.MapQuest({layer: 'osm'}) - }), - map = new ol.Map({ - target: doc.getElementById('map'), - view: olview, - loadTilesWhileAnimating: true, - loadTilesWhileInteracting: true, - layers: [baseLayer] - }) - ; + var olview = new ol.View({ + center: [0, 0], + zoom: 3, + minZoom: 2, + maxZoom: 20 + }), + baseLayer = new ol.layer.Tile({ + source: new ol.source.MapQuest({ layer: 'osm' }) + }), + map = new ol.Map({ + target: doc.getElementById('map'), + view: olview, + loadTilesWhileAnimating: true, + loadTilesWhileInteracting: true, + layers: [baseLayer] + }); //Instantiate with some options and add the Control var geocoder = new Geocoder('nominatim', { @@ -32,11 +30,10 @@ //Listen when an address is chosen geocoder.on('addresschosen', function(evt){ - var - feature = evt.feature, - coord = evt.coordinate, - address_html = feature.get('address_html') - ; + var feature = evt.feature, + coord = evt.coordinate, + address_html = feature.get('address_html'); + content.innerHTML = '

          '+address_html+'

          '; overlay.setPosition(coord); }); @@ -44,15 +41,13 @@ /** * Popup **/ - var - container = doc.getElementById('popup'), - content = doc.getElementById('popup-content'), - closer = doc.getElementById('popup-closer'), - overlay = new ol.Overlay({ - element: container, - offset: [0, -40] - }) - ; + var container = doc.getElementById('popup'), + content = doc.getElementById('popup-content'), + closer = doc.getElementById('popup-closer'), + overlay = new ol.Overlay({ + element: container, + offset: [0, -40] + }); closer.onclick = function() { overlay.setPosition(undefined); closer.blur(); diff --git a/package.json b/package.json index 41344aa..d1dd5c2 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,36 @@ { "name": "ol3-geocoder", - "version": "1.7.0", + "version": "2.0.0", "description": "A geocoder extension for OpenLayers 3.", - "main": "ol3-geocoder.js", "author": "Jonatas Walker", + "homepage": "https://github.com/jonataswalker/ol3-geocoder", "license": "MIT", + "main": "build/ol3-geocoder.js", + "rollup": { + "entry": "src/js/base.js", + "dest": "build/ol3-geocoder-debug.js", + "moduleName": "Geocoder" + }, + "repository": { + "type": "git", + "url": "git://github.com/jonataswalker/ol3-geocoder.git" + }, + "bugs": { + "url": "https://github.com/jonataswalker/ol3-geocoder/issues" + }, "devDependencies": { - "eslint": "latest", - "js-beautify": "latest", - "uglify-js": "latest", - "clean-css": "latest", - "autoprefixer": "latest", - "postcss-cli": "latest", - "nodemon": "latest", - "parallelshell": "latest" + "autoprefixer": "^6.3.6", + "clean-css": "^3.4.12", + "eslint": "^2.8.0", + "node-sass": "^3.4.2", + "node-sass-json-importer": "^1.0.6", + "nodemon": "^1.9.1", + "parallelshell": "^2.0.0", + "postcss-cli": "^2.5.1", + "rollup": "^0.25.8", + "rollup-plugin-buble": "^0.5.0", + "rollup-plugin-json": "^2.0.0", + "uglify-js": "^2.6.2" }, "eslintConfig": { "env": { @@ -43,11 +60,16 @@ "no-undef": 2, "no-use-before-define": 2, "no-unused-vars": 1, - "no-unreachable": 2, - "strict": [1, "global"], - "key-spacing": 1, + "strict": [ + 1, + "global" + ], + "key-spacing": 0, "new-cap": 1, - "quotes": [2, "single"] + "quotes": [ + 1, + "single" + ] } } } diff --git a/sass-vars.json b/sass-vars.json new file mode 100644 index 0000000..2286e5d --- /dev/null +++ b/sass-vars.json @@ -0,0 +1,14 @@ +{ + "namespace": "ol3-geocoder", + "container_class": "-container", + "control_class": "-search", + "btn_search_class": "-btn-search", + "loading_class": "-loading", + "input_search_class": "-input-search", + "result_class": "-result", + "expanded_class": "-search-expanded", + "country_class": "-country", + "city_class": "-city", + "road_class": "-road", + "OL3_control_class": "ol-control" +} \ No newline at end of file diff --git a/src/base.js b/src/base.js deleted file mode 100644 index f9b8a31..0000000 --- a/src/base.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @constructor - * @extends {ol.control.Control} - * @fires {G.EventType} - * @param {string} control_type Nominatim|Reverse. - * @param {object|undefined} opt_options Options. - */ -G.Base = function(control_type, opt_options){ - utils.assert(typeof control_type === 'string', '@param `control_type`' + - ' should be string type!' - ); - utils.assert(typeof opt_options === 'object' || typeof opt_options === 'undefined', - '@param `opt_options` should be object|undefined type!' - ); - - control_type = control_type || 'nominatim'; - - G.$base = this; - G.$nominatim = new G.Nominatim(opt_options); - - ol.control.Control.call(this, { - element: G.$nominatim.container - }); -}; -ol.inherits(G.Base, ol.control.Control); - -/** - * @return {ol.source.Vector} Returns the source created by this control - */ -G.Base.prototype.getSource = function(){ - return this.getLayer().getSource(); -}; - -/** - * @return {ol.layer.Vector} Returns the layer created by this control - */ -G.Base.prototype.getLayer = function(){ - return G.$nominatim.layer; -}; diff --git a/src/js/base.js b/src/js/base.js new file mode 100644 index 0000000..2cab3a8 --- /dev/null +++ b/src/js/base.js @@ -0,0 +1,47 @@ +import { Nominatim } from './nominatim'; +import utils from './utils'; +import * as constants from './constants'; +import * as vars from '../../sass-vars.json'; + +/** + * @class Base + * @extends {ol.control.Control} + */ +export default class Base { + /** + * @constructor + * @param {string} control_type Nominatim|Reverse. + * @param {object|undefined} opt_options Options. + */ + constructor(control_type = 'nominatim', opt_options = {}) { + utils.assert(typeof control_type == 'string', + '@param `control_type` should be string type!' + ); + utils.assert(typeof opt_options == 'object', + '@param `opt_options` should be object type!' + ); + + this.options = utils.mergeOptions(constants.defaultOptions, opt_options); + + Base.Nominatim = new Nominatim(this); + + ol.control.Control.call(this, { + element: Base.Nominatim.container + }); + } + + /** + * @return {ol.layer.Vector} Returns the layer created by this control + */ + getLayer() { + return Base.Nominatim.layer; + } + + /** + * @return {ol.source.Vector} Returns the source created by this control + */ + getSource() { + return this.getLayer().getSource(); + } +} +ol.inherits(Base, ol.control.Control); diff --git a/src/js/constants.js b/src/js/constants.js new file mode 100644 index 0000000..8517a90 --- /dev/null +++ b/src/js/constants.js @@ -0,0 +1,55 @@ +export const eventType = { + ADDRESSCHOSEN: 'addresschosen' +}; + +export const featureStyle = [ + new ol.style.Style({ + image: new ol.style.Icon({ + anchor: [0.5, 1], + src: [ + 'data:image/png;base64,', + 'iVBORw0KGgoAAAANSUhEUgAAAC0AAAAtCAYAAAA6GuKaAAAABmJLR0QA/wD/AP+gvaeT', + 'AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AQWCiErd9Z21AAABAJJREFUWMPVm', + 'U1oXFUUx3/3zatJx04SDOgiVUMSgrXJwpqIKy26SrKoLjQgCkIFW7otuCvdllbo1q6Epg', + 'vNQvtx710lEFdihwpSjdikJLGJWEhrM9MyX7nPxbypwzBv5n3cqXpgmOHOuff/mzPn3Pf', + 'ueWDBpqZnrPq1M5EUVitZ+9wPvA0cAgaALqAIbAI3gAWt5HbjvCcGXROdmp4RwDDwBfBW', + 'iKmLwKfAqlbSiwvvJAAeAeaBWyGB8f1uAfNT0zMj/jqdjXQd8Ds+sJsguyrAe1rJb6NGX', + 'MQAPgJ8k7QefPOAd7WSl6OAi4jAk8D3cdKqhRngda3k9bDgUSL9NLAO9GPftoEXtZIPrR', + 'WiXyzHwwAbA8WyoFAUFMsCY0JB9wPHwxalGyH3T4RxHByo8MZEgf4+w/ZfDt9lu9n4I5T', + 'MCeBzP8+tQL8KDAZuA7swOljh4yM5JsaKGAPGA0fABzN5sje7+PJyht/WXNxU8O/1dbK2', + '9ulPWn05tL/CqWP3GR8tUSgKSmVBpVJ9LxQF46MlTh27z9D+SiKdqNCBFw/jwexUnr4eg', + 'xfwx3oe9PUYZqfyGC+eThzo4SCYTNpweLLQtuCMgcOTBTLp4B8XpBMXuqnfroGxkTIi5M', + 'YpRNV/1yTjCQv9oHmkBXu7vRD1/s/1b2+3h+eJSDpxoa83G0w5HisbLqRCrpKClQ2XlON', + 'F0okL/XXTyQ6sbe1h/Y7bNkWEgPU7Lmtbe3CcaDpxoS8CuaYbfcpj7mqmVXE9Ltq5qxnc', + 'VKBjztexBl0Azgd9uZTt4spimlJZkHKqUa29Ug6UyoIri2mWsl2tNM77OlZvmIaBn4B00', + '6tiRfDSUIk3JwocerlIzz7DTt7hxi9dLGW7+fX2U7huYJQfAeNayduduDX9Cni/3X5sPI', + 'HnVSPtCK9VDj/OZa3krPVbUx++J+y2FNF6tZI71s+IfhR2gNOWgU9rJXeinBUjnxGBF4A', + 'fgWcsAN8DXgE2OnJGbIC/CHxoAXpOK/lRx1sIvn1mKTVirRO377EFnE0IfFYrudXxvkdD', + 'bvcCvwOZGEvkgOeBB0+kwwTU9tIccClmlC8Bubj9vKQNyAPAzxHX8YCDWsnluLpOAmB84', + 'fmIU+e1kstJ2r42OkVH/S5R2G7S0aSCsaFrHU+tZB44F3LaOa1k/l/pTzfZSQ4APwD7Wr', + 'jmgdeA5STAttKjltsLbdwWkhSf1UjXRfxZ4M8WLs9pJe/a0HIsAeMDnQlwOaOVvPufeFD', + 'UJLcH/H27t6EtcBDYTJrLViNdl9ubwLWG4Wv+uDUTWDb/LLlSNzSilVy1qeFYBsYHvOAP', + 'XdBKrtrK5Y5A19lJqo8kTnZi8U6kRy0YY8BNwNgqwP+1/Q09w5giQWRk7AAAAABJRU5Er', + 'kJggg==' + ].join('') + }) + }) +]; + +export const providers = { + OSM: 'osm', + MAPQUEST: 'mapquest', + GOOGLE: 'google', + PHOTON: 'photon', + PELIAS: 'pelias' +}; + +export const defaultOptions = { + provider: providers.OSM, + placeholder: 'Search for an address', + featureStyle: featureStyle, + lang: 'en-US', + limit: 5, + keepOpen: false, + debug: false +}; \ No newline at end of file diff --git a/src/js/nominatim.js b/src/js/nominatim.js new file mode 100644 index 0000000..02a82b8 --- /dev/null +++ b/src/js/nominatim.js @@ -0,0 +1,337 @@ +import * as vars from '../../sass-vars.json'; +import * as constants from './constants'; +import utils from './utils'; +import { Photon } from './providers/photon'; +import { OpenStreet } from './providers/osm'; +import { MapQuest } from './providers/mapquest'; +import { Pelias } from './providers/pelias'; +import { Google } from './providers/google'; + +/** + * @class Nominatim + */ +export class Nominatim { + /** + * @constructor + * @param {Function} base Base class. + */ + constructor(base) { + this.Base = base; + + this.layer_name = utils.randomId('geocoder-layer-'); + this.layer = new ol.layer.Vector({ + name: this.layer_name, + source: new ol.source.Vector() + }); + + this.options = base.options; + this.options.provider = this.options.provider.toLowerCase(); + + this.els = this.createControl(); + this.container = this.els.container; + this.registered_listeners = { + map_click: false + }; + this.setListeners(); + + // providers + this.Photon = new Photon(); + this.OpenStreet = new OpenStreet(); + this.MapQuest = new MapQuest(); + this.Pelias = new Pelias(); + this.Google = new Google(); + + return this; + } + + createControl() { + const container = utils.createElement([ + 'div', { classname: vars.namespace + vars.container_class } + ], Nominatim.html); + + const elements = { + container: container, + control: + container.querySelector(`.${vars.namespace + vars.control_class}`), + btn_search: + container.querySelector(`.${vars.namespace + vars.btn_search_class}`), + input_search: + container.querySelector(`.${vars.namespace + vars.input_search_class}`), + result_container: + container.querySelector(`.${vars.namespace + vars.result_class}`) + }; + //set placeholder from options + elements.input_search.placeholder = this.options.placeholder; + return elements; + } + + setListeners() { + let openSearch = () => { + if(utils.hasClass(this.els.control, vars.namespace + vars.expanded_class)) { + this.collapse(); + } else { + this.expand(); + } + }, + query = evt => { + if (evt.keyCode == 13) { //enter key + const q = utils.htmlEscape(this.els.input_search.value); + this.query(q); + } + }; + this.els.input_search.addEventListener('keydown', query, false); + this.els.btn_search.addEventListener('click', openSearch, false); + } + + query(q) { + let this_ = this, + options = this.options, + input = this.els.input_search, + provider = this.getProvider({ + query: q, + provider: options.provider, + key: options.key, + lang: options.lang, + countrycodes: options.countrycodes, + limit: options.limit + }); + + this.clearResults(); + utils.addClass(input, vars.namespace + vars.loading_class); + + utils.json(provider.url, provider.params).when({ + ready: response => { + if (options.debug) { + console.info(response); + } + + utils.removeClass(input, vars.namespace + vars.loading_class); + + //will be fullfiled according to provider + let response__; + + switch (options.provider) { + case constants.providers.OSM: + response__ = response.length > 0 ? + this.OpenStreet.handleResponse(response) : undefined; + break; + case constants.providers.MAPQUEST: + response__ = response.length > 0 ? + this.MapQuest.handleResponse(response) : undefined; + break; + case constants.providers.PELIAS: + response__ = response.features.length > 0 ? + this.Pelias.handleResponse(response.features) : undefined; + break; + case constants.providers.PHOTON: + response__ = response.features.length > 0 ? + this.Photon.handleResponse(response.features) : undefined; + break; + case constants.providers.GOOGLE: + response__ = response.results.length > 0 ? + this.Google.handleResponse(response.results) : undefined; + break; + } + if(response__){ + this.createList(response__); + this.listenMapClick(); + } + }, + error: () => { + utils.removeClass(input, vars.namespace + vars.loading_class); + const li = utils.createElement('li', + '
          Error! No internet connection?
          '); + this.els.result_container.appendChild(li); + } + }); + } + + createList(response) { + const ul = this.els.result_container; + response.forEach(row => { + let address_html = this.addressTemplate(row.address), + html = '' + address_html + '', + li = utils.createElement('li', html); + + li.addEventListener('click', evt => { + evt.preventDefault(); + this.chosen(row, address_html, row.address, row.original); + }, false); + + ul.appendChild(li); + }); + } + + chosen(place, address_html, address_obj, address_original) { + if(this.options.keepOpen === false){ + this.clearResults(true); + } + + let map = this.Base.getMap(), + view = map.getView(), + projection = view.getProjection(), + coord = ol.proj.transform( + [parseFloat(place.lon), parseFloat(place.lat)], + 'EPSG:4326', projection + ), + resolution = 2.388657133911758, duration = 500, + obj = { + coord: coord, + address_html: address_html, + address_obj: address_obj, + address_original: address_original + }, + pan = ol.animation.pan({ + duration: duration, + source: view.getCenter() + }), + zoom = ol.animation.zoom({ + duration: duration, + resolution: view.getResolution() + }); + + map.beforeRender(pan, zoom); + view.setCenter(coord); + view.setResolution(resolution); + this.createFeature(obj); + } + + createFeature(obj) { + const feature = new ol.Feature({ + address_html: obj.address_html, + address_obj: obj.address_obj, + address_original: obj.address_original, + geometry: new ol.geom.Point(obj.coord) + }); + + this.addLayer(); + feature.setStyle(this.options.featureStyle); + feature.setId(utils.randomId('geocoder-ft-')); + this.getSource().addFeature(feature); + this.Base.dispatchEvent({ + type: constants.eventType.ADDRESSCHOSEN, + feature: feature, + coordinate: obj.coord, + }); + } + + addressTemplate(address) { + let html = []; + if (address.name) { + html.push( + '{name}' + ); + } + if (address.road || address.building || address.house_number) { + html.push( + '{building} {road} {house_number}' + ); + } + if (address.city || address.town || address.village) { + html.push( + '{postcode} {city} {town} {village}' + ); + } + if (address.state || address.country) { + html.push( + '{state} {country}' + ); + } + return utils.template(html.join('
          '), address); + } + + getProvider(options) { + let provider; + + switch(options.provider) { + case constants.providers.OSM: + provider = this.OpenStreet.getParameters(options); + break; + case constants.providers.MAPQUEST: + provider = this.MapQuest.getParameters(options); + break; + case constants.providers.PHOTON: + provider = this.Photon.getParameters(options); + break; + case constants.providers.GOOGLE: + provider = this.Google.getParameters(options); + break; + case constants.providers.PELIAS: + provider = this.Pelias.getParameters(options); + break; + } + return provider; + } + + expand() { + utils.removeClass(this.els.input_search, vars.namespace + vars.loading_class); + utils.addClass(this.els.control, vars.namespace + vars.expanded_class); + window.setTimeout(() => { + this.els.input_search.focus(); + }, 100); + this.listenMapClick(); + } + + collapse() { + this.els.input_search.value = ''; + this.els.input_search.blur(); + utils.removeClass(this.els.control, vars.namespace + vars.expanded_class); + this.clearResults(); + } + + listenMapClick() { + if(this.registered_listeners.map_click) { + // already registered + return; + } + + const this_ = this; + const map_element = this.Base.getMap().getTargetElement(); + this.registered_listeners.map_click = true; + + //one-time fire click + map_element.addEventListener('click', { + handleEvent: function (evt) { + this_.clearResults(true); + map_element.removeEventListener(evt.type, this, false); + this_.registered_listeners.map_click = false; + } + }, false); + } + + clearResults(collapse) { + if(collapse) { + this.collapse(); + } else { + utils.removeAllChildren(this.els.result_container); + } + } + + getSource() { + return this.layer.getSource(); + } + + addLayer() { + let found = false; + const map = this.Base.getMap(); + + map.getLayers().forEach(layer => { + if (layer === this.layer) found = true; + }); + if (!found) { + map.addLayer(this.layer); + } + } +} + +Nominatim.html = [ + `
          `, + ``, + '`, + '
          ', + `
            ` +].join(''); diff --git a/src/js/providers/google.js b/src/js/providers/google.js new file mode 100644 index 0000000..34bac58 --- /dev/null +++ b/src/js/providers/google.js @@ -0,0 +1,107 @@ +import utils from '../utils'; + +/** + * @class Google + */ +export class Google { + /** + * @constructor + */ + constructor() { + + this.settings = { + url: 'https://maps.googleapis.com/maps/api/geocode/json', + params: { + address: '', + key: '', + language: 'en-US' + } + }; + } + + getParameters(options) { + return { + url: this.settings.url, + params: { + address: options.query, + key: options.key, + language: options.lang || this.settings.params.language + } + }; + } + + handleResponse(results) { + const name = [ + 'point_of_interest', + 'establishment', + 'natural_feature', + 'airport' + ], + road = [ + 'street_address', + 'route', + 'sublocality_level_5', + 'intersection' + ], + postcode = [ 'postal_code' ], + city = [ 'locality' ], + state = [ 'administrative_area_level_1' ], + country = [ 'country' ]; + + /* + * @param {Array} details - address_components + */ + const getDetails = details => { + let parts = { + name: '', + road: '', + postcode: '', + city: '', + state: '', + country: '' + }; + details.forEach(detail => { + if(utils.anyMatchInArray(detail.types, name)){ + parts.name = detail.long_name; + } else if(utils.anyMatchInArray(detail.types, road)){ + parts.road = detail.long_name; + } else if(utils.anyMatchInArray(detail.types, postcode)){ + parts.postcode = detail.long_name; + } else if(utils.anyMatchInArray(detail.types, city)){ + parts.city = detail.long_name; + } else if(utils.anyMatchInArray(detail.types, state)){ + parts.state = detail.long_name; + } else if(utils.anyMatchInArray(detail.types, country)){ + parts.country = detail.long_name; + } + }); + return parts; + }; + + let array = []; + + results.forEach(result => { + let details = getDetails(result.address_components); + if(utils.anyItemHasValue(details)){ + array.push({ + lon: result.geometry.location.lng, + lat: result.geometry.location.lat, + address: { + name: details.name, + postcode: details.postcode, + road: details.road, + city: details.city, + state: details.state, + country: details.country + }, + original: { + formatted: result.formatted_address, + details: result.address_components + } + }); + } + }); + + return array; + } +} \ No newline at end of file diff --git a/src/js/providers/mapquest.js b/src/js/providers/mapquest.js new file mode 100644 index 0000000..188811a --- /dev/null +++ b/src/js/providers/mapquest.js @@ -0,0 +1,57 @@ +/** + * @class MapQuest + */ +export class MapQuest { + /** + * @constructor + */ + constructor() { + + this.settings = { + url: 'http://open.mapquestapi.com/nominatim/v1/search.php', + params: { + q: '', + key: '', + format: 'json', + addressdetails: 1, + limit: 10, + countrycodes: '', + 'accept-language': 'en-US' + } + }; + } + + getParameters(options) { + return { + url: this.settings.url, + params: { + q: options.query, + key: options.key, + format: 'json', + addressdetails: 1, + limit: options.limit || this.settings.params.limit, + countrycodes: options.countrycodes || this.settings.params.countrycodes, + 'accept-language': options.lang || this.settings.params['accept-language'] + } + }; + } + + handleResponse(results) { + return results.map(result => ({ + lon: result.lon, + lat: result.lat, + address: { + name: result.address.neighbourhood || '', + road: result.address.road || '', + postcode: result.address.postcode, + city: result.address.city || result.address.town, + state: result.address.state, + country: result.address.country + }, + original: { + formatted: result.display_name, + details: result.address + } + })); + } +} \ No newline at end of file diff --git a/src/js/providers/osm.js b/src/js/providers/osm.js new file mode 100644 index 0000000..a9d5bff --- /dev/null +++ b/src/js/providers/osm.js @@ -0,0 +1,55 @@ +/** + * @class OpenStreet + */ +export class OpenStreet { + /** + * @constructor + */ + constructor() { + + this.settings = { + url: 'http://nominatim.openstreetmap.org/search/', + params: { + q: '', + format: 'json', + addressdetails: 1, + limit: 10, + countrycodes: '', + 'accept-language': 'en-US' + } + }; + } + + getParameters(options) { + return { + url: this.settings.url, + params: { + q: options.query, + format: 'json', + addressdetails: 1, + limit: options.limit || this.settings.params.limit, + countrycodes: options.countrycodes || this.settings.params.countrycodes, + 'accept-language': options.lang || this.settings.params['accept-language'] + } + }; + } + + handleResponse(results) { + return results.map(result => ({ + lon: result.lon, + lat: result.lat, + address: { + name: result.address.neighbourhood || '', + road: result.address.road || '', + postcode: result.address.postcode, + city: result.address.city || result.address.town, + state: result.address.state, + country: result.address.country + }, + original: { + formatted: result.display_name, + details: result.address + } + })); + } +} \ No newline at end of file diff --git a/src/js/providers/pelias.js b/src/js/providers/pelias.js new file mode 100644 index 0000000..d364fef --- /dev/null +++ b/src/js/providers/pelias.js @@ -0,0 +1,50 @@ +/** + * @class Pelias + */ +export class Pelias { + /** + * @constructor + */ + constructor() { + + this.settings = { + url: 'https://search.mapzen.com/v1/search', + params: { + text: '', + key: '', + size: 10 + } + }; + } + + getParameters(options) { + return { + url: this.settings.url, + params: { + text: options.query, + key: options.key, + size: options.limit || this.settings.params.size + } + }; + } + + handleResponse(results) { + return results.map(result => ({ + lon: result.geometry.coordinates[0], + lat: result.geometry.coordinates[1], + address: { + name: result.properties.name, + house_number: result.properties.housenumber, + postcode: result.properties.postalcode, + road: result.properties.street, + city: result.properties.city, + state: result.properties.region, + country: result.properties.country + }, + original: { + formatted: result.properties.label, + details: result.properties + } + })); + } +} \ No newline at end of file diff --git a/src/js/providers/photon.js b/src/js/providers/photon.js new file mode 100644 index 0000000..43800a8 --- /dev/null +++ b/src/js/providers/photon.js @@ -0,0 +1,53 @@ +/** + * @class Photon + */ +export class Photon { + /** + * @constructor + */ + constructor() { + + this.settings = { + url: 'http://photon.komoot.de/api/', + params: { + q: '', + limit: 10, + lang: 'en' + }, + langs: ['de', 'it', 'fr', 'en'] + }; + + } + + getParameters(options) { + options.lang = options.lang.toLowerCase(); + + return { + url: this.settings.url, + params: { + q: options.query, + limit: options.limit || this.settings.params.limit, + lang: this.settings.langs.indexOf(options.lang) > -1 ? + options.lang : this.settings.params.lang + } + }; + } + + handleResponse(results) { + return results.map(result => ({ + lon: result.geometry.coordinates[0], + lat: result.geometry.coordinates[1], + address: { + name: result.properties.name, + postcode: result.properties.postcode, + city: result.properties.city, + state: result.properties.state, + country: result.properties.country + }, + original: { + formatted: result.properties.name, + details: result.properties + } + })); + } +} \ No newline at end of file diff --git a/src/js/utils.js b/src/js/utils.js new file mode 100644 index 0000000..bc1a180 --- /dev/null +++ b/src/js/utils.js @@ -0,0 +1,279 @@ +/** + * @module utils + * All the helper functions needed in this project + */ +export default { + toQueryString(obj) { + return Object.keys(obj).reduce((a, k) => { + a.push( + typeof obj[k] === 'object' ? + this.toQueryString(obj[k]) : + encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]) + ); + return a; + }, []).join('&'); + }, + encodeUrlXhr(url, data) { + if(data && typeof(data) === 'object') { + const str_data = this.toQueryString(data); + url += (/\?/.test(url) ? '&' : '?') + str_data; + } + return url; + }, + json(url, data) { + let xhr = new XMLHttpRequest(), + when = {}, + onload = () => { + if (xhr.status === 200) { + when.ready.call(undefined, JSON.parse(xhr.response)); + } + }, + onerror = () => { + console.info('Cannot XHR ' + JSON.stringify(url)); + }; + url = this.encodeUrlXhr(url, data); + xhr.open('GET', url, true); + xhr.setRequestHeader('Accept','application/json'); + xhr.onload = onload; + xhr.onerror = onerror; + xhr.send(null); + + return { + when: obj => { when.ready = obj.ready; } + }; + }, + randomId(prefix) { + const id = window.performance.now().toString(36); + return prefix ? prefix + id : id; + }, + to3857(coord) { + return ol.proj.transform( + [parseFloat(coord[0]), parseFloat(coord[1])], + 'EPSG:4326', 'EPSG:3857' + ); + }, + to4326(coord) { + return ol.proj.transform( + [parseFloat(coord[0]), parseFloat(coord[1])], + 'EPSG:3857', 'EPSG:4326' + ); + }, + isNumeric(str) { + return /^\d+$/.test(str); + }, + classRegex(classname) { + return new RegExp(`(^|\\s+) ${classname} (\\s+|$)`); + }, + /** + * @param {Element|Array} element DOM node or array of nodes. + * @param {String|Array} classname Class or array of classes. + * For example: 'class1 class2' or ['class1', 'class2'] + * @param {Number|undefined} timeout Timeout to remove a class. + */ + addClass(element, classname, timeout) { + if (Array.isArray(element)) { + element.forEach(each => { this.addClass(each, classname) }); + return; + } + + const array = (Array.isArray(classname)) ? classname : classname.split(/\s+/); + let i = array.length; + + while(i--) { + if (!this.hasClass(element, array[i])) { + this._addClass(element, array[i], timeout); + } + } + }, + _addClass(el, c, timeout) { + // use native if available + if (el.classList) { + el.classList.add(c); + } else { + el.className = (el.className +' '+ c).trim(); + } + + if (timeout && this.isNumeric(timeout)) { + window.setTimeout(() => { this._removeClass(el, c) }, timeout); + } + }, + /** + * @param {Element|Array} element DOM node or array of nodes. + * @param {String|Array} classname Class or array of classes. + * For example: 'class1 class2' or ['class1', 'class2'] + * @param {Number|undefined} timeout Timeout to add a class. + */ + removeClass(element, classname, timeout) { + if (Array.isArray(element)) { + element.forEach(each => { this.removeClass(each, classname, timeout) }); + return; + } + + const array = (Array.isArray(classname)) ? classname : classname.split(/\s+/); + let i = array.length; + + while(i--) { + if (this.hasClass(element, array[i])) { + this._removeClass(element, array[i], timeout); + } + } + }, + _removeClass(el, c, timeout) { + if (el.classList) { + el.classList.remove(c); + } else { + el.className = (el.className.replace(this.classRegex(c), ' ')).trim(); + } + if (timeout && this.isNumeric(timeout)) { + window.setTimeout(() => { + this._addClass(el, c); + }, timeout); + } + }, + /** + * @param {Element} element DOM node. + * @param {String} classname Classname. + * @return {Boolean} + */ + hasClass(element, c) { + // use native if available + return (element.classList) ? + element.classList.contains(c) : this.classRegex(c).test(element.className); + }, + /** + * @param {Element|Array} element DOM node or array of nodes. + * @param {String} classname Classe. + */ + toggleClass(element, classname) { + if (Array.isArray(element)) { + element.forEach(each => { this.toggleClass(each, classname) }); + return; + } + + // use native if available + if (element.classList) { + element.classList.toggle(classname); + } else { + if (this.hasClass(element, classname)) { + this._removeClass(element, classname); + } else { + this._addClass(element, classname); + } + } + }, + $(id) { + id = (id[0] === '#') ? id.substr(1, id.length) : id; + return document.getElementById(id); + }, + isElement(obj) { + // DOM, Level2 + if ('HTMLElement' in window) { + return (!!obj && obj instanceof HTMLElement); + } + // Older browsers + return (!!obj && typeof obj === 'object' && + obj.nodeType === 1 && !!obj.nodeName); + }, + getAllChildren(node, tag) { + return [].slice.call(node.getElementsByTagName(tag)); + }, + isEmpty(str) { + return (!str || 0 === str.length); + }, + emptyArray(array) { + while(array.length) array.pop(); + }, + anyMatchInArray(source, target) { + return source.some(each => target.indexOf(each) >= 0); + }, + everyMatchInArray(arr1, arr2) { + return arr2.every(each => arr1.indexOf(each) >= 0); + }, + anyItemHasValue(obj, has = false) { + for(let key in obj) { + if(!this.isEmpty(obj[key])) { + has = true; + } + } + return has; + }, + removeAllChildren(node) { + while (node.firstChild) { + node.removeChild(node.firstChild); + } + }, + removeAll(collection) { + let node; + while ((node = collection[0])) { + node.parentNode.removeChild(node); + } + }, + getChildren(node, tag) { + return [].filter.call(node.childNodes, el => tag ? + el.nodeType == 1 && el.tagName.toLowerCase() == tag : el.nodeType == 1); + }, + template(html, row) { + return html.replace(/\{ *([\w_-]+) *\}/g, (html, key) => { + let value = (row[key] === undefined) ? '' : row[key]; + return this.htmlEscape(value); + }); + }, + htmlEscape(str) { + return String(str) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + }, + /** + * Overwrites obj1's values with obj2's and adds + * obj2's if non existent in obj1 + * @returns obj3 a new object based on obj1 and obj2 + */ + mergeOptions: function(obj1, obj2){ + let obj3 = {}; + for (let attr1 in obj1) { obj3[attr1] = obj1[attr1]; } + for (let attr2 in obj2) { obj3[attr2] = obj2[attr2]; } + return obj3; + }, + createElement(node, html) { + let elem; + if (Array.isArray(node)) { + elem = document.createElement(node[0]); + + if (node[1].id) elem.id = node[1].id; + if (node[1].classname) elem.className = node[1].classname; + + if (node[1].attr) { + let attr = node[1].attr; + if (Array.isArray(attr)) { + let i = -1; + while(++i < attr.length) { + elem.setAttribute(attr[i].name, attr[i].value); + } + } else { + elem.setAttribute(attr.name, attr.value); + } + } + } else { + elem = document.createElement(node); + } + elem.innerHTML = html; + let frag = document.createDocumentFragment(); + + while (elem.childNodes[0]) { + frag.appendChild(elem.childNodes[0]); + } + elem.appendChild(frag); + return elem; + }, + assert(condition, message = 'Assertion failed') { + if (!condition) { + if (typeof Error !== 'undefined') { + throw new Error(message); + } + throw message; // Fallback + } + } +}; diff --git a/src/nominatim.js b/src/nominatim.js deleted file mode 100644 index 7ae1a96..0000000 --- a/src/nominatim.js +++ /dev/null @@ -1,569 +0,0 @@ -/** - * @constructor - */ -G.Nominatim = function(opt_options){ - this.layer_name = utils.randomId('geocoder-layer-'); - this.layer = new ol.layer.Vector({ - name: this.layer_name, - source: new ol.source.Vector() - }); - var defaults = { - provider: 'osm', - placeholder: 'Search for an address', - featureStyle: G.Nominatim.featureStyle, - lang: 'en-US', - limit: 5, - keepOpen: false, - debug: false - }; - - this.options = utils.mergeOptions(defaults, opt_options); - this.options.provider = this.options.provider.toLowerCase(); - this.constants = { - road: 'ol-geocoder-road', - city: 'ol-geocoder-city', - country: 'ol-geocoder-country', - class_container: 'ol-geocoder', - expanded_class: 'ol-geocoder-search-expanded' - }; - - this.container = this.createControl(); - this.els = G.Nominatim.elements; - this.registered_listeners = { - map_click: false - }; - this.setListeners(); - return this; -}; - -G.Nominatim.prototype = { - createControl: function(){ - var container = utils.createElement([ - 'div', { classname: this.constants.class_container } - ], G.Nominatim.html); - - G.Nominatim.elements = { - container: container, - control: container.querySelector('.ol-geocoder-search'), - btn_search: container.querySelector('.ol-geocoder-btn-search'), - input_search: container.querySelector('.ol-geocoder-input-search'), - result_container: container.querySelector('.ol-geocoder-result') - }; - //set placeholder from options - G.Nominatim.elements.input_search.placeholder = this.options.placeholder; - - return container; - }, - setListeners: function(){ - var - this_ = this, - openSearch = function() { - if(utils.hasClass(this_.els.control, this_.constants.expanded_class)){ - this_.collapse(); - } else { - this_.expand(); - } - }, - query = function(evt){ - if (evt.keyCode == 13){ //enter key - var q = utils.htmlEscape(this_.els.input_search.value); - this_.query(q); - } - } - ; - this_.els.input_search.addEventListener('keydown', query, false); - this_.els.btn_search.addEventListener('click', openSearch, false); - }, - listenMapClick: function() { - if(this.registered_listeners.map_click) { - // already registered - return; - } - - var this_ = this; - var map_element = G.$base.getMap().getTargetElement(); - this.registered_listeners.map_click = true; - - //one-time fire click - map_element.addEventListener('click', { - handleEvent: function (evt) { - this_.clearResults(true); - map_element.removeEventListener(evt.type, this, false); - this_.registered_listeners.map_click = false; - } - }, false); - }, - expand: function(){ - utils.removeClass(this.els.input_search, 'ol-geocoder-loading'); - utils.addClass(this.els.control, this.constants.expanded_class); - var input = this.els.input_search; - window.setTimeout(function(){ - input.focus(); - }, 100); - this.listenMapClick(); - }, - collapse: function(){ - this.els.input_search.value = ''; - this.els.input_search.blur(); - utils.removeClass(this.els.control, this.constants.expanded_class); - this.clearResults(); - }, - clearResults: function(collapse){ - if(collapse) { - this.collapse(); - } else { - utils.removeAllChildren(this.els.result_container); - } - }, - query: function(query){ - var this_ = this, - options = this.options, - input = this.els.input_search, - providers_names = G.Nominatim.providers.names, - provider = this.getProvider({ - provider: options.provider, - key: options.key, - query: query, - lang: options.lang, - countrycodes: options.countrycodes, - limit: options.limit - }); - - this.clearResults(); - utils.addClass(input, 'ol-geocoder-loading'); - - utils.json(provider.url, provider.params).when({ - ready: function(response){ - if(options.debug){ - console.info(response); - } - - utils.removeClass(input, 'ol-geocoder-loading'); - - //will be fullfiled according to provider - var response__; - - switch (this_.options.provider) { - case providers_names.OSM: - case providers_names.MAPQUEST: - response__ = response.length > 0 ? - this_.mapquestResponse(response) : undefined; - break; - case providers_names.PELIAS: - response__ = response.features.length > 0 ? - this_.peliasResponse(response.features) : undefined; - break; - case providers_names.PHOTON: - response__ = response.features.length > 0 ? - this_.photonResponse(response.features) : undefined; - break; - case providers_names.GOOGLE: - response__ = response.results.length > 0 ? - this_.googleResponse(response.results) : undefined; - break; - } - if(response__){ - this_.createList(response__); - this_.listenMapClick(); - } - }, - error: function(){ - utils.removeClass(input, 'ol-geocoder-loading'); - var li = utils.createElement('li', - '
            Error! No internet connection?
            '); - this_.els.result_container.appendChild(li); - } - }); - }, - createList: function(response){ - var this_ = this; - var ul = this.els.result_container; - response.forEach(function(row) { - var - address_html = this_.addressTemplate(row), - html = '' + address_html + '', - li = utils.createElement('li', html) - ; - li.addEventListener('click', function(evt){ - evt.preventDefault(); - this_.chosen(row, address_html, row.address, row.original); - }, false); - - ul.appendChild(li); - }); - }, - addressTemplate: function(r){ - var row = r.address, html = []; - if (row.name) { - html.push( - '{name}' - ); - } - if (row.road || row.building || row.house_number) { - html.push( - '{building} {road} {house_number}' - ); - } - if (row.city || row.town || row.village) { - html.push( - '{postcode} {city} {town} {village}' - ); - } - if (row.state || row.country) { - html.push( - '{state} {country}' - ); - } - return utils.template(html.join('
            '), row); - }, - chosen: function(place, address_html, address_obj, address_original){ - if(this.options.keepOpen === false){ - this.clearResults(true); - } - - var map = G.$base.getMap(), - view = map.getView(), - projection = view.getProjection(), - coord = ol.proj.transform( - [parseFloat(place.lon), parseFloat(place.lat)], - 'EPSG:4326', projection - ), - resolution = 2.388657133911758, duration = 500, - obj = { - coord: coord, - address_html: address_html, - address_obj: address_obj, - address_original: address_original - }, - pan = ol.animation.pan({ - duration: duration, - source: view.getCenter() - }), - zoom = ol.animation.zoom({ - duration: duration, - resolution: view.getResolution() - }); - - map.beforeRender(pan, zoom); - view.setCenter(coord); - view.setResolution(resolution); - this.createFeature(obj); - }, - createFeature: function(obj){ - var feature = new ol.Feature({ - address_html: obj.address_html, - address_obj: obj.address_obj, - address_original: obj.address_original, - geometry: new ol.geom.Point(obj.coord) - }), - feature_id = utils.randomId('geocoder-ft-'), - feature_style = this.options.featureStyle || G.Nominatim.featureStyle; - - this.addLayer(); - feature.setStyle(feature_style); - feature.setId(feature_id); - this.getSource().addFeature(feature); - G.$base.dispatchEvent({ - type: G.EventType.ADDRESSCHOSEN, - feature: feature, - coordinate: obj.coord, - }); - }, - mapquestResponse: function(results){ - var array = results.map(function(result){ - return { - lon: result.lon, - lat: result.lat, - address: { - name: result.address.neighbourhood || '', - road: result.address.road || '', - postcode: result.address.postcode, - city: result.address.city || result.address.town, - state: result.address.state, - country: result.address.country - }, - original: { - formatted: result.display_name, - details: result.address - } - }; - }); - return array; - }, - photonResponse: function(features){ - var array = features.map(function(feature){ - return { - lon: feature.geometry.coordinates[0], - lat: feature.geometry.coordinates[1], - address: { - name: feature.properties.name, - postcode: feature.properties.postcode, - city: feature.properties.city, - state: feature.properties.state, - country: feature.properties.country - }, - original: { - formatted: feature.properties.name, - details: feature.properties - } - }; - }); - return array; - }, - peliasResponse: function(features){ - var array = features.map(function(feature){ - return { - lon: feature.geometry.coordinates[0], - lat: feature.geometry.coordinates[1], - address: { - name: feature.properties.name, - house_number: feature.properties.housenumber, - postcode: feature.properties.postalcode, - road: feature.properties.street, - city: feature.properties.city, - state: feature.properties.region, - country: feature.properties.country - }, - original: { - formatted: feature.properties.label, - details: feature.properties - } - }; - }); - return array; - }, - googleResponse: function(results){ - var - name = [ - 'point_of_interest', - 'establishment', - 'natural_feature', - 'airport' - ], - road = [ - 'street_address', - 'route', - 'sublocality_level_5', - 'intersection' - ], - postcode = [ 'postal_code' ], - city = [ 'locality' ], - state = [ 'administrative_area_level_1' ], - country = [ 'country' ] - ; - - /* - * @param {Array} details - address_components - */ - var getDetails = function(details){ - var parts = { - name: '', - road: '', - postcode: '', - city: '', - state: '', - country: '' - }; - details.forEach(function(detail){ - if(utils.anyMatchInArray(detail.types, name)){ - parts.name = detail.long_name; - } else if(utils.anyMatchInArray(detail.types, road)){ - parts.road = detail.long_name; - } else if(utils.anyMatchInArray(detail.types, postcode)){ - parts.postcode = detail.long_name; - } else if(utils.anyMatchInArray(detail.types, city)){ - parts.city = detail.long_name; - } else if(utils.anyMatchInArray(detail.types, state)){ - parts.state = detail.long_name; - } else if(utils.anyMatchInArray(detail.types, country)){ - parts.country = detail.long_name; - } - }); - return parts; - }; - - var array = []; - results.forEach(function(result){ - var details = getDetails(result.address_components); - if(utils.anyItemHasValue(details)){ - array.push({ - lon: result.geometry.location.lng, - lat: result.geometry.location.lat, - address: { - name: details.name, - postcode: details.postcode, - road: details.road, - city: details.city, - state: details.state, - country: details.country - }, - original: { - formatted: result.formatted_address, - details: result.address_components - } - }); - } - }); - return array; - }, - getSource: function() { - return this.layer.getSource(); - }, - addLayer: function() { - var this_ = this, found = false; - var map = G.$base.getMap(); - - map.getLayers().forEach(function(layer){ - if (layer === this_.layer) found = true; - }); - if (!found) { - map.addLayer(this.layer); - } - }, - getProvider: function(options) { - var params, - provider = G.Nominatim.providers[options.provider], - providers_names = G.Nominatim.providers.names, - requires_key = [ - providers_names.MAPQUEST, - providers_names.PELIAS, - providers_names.GOOGLE - ], - langs_photon = ['de', 'it', 'fr', 'en']; - switch(options.provider) { - case providers_names.OSM: - case providers_names.MAPQUEST: - params = { - q: options.query, - limit: options.limit, - countrycodes: options.countrycodes, - 'accept-language': options.lang - }; - provider.params = utils.mergeOptions(provider.params, params); - break; - case providers_names.PHOTON: - options.lang = options.lang.toLowerCase(); - params = { - q: options.query, - limit: options.limit || provider.params.limit, - lang: (langs_photon.indexOf(options.lang) > -1) ? - options.lang : provider.params.lang - }; - provider.params = utils.mergeOptions(provider.params, params); - break; - case providers_names.GOOGLE: - params = { - address: options.query, - language: options.lang - }; - provider.params = utils.mergeOptions(provider.params, params); - break; - case providers_names.PELIAS: - params = { - text: options.query, - size: options.limit - }; - provider.params = utils.mergeOptions(provider.params, params); - break; - } - if (requires_key.indexOf(options.provider) > -1) { - provider.params.key = options.key; - } - return provider; - } -}; -G.EventType = { - /** - * Triggered when an address is chosen. - */ - ADDRESSCHOSEN: 'addresschosen' -}; - -G.Nominatim.elements = {}; -G.Nominatim.providers = { - names: { - OSM: 'osm', - MAPQUEST: 'mapquest', - GOOGLE: 'google', - PHOTON: 'photon', - PELIAS: 'pelias' - }, - osm: { - url: 'http://nominatim.openstreetmap.org/search/', - params: { - format: 'json', - q: '', - addressdetails: 1, - limit: 10, - countrycodes: '', - 'accept-language': 'en-US' - } - }, - mapquest: { - url: 'http://open.mapquestapi.com/nominatim/v1/search.php', - params: { - key: '', - format: 'json', - q: '', - addressdetails: 1, - limit: 10, - countrycodes: '', - 'accept-language': 'en-US' - } - }, - google: { - url: 'https://maps.googleapis.com/maps/api/geocode/json', - params: { - key: '', - address: '', - language: 'en-US' - } - }, - pelias: { - url: 'https://search.mapzen.com/v1/search', - params: { - key: '', - text: '', - size: 10 - } - }, - photon: { - url: 'http://photon.komoot.de/api/', - params: { - q: '', - limit: 10, - lang: 'en' - } - } -}; -G.Nominatim.featureStyle = [ - new ol.style.Style({ - image: new ol.style.Icon({ - scale: 0.7, - anchor: [0.5, 1], - src: '//cdn.rawgit.com/jonataswalker/' - + 'map-utils/master/images/marker.png' - }), - zIndex: 5 - }), - new ol.style.Style({ - image: new ol.style.Circle({ - fill: new ol.style.Fill({ color: [235, 235, 235, 1]}), - stroke: new ol.style.Stroke({ color: [0, 0, 0, 1]}), - radius: 5 - }), - zIndex: 4 - }) -]; -G.Nominatim.html = [ - '', - '
              ' -].join(''); diff --git a/src/sass/main.scss b/src/sass/main.scss new file mode 100644 index 0000000..3f44d05 --- /dev/null +++ b/src/sass/main.scss @@ -0,0 +1,34 @@ +// dependencies +@import "partials/functions"; +@import "partials/mixins"; + +// global project variables + +@import "../../sass-vars.json"; + +$control-width: 31px; +$control-height: 31px; +$control-expand-width: 220px; +$control-expand-height: 35px; +$input-width: 180px; +$input-left: 32px; +$input-top: 2px; + +$result-width: 260px; +$result-max-height: 300px; +$result-left: $input-left; +$result-top: sum-pixel($control-expand-height, $input-top); + +$btn-search-width: 25px; +$btn-search-height: 25px; +$btn-search-top: $input-top; +$btn-search-left: 2px; + + +$font-big: 16px; +$font-medium: 14px; +$font-small: 12px; + + +// partials +@import "partials/grids"; diff --git a/src/sass/partials/_functions.scss b/src/sass/partials/_functions.scss new file mode 100644 index 0000000..d4126be --- /dev/null +++ b/src/sass/partials/_functions.scss @@ -0,0 +1,24 @@ +@function strip-unit($value) { + @if type-of($value) != "number" { + @warn "You tried to remove unit from NaN (#{type-of($value)})"; + @return $value; + } + @return $value / ($value * 0 + 1); +} + +@function sum-pixel($v1, $v2) { + @return strip-unit($v1) + strip-unit($v2) * 1px; +} + +/// Map deep get +/// @param {Map} $map - Map +/// @param {Arglist} $keys - Key chain +/// @return {*} - Desired value +@function map-deep-get($map, $keys...) { + $value: $map; + @each $key in $keys { + $value: map-get($value, $key); + } + @return $value; +} + diff --git a/src/ol3-geocoder.css b/src/sass/partials/_grids.scss similarity index 85% rename from src/ol3-geocoder.css rename to src/sass/partials/_grids.scss index dea0204..b6bb775 100644 --- a/src/ol3-geocoder.css +++ b/src/sass/partials/_grids.scss @@ -1,99 +1,109 @@ -.ol-geocoder { - position: absolute; +.#{$namespace}#{$container_class} { + position: absolute; top: calc(.5em + 65px); left: .5em; box-sizing: border-box; + + *, + *::before, + *::after { + box-sizing: inherit; + } } -.ol-geocoder *, -.ol-geocoder *::before, -.ol-geocoder *::after { - box-sizing: inherit; -} -.ol-geocoder-search { - width: 31px; - height: 31px; +.#{$namespace}#{$control_class} { + width: $control-width; + height: $control-height; overflow: hidden; - transition: width .2s, height .2s; + transition: width 200ms, height 200ms; } -.ol-geocoder-search-expanded { - width: 220px; - height: 35px; +.#{$namespace}#{$expanded_class} { + width: $control-expand-width; + height: $control-expand-height; } -.ol-geocoder-input-search{ +.#{$namespace}#{$input_search_class} { position: absolute; - top: 2px; left: 32px; - width: 180px; + top: $input-top; + left: $input-left; + width: $input-width; padding: 5px; border: 1px solid #ccc; font-family:inherit; - font-size: 14px; + @include font-size($font-medium); + + &:focus { + border-color: #35b5f4; + } } -.ol-geocoder-input-search:focus { - border-color: #35b5f4; -} -ul.ol-geocoder-result { +ul.#{$namespace}#{$result_class} { position: absolute; - top: 37px; left: 32px; - width: 260px; - max-height: 300px; + top: $result-top; + left: $result-left; + width: $result-width; + max-height: $result-max-height; white-space: normal; list-style: none; padding: 0; margin: 0; - border-top: none; background-color: white; - box-shadow: 0 1px 7px rgba(0, 0, 0, 0.8); border-radius: 4px; + border-top: none; border-top-left-radius: 0; border-top-right-radius: 0; - line-height: 1.2; overflow-x: hidden; overflow-y: auto; + box-shadow: 0 1px 7px rgba(0, 0, 0, 0.8); - transition: height 300ms ease-in; -} -ul.ol-geocoder-result li { - width: 100%; - overflow: hidden; - border-bottom: 1px solid #eee; - padding: 0; -} -ul.ol-geocoder-result li:nth-child(odd) { - background-color: rgb(224, 255, 224); -} -ul.ol-geocoder-result li a { - display: block; - text-decoration: none; - padding: 3px 5px; -} -ul.ol-geocoder-result li a:hover { - background-color: rgb(212, 212, 212); + transition: max-height 300ms ease-in; + + > li { + width: 100%; + overflow: hidden; + border-bottom: 1px solid #eee; + padding: 0; + @include line-height(14); + + > a { + display: block; + text-decoration: none; + padding: 3px 5px; + + &:hover { + background-color: rgb(212, 212, 212); + } + } + } + + > li:nth-child(odd) { + background-color: rgb(224, 255, 224); + } } -.ol-geocoder-road{ - font-size: 14px; - font-weight: bold; +.#{$namespace}#{$road_class} { + @include font-size($font-medium); + font-weight: 700; color: #000; } -.ol-geocoder-city{ - font-size: 12px; +.#{$namespace}#{$city_class} { + @include font-size($font-small); font-weight: normal; color: #000; } -.ol-geocoder-country{ - font-size: 12px; +.#{$namespace}#{$country_class} { + @include font-size($font-small); font-weight: lighter; color: #444; } -.ol-geocoder-btn-search{ +.#{$namespace}#{$btn_search_class} { position: absolute; - width: 25px; height: 25px; - top: 2px; left: 2px; + width: $btn-search-width; + height: $btn-search-height; + top: $btn-search-top; + left: $btn-search-left; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAABPUlEQVQoU41SwXHCQAzUHh58eoUOIBWEDkI6oAToIKkg7iAuwakgpAIowXRACcnrzp6BzchjMx4wE/S6kW5XK60gvQghzJIkmVoqSZI9gJ9+/fINS5Cc1HX9QXIlIr/tpwcRyb33b7cIGnAIYQdg4pxbjcfj0nJ1Xc+Px+PGObdN03Q9RIAQwgpAnqbp7FKmjQGgJLlU1d2V7BjjRkQO3vvXIXarkyxVNbsCm2QR2Q0V7XOMMReRmfd+OQQubN6hYgs22ZtbnRcAtiRfLueqqmpJ8ovko6oeBq0KIWQA3gFkzrlmMafTaUEyI/mpqmbhVTRWWbRdbClPbeobQNES5KPRqOxs7DBn8K1DsAOKMZYApiTXqlrcDe4d0XN7jWeCfzt351tVle2iGalTcBd4gGDvvZ/fDe4RmCOFLe8Pr7mvEP2N9PQAAAAASUVORK5CYII='); background-repeat: no-repeat; background-position: center center; } -.ol-geocoder-loading { +.#{$namespace}#{$loading_class} { background-image: url('data:image/gif;base64,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'); background-repeat: no-repeat; background-position: right center; diff --git a/src/sass/partials/_mixins.scss b/src/sass/partials/_mixins.scss new file mode 100644 index 0000000..e88f373 --- /dev/null +++ b/src/sass/partials/_mixins.scss @@ -0,0 +1,22 @@ +@mixin clearfix { + &::before, + &::after { + content: ""; + display: table; + } + &::after { + clear: both; + } +} + +@mixin font-size($size: 12, $base: 16) { + font-size: (strip-unit($size) / strip-unit($base)) * 1rem; +} + +@mixin line-height($height: 16, $base: 16) { + line-height: (strip-unit($height) / strip-unit($base)) * 1rem; +} + +@mixin background-linear-gradient($color1, $color2) { + background: linear-gradient($color1, $color2); +} \ No newline at end of file diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index ed26da6..0000000 --- a/src/utils.js +++ /dev/null @@ -1,309 +0,0 @@ -/** - * Helper - */ -var utils = { - whiteSpaceRegex: /\s+/, - toQueryString: function(obj){ - return Object.keys(obj).reduce(function(a, k) { - a.push((typeof obj[k] === 'object') ? - utils.toQueryString(obj[k]) : - encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]) - ); - return a; - }, []).join('&'); - }, - encodeUrlXhr: function(url, data) { - if(data && typeof(data) === 'object') { - var str_data = utils.toQueryString(data); - url += (/\?/.test(url) ? '&' : '?') + str_data; - } - return url; - }, - json: function(url, data) { - var xhr = new XMLHttpRequest(), - when = {}, - onload = function() { - if (xhr.status === 200) { - when.ready.call(undefined, JSON.parse(xhr.response)); - } - }, - onerror = function() { - console.info('Cannot XHR ' + JSON.stringify(url)); - }; - url = utils.encodeUrlXhr(url, data); - xhr.open('GET', url, true); - xhr.setRequestHeader('Accept','application/json'); - xhr.onload = onload; - xhr.onerror = onerror; - xhr.send(null); - - return { - when: function(obj) { when.ready = obj.ready; } - }; - }, - randomId: function(prefix){ - var id = (new Date().getTime()).toString(36); - return (prefix) ? prefix + id : id; - }, - to3857: function(coord){ - return ol.proj.transform( - [parseFloat(coord[0]), parseFloat(coord[1])], - 'EPSG:4326', 'EPSG:3857' - ); - }, - to4326: function(coord){ - return ol.proj.transform( - [parseFloat(coord[0]), parseFloat(coord[1])], - 'EPSG:3857', 'EPSG:4326' - ); - }, - isNumeric: function(str){ - return /^\d+$/.test(str); - }, - classRegex: function(classname) { - return new RegExp('(^|\\s+)' + classname + '(\\s+|$)'); - }, - /** - * @param {Element|Array} element DOM node or array of nodes. - * @param {String|Array} classname Class or array of classes. - * For example: 'class1 class2' or ['class1', 'class2'] - * @param {Number|undefined} timeout Timeout to remove a class. - */ - addClass: function(element, classname, timeout){ - if(Array.isArray(element)){ - element.forEach(function(each){ - utils.addClass(each, classname); - }); - return; - } - - var - array = (Array.isArray(classname)) ? classname : classname.split(/\s+/), - i = array.length - ; - while(i--){ - if(!utils.hasClass(element, array[i])) { - utils._addClass(element, array[i], timeout); - } - } - }, - _addClass: function(el, c, timeout){ - // use native if available - if (el.classList) { - el.classList.add(c); - } else { - el.className = (el.className + ' ' + c).trim(); - } - - if(timeout && utils.isNumeric(timeout)){ - window.setTimeout(function(){ - utils._removeClass(el, c); - }, timeout); - } - }, - /** - * @param {Element|Array} element DOM node or array of nodes. - * @param {String|Array} classname Class or array of classes. - * For example: 'class1 class2' or ['class1', 'class2'] - * @param {Number|undefined} timeout Timeout to add a class. - */ - removeClass: function(element, classname, timeout){ - if(Array.isArray(element)){ - element.forEach(function(each){ - utils.removeClass(each, classname, timeout); - }); - return; - } - - var - array = (Array.isArray(classname)) ? classname : classname.split(/\s+/), - i = array.length - ; - while(i--){ - if(utils.hasClass(element, array[i])) { - utils._removeClass(element, array[i], timeout); - } - } - }, - _removeClass: function(el, c, timeout){ - if (el.classList){ - el.classList.remove(c); - } else { - el.className = (el.className.replace(utils.classRegex(c), ' ')).trim(); - } - if(timeout && utils.isNumeric(timeout)){ - window.setTimeout(function() { - utils._addClass(el, c); - }, timeout); - } - }, - /** - * @param {Element} element DOM node. - * @param {String} classname Classname. - * @return {Boolean} - */ - hasClass: function(element, c) { - // use native if available - return (element.classList) ? - element.classList.contains(c) : utils.classRegex(c).test(element.className); - }, - /** - * @param {Element|Array} element DOM node or array of nodes. - * @param {String} classname Classe. - */ - toggleClass: function(element, classname){ - if(Array.isArray(element)) { - element.forEach(function(each) { - utils.toggleClass(each, classname); - }); - return; - } - - // use native if available - if(element.classList) { - element.classList.toggle(classname); - } else { - if(utils.hasClass(element, classname)){ - utils._removeClass(element, classname); - } else { - utils._addClass(element, classname); - } - } - }, - $: function(id){ - id = (id[0] === '#') ? id.substr(1, id.length) : id; - return document.getElementById(id); - }, - isElement: function(obj){ - // DOM, Level2 - if ('HTMLElement' in window) { - return (!!obj && obj instanceof HTMLElement); - } - // Older browsers - return (!!obj && typeof obj === 'object' && - obj.nodeType === 1 && !!obj.nodeName); - }, - getAllChildren: function(node, tag){ - return [].slice.call(node.getElementsByTagName(tag)); - }, - isEmpty: function(str){ - return (!str || 0 === str.length); - }, - emptyArray: function(array){ - while(array.length) array.pop(); - }, - anyMatchInArray: function(source, target) { - return source.some(function(each){ - return target.indexOf(each) >= 0; - }); - }, - everyMatchInArray: function(arr1, arr2) { - return arr2.every(function(each){ - return arr1.indexOf(each) >= 0; - }); - }, - anyItemHasValue: function(obj){ - var has = false; - for(var key in obj){ - if(!utils.isEmpty(obj[key])){ - has = true; - } - } - return has; - }, - removeAllChildren: function(node) { - while (node.firstChild) { - node.removeChild(node.firstChild); - } - }, - removeAll: function(collection) { - var node; - while ((node = collection[0])) { - node.parentNode.removeChild(node); - } - }, - getChildren: function(node, tag){ - return [].filter.call(node.childNodes, function(el) { - return (tag) ? - el.nodeType == 1 && el.tagName.toLowerCase() == tag - : - el.nodeType == 1; - }); - }, - template: function(html, row){ - var this_ = this; - - return html.replace(/\{ *([\w_-]+) *\}/g, function (html, key) { - var value = (row[key] === undefined) ? '' : row[key]; - return this_.htmlEscape(value); - }); - }, - htmlEscape: function(str){ - return String(str) - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); - }, - /** - * Overwrites obj1's values with obj2's and adds - * obj2's if non existent in obj1 - * @returns obj3 a new object based on obj1 and obj2 - */ - mergeOptions: function(obj1, obj2){ - var obj3 = {}; - for (var attr1 in obj1) { obj3[attr1] = obj1[attr1]; } - for (var attr2 in obj2) { obj3[attr2] = obj2[attr2]; } - return obj3; - }, - createElement: function(node, html){ - var elem; - if(Array.isArray(node)){ - elem = document.createElement(node[0]); - - if(node[1].id) { - elem.id = node[1].id; - } - if(node[1].classname) { - elem.className = node[1].classname; - } - - if(node[1].attr){ - var attr = node[1].attr; - if(Array.isArray(attr)){ - var i = -1; - while(++i < attr.length){ - elem.setAttribute(attr[i].name, attr[i].value); - } - } else { - elem.setAttribute(attr.name, attr.value); - } - } - } else{ - elem = document.createElement(node); - } - elem.innerHTML = html; - var frag = document.createDocumentFragment(); - - while (elem.childNodes[0]) { - frag.appendChild(elem.childNodes[0]); - } - elem.appendChild(frag); - return elem; - }, - assert: function(condition, message) { - if (!condition) { - message = message || 'Assertion failed'; - if (typeof Error !== 'undefined') { - throw new Error(message); - } - throw message; // Fallback - } - }, - assertEqual: function(a, b, message) { - if (a != b) { - throw new Error(message + ' mismatch: ' + a + ' != ' + b); - } - } -}; diff --git a/src/wrapper-head.js b/src/wrapper-head.js deleted file mode 100644 index a8abae8..0000000 --- a/src/wrapper-head.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -(function (root, factory) { - if (typeof exports === 'object') { - module.exports = factory(); - } else if (typeof define === 'function' && define.amd) { - define([], factory); - } else { - root.Geocoder = factory(); - } -}(this, function () { - - var G = {}; \ No newline at end of file diff --git a/src/wrapper-tail.js b/src/wrapper-tail.js deleted file mode 100644 index 66f34cf..0000000 --- a/src/wrapper-tail.js +++ /dev/null @@ -1,2 +0,0 @@ - return G.Base; -}));