Commit 6a1ec6b5 authored by Matthias Larisch's avatar Matthias Larisch

Komoot addresspicker, update leaflet and typeahead

parent ef254727
Pipeline #44059410 passed with stages
in 14 minutes and 5 seconds
......@@ -9,6 +9,7 @@
- prepare support for separated email domain for platform mailboxes
- add security headers !633 @nicksellen
- changed tile maps to wikimedia !639 @alex.simm
- Use typeahead-address-photon for address autocomplete. Update leaflet and typeahead for recent NPM versions in the same go !640 @NerdyProjects
## Bugfixes
- Improve/correct user profile badge count !612 @pmayd
......
/*
Leaflet.AwesomeMarkers, a plugin that adds colorful iconic markers for Leaflet, based on the Font Awesome icons
(c) 2012-2013, Lennard Voogdt
http://leafletjs.com
https://github.com/lvoogdt
*//*global L*/(function(e,t,n){"use strict";L.AwesomeMarkers={};L.AwesomeMarkers.version="2.0.1";L.AwesomeMarkers.Icon=L.Icon.extend({options:{iconSize:[35,45],iconAnchor:[17,42],popupAnchor:[1,-32],shadowAnchor:[10,12],shadowSize:[36,16],className:"awesome-marker",prefix:"glyphicon",spinClass:"fa-spin",icon:"home",markerColor:"blue",iconColor:"white"},initialize:function(e){e=L.Util.setOptions(this,e)},createIcon:function(){var e=t.createElement("div"),n=this.options;n.icon&&(e.innerHTML=this._createInner());n.bgPos&&(e.style.backgroundPosition=-n.bgPos.x+"px "+ -n.bgPos.y+"px");this._setIconStyles(e,"icon-"+n.markerColor);return e},_createInner:function(){var e,t="",n="",r="",i=this.options;i.icon.slice(0,i.prefix.length+1)===i.prefix+"-"?e=i.icon:e=i.prefix+"-"+i.icon;i.spin&&typeof i.spinClass=="string"&&(t=i.spinClass);i.iconColor&&(i.iconColor==="white"||i.iconColor==="black"?n="icon-"+i.iconColor:r="style='color: "+i.iconColor+"' ");return"<i "+r+"class='"+i.prefix+" "+e+" "+t+" "+n+"'></i>"},_setIconStyles:function(e,t){var n=this.options,r=L.point(n[t==="shadow"?"shadowSize":"iconSize"]),i;t==="shadow"?i=L.point(n.shadowAnchor||n.iconAnchor):i=L.point(n.iconAnchor);!i&&r&&(i=r.divideBy(2,!0));e.className="awesome-marker-"+t+" "+n.className;if(i){e.style.marginLeft=-i.x+"px";e.style.marginTop=-i.y+"px"}if(r){e.style.width=r.x+"px";e.style.height=r.y+"px"}},createShadow:function(){var e=t.createElement("div");this._setIconStyles(e,"shadow");return e}});L.AwesomeMarkers.icon=function(e){return new L.AwesomeMarkers.Icon(e)}})(this,document);
(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
(function($) {
this.AddressPickerResult = (function() {
function AddressPickerResult(placeResult, fromReverseGeocoding) {
this.placeResult = placeResult;
this.fromReverseGeocoding = fromReverseGeocoding != null ? fromReverseGeocoding : false;
this.latitude = this.placeResult.geometry.location.lat();
this.longitude = this.placeResult.geometry.location.lng();
}
AddressPickerResult.prototype.addressTypes = function() {
var component, type, types, _i, _j, _len, _len1, _ref, _ref1;
types = [];
_ref = this.addressComponents();
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
component = _ref[_i];
_ref1 = component.types;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
type = _ref1[_j];
if (types.indexOf(type) === -1) {
types.push(type);
}
}
}
return types;
};
AddressPickerResult.prototype.addressComponents = function() {
return this.placeResult.address_components || [];
};
AddressPickerResult.prototype.address = function() {
return this.placeResult.formatted_address;
};
AddressPickerResult.prototype.nameForType = function(type, shortName) {
var component, _i, _len, _ref;
if (shortName == null) {
shortName = false;
}
_ref = this.addressComponents();
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
component = _ref[_i];
if (component.types.indexOf(type) !== -1) {
return (shortName ? component.short_name : component.long_name);
}
}
return null;
};
AddressPickerResult.prototype.lat = function() {
return this.latitude;
};
AddressPickerResult.prototype.lng = function() {
return this.longitude;
};
AddressPickerResult.prototype.setLatLng = function(latitude, longitude) {
this.latitude = latitude;
this.longitude = longitude;
};
AddressPickerResult.prototype.isAccurate = function() {
return !this.placeResult.geometry.viewport;
};
AddressPickerResult.prototype.isReverseGeocoding = function() {
return this.fromReverseGeocoding;
};
return AddressPickerResult;
})();
return this.AddressPicker = (function(_super) {
__extends(AddressPicker, _super);
function AddressPicker(options) {
if (options == null) {
options = {};
}
this.sessionToken = new google.maps.places.AutocompleteSessionToken();
this.markerDragged = __bind(this.markerDragged, this);
this.updateBoundsForPlace = __bind(this.updateBoundsForPlace, this);
this.updateMap = __bind(this.updateMap, this);
this.options = $.extend({
local: [],
datumTokenizer: function(d) {
return Bloodhound.tokenizers.whitespace(d.num);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
autocompleteService: {
types: ["geocode"]
},
zoomForLocation: 16,
reverseGeocoding: false,
placeDetails: true
}, options);
AddressPicker.__super__.constructor.call(this, this.options);
if (this.options.map) {
this.initMap();
}
this.placeService = new google.maps.places.PlacesService(document.createElement('div'));
}
AddressPicker.prototype.bindDefaultTypeaheadEvent = function(typeahead) {
typeahead.bind("typeahead:selected", this.updateMap);
return typeahead.bind("typeahead:cursorchanged", this.updateMap);
};
AddressPicker.prototype.initMap = function() {
var _ref, _ref1;
this.mapOptions = $.extend({
zoom: 3,
center: L.latLng(0, 0),
boundsForLocation: this.updateBoundsForPlace,
}, this.options.map);
if(this.mapOptions.map) {
this.map = this.mapOptions.map
}
else {
this.map = L.map(this.mapOptions.id, this.mapOptions);
L.tileLayer("https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png", {
attribution: "Geocoding by <a href=\"https://google.com\">Google</a>, Tiles by <a href=\"https://foundation.wikimedia.org/w/index.php?title=Maps_Terms_of_Use\">Wikimedia</a>"
}).addTo(this.map);
}
this.lastResult = null;
var fsIcon = L.AwesomeMarkers.icon({
icon: "smile",
markerColor: "orange",
prefix: "img"
});
this.marker = L.marker(this.mapOptions.center, {icon: fsIcon}).addTo(this.map);
};
AddressPicker.prototype.get = function(query, cb) {
var service;
service = new google.maps.places.AutocompleteService();
this.options.autocompleteService.input = query;
this.options.autocompleteService.sessionToken = this.sessionToken;
return service.getPlacePredictions(this.options.autocompleteService, (function(_this) {
return function(predictions) {
$(_this).trigger('addresspicker:predictions', [predictions]);
return cb(predictions);
};
})(this));
};
AddressPicker.prototype.updateMap = function(event, place) {
if (this.options.placeDetails) {
place.sessionToken = this.sessionToken
return this.placeService.getDetails(place, (function(_this) {
return function(response) {
var _ref;
_this.lastResult = new AddressPickerResult(response);
if (_this.marker) {
_this.marker.setLatLng(L.latLng(response.geometry.location.lat(), response.geometry.location.lng()));
}
if (_this.map) {
if ((_ref = _this.mapOptions) != null) {
_ref.boundsForLocation(response);
}
}
_this.sessionToken = new google.maps.places.AutocompleteSessionToken();
return $(_this).trigger('addresspicker:selected', _this.lastResult);
};
})(this));
} else {
return $(this).trigger('addresspicker:selected', place);
}
};
AddressPicker.prototype.updateBoundsForPlace = function(response) {
if (response.geometry.viewport) {
return this.map.fitBounds(L.latLngBounds(L.latLng(response.geometry.viewport.getNorthEast().lat(), response.geometry.viewport.getNorthEast().lng()),
L.latLng(response.geometry.viewport.getSouthWest().lat(), response.geometry.viewport.getSouthWest().lng())));
} else {
this.map.setCenter(L.latLng(response.geometry.location.lat(), response.geometry.location.lng()));
return this.map.setZoom(this.options.zoomForLocation);
}
};
AddressPicker.prototype.markerDragged = function() {
if (this.options.reverseGeocoding) {
return this.reverseGeocode(this.marker.getPosition());
} else {
if (this.lastResult) {
this.lastResult.setLatLng(this.marker.getPosition().lat(), this.marker.getPosition().lng());
} else {
this.lastResult = new AddressPickerResult({
geometry: {
location: this.marker.getPosition()
}
});
}
return $(this).trigger('addresspicker:selected', this.lastResult);
}
};
AddressPicker.prototype.reverseGeocode = function(position) {
if (this.geocoder == null) {
this.geocoder = new google.maps.Geocoder();
}
return this.geocoder.geocode({
location: position
}, (function(_this) {
return function(results) {
if (results && results.length > 0) {
_this.lastResult = new AddressPickerResult(results[0], true);
return $(_this).trigger('addresspicker:selected', _this.lastResult);
}
};
})(this));
};
AddressPicker.prototype.getGMap = function() {
return this.map;
};
AddressPicker.prototype.getGMarker = function() {
return this.marker;
};
return AddressPicker;
})(Bloodhound);
})(jQuery);
}).call(this);
This diff is collapsed.
......@@ -15,6 +15,7 @@
"@fortawesome/fontawesome-free": "^5.6.3",
"bootstrap-vue": "^2.0.0-rc.11",
"copy-webpack-plugin": "^4.6.0",
"corejs-typeahead": "^1.2.1",
"cropperjs": "^1.4.3",
"date-fns": "^1.30.1",
"fullpage.js": "<2.9.6",
......@@ -25,9 +26,9 @@
"jquery-slimscroll": "^1.3.8",
"jquery-ui": "<1.12.0-beta.1",
"jquery.ui.position": "^1.11.4",
"leaflet": "<1.0.0-beta.1",
"leaflet": "^1.4.0",
"leaflet.awesome-markers": "^2.0.5",
"leaflet.markercluster": "<1.0.0-rc.1.0",
"leaflet.markercluster": "^1.4.1",
"lodash.pickby": "^4.6.0",
"magnific-popup": "^1.1.0",
"node-sass": "^4.11.0",
......@@ -37,6 +38,7 @@
"timeago": "^1.4.3",
"tinysort": "^3.2.5",
"twemoji": "^11.2.0",
"typeahead-address-photon": "^1.0.0",
"typeahead-addresspicker": "^1.0.1",
"typeface-alfa-slab-one": "^0.0.54",
"underscore": "^1.9.1",
......
......@@ -62,15 +62,18 @@ Object.assign(module.exports, convert({
}
},
'typeahead-addresspicker': {
resolve: lib('typeahead-addresspicker.js'),
'corejs-typeahead': {
dependencies: [
'css/typeahead.css'
]
},
'typeahead-address-photon': {
imports: {
jQuery: 'jquery'
jQuery: 'jquery',
Bloodhound: 'corejs-typeahead'
},
dependencies: [
'typeahead'
],
exports: 'AddressPicker'
exports: 'this.PhotonAddressEngine'
},
'jquery-ui-addons': {
......@@ -101,13 +104,6 @@ Object.assign(module.exports, convert({
]
},
'typeahead': {
resolve: lib('typeahead.bundle.js'),
imports: {
'window.jQuery': 'jquery'
}
},
'jquery-tablesorter': {
resolve: lib('tablesorter/jquery.tablesorter.js'),
imports: {
......
import $ from 'jquery'
import 'corejs-typeahead'
import PhotonAddressEngine from 'typeahead-address-photon'
import L from 'leaflet'
import 'leaflet.awesome-markers'
let fsIcon = L.AwesomeMarkers.icon({
icon: 'smile',
markerColor: 'lorange',
prefix: 'img'
})
let markers = L.featureGroup()
function showSelected (event, selected, map, engine) {
map.removeLayer(markers)
markers = L.featureGroup()
markers.addTo(map)
L.marker([
selected.geometry.coordinates[1],
selected.geometry.coordinates[0]
], {
icon: fsIcon,
draggable: true
}).on('dragend', function (event) {
let pos = event.target.getLatLng()
engine.reverseGeocode([pos.lat, pos.lng])
}).addTo(markers)
map.fitBounds(markers.getBounds())
}
export function attachAddresspicker () {
let map = L.map('map').setView([51, 11], 4)
setTimeout(() => (map.invalidateSize()), 400)
L.tileLayer('https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png', {
zoomControl: true,
maxZoom: 18,
attribution: 'Geocoding by <a href="https://photon.komoot.de">Komoot Photon</a>, Tiles by <a href="https://foundation.wikimedia.org/w/index.php?title=Maps_Terms_of_Use">Wikimedia</a>'
}).addTo(map)
let engine = new PhotonAddressEngine(
{
url: 'https://photon.komoot.de',
formatResult: function (feature) {
let prop = feature.properties
let formatted = [prop.name || '', prop.street, prop.housenumber || '', prop.postcode, prop.city, prop.country].filter(Boolean).join(' ')
return formatted
},
lang: 'de'
}
)
$('#addresspicker').typeahead(
{
highlight: true,
minLength: 3,
hint: true
},
{
displayKey: 'description',
source: engine.ttAdapter()
})
engine.bindDefaultTypeaheadEvent($('#addresspicker'))
$(engine).bind('addresspicker:selected', function (event, selectedPlace) {
showSelected(event, selectedPlace, map, engine)
let prop = selectedPlace.properties
let geo = selectedPlace.geometry.coordinates
$('#lat').val(geo[1])
$('#lon').val(geo[0])
$('#plz').val(prop.postcode)
$('#ort').val(prop.city)
$('#anschrift').val(prop.street + (prop.housenumber ? ' ' + prop.housenumber : ''))
$('#addresspicker').val(selectedPlace.description)
})
$('#lat-wrapper,#lon-wrapper').hide()
}
......@@ -13,8 +13,7 @@ var join = {
marker: null,
isLoading: false,
mapInitialized: false,
init: function (googleApiKey) {
this.googleApiKey = googleApiKey
init: function () {
this.mapInitialized = false
},
photoUploadError: function (error) {
......@@ -41,15 +40,15 @@ var join = {
const mapEL = document.getElementById('map')
if (mapEL) {
initializeMap(mapEL, (result) => {
var number = result.nameForType('street_number') || ''
var address = result.nameForType('route') || ''
$('#join_lat').val(result.lat())
$('#join_lon').val(result.lng())
$('#join_plz').val(result.nameForType('postal_code'))
$('#join_ort').val(result.nameForType('locality'))
$('#join_str').val(address)
$('#join_hsnr').val(number)
$('#join_country').val(result.nameForType('country'))
let prop = result.properties
let geo = result.geometry.coordinates
$('#join_lat').val(geo[1])
$('#join_lon').val(geo[0])
$('#join_plz').val(prop.postcode)
$('#join_ort').val(prop.city)
$('#join_str').val(prop.street)
$('#join_hsnr').val(prop.housenumber)
$('#join_country').val(prop.country)
})
}
this.mapInitialized = true
......
......@@ -10,5 +10,4 @@ import 'css/chat.css'
import 'css/jquery.switchButton.css'
import 'css/icons.css'
import 'css/popup.css'
import 'css/typeahead.css'
import 'typeface-alfa-slab-one'
......@@ -2071,6 +2071,13 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
corejs-typeahead@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/corejs-typeahead/-/corejs-typeahead-1.2.1.tgz#345a8afe664cc494075b59b64777807f0b3f132b"
integrity sha1-NFqK/mZMxJQHW1m2R3eAfws/Eys=
dependencies:
jquery ">=1.11"
create-ecdh@^4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff"
......@@ -4304,7 +4311,7 @@ jquery@<3.0.0-alpha1:
resolved "https://registry.yarnpkg.com/jquery/-/jquery-2.2.4.tgz#2c89d6889b5eac522a7eea32c14521559c6cbf02"
integrity sha1-LInWiJterFIqfuoywUUhVZxsvwI=
"jquery@>= 1.7", jquery@>=1.2.3, jquery@>=1.6.0:
"jquery@>= 1.7", jquery@>=1.11, jquery@>=1.2.3, jquery@>=1.6.0:
version "3.3.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
integrity sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==
......@@ -4501,17 +4508,15 @@ leaflet.awesome-markers@^2.0.5:
resolved "https://registry.yarnpkg.com/leaflet.awesome-markers/-/leaflet.awesome-markers-2.0.5.tgz#b7b0210d87e2566359bf478c1ab3ab07c7246f30"
integrity sha512-Ne/xDjkGyaujwNVVkv2tyXQUV0ZW7gZ0Mo0FuQY4jp2qWrvXi0hwDBvmZyF/8YOvybyMabTMM/mFWCTd1jZIQA==
leaflet.markercluster@<1.0.0-rc.1.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/leaflet.markercluster/-/leaflet.markercluster-0.5.0.tgz#804a5c2b02ecacb19c064a253396ab60d5df699b"
integrity sha1-gEpcKwLsrLGcBkolM5arYNXfaZs=
dependencies:
leaflet "~0.7.1"
leaflet.markercluster@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/leaflet.markercluster/-/leaflet.markercluster-1.4.1.tgz#b53f2c4f2ca7306ddab1dbb6f1861d5e8aa6c5e5"
integrity sha512-ZSEpE/EFApR0bJ1w/dUGwTSUvWlpalKqIzkaYdYB7jaftQA/Y2Jav+eT4CMtEYFj+ZK4mswP13Q2acnPBnhGOw==
leaflet@<1.0.0-beta.1, leaflet@~0.7.1:
version "0.7.7"
resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-0.7.7.tgz#1e352ba54e63d076451fa363c900890cb2cf75ee"
integrity sha1-HjUrpU5j0HZFH6NjyQCJDLLPde4=
leaflet@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.4.0.tgz#d5f56eeb2aa32787c24011e8be4c77e362ae171b"
integrity sha512-x9j9tGY1+PDLN9pcWTx9/y6C5nezoTMB8BLK5jTakx+H7bPlnbCHfi9Hjg+Qt36sgDz/cb9lrSpNQXmk45Tvhw==
levn@^0.3.0, levn@~0.3.0:
version "0.3.0"
......@@ -7286,6 +7291,11 @@ type-is@~1.6.16:
media-typer "0.3.0"
mime-types "~2.1.18"
typeahead-address-photon@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/typeahead-address-photon/-/typeahead-address-photon-1.0.0.tgz#9b8437d2eb8aad101848e7c39e0e0e59c3da34df"
integrity sha1-m4Q30uuKrRAYSOfDng4OWcPaNN8=
typeahead-addresspicker@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/typeahead-addresspicker/-/typeahead-addresspicker-1.0.1.tgz#933b36ec2aad4cca4575d8d240bac15e3fd10ae2"
......
......@@ -28,9 +28,6 @@ define('EMAIL_PUBLIC', 'info@foodsharing.de');
define('EMAIL_PUBLIC_NAME', 'foodsharing-Freiwillige');
define('NOREPLY_EMAIL_HOST', 'foodsharing.de');
define('PLATFORM_MAILBOX_HOST', 'foodsharing.network');
//define('GOOGLE_API_KEY', 'AIzaSyCkFfCoOnj8ZjGGcApHS1rX6Rt6OxrW6hQ'); // Original key; API limit reached 20181121
//define('GOOGLE_API_KEY', 'AIzaSyD6MLWJNn7I_Qdpkixxo2uL77hW5srdQwk'); // This key is sponsored by @Jo for testing purpose.
define('GOOGLE_API_KEY', 'AIzaSyCkFfCoOnj8ZjGGcApHS1rX6Rt6OxrW6hQ'); // matthias fsdev key
define('MAILBOX_OWN_DOMAINS', array('foodsharing.network', 'lebensmittelretten.de', 'foodsharing.de'));
......
......@@ -31,7 +31,6 @@ define('EMAIL_PUBLIC', 'info@foodsharing.de');
define('EMAIL_PUBLIC_NAME', 'foodsharing-Freiwillige');
define('NOREPLY_EMAIL_HOST', 'foodsharing.de');
define('PLATFORM_MAILBOX_HOST', 'foodsharing.network');
define('GOOGLE_API_KEY', '');
define('MAILBOX_OWN_DOMAINS', array('foodsharing.network', 'lebensmittelretten.de', 'foodsharing.de'));
......
......@@ -1482,12 +1482,6 @@ a.light {
color: #533a20;
}
.leaflet-top, .leaflet-bottom {
z-index: 25 !important;
right: auto;
left: 0;
}
.quicks {
background-color: #c2bab4;
border: 0 none;
......
/*typahead*/
.twitter-typeahead {
width: 100%;
span.twitter-typeahead .tt-menu,
span.twitter-typeahead .tt-dropdown-menu {
cursor: pointer;
position: absolute;
top: 100%;
left: 0;
z-index: 1100 !important;
display: none;
float: left;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0;
list-style: none;
font-size: 14px;
text-align: left;
background-color: #ffffff;
border: 1px solid #cccccc;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 4px;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
background-clip: padding-box;
}
.typeahead,
.tt-query,
.tt-hint {
height: 11px;
padding: 8px 6px;
font-size: 13px;
line-height: 30px;
border: 2px solid #ccc;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
outline: none;
span.twitter-typeahead .tt-suggestion {
display: block;
padding: 3px 20px;
clear: both;
font-weight: normal;
line-height: 1.42857143;
color: #333333;
white-space: nowrap;
}
.typeahead {
background-color: #fff;
span.twitter-typeahead .tt-suggestion.tt-cursor,
span.twitter-typeahead .tt-suggestion:hover,
span.twitter-typeahead .tt-suggestion:focus {
color: #ffffff;
text-decoration: none;
outline: 0;
background-color: #337ab7;
}
.typeahead:focus {
border: 2px solid #46891b;
color: #fff !important;
.input-group.input-group-lg span.twitter-typeahead .form-control {
height: 46px;
padding: 10px 16px;
font-size: 18px;
line-height: 1.3333333;
border-radius: 6px;
}
.typeahead.empty {
border: 2px solid red;
.input-group.input-group-sm span.twitter-typeahead .form-control {
height: 30px;
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
}
.tt-query {
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
span.twitter-typeahead {
width: 100%;
}
.tt-hint {
color: #999;
.input-group span.twitter-typeahead {
display: block !important;
height: 34px;
}
.tt-dropdown-menu {
margin-top: 12px;
padding: 8px 0;
background-color: #fff;
border: 1px solid #ccc;
border: 1px solid rgba(0, 0, 0, 0.2);
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
.input-group span.twitter-typeahead .tt-menu,
.input-group span.twitter-typeahead .tt-dropdown-menu {
top: 32px !important;
}
.tt-suggestion {
padding: 3px 20px;
font-size: 18px;
line-height: 24px;
.input-group span.twitter-typeahead:not(:first-child):not(:last-child) .form-control {
border-radius: 0;
}
.tt-suggestion.tt-cursor {
color: #fff !important;
background-color: #46891b;
.input-group span.twitter-typeahead:first-child .form-control {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.tt-suggestion p {
margin: 0;
.input-group span.twitter-typeahead:last-child .form-control {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
.gist {
font-size: 14px;
.input-group.input-group-sm span.twitter-typeahead {
height: 30px;
}
.input-group.input-group-sm span.twitter-typeahead .tt-menu,
.input-group.input-group-sm span.twitter-typeahead .tt-dropdown-menu {
top: 30px !important;
}
.input-group.input-group-lg span.twitter-typeahead {
height: 46px;
}
.input-group.input-group-lg span.twitter-typeahead .tt-menu,
.input-group.input-group-lg span.twitter-typeahead .tt-dropdown-menu {
top: 46px !important;
}