diff --git a/fabfile.py b/fabfile.py
index ac773963..62b26cfd 100644
--- a/fabfile.py
+++ b/fabfile.py
@@ -244,7 +244,6 @@ def collect_remote_statics():
'storage': 'git://github.com/yohanboniface/Leaflet.Storage.git@master',
'edit_in_osm': 'git://github.com/yohanboniface/Leaflet.EditInOSM.git@master',
'minimap': 'git://github.com/Norkart/Leaflet-MiniMap.git@master',
- 'darline': 'git://github.com/yohanboniface/Darline.git@master',
'i18n': 'git://github.com/yohanboniface/Leaflet.i18n.git@master',
'csv2geojson': 'git://github.com/mapbox/csv2geojson.git@gh-pages',
'togeojson': 'git://github.com/mapbox/togeojson.git@gh-pages',
diff --git a/umap/static/darline b/umap/static/darline
deleted file mode 160000
index 987916f7..00000000
--- a/umap/static/darline
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 987916f72bf3601e4c70402a4434d53b951284ac
diff --git a/umap/static/favicon.ico b/umap/static/favicon.ico
index 8db4c81a..0aa459cc 100644
Binary files a/umap/static/favicon.ico and b/umap/static/favicon.ico differ
diff --git a/umap/static/umap/js/autocomplete.js b/umap/static/umap/js/autocomplete.js
new file mode 100644
index 00000000..df9e1a6d
--- /dev/null
+++ b/umap/static/umap/js/autocomplete.js
@@ -0,0 +1,339 @@
+
+L.S.autoComplete = function (el, options) {
+
+ var API = {
+ options: {
+ placeholder: "Start typing...",
+ emptyMessage: "No result",
+ allowFree: true,
+ minChar: 2,
+ maxResults: 5
+ },
+
+ CACHE: '',
+ RESULTS: [],
+
+ _init: function (el, options) {
+ this.el = L.DomUtil.get(el);
+ this.options = L.Util.extend(this.options, options);
+ var CURRENT = null;
+ try {
+ Object.defineProperty(this, "CURRENT", {
+ get: function () {
+ return CURRENT;
+ },
+ set: function (index) {
+ if (typeof index === "object") {
+ index = this.resultToIndex(index);
+ }
+ CURRENT = index;
+ }
+ });
+ } catch (e) {
+ // Hello IE8
+ }
+ return this;
+ },
+
+ createInput: function () {
+ this.input = L.DomUtil.element('input', {
+ type: 'text',
+ placeholder: this.options.placeholder,
+ autocomplete: "off"
+ });
+ L.DomUtil.before(this.el, this.input);
+ L.DomEvent.on(this.input, "keydown", this.onKeyDown, this);
+ L.DomEvent.on(this.input, "keyup", this.onKeyUp, this);
+ L.DomEvent.on(this.input, "blur", this.onBlur, this);
+ },
+
+ createContainer: function () {
+ this.container = L.DomUtil.element('ul', {className: 'umap-autocomplete'}, document.querySelector('body'));
+ },
+
+ resizeContainer: function()
+ {
+ var l = this.getLeft(this.input);
+ var t = this.getTop(this.input) + this.input.offsetHeight;
+ this.container.style.left = l + 'px';
+ this.container.style.top = t + 'px';
+ var width = this.options.width ? this.options.width : this.input.offsetWidth - 2;
+ this.container.style.width = width + "px";
+ },
+
+ onKeyDown: function (e) {
+ switch (e.keyCode) {
+ case L.S.Keys.TAB:
+ if(this.CURRENT !== null)
+ {
+ this.setChoice();
+ }
+ L.DomEvent.stop(e);
+ break;
+ case L.S.Keys.RETURN:
+ L.DomEvent.stop(e);
+ this.setChoice();
+ break;
+ case L.S.Keys.ESC:
+ L.DomEvent.stop(e);
+ this.hide();
+ break;
+ case L.S.Keys.DOWN:
+ if(this.RESULTS.length > 0) {
+ if(this.CURRENT !== null && this.CURRENT < this.RESULTS.length - 1) { // what if one resutl?
+ this.CURRENT++;
+ this.highlight();
+ }
+ else if(this.CURRENT === null) {
+ this.CURRENT = 0;
+ this.highlight();
+ }
+ }
+ break;
+ case L.S.Keys.UP:
+ if(this.CURRENT !== null) {
+ L.DomEvent.stop(e);
+ }
+ if(this.RESULTS.length > 0) {
+ if(this.CURRENT > 0) {
+ this.CURRENT--;
+ this.highlight();
+ }
+ else if(this.CURRENT === 0) {
+ this.CURRENT = null;
+ this.highlight();
+ }
+ }
+ break;
+ }
+ },
+
+ onKeyUp: function (e) {
+ var special = [
+ L.S.Keys.TAB,
+ L.S.Keys.RETURN,
+ L.S.Keys.LEFT,
+ L.S.Keys.RIGHT,
+ L.S.Keys.DOWN,
+ L.S.Keys.UP,
+ L.S.Keys.APPLE,
+ L.S.Keys.SHIFT,
+ L.S.Keys.ALT,
+ L.S.Keys.CTRL
+ ];
+ if (special.indexOf(e.keyCode) === -1)
+ {
+ this.search();
+ }
+ },
+
+ onBlur: function (e) {
+ var self = this;
+ setTimeout(function () {
+ self.hide();
+ }, 100);
+ },
+
+ clear: function () {
+ this.RESULTS = [];
+ this.CURRENT = null;
+ this.CACHE = '';
+ this.container.innerHTML = '';
+ },
+
+ hide: function() {
+ this.clear();
+ this.container.style.display = 'none';
+ this.input.value = "";
+ },
+
+ setChoice: function (choice) {
+ choice = choice || this.RESULTS[this.CURRENT];
+ if (choice) {
+ this.input.value = choice.display;
+ this.select(choice);
+ this.displaySelected(choice);
+ this.hide();
+ if (this.options.callback) {
+ L.Util.bind(this.options.callback, this)(choice);
+ }
+ }
+ },
+
+ search: function() {
+ var val = this.input.value;
+ if (val.length < this.options.minChar) {
+ this.clear();
+ return;
+ }
+ if(!val) {
+ this.clear();
+ return;
+ }
+ if( val + '' === this.CACHE + '') {
+ return;
+ }
+ else {
+ this.CACHE = val;
+ }
+ var results = this._do_search(val);
+ return this.handleResults(results);
+ },
+
+ createResult: function (item) {
+ var el = L.DomUtil.element('li', {}, this.container);
+ el.innerHTML = item.display;
+ var result = {
+ value: item.value,
+ display: item.display,
+ el: el
+ };
+ L.DomEvent.on(el, 'mouseover', function (e) {
+ this.CURRENT = result;
+ this.highlight();
+ }, this);
+ L.DomEvent.on(el, 'mousedown', function (e) {
+ this.setChoice();
+ }, this);
+ return result;
+ },
+
+ resultToIndex: function (result) {
+ var out = null;
+ this.forEach(this.RESULTS, function (item, index) {
+ if (item.value == result.value) {
+ out = index;
+ return;
+ }
+ });
+ return out;
+ },
+
+ handleResults: function(data) {
+ var self = this;
+ this.clear();
+ this.container.style.display = "block";
+ this.resizeContainer();
+ this.forEach(data, function (item, index) {
+ self.RESULTS.push(self.createResult(item));
+ });
+ this.CURRENT = 0;
+ this.highlight();
+ //TODO manage no results
+ },
+
+ highlight: function () {
+ var self = this;
+ this.forEach(this.RESULTS, function (item, index) {
+ if (index === self.CURRENT) {
+ L.DomUtil.addClass(item.el, 'on');
+ }
+ else {
+ L.DomUtil.removeClass(item.el, 'on');
+ }
+ });
+ },
+
+ getLeft: function (el) {
+ var tmp = el.offsetLeft;
+ el = el.offsetParent;
+ while(el) {
+ tmp += el.offsetLeft;
+ el = el.offsetParent;
+ }
+ return tmp;
+ },
+
+ getTop: function (el) {
+ var tmp = el.offsetTop;
+ el = el.offsetParent;
+ while(el) {
+ tmp += el.offsetTop;
+ el = el.offsetParent;
+ }
+ return tmp;
+ },
+
+ forEach: function (els, callback) {
+ Array.prototype.forEach.call(els, callback);
+ }
+
+ };
+
+ var MULTISELECT = {
+
+ init: function (el, options) {
+ this._init(el, options);
+ if (!this.el) return this;
+ this.el.style.display = "none";
+ this.createInput();
+ this.createContainer();
+ this.initSelectedContainer();
+ },
+
+ initSelectedContainer: function (initial) {
+ this.selected_container = L.DomUtil.after(this.input, L.DomUtil.element('ul', {className: 'umap-multiresult'}));
+ var self = this;
+ this.forEach(this.el, function (option) {
+ if (option.selected) {
+ self.displaySelected(self.optionToResult(option));
+ }
+ });
+ },
+
+ optionToResult: function (option) {
+ return {
+ value: option.value,
+ display: option.innerHTML
+ };
+ },
+
+ displaySelected: function (result) {
+ var result_el = L.DomUtil.element('li', {}, this.selected_container);
+ result_el.innerHTML = result.display;
+ var close = L.DomUtil.element('span', {className: 'close'}, result_el);
+ close.innerHTML = "×";
+ L.DomEvent.on(close, 'click', function () {
+ this.selected_container.removeChild(result_el);
+ this.unselect(result);
+ }, this);
+ this.hide();
+ },
+
+ _do_search: function (val) {
+ var results = [],
+ self = this,
+ count = 0;
+ this.forEach(this.el, function (item, index) {
+ if (item.innerHTML.toLowerCase().indexOf(val.toLowerCase()) !== -1 && !item.selected && count < self.options.maxResults) {
+ results.push(self.optionToResult(item));
+ count++;
+ }
+ });
+ return results;
+ },
+
+ select: function (option) {
+ this.forEach(this.el, function (item, index) {
+ if (item.value == option.value) {
+ item.selected = true;
+ }
+ });
+ },
+
+ unselect: function (option) {
+ this.forEach(this.el, function (item, index) {
+ if (item.value == option.value) {
+ item.selected = false;
+ }
+ });
+ }
+
+ };
+
+ this.multiselect = function () {
+ return L.Util.extend(API, MULTISELECT).init(el, options);
+ };
+ return this;
+
+};
\ No newline at end of file
diff --git a/umap/static/umap/umap.css b/umap/static/umap/umap.css
index 8143235b..54b69e59 100644
--- a/umap/static/umap/umap.css
+++ b/umap/static/umap/umap.css
@@ -552,6 +552,41 @@ a {
}
+/* **************************** */
+/* Autocomplete */
+/* **************************** */
+ul.umap-autocomplete {
+ position: absolute;
+ background-color: white;
+ z-index: 1000;
+ box-shadow: 0 4px 9px #999999;
+}
+.umap-autocomplete li {
+ height: 56px;
+ line-height: 28px;
+ padding: 14px;
+}
+.umap-autocomplete li.on {
+ background-color: SeaGreen;
+ cursor: pointer;
+}
+.umap-multiresult li {
+ width: 100%;
+ background-color: #e5e5e5;
+ border-radius: 2px;
+ padding: 7px;
+ color: #464646;
+}
+.umap-multiresult li + li {
+ margin-top: 7px;
+}
+.umap-multiresult li .close {
+ float: right;
+ cursor: pointer;
+}
+
+
+
/* **************************** */
/* Override Leaflet.Storage */
/* **************************** */
diff --git a/umap/templates/base.html b/umap/templates/base.html
index 6ac58a31..af4e8614 100644
--- a/umap/templates/base.html
+++ b/umap/templates/base.html
@@ -6,21 +6,18 @@
{% compress css %}
-
{% endcompress css %}
- {% compress js %}
-
-
-
- {% endcompress js %}
{% block extra_head %}
{% endblock extra_head %}
+ {% compress js %}
+
+ {% endcompress js %}
@@ -37,8 +34,8 @@
{% block bottom_js %}