├── README.md ├── index.html ├── js ├── styles.css ├── bootstrap3-typeahead.min.js ├── bootstrap-typeahead.js ├── leaflet.css ├── typeahead.jquery.js └── bootstrap.js ├── Leaflet-Select-Polygons.js └── app.js /README.md: -------------------------------------------------------------------------------- 1 | # Leaflet-Select-Polygons 2 | Example in leafletjs that allows you to select multiple polygons 3 | demo: https://olanaso.github.io/Leaflet-Select-Polygons/ 4 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet-Select-Polygons - map 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |
23 | 24 | 26 |
27 |
28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /js/styles.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | margin: 0; 4 | } 5 | #map { 6 | width: 100%; 7 | height: 100%; 8 | } 9 | 10 | #was 11 | { 12 | 13 | 14 | text-align:center; 15 | border-radius:5px; 16 | background: rgba(255,255,0,0.7); 17 | position:absolute; 18 | top:10px; 19 | left:calc(50% - 300px); 20 | margin:auto; 21 | z-index: 2000; 22 | display: inline-block; 23 | 24 | } 25 | 26 | .input.maps input { 27 | padding: 0 35px; 28 | } 29 | 30 | #places { 31 | float: left; 32 | 33 | width: 500px; 34 | border: 3px solid #d5eff6; 35 | -webkit-border-radius: 6px; 36 | border-radius: 6px; 37 | background-color: #fff; 38 | 39 | } 40 | 41 | #map { width: 100%; 42 | height: 100%; } 43 | .info { padding: 6px 8px; font: 14px/16px Arial, Helvetica, sans-serif; background: white; background: rgba(255,255,255,0.8); box-shadow: 0 0 15px rgba(0,0,0,0.2); border-radius: 5px; } .info h4 { margin: 0 0 5px; color: #777; } 44 | .legend { text-align: left; line-height: 18px; color: #555; } .legend i { width: 18px; height: 18px; float: left; margin-right: 8px; opacity: 0.7; } 45 | 46 | .scroler{ 47 | 48 | width: 250px; 49 | height: 800px; 50 | z-index: 999; 51 | overflow-y: scroll; 52 | } 53 | 54 | .left-inner-addon { 55 | position: relative; 56 | } 57 | .left-inner-addon input { 58 | padding-left: 30px; 59 | } 60 | .left-inner-addon i { 61 | position: absolute; 62 | padding: 10px 12px; 63 | pointer-events: none; 64 | } -------------------------------------------------------------------------------- /js/bootstrap3-typeahead.min.js: -------------------------------------------------------------------------------- 1 | !function(a,b){"use strict";"undefined"!=typeof module&&module.exports?module.exports=b(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):b(a.jQuery)}(this,function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.typeahead.defaults,c),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.select=this.options.select||this.select,this.autoSelect="boolean"==typeof this.options.autoSelect?this.options.autoSelect:!0,this.highlighter=this.options.highlighter||this.highlighter,this.render=this.options.render||this.render,this.updater=this.options.updater||this.updater,this.displayText=this.options.displayText||this.displayText,this.source=this.options.source,this.delay=this.options.delay,this.$menu=a(this.options.menu),this.$appendTo=this.options.appendTo?a(this.options.appendTo):null,this.shown=!1,this.listen(),this.showHintOnFocus="boolean"==typeof this.options.showHintOnFocus?this.options.showHintOnFocus:!1,this.afterSelect=this.options.afterSelect,this.addItem=!1};b.prototype={constructor:b,select:function(){var a=this.$menu.find(".active").data("value");if(this.$element.data("active",a),this.autoSelect||a){var b=this.updater(a);b||(b=""),this.$element.val(this.displayText(b)||b).change(),this.afterSelect(b)}return this.hide()},updater:function(a){return a},setSource:function(a){this.source=a},show:function(){var b,c=a.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});b="function"==typeof this.options.scrollHeight?this.options.scrollHeight.call():this.options.scrollHeight;var d;return d=this.shown?this.$menu:this.$appendTo?this.$menu.appendTo(this.$appendTo):this.$menu.insertAfter(this.$element),d.css({top:c.top+c.height+b,left:c.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(b){if("undefined"!=typeof b&&null!==b?this.query=b:this.query=this.$element.val()||"",this.query.length0?this.$element.data("active",b[0]):this.$element.data("active",null),this.options.addItem&&b.push(this.options.addItem),"all"==this.options.items?this.render(b).show():this.render(b.slice(0,this.options.items)).show()):this.shown?this.hide():this},matcher:function(a){var b=this.displayText(a);return~b.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(a){for(var b,c=[],d=[],e=[];b=a.shift();){var f=this.displayText(b);f.toLowerCase().indexOf(this.query.toLowerCase())?~f.indexOf(this.query)?d.push(b):e.push(b):c.push(b)}return c.concat(d,e)},highlighter:function(b){var c,d,e,f,g,h=a("
"),i=this.query,j=b.toLowerCase().indexOf(i.toLowerCase());if(c=i.length,0===c)return h.text(b).html();for(;j>-1;)d=b.substr(0,j),e=b.substr(j,c),f=b.substr(j+c),g=a("").text(e),h.append(document.createTextNode(d)).append(g),b=f,j=b.toLowerCase().indexOf(i.toLowerCase());return h.append(document.createTextNode(b)).html()},render:function(b){var c=this,d=this,e=!1,f=[],g=c.options.separator;return a.each(b,function(a,c){a>0&&c[g]!==b[a-1][g]&&f.push({__type:"divider"}),!c[g]||0!==a&&c[g]===b[a-1][g]||f.push({__type:"category",name:c[g]}),f.push(c)}),b=a(f).map(function(b,f){if("category"==(f.__type||!1))return a(c.options.headerHtml).text(f.name)[0];if("divider"==(f.__type||!1))return a(c.options.headerDivider)[0];var g=d.displayText(f);return b=a(c.options.item).data("value",f),b.find("a").html(c.highlighter(g,f)),g==d.$element.val()&&(b.addClass("active"),d.$element.data("active",f),e=!0),b[0]}),this.autoSelect&&!e&&(b.filter(":not(.dropdown-header)").first().addClass("active"),this.$element.data("active",b.first().data("value"))),this.$menu.html(b),this},displayText:function(a){return"undefined"!=typeof a&&"undefined"!=typeof a.name&&a.name||a},next:function(b){var c=this.$menu.find(".active").removeClass("active"),d=c.next();d.length||(d=a(this.$menu.find("li")[0])),d.addClass("active")},prev:function(a){var b=this.$menu.find(".active").removeClass("active"),c=b.prev();c.length||(c=this.$menu.find("li").last()),c.addClass("active")},listen:function(){this.$element.on("focus",a.proxy(this.focus,this)).on("blur",a.proxy(this.blur,this)).on("keypress",a.proxy(this.keypress,this)).on("input",a.proxy(this.input,this)).on("keyup",a.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",a.proxy(this.keydown,this)),this.$menu.on("click",a.proxy(this.click,this)).on("mouseenter","li",a.proxy(this.mouseenter,this)).on("mouseleave","li",a.proxy(this.mouseleave,this))},destroy:function(){this.$element.data("typeahead",null),this.$element.data("active",null),this.$element.off("focus").off("blur").off("keypress").off("input").off("keyup"),this.eventSupported("keydown")&&this.$element.off("keydown"),this.$menu.remove()},eventSupported:function(a){var b=a in this.$element;return b||(this.$element.setAttribute(a,"return;"),b="function"==typeof this.$element[a]),b},move:function(a){if(this.shown)switch(a.keyCode){case 9:case 13:case 27:a.preventDefault();break;case 38:if(a.shiftKey)return;a.preventDefault(),this.prev();break;case 40:if(a.shiftKey)return;a.preventDefault(),this.next()}},keydown:function(b){this.suppressKeyPressRepeat=~a.inArray(b.keyCode,[40,38,9,13,27]),this.shown||40!=b.keyCode?this.move(b):this.lookup()},keypress:function(a){this.suppressKeyPressRepeat||this.move(a)},input:function(a){this.lookup(),a.preventDefault()},keyup:function(a){switch(a.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide()}a.preventDefault()},focus:function(a){this.focused||(this.focused=!0,this.options.showHintOnFocus&&this.lookup(""))},blur:function(a){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(a){a.preventDefault(),this.select(),this.$element.focus(),this.hide()},mouseenter:function(b){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),a(b.currentTarget).addClass("active")},mouseleave:function(a){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var c=a.fn.typeahead;a.fn.typeahead=function(c){var d=arguments;return"string"==typeof c&&"getActive"==c?this.data("active"):this.each(function(){var e=a(this),f=e.data("typeahead"),g="object"==typeof c&&c;f||e.data("typeahead",f=new b(this,g)),"string"==typeof c&&f[c]&&(d.length>1?f[c].apply(f,Array.prototype.slice.call(d,1)):f[c]())})},a.fn.typeahead.defaults={source:[],items:8,menu:'',item:'
  • ',minLength:1,scrollHeight:0,autoSelect:!0,afterSelect:a.noop,addItem:!1,delay:0,separator:"category",headerHtml:'',headerDivider:''},a.fn.typeahead.Constructor=b,a.fn.typeahead.noConflict=function(){return a.fn.typeahead=c,this},a(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(b){var c=a(this);c.data("typeahead")||c.typeahead(c.data())})}); -------------------------------------------------------------------------------- /Leaflet-Select-Polygons.js: -------------------------------------------------------------------------------- 1 | /*default style for layers*/ 2 | var stylelayer = { 3 | defecto: { 4 | color: "red", 5 | opacity: 1, 6 | fillcolor: "red", 7 | fillOpacity: 0.1, 8 | weight: 0.5 9 | }, 10 | reset: { 11 | color: "red", 12 | opacity: 0.4, 13 | weight: 1 14 | }, 15 | highlight: { 16 | weight: 5, 17 | color: '#0D8BE7', 18 | dashArray: '', 19 | fillOpacity: 0.7 20 | }, 21 | selected: { 22 | color: "blue", 23 | opacity: 0.3, 24 | weight: 0.5 25 | } 26 | } 27 | 28 | /*Initial map and add layer for mapbox*/ 29 | var map = L.map('map').setView([51.666, 6.097], 7); 30 | 31 | L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', { 32 | maxZoom: 18, 33 | attribution: 'my company', 34 | id: 'mapbox.light' 35 | }).addTo(map); 36 | 37 | /*declarando variables globales*/ 38 | var placenames = new Array(); 39 | var zipcodes = new Object(); 40 | 41 | $.each(statesData.features, function (index, feature) { 42 | var name = `${feature.properties.zipcode} ${feature.properties.municipality} ( ${feature.properties.province} - ${feature.properties.town})` 43 | placenames.push(name); 44 | zipcodes[name] = feature.properties.zipcode; 45 | }); 46 | 47 | /* area de busqueda */ 48 | $('#places').typeahead({ 49 | source: placenames, 50 | afterSelect: function (b) { 51 | redraw(b) 52 | } 53 | }); 54 | 55 | var arrayBounds = []; 56 | function redraw(b) { 57 | geojson.eachLayer(function (layer) { 58 | if (layer.feature.properties.zipcode == zipcodes[b]) { 59 | selectTypeaheadFeature(layer) 60 | } 61 | }) 62 | } 63 | 64 | var geojson = L.geoJson(statesData, { 65 | style: stylelayer.defecto, 66 | onEachFeature: onEachFeature 67 | }).addTo(map); 68 | 69 | function onEachFeature(feature, layer) { 70 | layer.on({ 71 | mouseover: highlightFeature, 72 | mouseout: resetHighlight, 73 | click: zoomToFeature 74 | //dblclick : selectFeature 75 | }); 76 | } 77 | 78 | var popupLayer; 79 | function highlightFeature(e) { 80 | var layer = e.target; 81 | layer.setStyle(stylelayer.highlight); 82 | info.update(layer.feature.properties); 83 | } 84 | 85 | 86 | function resetHighlight(e) { 87 | var layer = e.target; 88 | var feature = e.target.feature; 89 | if (checkExistsLayers(feature)) { 90 | setStyleLayer(layer, stylelayer.highlight) 91 | } else { 92 | setStyleLayer(layer, stylelayer.defecto) 93 | } 94 | } 95 | 96 | var featuresSelected = [] 97 | function zoomToFeature(e) { 98 | var layer = e.target; 99 | var feature = e.target.feature; 100 | 101 | if (checkExistsLayers(feature)) { 102 | removerlayers(feature, setStyleLayer, layer, stylelayer.defecto) 103 | removeBounds(layer) 104 | 105 | } else { 106 | addLayers(feature, setStyleLayer, layer, stylelayer.highlight) 107 | addBounds(layer) 108 | } 109 | map.fitBounds(arrayBounds); 110 | detailsselected.update(featuresSelected) 111 | } 112 | 113 | function selectTypeaheadFeature(layer) { 114 | var layer = layer; 115 | var feature = layer.feature; 116 | if (checkExistsLayers(feature)) { 117 | removerlayers(feature, setStyleLayer, layer, stylelayer.defecto) 118 | removeBounds(layer) 119 | } else { 120 | addLayers(feature, setStyleLayer, layer, stylelayer.highlight) 121 | addBounds(layer) 122 | } 123 | map.fitBounds(arrayBounds.length != 0 ? arrayBounds : initbounds) 124 | detailsselected.update(featuresSelected) 125 | } 126 | 127 | var corner1 = L.latLng(53.62, 2.931), 128 | corner2 = L.latLng(50.763, 7.182) 129 | var initbounds = L.latLngBounds(corner1, corner2) 130 | var arrayBounds = []; 131 | 132 | function addBounds(layer) { 133 | arrayBounds.push(layer.getBounds()) 134 | } 135 | 136 | function removeBounds(layer) { 137 | arrayBounds = arrayBounds.filter(bounds => bounds != layer.getBounds()) 138 | } 139 | 140 | function setStyleLayer(layer, styleSelected) { 141 | layer.setStyle(styleSelected) 142 | } 143 | 144 | function removerlayers(feature, callback) { 145 | featuresSelected = featuresSelected.filter(obj => obj.zipcode != feature.properties.zipcode) 146 | callback(arguments[2], arguments[3]) 147 | } 148 | 149 | function addLayers(feature, callback) { 150 | featuresSelected.push({ 151 | zipcode: feature.properties.zipcode, 152 | feature: feature 153 | }) 154 | callback(arguments[2], arguments[3]) 155 | } 156 | 157 | function checkExistsLayers(feature) { 158 | var result = false 159 | for (var i = 0; i < featuresSelected.length; i++) { 160 | if (featuresSelected[i].zipcode == feature.properties.zipcode) { 161 | result = true; 162 | break; 163 | } 164 | }; 165 | return result 166 | } 167 | 168 | /*show info layers*/ 169 | var info = L.control({ 170 | position: 'bottomleft' 171 | }); 172 | 173 | info.onAdd = function (map) { 174 | this._div = L.DomUtil.create('div', 'info'); 175 | this.update(); 176 | return this._div; 177 | }; 178 | 179 | info.update = function (properties) { 180 | this._div.innerHTML = 181 | 182 | '

    Properties

    ' + (properties ? 183 | ` 184 | Aantal: ${properties.amount}
    185 | Gemeente: ${properties.municipality}
    186 | Provincie:${properties.province}
    187 | Plaats:${properties.town}
    188 | Postcode:${properties.zipcode} 189 | 190 | ` : 'Hover over a state');; 191 | }; 192 | 193 | info.addTo(map); 194 | 195 | 196 | var detailsselected = L.control(); 197 | detailsselected.onAdd = function (map) { 198 | this._div = L.DomUtil.create('div', 'info scroler'); 199 | this.update(); 200 | return this._div; 201 | }; 202 | 203 | 204 | var detailshow = function () { 205 | var result = '' 206 | var total = 0 207 | for (var i = 0; i < featuresSelected.length; i++) { 208 | var properties = featuresSelected[i].feature.properties 209 | result += 210 | ` 211 | Amout: ${properties.amount}
    212 | Municipality: ${properties.municipality}
    213 | Province:${properties.province}
    214 | zipcode:${properties.zipcode} 215 | Delete 216 |
    `; 217 | total += properties.amount 218 | 219 | 220 | } 221 | return { 222 | result: result, 223 | total: total 224 | }; 225 | } 226 | 227 | detailsselected.update = function (arrayselected) { 228 | var details = detailshow() 229 | this._div.innerHTML = 'TOTAL: ' + details.total + '
    ' + details.result; 230 | $('#suma', window.parent.document).val(details.total); 231 | }; 232 | 233 | detailsselected.addTo(map); 234 | 235 | function dellayer(zipcode) { 236 | geojson.eachLayer(function (layer) { 237 | if (layer.feature.properties.zipcode == zipcode) { 238 | selectTypeaheadFeature(layer) 239 | } 240 | }) 241 | } 242 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | /*Style for layers*/ 2 | 3 | var stylelayer={ 4 | defecto:{ 5 | color: "red", 6 | opacity: 1, 7 | fillcolor:"red", 8 | fillOpacity:0.1, 9 | weight: 0.5 10 | } 11 | , 12 | reset:{ 13 | color: "red", 14 | opacity: 0.4, 15 | weight: 1 16 | } 17 | , 18 | highlight:{ 19 | weight: 5, 20 | color: '#0D8BE7', 21 | dashArray: '', 22 | fillOpacity: 0.7 23 | } 24 | , 25 | selected:{ 26 | color: "blue", 27 | opacity: 0.3, 28 | weight: 0.5 29 | } 30 | 31 | } 32 | 33 | var map = L.map('map').setView([51.666,6.097], 7); 34 | 35 | L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', { 36 | maxZoom: 18, 37 | attribution: 'my company', 38 | id: 'mapbox.light' 39 | }).addTo(map); 40 | 41 | 42 | var placenames = new Array(); 43 | var zipcodes = new Object(); 44 | //$.getJSON( '/getAjaxProducts', null, 45 | // function ( jsonData ) 46 | //{ 47 | $.each(statesData.features, function ( index, feature ) 48 | { 49 | var name=`${feature.properties.zipcode} ${feature.properties.municipality} ( ${feature.properties.province} - ${feature.properties.town})` 50 | placenames.push(name); 51 | zipcodes[name] = feature.properties.zipcode; 52 | } ); 53 | 54 | /* area de busqueda */ 55 | 56 | 57 | $('#places').typeahead({ 58 | source:placenames, 59 | afterSelect: function(b) { 60 | redraw(b) 61 | } 62 | }); 63 | 64 | var arrayBounds = []; 65 | function redraw(b){ 66 | 67 | geojson.eachLayer(function(layer) { 68 | if(layer.feature.properties.zipcode==zipcodes[b]){ 69 | selectTypeaheadFeature(layer) 70 | 71 | 72 | } 73 | }) 74 | 75 | } 76 | 77 | 78 | 79 | var geojson= L.geoJson(statesData, { 80 | style: stylelayer.defecto, 81 | onEachFeature: onEachFeature 82 | }).addTo(map); 83 | 84 | 85 | 86 | 87 | 88 | function onEachFeature(feature, layer) { 89 | layer.on({ 90 | mouseover: highlightFeature, 91 | mouseout: resetHighlight, 92 | click: zoomToFeature 93 | //dblclick : selectFeature 94 | }); 95 | } 96 | 97 | var popupLayer; 98 | function highlightFeature(e){ 99 | 100 | 101 | 102 | var layer = e.target; 103 | 104 | 105 | layer.setStyle(stylelayer.highlight); 106 | 107 | //var properties= e.target.feature.properties 108 | 109 | /* popupLayer= e.target.bindPopup(` 110 | Amout: ${properties.amount}
    111 | Municipality: ${properties.municipality}
    112 | Phone:${properties.phone}
    113 | Province:${properties.province}
    114 | ptype:${properties.ptype}
    115 | town:${properties.town}
    116 | zipcode:${properties.zipcode} 117 | 118 | `)*/ 119 | 120 | /* .on('mouseover', function(e) { 121 | this.openPopup(); 122 | })*/ 123 | 124 | 125 | info.update(layer.feature.properties); 126 | } 127 | 128 | 129 | 130 | function resetHighlight(e){ 131 | 132 | var layer=e.target; 133 | var feature=e.target.feature; 134 | 135 | if(checkExistsLayers(feature)){ 136 | setStyleLayer(layer,stylelayer.highlight) 137 | 138 | }else{ 139 | setStyleLayer(layer,stylelayer.defecto) 140 | } 141 | 142 | /* popupLayer.on('mouseout', function(e) { 143 | this.closePopup(); 144 | })*/ 145 | } 146 | 147 | var featuresSelected=[] 148 | function zoomToFeature(e){ 149 | 150 | var layer=e.target; 151 | var feature=e.target.feature; 152 | 153 | if(checkExistsLayers(feature)){ 154 | removerlayers(feature,setStyleLayer,layer,stylelayer.defecto) 155 | removeBounds(layer) 156 | 157 | }else{ 158 | addLayers(feature,setStyleLayer,layer,stylelayer.highlight) 159 | addBounds(layer) 160 | } 161 | map.fitBounds(arrayBounds); 162 | detailsselected.update(featuresSelected) 163 | 164 | } 165 | 166 | 167 | function selectTypeaheadFeature(layer){ 168 | 169 | var layer=layer; 170 | var feature=layer.feature; 171 | 172 | if(checkExistsLayers(feature)){ 173 | removerlayers(feature,setStyleLayer,layer,stylelayer.defecto) 174 | 175 | removeBounds(layer) 176 | 177 | }else{ 178 | addLayers(feature,setStyleLayer,layer,stylelayer.highlight) 179 | addBounds(layer) 180 | } 181 | map.fitBounds(arrayBounds.length!=0 ? arrayBounds: initbounds) 182 | detailsselected.update(featuresSelected) 183 | 184 | } 185 | 186 | var corner1 = L.latLng(53.62, 2.931), 187 | corner2 = L.latLng(50.763, 7.182) 188 | var initbounds = L.latLngBounds(corner1,corner2) 189 | var arrayBounds = []; 190 | 191 | function addBounds(layer){ 192 | arrayBounds.push(layer.getBounds()) 193 | } 194 | function removeBounds(layer){ 195 | arrayBounds = arrayBounds.filter(bounds => bounds!= layer.getBounds()) 196 | } 197 | 198 | 199 | function setStyleLayer(layer,styleSelected){ 200 | layer.setStyle(styleSelected) 201 | } 202 | 203 | function removerlayers(feature,callback){ 204 | featuresSelected = featuresSelected.filter(obj => obj.zipcode!= feature.properties.zipcode) 205 | callback(arguments[2],arguments[3]) 206 | } 207 | 208 | function addLayers(feature,callback){ 209 | featuresSelected.push({ 210 | zipcode: feature.properties.zipcode, 211 | feature: feature 212 | }) 213 | callback(arguments[2],arguments[3]) 214 | } 215 | 216 | function checkExistsLayers(feature){ 217 | 218 | var result=false 219 | for (var i = 0; i < featuresSelected.length; i++) { 220 | if(featuresSelected[i].zipcode==feature.properties.zipcode){ 221 | result=true; 222 | break; 223 | } 224 | 225 | }; 226 | return result 227 | } 228 | 229 | 230 | 231 | 232 | /**/ 233 | 234 | var info = L.control({ 235 | position:'bottomleft' 236 | }); 237 | 238 | info.onAdd = function (map) { 239 | this._div = L.DomUtil.create('div', 'info'); 240 | this.update(); 241 | return this._div; 242 | }; 243 | 244 | info.update = function (properties) { 245 | this._div.innerHTML = 246 | 247 | '

    Properties

    ' + (properties ? 248 | ` 249 | Aantal: ${properties.amount}
    250 | Gemeente: ${properties.municipality}
    251 | Provincie:${properties.province}
    252 | Plaats:${properties.town}
    253 | Postcode:${properties.zipcode} 254 | 255 | ` 256 | : 'Hover over a state'); 257 | ; 258 | }; 259 | 260 | info.addTo(map); 261 | 262 | 263 | var detailsselected = L.control(); 264 | 265 | detailsselected.onAdd = function (map) { 266 | this._div = L.DomUtil.create('div', 'info scroler'); 267 | this.update(); 268 | return this._div; 269 | }; 270 | 271 | 272 | 273 | var detailshow=function (){ 274 | var result='' 275 | var total=0 276 | for (var i = 0; i < featuresSelected.length; i++) { 277 | 278 | var properties=featuresSelected[i].feature.properties 279 | result+= 280 | ` 281 | Amout: ${properties.amount}
    282 | Municipality: ${properties.municipality}
    283 | Province:${properties.province}
    284 | zipcode:${properties.zipcode} 285 | Delete 286 |
    `; 287 | total+= properties.amount 288 | 289 | 290 | } 291 | return {result:result,total:total}; 292 | } 293 | 294 | detailsselected.update = function (arrayselected) { 295 | 296 | var details=detailshow() 297 | 298 | this._div.innerHTML ='TOTAL: '+ details.total+ '
    '+ details.result; 299 | $('#suma', window.parent.document).val(details.total); 300 | 301 | 302 | }; 303 | 304 | detailsselected.addTo(map); 305 | 306 | 307 | function dellayer(zipcode){ 308 | geojson.eachLayer(function(layer) { 309 | if(layer.feature.properties.zipcode==zipcode){ 310 | selectTypeaheadFeature(layer) 311 | } 312 | }) 313 | } 314 | -------------------------------------------------------------------------------- /js/bootstrap-typeahead.js: -------------------------------------------------------------------------------- 1 | /* ============================================================= 2 | * bootstrap-typeahead.js v2.3.2 3 | * http://twbs.github.com/bootstrap/javascript.html#typeahead 4 | * ============================================================= 5 | * Copyright 2013 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ============================================================ */ 19 | 20 | 21 | !function($){ 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* TYPEAHEAD PUBLIC CLASS DEFINITION 27 | * ================================= */ 28 | 29 | var Typeahead = function (element, options) { 30 | this.$element = $(element) 31 | this.options = $.extend({}, $.fn.typeahead.defaults, options) 32 | this.matcher = this.options.matcher || this.matcher 33 | this.sorter = this.options.sorter || this.sorter 34 | this.highlighter = this.options.highlighter || this.highlighter 35 | this.updater = this.options.updater || this.updater 36 | this.source = this.options.source 37 | this.$menu = $(this.options.menu) 38 | this.shown = false 39 | this.listen() 40 | } 41 | 42 | Typeahead.prototype = { 43 | 44 | constructor: Typeahead 45 | 46 | , select: function () { 47 | var val = this.$menu.find('.active').attr('data-value') 48 | this.$element 49 | .val(this.updater(val)) 50 | .change() 51 | return this.hide() 52 | } 53 | 54 | , updater: function (item) { 55 | return item 56 | } 57 | 58 | , show: function () { 59 | var pos = $.extend({}, this.$element.position(), { 60 | height: this.$element[0].offsetHeight 61 | }) 62 | 63 | this.$menu 64 | .insertAfter(this.$element) 65 | .css({ 66 | top: pos.top + pos.height 67 | , left: pos.left 68 | }) 69 | .show() 70 | 71 | this.shown = true 72 | return this 73 | } 74 | 75 | , hide: function () { 76 | this.$menu.hide() 77 | this.shown = false 78 | return this 79 | } 80 | 81 | , lookup: function (event) { 82 | var items 83 | 84 | this.query = this.$element.val() 85 | 86 | if (!this.query || this.query.length < this.options.minLength) { 87 | return this.shown ? this.hide() : this 88 | } 89 | 90 | items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source 91 | 92 | return items ? this.process(items) : this 93 | } 94 | 95 | , process: function (items) { 96 | var that = this 97 | 98 | items = $.grep(items, function (item) { 99 | return that.matcher(item) 100 | }) 101 | 102 | items = this.sorter(items) 103 | 104 | if (!items.length) { 105 | return this.shown ? this.hide() : this 106 | } 107 | 108 | return this.render(items.slice(0, this.options.items)).show() 109 | } 110 | 111 | , matcher: function (item) { 112 | return ~item.toLowerCase().indexOf(this.query.toLowerCase()) 113 | } 114 | 115 | , sorter: function (items) { 116 | var beginswith = [] 117 | , caseSensitive = [] 118 | , caseInsensitive = [] 119 | , item 120 | 121 | while (item = items.shift()) { 122 | if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item) 123 | else if (~item.indexOf(this.query)) caseSensitive.push(item) 124 | else caseInsensitive.push(item) 125 | } 126 | 127 | return beginswith.concat(caseSensitive, caseInsensitive) 128 | } 129 | 130 | , highlighter: function (item) { 131 | var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&') 132 | return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) { 133 | return '' + match + '' 134 | }) 135 | } 136 | 137 | , render: function (items) { 138 | var that = this 139 | 140 | items = $(items).map(function (i, item) { 141 | i = $(that.options.item).attr('data-value', item) 142 | i.find('a').html(that.highlighter(item)) 143 | return i[0] 144 | }) 145 | 146 | items.first().addClass('active') 147 | this.$menu.html(items) 148 | return this 149 | } 150 | 151 | , next: function (event) { 152 | var active = this.$menu.find('.active').removeClass('active') 153 | , next = active.next() 154 | 155 | if (!next.length) { 156 | next = $(this.$menu.find('li')[0]) 157 | } 158 | 159 | next.addClass('active') 160 | } 161 | 162 | , prev: function (event) { 163 | var active = this.$menu.find('.active').removeClass('active') 164 | , prev = active.prev() 165 | 166 | if (!prev.length) { 167 | prev = this.$menu.find('li').last() 168 | } 169 | 170 | prev.addClass('active') 171 | } 172 | 173 | , listen: function () { 174 | this.$element 175 | .on('focus', $.proxy(this.focus, this)) 176 | .on('blur', $.proxy(this.blur, this)) 177 | .on('keypress', $.proxy(this.keypress, this)) 178 | .on('keyup', $.proxy(this.keyup, this)) 179 | 180 | if (this.eventSupported('keydown')) { 181 | this.$element.on('keydown', $.proxy(this.keydown, this)) 182 | } 183 | 184 | this.$menu 185 | .on('click', $.proxy(this.click, this)) 186 | .on('mouseenter', 'li', $.proxy(this.mouseenter, this)) 187 | .on('mouseleave', 'li', $.proxy(this.mouseleave, this)) 188 | } 189 | 190 | , eventSupported: function(eventName) { 191 | var isSupported = eventName in this.$element 192 | if (!isSupported) { 193 | this.$element.setAttribute(eventName, 'return;') 194 | isSupported = typeof this.$element[eventName] === 'function' 195 | } 196 | return isSupported 197 | } 198 | 199 | , move: function (e) { 200 | if (!this.shown) return 201 | 202 | switch(e.keyCode) { 203 | case 9: // tab 204 | case 13: // enter 205 | case 27: // escape 206 | e.preventDefault() 207 | break 208 | 209 | case 38: // up arrow 210 | e.preventDefault() 211 | this.prev() 212 | break 213 | 214 | case 40: // down arrow 215 | e.preventDefault() 216 | this.next() 217 | break 218 | } 219 | 220 | e.stopPropagation() 221 | } 222 | 223 | , keydown: function (e) { 224 | this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27]) 225 | this.move(e) 226 | } 227 | 228 | , keypress: function (e) { 229 | if (this.suppressKeyPressRepeat) return 230 | this.move(e) 231 | } 232 | 233 | , keyup: function (e) { 234 | switch(e.keyCode) { 235 | case 40: // down arrow 236 | case 38: // up arrow 237 | case 16: // shift 238 | case 17: // ctrl 239 | case 18: // alt 240 | break 241 | 242 | case 9: // tab 243 | case 13: // enter 244 | if (!this.shown) return 245 | this.select() 246 | break 247 | 248 | case 27: // escape 249 | if (!this.shown) return 250 | this.hide() 251 | break 252 | 253 | default: 254 | this.lookup() 255 | } 256 | 257 | e.stopPropagation() 258 | e.preventDefault() 259 | } 260 | 261 | , focus: function (e) { 262 | this.focused = true 263 | } 264 | 265 | , blur: function (e) { 266 | this.focused = false 267 | if (!this.mousedover && this.shown) this.hide() 268 | } 269 | 270 | , click: function (e) { 271 | e.stopPropagation() 272 | e.preventDefault() 273 | this.select() 274 | this.$element.focus() 275 | } 276 | 277 | , mouseenter: function (e) { 278 | this.mousedover = true 279 | this.$menu.find('.active').removeClass('active') 280 | $(e.currentTarget).addClass('active') 281 | } 282 | 283 | , mouseleave: function (e) { 284 | this.mousedover = false 285 | if (!this.focused && this.shown) this.hide() 286 | } 287 | 288 | } 289 | 290 | 291 | /* TYPEAHEAD PLUGIN DEFINITION 292 | * =========================== */ 293 | 294 | var old = $.fn.typeahead 295 | 296 | $.fn.typeahead = function (option) { 297 | return this.each(function () { 298 | var $this = $(this) 299 | , data = $this.data('typeahead') 300 | , options = typeof option == 'object' && option 301 | if (!data) $this.data('typeahead', (data = new Typeahead(this, options))) 302 | if (typeof option == 'string') data[option]() 303 | }) 304 | } 305 | 306 | $.fn.typeahead.defaults = { 307 | source: [] 308 | , items: 8 309 | , menu: '' 310 | , item: '
  • ' 311 | , minLength: 1 312 | } 313 | 314 | $.fn.typeahead.Constructor = Typeahead 315 | 316 | 317 | /* TYPEAHEAD NO CONFLICT 318 | * =================== */ 319 | 320 | $.fn.typeahead.noConflict = function () { 321 | $.fn.typeahead = old 322 | return this 323 | } 324 | 325 | 326 | /* TYPEAHEAD DATA-API 327 | * ================== */ 328 | 329 | $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) { 330 | var $this = $(this) 331 | if ($this.data('typeahead')) return 332 | $this.typeahead($this.data()) 333 | }) 334 | 335 | }(window.jQuery); 336 | -------------------------------------------------------------------------------- /js/leaflet.css: -------------------------------------------------------------------------------- 1 | /* required styles */ 2 | 3 | .leaflet-pane, 4 | .leaflet-tile, 5 | .leaflet-marker-icon, 6 | .leaflet-marker-shadow, 7 | .leaflet-tile-container, 8 | .leaflet-pane > svg, 9 | .leaflet-pane > canvas, 10 | .leaflet-zoom-box, 11 | .leaflet-image-layer, 12 | .leaflet-layer { 13 | position: absolute; 14 | left: 0; 15 | top: 0; 16 | } 17 | .leaflet-container { 18 | overflow: hidden; 19 | } 20 | .leaflet-tile, 21 | .leaflet-marker-icon, 22 | .leaflet-marker-shadow { 23 | -webkit-user-select: none; 24 | -moz-user-select: none; 25 | user-select: none; 26 | -webkit-user-drag: none; 27 | } 28 | /* Safari renders non-retina tile on retina better with this, but Chrome is worse */ 29 | .leaflet-safari .leaflet-tile { 30 | image-rendering: -webkit-optimize-contrast; 31 | } 32 | /* hack that prevents hw layers "stretching" when loading new tiles */ 33 | .leaflet-safari .leaflet-tile-container { 34 | width: 1600px; 35 | height: 1600px; 36 | -webkit-transform-origin: 0 0; 37 | } 38 | .leaflet-marker-icon, 39 | .leaflet-marker-shadow { 40 | display: block; 41 | } 42 | /* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */ 43 | /* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */ 44 | .leaflet-container .leaflet-overlay-pane svg, 45 | .leaflet-container .leaflet-marker-pane img, 46 | .leaflet-container .leaflet-shadow-pane img, 47 | .leaflet-container .leaflet-tile-pane img, 48 | .leaflet-container img.leaflet-image-layer { 49 | max-width: none !important; 50 | max-height: none !important; 51 | } 52 | 53 | .leaflet-container.leaflet-touch-zoom { 54 | -ms-touch-action: pan-x pan-y; 55 | touch-action: pan-x pan-y; 56 | } 57 | .leaflet-container.leaflet-touch-drag { 58 | -ms-touch-action: pinch-zoom; 59 | /* Fallback for FF which doesn't support pinch-zoom */ 60 | touch-action: none; 61 | touch-action: pinch-zoom; 62 | } 63 | .leaflet-container.leaflet-touch-drag.leaflet-touch-zoom { 64 | -ms-touch-action: none; 65 | touch-action: none; 66 | } 67 | .leaflet-container { 68 | -webkit-tap-highlight-color: transparent; 69 | } 70 | .leaflet-container a { 71 | -webkit-tap-highlight-color: rgba(51, 181, 229, 0.4); 72 | } 73 | .leaflet-tile { 74 | filter: inherit; 75 | visibility: hidden; 76 | } 77 | .leaflet-tile-loaded { 78 | visibility: inherit; 79 | } 80 | .leaflet-zoom-box { 81 | width: 0; 82 | height: 0; 83 | -moz-box-sizing: border-box; 84 | box-sizing: border-box; 85 | z-index: 800; 86 | } 87 | /* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ 88 | .leaflet-overlay-pane svg { 89 | -moz-user-select: none; 90 | } 91 | 92 | .leaflet-pane { z-index: 400; } 93 | 94 | .leaflet-tile-pane { z-index: 200; } 95 | .leaflet-overlay-pane { z-index: 400; } 96 | .leaflet-shadow-pane { z-index: 500; } 97 | .leaflet-marker-pane { z-index: 600; } 98 | .leaflet-tooltip-pane { z-index: 650; } 99 | .leaflet-popup-pane { z-index: 700; } 100 | 101 | .leaflet-map-pane canvas { z-index: 100; } 102 | .leaflet-map-pane svg { z-index: 200; } 103 | 104 | .leaflet-vml-shape { 105 | width: 1px; 106 | height: 1px; 107 | } 108 | .lvml { 109 | behavior: url(#default#VML); 110 | display: inline-block; 111 | position: absolute; 112 | } 113 | 114 | 115 | /* control positioning */ 116 | 117 | .leaflet-control { 118 | position: relative; 119 | z-index: 800; 120 | pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ 121 | pointer-events: auto; 122 | } 123 | .leaflet-top, 124 | .leaflet-bottom { 125 | position: absolute; 126 | z-index: 1000; 127 | pointer-events: none; 128 | } 129 | .leaflet-top { 130 | top: 0; 131 | } 132 | .leaflet-right { 133 | right: 0; 134 | } 135 | .leaflet-bottom { 136 | bottom: 0; 137 | } 138 | .leaflet-left { 139 | left: 0; 140 | } 141 | .leaflet-control { 142 | float: left; 143 | clear: both; 144 | } 145 | .leaflet-right .leaflet-control { 146 | float: right; 147 | } 148 | .leaflet-top .leaflet-control { 149 | margin-top: 10px; 150 | } 151 | .leaflet-bottom .leaflet-control { 152 | margin-bottom: 10px; 153 | } 154 | .leaflet-left .leaflet-control { 155 | margin-left: 10px; 156 | } 157 | .leaflet-right .leaflet-control { 158 | margin-right: 10px; 159 | } 160 | 161 | 162 | /* zoom and fade animations */ 163 | 164 | .leaflet-fade-anim .leaflet-tile { 165 | will-change: opacity; 166 | } 167 | .leaflet-fade-anim .leaflet-popup { 168 | opacity: 0; 169 | -webkit-transition: opacity 0.2s linear; 170 | -moz-transition: opacity 0.2s linear; 171 | -o-transition: opacity 0.2s linear; 172 | transition: opacity 0.2s linear; 173 | } 174 | .leaflet-fade-anim .leaflet-map-pane .leaflet-popup { 175 | opacity: 1; 176 | } 177 | .leaflet-zoom-animated { 178 | -webkit-transform-origin: 0 0; 179 | -ms-transform-origin: 0 0; 180 | transform-origin: 0 0; 181 | } 182 | .leaflet-zoom-anim .leaflet-zoom-animated { 183 | will-change: transform; 184 | } 185 | .leaflet-zoom-anim .leaflet-zoom-animated { 186 | -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); 187 | -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); 188 | -o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1); 189 | transition: transform 0.25s cubic-bezier(0,0,0.25,1); 190 | } 191 | .leaflet-zoom-anim .leaflet-tile, 192 | .leaflet-pan-anim .leaflet-tile { 193 | -webkit-transition: none; 194 | -moz-transition: none; 195 | -o-transition: none; 196 | transition: none; 197 | } 198 | 199 | .leaflet-zoom-anim .leaflet-zoom-hide { 200 | visibility: hidden; 201 | } 202 | 203 | 204 | /* cursors */ 205 | 206 | .leaflet-interactive { 207 | cursor: pointer; 208 | } 209 | .leaflet-grab { 210 | cursor: -webkit-grab; 211 | cursor: -moz-grab; 212 | } 213 | .leaflet-crosshair, 214 | .leaflet-crosshair .leaflet-interactive { 215 | cursor: crosshair; 216 | } 217 | .leaflet-popup-pane, 218 | .leaflet-control { 219 | cursor: auto; 220 | } 221 | .leaflet-dragging .leaflet-grab, 222 | .leaflet-dragging .leaflet-grab .leaflet-interactive, 223 | .leaflet-dragging .leaflet-marker-draggable { 224 | cursor: move; 225 | cursor: -webkit-grabbing; 226 | cursor: -moz-grabbing; 227 | } 228 | 229 | /* marker & overlays interactivity */ 230 | .leaflet-marker-icon, 231 | .leaflet-marker-shadow, 232 | .leaflet-image-layer, 233 | .leaflet-pane > svg path, 234 | .leaflet-tile-container { 235 | pointer-events: none; 236 | } 237 | 238 | .leaflet-marker-icon.leaflet-interactive, 239 | .leaflet-image-layer.leaflet-interactive, 240 | .leaflet-pane > svg path.leaflet-interactive { 241 | pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ 242 | pointer-events: auto; 243 | } 244 | 245 | /* visual tweaks */ 246 | 247 | .leaflet-container { 248 | background: #ddd; 249 | outline: 0; 250 | } 251 | .leaflet-container a { 252 | color: #0078A8; 253 | } 254 | .leaflet-container a.leaflet-active { 255 | outline: 2px solid orange; 256 | } 257 | .leaflet-zoom-box { 258 | border: 2px dotted #38f; 259 | background: rgba(255,255,255,0.5); 260 | } 261 | 262 | 263 | /* general typography */ 264 | .leaflet-container { 265 | font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; 266 | } 267 | 268 | 269 | /* general toolbar styles */ 270 | 271 | .leaflet-bar { 272 | box-shadow: 0 1px 5px rgba(0,0,0,0.65); 273 | border-radius: 4px; 274 | } 275 | .leaflet-bar a, 276 | .leaflet-bar a:hover { 277 | background-color: #fff; 278 | border-bottom: 1px solid #ccc; 279 | width: 26px; 280 | height: 26px; 281 | line-height: 26px; 282 | display: block; 283 | text-align: center; 284 | text-decoration: none; 285 | color: black; 286 | } 287 | .leaflet-bar a, 288 | .leaflet-control-layers-toggle { 289 | background-position: 50% 50%; 290 | background-repeat: no-repeat; 291 | display: block; 292 | } 293 | .leaflet-bar a:hover { 294 | background-color: #f4f4f4; 295 | } 296 | .leaflet-bar a:first-child { 297 | border-top-left-radius: 4px; 298 | border-top-right-radius: 4px; 299 | } 300 | .leaflet-bar a:last-child { 301 | border-bottom-left-radius: 4px; 302 | border-bottom-right-radius: 4px; 303 | border-bottom: none; 304 | } 305 | .leaflet-bar a.leaflet-disabled { 306 | cursor: default; 307 | background-color: #f4f4f4; 308 | color: #bbb; 309 | } 310 | 311 | .leaflet-touch .leaflet-bar a { 312 | width: 30px; 313 | height: 30px; 314 | line-height: 30px; 315 | } 316 | .leaflet-touch .leaflet-bar a:first-child { 317 | border-top-left-radius: 2px; 318 | border-top-right-radius: 2px; 319 | } 320 | .leaflet-touch .leaflet-bar a:last-child { 321 | border-bottom-left-radius: 2px; 322 | border-bottom-right-radius: 2px; 323 | } 324 | 325 | /* zoom control */ 326 | 327 | .leaflet-control-zoom-in, 328 | .leaflet-control-zoom-out { 329 | font: bold 18px 'Lucida Console', Monaco, monospace; 330 | text-indent: 1px; 331 | } 332 | 333 | .leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out { 334 | font-size: 22px; 335 | } 336 | 337 | 338 | /* layers control */ 339 | 340 | .leaflet-control-layers { 341 | box-shadow: 0 1px 5px rgba(0,0,0,0.4); 342 | background: #fff; 343 | border-radius: 5px; 344 | } 345 | .leaflet-control-layers-toggle { 346 | background-image: url(images/layers.png); 347 | width: 36px; 348 | height: 36px; 349 | } 350 | .leaflet-retina .leaflet-control-layers-toggle { 351 | background-image: url(images/layers-2x.png); 352 | background-size: 26px 26px; 353 | } 354 | .leaflet-touch .leaflet-control-layers-toggle { 355 | width: 44px; 356 | height: 44px; 357 | } 358 | .leaflet-control-layers .leaflet-control-layers-list, 359 | .leaflet-control-layers-expanded .leaflet-control-layers-toggle { 360 | display: none; 361 | } 362 | .leaflet-control-layers-expanded .leaflet-control-layers-list { 363 | display: block; 364 | position: relative; 365 | } 366 | .leaflet-control-layers-expanded { 367 | padding: 6px 10px 6px 6px; 368 | color: #333; 369 | background: #fff; 370 | } 371 | .leaflet-control-layers-scrollbar { 372 | overflow-y: scroll; 373 | overflow-x: hidden; 374 | padding-right: 5px; 375 | } 376 | .leaflet-control-layers-selector { 377 | margin-top: 2px; 378 | position: relative; 379 | top: 1px; 380 | } 381 | .leaflet-control-layers label { 382 | display: block; 383 | } 384 | .leaflet-control-layers-separator { 385 | height: 0; 386 | border-top: 1px solid #ddd; 387 | margin: 5px -10px 5px -6px; 388 | } 389 | 390 | /* Default icon URLs */ 391 | .leaflet-default-icon-path { 392 | background-image: url(images/marker-icon.png); 393 | } 394 | 395 | 396 | /* attribution and scale controls */ 397 | 398 | .leaflet-container .leaflet-control-attribution { 399 | background: #fff; 400 | background: rgba(255, 255, 255, 0.7); 401 | margin: 0; 402 | } 403 | .leaflet-control-attribution, 404 | .leaflet-control-scale-line { 405 | padding: 0 5px; 406 | color: #333; 407 | } 408 | .leaflet-control-attribution a { 409 | text-decoration: none; 410 | } 411 | .leaflet-control-attribution a:hover { 412 | text-decoration: underline; 413 | } 414 | .leaflet-container .leaflet-control-attribution, 415 | .leaflet-container .leaflet-control-scale { 416 | font-size: 11px; 417 | } 418 | .leaflet-left .leaflet-control-scale { 419 | margin-left: 5px; 420 | } 421 | .leaflet-bottom .leaflet-control-scale { 422 | margin-bottom: 5px; 423 | } 424 | .leaflet-control-scale-line { 425 | border: 2px solid #777; 426 | border-top: none; 427 | line-height: 1.1; 428 | padding: 2px 5px 1px; 429 | font-size: 11px; 430 | white-space: nowrap; 431 | overflow: hidden; 432 | -moz-box-sizing: border-box; 433 | box-sizing: border-box; 434 | 435 | background: #fff; 436 | background: rgba(255, 255, 255, 0.5); 437 | } 438 | .leaflet-control-scale-line:not(:first-child) { 439 | border-top: 2px solid #777; 440 | border-bottom: none; 441 | margin-top: -2px; 442 | } 443 | .leaflet-control-scale-line:not(:first-child):not(:last-child) { 444 | border-bottom: 2px solid #777; 445 | } 446 | 447 | .leaflet-touch .leaflet-control-attribution, 448 | .leaflet-touch .leaflet-control-layers, 449 | .leaflet-touch .leaflet-bar { 450 | box-shadow: none; 451 | } 452 | .leaflet-touch .leaflet-control-layers, 453 | .leaflet-touch .leaflet-bar { 454 | border: 2px solid rgba(0,0,0,0.2); 455 | background-clip: padding-box; 456 | } 457 | 458 | 459 | /* popup */ 460 | 461 | .leaflet-popup { 462 | position: absolute; 463 | text-align: center; 464 | margin-bottom: 20px; 465 | } 466 | .leaflet-popup-content-wrapper { 467 | padding: 1px; 468 | text-align: left; 469 | border-radius: 12px; 470 | } 471 | .leaflet-popup-content { 472 | margin: 13px 19px; 473 | line-height: 1.4; 474 | } 475 | .leaflet-popup-content p { 476 | margin: 18px 0; 477 | } 478 | .leaflet-popup-tip-container { 479 | width: 40px; 480 | height: 20px; 481 | position: absolute; 482 | left: 50%; 483 | margin-left: -20px; 484 | overflow: hidden; 485 | pointer-events: none; 486 | } 487 | .leaflet-popup-tip { 488 | width: 17px; 489 | height: 17px; 490 | padding: 1px; 491 | 492 | margin: -10px auto 0; 493 | 494 | -webkit-transform: rotate(45deg); 495 | -moz-transform: rotate(45deg); 496 | -ms-transform: rotate(45deg); 497 | -o-transform: rotate(45deg); 498 | transform: rotate(45deg); 499 | } 500 | .leaflet-popup-content-wrapper, 501 | .leaflet-popup-tip { 502 | background: white; 503 | color: #333; 504 | box-shadow: 0 3px 14px rgba(0,0,0,0.4); 505 | } 506 | .leaflet-container a.leaflet-popup-close-button { 507 | position: absolute; 508 | top: 0; 509 | right: 0; 510 | padding: 4px 4px 0 0; 511 | border: none; 512 | text-align: center; 513 | width: 18px; 514 | height: 14px; 515 | font: 16px/14px Tahoma, Verdana, sans-serif; 516 | color: #c3c3c3; 517 | text-decoration: none; 518 | font-weight: bold; 519 | background: transparent; 520 | } 521 | .leaflet-container a.leaflet-popup-close-button:hover { 522 | color: #999; 523 | } 524 | .leaflet-popup-scrolled { 525 | overflow: auto; 526 | border-bottom: 1px solid #ddd; 527 | border-top: 1px solid #ddd; 528 | } 529 | 530 | .leaflet-oldie .leaflet-popup-content-wrapper { 531 | zoom: 1; 532 | } 533 | .leaflet-oldie .leaflet-popup-tip { 534 | width: 24px; 535 | margin: 0 auto; 536 | 537 | -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; 538 | filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); 539 | } 540 | .leaflet-oldie .leaflet-popup-tip-container { 541 | margin-top: -1px; 542 | } 543 | 544 | .leaflet-oldie .leaflet-control-zoom, 545 | .leaflet-oldie .leaflet-control-layers, 546 | .leaflet-oldie .leaflet-popup-content-wrapper, 547 | .leaflet-oldie .leaflet-popup-tip { 548 | border: 1px solid #999; 549 | } 550 | 551 | 552 | /* div icon */ 553 | 554 | .leaflet-div-icon { 555 | background: #fff; 556 | border: 1px solid #666; 557 | } 558 | 559 | 560 | /* Tooltip */ 561 | /* Base styles for the element that has a tooltip */ 562 | .leaflet-tooltip { 563 | position: absolute; 564 | padding: 6px; 565 | background-color: #fff; 566 | border: 1px solid #fff; 567 | border-radius: 3px; 568 | color: #222; 569 | white-space: nowrap; 570 | -webkit-user-select: none; 571 | -moz-user-select: none; 572 | -ms-user-select: none; 573 | user-select: none; 574 | pointer-events: none; 575 | box-shadow: 0 1px 3px rgba(0,0,0,0.4); 576 | } 577 | .leaflet-tooltip.leaflet-clickable { 578 | cursor: pointer; 579 | pointer-events: auto; 580 | } 581 | .leaflet-tooltip-top:before, 582 | .leaflet-tooltip-bottom:before, 583 | .leaflet-tooltip-left:before, 584 | .leaflet-tooltip-right:before { 585 | position: absolute; 586 | pointer-events: none; 587 | border: 6px solid transparent; 588 | background: transparent; 589 | content: ""; 590 | } 591 | 592 | /* Directions */ 593 | 594 | .leaflet-tooltip-bottom { 595 | margin-top: 6px; 596 | } 597 | .leaflet-tooltip-top { 598 | margin-top: -6px; 599 | } 600 | .leaflet-tooltip-bottom:before, 601 | .leaflet-tooltip-top:before { 602 | left: 50%; 603 | margin-left: -6px; 604 | } 605 | .leaflet-tooltip-top:before { 606 | bottom: 0; 607 | margin-bottom: -12px; 608 | border-top-color: #fff; 609 | } 610 | .leaflet-tooltip-bottom:before { 611 | top: 0; 612 | margin-top: -12px; 613 | margin-left: -6px; 614 | border-bottom-color: #fff; 615 | } 616 | .leaflet-tooltip-left { 617 | margin-left: -6px; 618 | } 619 | .leaflet-tooltip-right { 620 | margin-left: 6px; 621 | } 622 | .leaflet-tooltip-left:before, 623 | .leaflet-tooltip-right:before { 624 | top: 50%; 625 | margin-top: -6px; 626 | } 627 | .leaflet-tooltip-left:before { 628 | right: 0; 629 | margin-right: -12px; 630 | border-left-color: #fff; 631 | } 632 | .leaflet-tooltip-right:before { 633 | left: 0; 634 | margin-left: -12px; 635 | border-right-color: #fff; 636 | } 637 | -------------------------------------------------------------------------------- /js/typeahead.jquery.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * typeahead.js 0.11.1 3 | * https://github.com/twitter/typeahead.js 4 | * Copyright 2013-2015 Twitter, Inc. and other contributors; Licensed MIT 5 | */ 6 | 7 | (function(root, factory) { 8 | if (typeof define === "function" && define.amd) { 9 | define("typeahead.js", [ "jquery" ], function(a0) { 10 | return factory(a0); 11 | }); 12 | } else if (typeof exports === "object") { 13 | module.exports = factory(require("jquery")); 14 | } else { 15 | factory(jQuery); 16 | } 17 | })(this, function($) { 18 | var _ = function() { 19 | "use strict"; 20 | return { 21 | isMsie: function() { 22 | return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; 23 | }, 24 | isBlankString: function(str) { 25 | return !str || /^\s*$/.test(str); 26 | }, 27 | escapeRegExChars: function(str) { 28 | return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 29 | }, 30 | isString: function(obj) { 31 | return typeof obj === "string"; 32 | }, 33 | isNumber: function(obj) { 34 | return typeof obj === "number"; 35 | }, 36 | isArray: $.isArray, 37 | isFunction: $.isFunction, 38 | isObject: $.isPlainObject, 39 | isUndefined: function(obj) { 40 | return typeof obj === "undefined"; 41 | }, 42 | isElement: function(obj) { 43 | return !!(obj && obj.nodeType === 1); 44 | }, 45 | isJQuery: function(obj) { 46 | return obj instanceof $; 47 | }, 48 | toStr: function toStr(s) { 49 | return _.isUndefined(s) || s === null ? "" : s + ""; 50 | }, 51 | bind: $.proxy, 52 | each: function(collection, cb) { 53 | $.each(collection, reverseArgs); 54 | function reverseArgs(index, value) { 55 | return cb(value, index); 56 | } 57 | }, 58 | map: $.map, 59 | filter: $.grep, 60 | every: function(obj, test) { 61 | var result = true; 62 | if (!obj) { 63 | return result; 64 | } 65 | $.each(obj, function(key, val) { 66 | if (!(result = test.call(null, val, key, obj))) { 67 | return false; 68 | } 69 | }); 70 | return !!result; 71 | }, 72 | some: function(obj, test) { 73 | var result = false; 74 | if (!obj) { 75 | return result; 76 | } 77 | $.each(obj, function(key, val) { 78 | if (result = test.call(null, val, key, obj)) { 79 | return false; 80 | } 81 | }); 82 | return !!result; 83 | }, 84 | mixin: $.extend, 85 | identity: function(x) { 86 | return x; 87 | }, 88 | clone: function(obj) { 89 | return $.extend(true, {}, obj); 90 | }, 91 | getIdGenerator: function() { 92 | var counter = 0; 93 | return function() { 94 | return counter++; 95 | }; 96 | }, 97 | templatify: function templatify(obj) { 98 | return $.isFunction(obj) ? obj : template; 99 | function template() { 100 | return String(obj); 101 | } 102 | }, 103 | defer: function(fn) { 104 | setTimeout(fn, 0); 105 | }, 106 | debounce: function(func, wait, immediate) { 107 | var timeout, result; 108 | return function() { 109 | var context = this, args = arguments, later, callNow; 110 | later = function() { 111 | timeout = null; 112 | if (!immediate) { 113 | result = func.apply(context, args); 114 | } 115 | }; 116 | callNow = immediate && !timeout; 117 | clearTimeout(timeout); 118 | timeout = setTimeout(later, wait); 119 | if (callNow) { 120 | result = func.apply(context, args); 121 | } 122 | return result; 123 | }; 124 | }, 125 | throttle: function(func, wait) { 126 | var context, args, timeout, result, previous, later; 127 | previous = 0; 128 | later = function() { 129 | previous = new Date(); 130 | timeout = null; 131 | result = func.apply(context, args); 132 | }; 133 | return function() { 134 | var now = new Date(), remaining = wait - (now - previous); 135 | context = this; 136 | args = arguments; 137 | if (remaining <= 0) { 138 | clearTimeout(timeout); 139 | timeout = null; 140 | previous = now; 141 | result = func.apply(context, args); 142 | } else if (!timeout) { 143 | timeout = setTimeout(later, remaining); 144 | } 145 | return result; 146 | }; 147 | }, 148 | stringify: function(val) { 149 | return _.isString(val) ? val : JSON.stringify(val); 150 | }, 151 | noop: function() {} 152 | }; 153 | }(); 154 | var WWW = function() { 155 | "use strict"; 156 | var defaultClassNames = { 157 | wrapper: "twitter-typeahead", 158 | input: "tt-input", 159 | hint: "tt-hint", 160 | menu: "tt-menu", 161 | dataset: "tt-dataset", 162 | suggestion: "tt-suggestion", 163 | selectable: "tt-selectable", 164 | empty: "tt-empty", 165 | open: "tt-open", 166 | cursor: "tt-cursor", 167 | highlight: "tt-highlight" 168 | }; 169 | return build; 170 | function build(o) { 171 | var www, classes; 172 | classes = _.mixin({}, defaultClassNames, o); 173 | www = { 174 | css: buildCss(), 175 | classes: classes, 176 | html: buildHtml(classes), 177 | selectors: buildSelectors(classes) 178 | }; 179 | return { 180 | css: www.css, 181 | html: www.html, 182 | classes: www.classes, 183 | selectors: www.selectors, 184 | mixin: function(o) { 185 | _.mixin(o, www); 186 | } 187 | }; 188 | } 189 | function buildHtml(c) { 190 | return { 191 | wrapper: '', 192 | menu: '
    ' 193 | }; 194 | } 195 | function buildSelectors(classes) { 196 | var selectors = {}; 197 | _.each(classes, function(v, k) { 198 | selectors[k] = "." + v; 199 | }); 200 | return selectors; 201 | } 202 | function buildCss() { 203 | var css = { 204 | wrapper: { 205 | position: "relative", 206 | display: "inline-block" 207 | }, 208 | hint: { 209 | position: "absolute", 210 | top: "0", 211 | left: "0", 212 | borderColor: "transparent", 213 | boxShadow: "none", 214 | opacity: "1" 215 | }, 216 | input: { 217 | position: "relative", 218 | verticalAlign: "top", 219 | backgroundColor: "transparent" 220 | }, 221 | inputWithNoHint: { 222 | position: "relative", 223 | verticalAlign: "top" 224 | }, 225 | menu: { 226 | position: "absolute", 227 | top: "100%", 228 | left: "0", 229 | zIndex: "100", 230 | display: "none" 231 | }, 232 | ltr: { 233 | left: "0", 234 | right: "auto" 235 | }, 236 | rtl: { 237 | left: "auto", 238 | right: " 0" 239 | } 240 | }; 241 | if (_.isMsie()) { 242 | _.mixin(css.input, { 243 | backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)" 244 | }); 245 | } 246 | return css; 247 | } 248 | }(); 249 | var EventBus = function() { 250 | "use strict"; 251 | var namespace, deprecationMap; 252 | namespace = "typeahead:"; 253 | deprecationMap = { 254 | render: "rendered", 255 | cursorchange: "cursorchanged", 256 | select: "selected", 257 | autocomplete: "autocompleted" 258 | }; 259 | function EventBus(o) { 260 | if (!o || !o.el) { 261 | $.error("EventBus initialized without el"); 262 | } 263 | this.$el = $(o.el); 264 | } 265 | _.mixin(EventBus.prototype, { 266 | _trigger: function(type, args) { 267 | var $e; 268 | $e = $.Event(namespace + type); 269 | (args = args || []).unshift($e); 270 | this.$el.trigger.apply(this.$el, args); 271 | return $e; 272 | }, 273 | before: function(type) { 274 | var args, $e; 275 | args = [].slice.call(arguments, 1); 276 | $e = this._trigger("before" + type, args); 277 | return $e.isDefaultPrevented(); 278 | }, 279 | trigger: function(type) { 280 | var deprecatedType; 281 | this._trigger(type, [].slice.call(arguments, 1)); 282 | if (deprecatedType = deprecationMap[type]) { 283 | this._trigger(deprecatedType, [].slice.call(arguments, 1)); 284 | } 285 | } 286 | }); 287 | return EventBus; 288 | }(); 289 | var EventEmitter = function() { 290 | "use strict"; 291 | var splitter = /\s+/, nextTick = getNextTick(); 292 | return { 293 | onSync: onSync, 294 | onAsync: onAsync, 295 | off: off, 296 | trigger: trigger 297 | }; 298 | function on(method, types, cb, context) { 299 | var type; 300 | if (!cb) { 301 | return this; 302 | } 303 | types = types.split(splitter); 304 | cb = context ? bindContext(cb, context) : cb; 305 | this._callbacks = this._callbacks || {}; 306 | while (type = types.shift()) { 307 | this._callbacks[type] = this._callbacks[type] || { 308 | sync: [], 309 | async: [] 310 | }; 311 | this._callbacks[type][method].push(cb); 312 | } 313 | return this; 314 | } 315 | function onAsync(types, cb, context) { 316 | return on.call(this, "async", types, cb, context); 317 | } 318 | function onSync(types, cb, context) { 319 | return on.call(this, "sync", types, cb, context); 320 | } 321 | function off(types) { 322 | var type; 323 | if (!this._callbacks) { 324 | return this; 325 | } 326 | types = types.split(splitter); 327 | while (type = types.shift()) { 328 | delete this._callbacks[type]; 329 | } 330 | return this; 331 | } 332 | function trigger(types) { 333 | var type, callbacks, args, syncFlush, asyncFlush; 334 | if (!this._callbacks) { 335 | return this; 336 | } 337 | types = types.split(splitter); 338 | args = [].slice.call(arguments, 1); 339 | while ((type = types.shift()) && (callbacks = this._callbacks[type])) { 340 | syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args)); 341 | asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args)); 342 | syncFlush() && nextTick(asyncFlush); 343 | } 344 | return this; 345 | } 346 | function getFlush(callbacks, context, args) { 347 | return flush; 348 | function flush() { 349 | var cancelled; 350 | for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) { 351 | cancelled = callbacks[i].apply(context, args) === false; 352 | } 353 | return !cancelled; 354 | } 355 | } 356 | function getNextTick() { 357 | var nextTickFn; 358 | if (window.setImmediate) { 359 | nextTickFn = function nextTickSetImmediate(fn) { 360 | setImmediate(function() { 361 | fn(); 362 | }); 363 | }; 364 | } else { 365 | nextTickFn = function nextTickSetTimeout(fn) { 366 | setTimeout(function() { 367 | fn(); 368 | }, 0); 369 | }; 370 | } 371 | return nextTickFn; 372 | } 373 | function bindContext(fn, context) { 374 | return fn.bind ? fn.bind(context) : function() { 375 | fn.apply(context, [].slice.call(arguments, 0)); 376 | }; 377 | } 378 | }(); 379 | var highlight = function(doc) { 380 | "use strict"; 381 | var defaults = { 382 | node: null, 383 | pattern: null, 384 | tagName: "strong", 385 | className: null, 386 | wordsOnly: false, 387 | caseSensitive: false 388 | }; 389 | return function hightlight(o) { 390 | var regex; 391 | o = _.mixin({}, defaults, o); 392 | if (!o.node || !o.pattern) { 393 | return; 394 | } 395 | o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ]; 396 | regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly); 397 | traverse(o.node, hightlightTextNode); 398 | function hightlightTextNode(textNode) { 399 | var match, patternNode, wrapperNode; 400 | if (match = regex.exec(textNode.data)) { 401 | wrapperNode = doc.createElement(o.tagName); 402 | o.className && (wrapperNode.className = o.className); 403 | patternNode = textNode.splitText(match.index); 404 | patternNode.splitText(match[0].length); 405 | wrapperNode.appendChild(patternNode.cloneNode(true)); 406 | textNode.parentNode.replaceChild(wrapperNode, patternNode); 407 | } 408 | return !!match; 409 | } 410 | function traverse(el, hightlightTextNode) { 411 | var childNode, TEXT_NODE_TYPE = 3; 412 | for (var i = 0; i < el.childNodes.length; i++) { 413 | childNode = el.childNodes[i]; 414 | if (childNode.nodeType === TEXT_NODE_TYPE) { 415 | i += hightlightTextNode(childNode) ? 1 : 0; 416 | } else { 417 | traverse(childNode, hightlightTextNode); 418 | } 419 | } 420 | } 421 | }; 422 | function getRegex(patterns, caseSensitive, wordsOnly) { 423 | var escapedPatterns = [], regexStr; 424 | for (var i = 0, len = patterns.length; i < len; i++) { 425 | escapedPatterns.push(_.escapeRegExChars(patterns[i])); 426 | } 427 | regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")"; 428 | return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i"); 429 | } 430 | }(window.document); 431 | var Input = function() { 432 | "use strict"; 433 | var specialKeyCodeMap; 434 | specialKeyCodeMap = { 435 | 9: "tab", 436 | 27: "esc", 437 | 37: "left", 438 | 39: "right", 439 | 13: "enter", 440 | 38: "up", 441 | 40: "down" 442 | }; 443 | function Input(o, www) { 444 | o = o || {}; 445 | if (!o.input) { 446 | $.error("input is missing"); 447 | } 448 | www.mixin(this); 449 | this.$hint = $(o.hint); 450 | this.$input = $(o.input); 451 | this.query = this.$input.val(); 452 | this.queryWhenFocused = this.hasFocus() ? this.query : null; 453 | this.$overflowHelper = buildOverflowHelper(this.$input); 454 | this._checkLanguageDirection(); 455 | if (this.$hint.length === 0) { 456 | this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop; 457 | } 458 | } 459 | Input.normalizeQuery = function(str) { 460 | return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " "); 461 | }; 462 | _.mixin(Input.prototype, EventEmitter, { 463 | _onBlur: function onBlur() { 464 | this.resetInputValue(); 465 | this.trigger("blurred"); 466 | }, 467 | _onFocus: function onFocus() { 468 | this.queryWhenFocused = this.query; 469 | this.trigger("focused"); 470 | }, 471 | _onKeydown: function onKeydown($e) { 472 | var keyName = specialKeyCodeMap[$e.which || $e.keyCode]; 473 | this._managePreventDefault(keyName, $e); 474 | if (keyName && this._shouldTrigger(keyName, $e)) { 475 | this.trigger(keyName + "Keyed", $e); 476 | } 477 | }, 478 | _onInput: function onInput() { 479 | this._setQuery(this.getInputValue()); 480 | this.clearHintIfInvalid(); 481 | this._checkLanguageDirection(); 482 | }, 483 | _managePreventDefault: function managePreventDefault(keyName, $e) { 484 | var preventDefault; 485 | switch (keyName) { 486 | case "up": 487 | case "down": 488 | preventDefault = !withModifier($e); 489 | break; 490 | 491 | default: 492 | preventDefault = false; 493 | } 494 | preventDefault && $e.preventDefault(); 495 | }, 496 | _shouldTrigger: function shouldTrigger(keyName, $e) { 497 | var trigger; 498 | switch (keyName) { 499 | case "tab": 500 | trigger = !withModifier($e); 501 | break; 502 | 503 | default: 504 | trigger = true; 505 | } 506 | return trigger; 507 | }, 508 | _checkLanguageDirection: function checkLanguageDirection() { 509 | var dir = (this.$input.css("direction") || "ltr").toLowerCase(); 510 | if (this.dir !== dir) { 511 | this.dir = dir; 512 | this.$hint.attr("dir", dir); 513 | this.trigger("langDirChanged", dir); 514 | } 515 | }, 516 | _setQuery: function setQuery(val, silent) { 517 | var areEquivalent, hasDifferentWhitespace; 518 | areEquivalent = areQueriesEquivalent(val, this.query); 519 | hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false; 520 | this.query = val; 521 | if (!silent && !areEquivalent) { 522 | this.trigger("queryChanged", this.query); 523 | } else if (!silent && hasDifferentWhitespace) { 524 | this.trigger("whitespaceChanged", this.query); 525 | } 526 | }, 527 | bind: function() { 528 | var that = this, onBlur, onFocus, onKeydown, onInput; 529 | onBlur = _.bind(this._onBlur, this); 530 | onFocus = _.bind(this._onFocus, this); 531 | onKeydown = _.bind(this._onKeydown, this); 532 | onInput = _.bind(this._onInput, this); 533 | this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown); 534 | if (!_.isMsie() || _.isMsie() > 9) { 535 | this.$input.on("input.tt", onInput); 536 | } else { 537 | this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) { 538 | if (specialKeyCodeMap[$e.which || $e.keyCode]) { 539 | return; 540 | } 541 | _.defer(_.bind(that._onInput, that, $e)); 542 | }); 543 | } 544 | return this; 545 | }, 546 | focus: function focus() { 547 | this.$input.focus(); 548 | }, 549 | blur: function blur() { 550 | this.$input.blur(); 551 | }, 552 | getLangDir: function getLangDir() { 553 | return this.dir; 554 | }, 555 | getQuery: function getQuery() { 556 | return this.query || ""; 557 | }, 558 | setQuery: function setQuery(val, silent) { 559 | this.setInputValue(val); 560 | this._setQuery(val, silent); 561 | }, 562 | hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() { 563 | return this.query !== this.queryWhenFocused; 564 | }, 565 | getInputValue: function getInputValue() { 566 | return this.$input.val(); 567 | }, 568 | setInputValue: function setInputValue(value) { 569 | this.$input.val(value); 570 | this.clearHintIfInvalid(); 571 | this._checkLanguageDirection(); 572 | }, 573 | resetInputValue: function resetInputValue() { 574 | this.setInputValue(this.query); 575 | }, 576 | getHint: function getHint() { 577 | return this.$hint.val(); 578 | }, 579 | setHint: function setHint(value) { 580 | this.$hint.val(value); 581 | }, 582 | clearHint: function clearHint() { 583 | this.setHint(""); 584 | }, 585 | clearHintIfInvalid: function clearHintIfInvalid() { 586 | var val, hint, valIsPrefixOfHint, isValid; 587 | val = this.getInputValue(); 588 | hint = this.getHint(); 589 | valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0; 590 | isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow(); 591 | !isValid && this.clearHint(); 592 | }, 593 | hasFocus: function hasFocus() { 594 | return this.$input.is(":focus"); 595 | }, 596 | hasOverflow: function hasOverflow() { 597 | var constraint = this.$input.width() - 2; 598 | this.$overflowHelper.text(this.getInputValue()); 599 | return this.$overflowHelper.width() >= constraint; 600 | }, 601 | isCursorAtEnd: function() { 602 | var valueLength, selectionStart, range; 603 | valueLength = this.$input.val().length; 604 | selectionStart = this.$input[0].selectionStart; 605 | if (_.isNumber(selectionStart)) { 606 | return selectionStart === valueLength; 607 | } else if (document.selection) { 608 | range = document.selection.createRange(); 609 | range.moveStart("character", -valueLength); 610 | return valueLength === range.text.length; 611 | } 612 | return true; 613 | }, 614 | destroy: function destroy() { 615 | this.$hint.off(".tt"); 616 | this.$input.off(".tt"); 617 | this.$overflowHelper.remove(); 618 | this.$hint = this.$input = this.$overflowHelper = $("
    "); 619 | } 620 | }); 621 | return Input; 622 | function buildOverflowHelper($input) { 623 | return $('').css({ 624 | position: "absolute", 625 | visibility: "hidden", 626 | whiteSpace: "pre", 627 | fontFamily: $input.css("font-family"), 628 | fontSize: $input.css("font-size"), 629 | fontStyle: $input.css("font-style"), 630 | fontVariant: $input.css("font-variant"), 631 | fontWeight: $input.css("font-weight"), 632 | wordSpacing: $input.css("word-spacing"), 633 | letterSpacing: $input.css("letter-spacing"), 634 | textIndent: $input.css("text-indent"), 635 | textRendering: $input.css("text-rendering"), 636 | textTransform: $input.css("text-transform") 637 | }).insertAfter($input); 638 | } 639 | function areQueriesEquivalent(a, b) { 640 | return Input.normalizeQuery(a) === Input.normalizeQuery(b); 641 | } 642 | function withModifier($e) { 643 | return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey; 644 | } 645 | }(); 646 | var Dataset = function() { 647 | "use strict"; 648 | var keys, nameGenerator; 649 | keys = { 650 | val: "tt-selectable-display", 651 | obj: "tt-selectable-object" 652 | }; 653 | nameGenerator = _.getIdGenerator(); 654 | function Dataset(o, www) { 655 | o = o || {}; 656 | o.templates = o.templates || {}; 657 | o.templates.notFound = o.templates.notFound || o.templates.empty; 658 | if (!o.source) { 659 | $.error("missing source"); 660 | } 661 | if (!o.node) { 662 | $.error("missing node"); 663 | } 664 | if (o.name && !isValidName(o.name)) { 665 | $.error("invalid dataset name: " + o.name); 666 | } 667 | www.mixin(this); 668 | this.highlight = !!o.highlight; 669 | this.name = o.name || nameGenerator(); 670 | this.limit = o.limit || 5; 671 | this.displayFn = getDisplayFn(o.display || o.displayKey); 672 | this.templates = getTemplates(o.templates, this.displayFn); 673 | this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source; 674 | this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async; 675 | this._resetLastSuggestion(); 676 | this.$el = $(o.node).addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name); 677 | } 678 | Dataset.extractData = function extractData(el) { 679 | var $el = $(el); 680 | if ($el.data(keys.obj)) { 681 | return { 682 | val: $el.data(keys.val) || "", 683 | obj: $el.data(keys.obj) || null 684 | }; 685 | } 686 | return null; 687 | }; 688 | _.mixin(Dataset.prototype, EventEmitter, { 689 | _overwrite: function overwrite(query, suggestions) { 690 | suggestions = suggestions || []; 691 | if (suggestions.length) { 692 | this._renderSuggestions(query, suggestions); 693 | } else if (this.async && this.templates.pending) { 694 | this._renderPending(query); 695 | } else if (!this.async && this.templates.notFound) { 696 | this._renderNotFound(query); 697 | } else { 698 | this._empty(); 699 | } 700 | this.trigger("rendered", this.name, suggestions, false); 701 | }, 702 | _append: function append(query, suggestions) { 703 | suggestions = suggestions || []; 704 | if (suggestions.length && this.$lastSuggestion.length) { 705 | this._appendSuggestions(query, suggestions); 706 | } else if (suggestions.length) { 707 | this._renderSuggestions(query, suggestions); 708 | } else if (!this.$lastSuggestion.length && this.templates.notFound) { 709 | this._renderNotFound(query); 710 | } 711 | this.trigger("rendered", this.name, suggestions, true); 712 | }, 713 | _renderSuggestions: function renderSuggestions(query, suggestions) { 714 | var $fragment; 715 | $fragment = this._getSuggestionsFragment(query, suggestions); 716 | this.$lastSuggestion = $fragment.children().last(); 717 | this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions)); 718 | }, 719 | _appendSuggestions: function appendSuggestions(query, suggestions) { 720 | var $fragment, $lastSuggestion; 721 | $fragment = this._getSuggestionsFragment(query, suggestions); 722 | $lastSuggestion = $fragment.children().last(); 723 | this.$lastSuggestion.after($fragment); 724 | this.$lastSuggestion = $lastSuggestion; 725 | }, 726 | _renderPending: function renderPending(query) { 727 | var template = this.templates.pending; 728 | this._resetLastSuggestion(); 729 | template && this.$el.html(template({ 730 | query: query, 731 | dataset: this.name 732 | })); 733 | }, 734 | _renderNotFound: function renderNotFound(query) { 735 | var template = this.templates.notFound; 736 | this._resetLastSuggestion(); 737 | template && this.$el.html(template({ 738 | query: query, 739 | dataset: this.name 740 | })); 741 | }, 742 | _empty: function empty() { 743 | this.$el.empty(); 744 | this._resetLastSuggestion(); 745 | }, 746 | _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) { 747 | var that = this, fragment; 748 | fragment = document.createDocumentFragment(); 749 | _.each(suggestions, function getSuggestionNode(suggestion) { 750 | var $el, context; 751 | context = that._injectQuery(query, suggestion); 752 | $el = $(that.templates.suggestion(context)).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable); 753 | fragment.appendChild($el[0]); 754 | }); 755 | this.highlight && highlight({ 756 | className: this.classes.highlight, 757 | node: fragment, 758 | pattern: query 759 | }); 760 | return $(fragment); 761 | }, 762 | _getFooter: function getFooter(query, suggestions) { 763 | return this.templates.footer ? this.templates.footer({ 764 | query: query, 765 | suggestions: suggestions, 766 | dataset: this.name 767 | }) : null; 768 | }, 769 | _getHeader: function getHeader(query, suggestions) { 770 | return this.templates.header ? this.templates.header({ 771 | query: query, 772 | suggestions: suggestions, 773 | dataset: this.name 774 | }) : null; 775 | }, 776 | _resetLastSuggestion: function resetLastSuggestion() { 777 | this.$lastSuggestion = $(); 778 | }, 779 | _injectQuery: function injectQuery(query, obj) { 780 | return _.isObject(obj) ? _.mixin({ 781 | _query: query 782 | }, obj) : obj; 783 | }, 784 | update: function update(query) { 785 | var that = this, canceled = false, syncCalled = false, rendered = 0; 786 | this.cancel(); 787 | this.cancel = function cancel() { 788 | canceled = true; 789 | that.cancel = $.noop; 790 | that.async && that.trigger("asyncCanceled", query); 791 | }; 792 | this.source(query, sync, async); 793 | !syncCalled && sync([]); 794 | function sync(suggestions) { 795 | if (syncCalled) { 796 | return; 797 | } 798 | syncCalled = true; 799 | suggestions = (suggestions || []).slice(0, that.limit); 800 | rendered = suggestions.length; 801 | that._overwrite(query, suggestions); 802 | if (rendered < that.limit && that.async) { 803 | that.trigger("asyncRequested", query); 804 | } 805 | } 806 | function async(suggestions) { 807 | suggestions = suggestions || []; 808 | if (!canceled && rendered < that.limit) { 809 | that.cancel = $.noop; 810 | rendered += suggestions.length; 811 | that._append(query, suggestions.slice(0, that.limit - rendered)); 812 | that.async && that.trigger("asyncReceived", query); 813 | } 814 | } 815 | }, 816 | cancel: $.noop, 817 | clear: function clear() { 818 | this._empty(); 819 | this.cancel(); 820 | this.trigger("cleared"); 821 | }, 822 | isEmpty: function isEmpty() { 823 | return this.$el.is(":empty"); 824 | }, 825 | destroy: function destroy() { 826 | this.$el = $("
    "); 827 | } 828 | }); 829 | return Dataset; 830 | function getDisplayFn(display) { 831 | display = display || _.stringify; 832 | return _.isFunction(display) ? display : displayFn; 833 | function displayFn(obj) { 834 | return obj[display]; 835 | } 836 | } 837 | function getTemplates(templates, displayFn) { 838 | return { 839 | notFound: templates.notFound && _.templatify(templates.notFound), 840 | pending: templates.pending && _.templatify(templates.pending), 841 | header: templates.header && _.templatify(templates.header), 842 | footer: templates.footer && _.templatify(templates.footer), 843 | suggestion: templates.suggestion || suggestionTemplate 844 | }; 845 | function suggestionTemplate(context) { 846 | return $("
    ").text(displayFn(context)); 847 | } 848 | } 849 | function isValidName(str) { 850 | return /^[_a-zA-Z0-9-]+$/.test(str); 851 | } 852 | }(); 853 | var Menu = function() { 854 | "use strict"; 855 | function Menu(o, www) { 856 | var that = this; 857 | o = o || {}; 858 | if (!o.node) { 859 | $.error("node is required"); 860 | } 861 | www.mixin(this); 862 | this.$node = $(o.node); 863 | this.query = null; 864 | this.datasets = _.map(o.datasets, initializeDataset); 865 | function initializeDataset(oDataset) { 866 | var node = that.$node.find(oDataset.node).first(); 867 | oDataset.node = node.length ? node : $("
    ").appendTo(that.$node); 868 | return new Dataset(oDataset, www); 869 | } 870 | } 871 | _.mixin(Menu.prototype, EventEmitter, { 872 | _onSelectableClick: function onSelectableClick($e) { 873 | this.trigger("selectableClicked", $($e.currentTarget)); 874 | }, 875 | _onRendered: function onRendered(type, dataset, suggestions, async) { 876 | this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); 877 | this.trigger("datasetRendered", dataset, suggestions, async); 878 | }, 879 | _onCleared: function onCleared() { 880 | this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); 881 | this.trigger("datasetCleared"); 882 | }, 883 | _propagate: function propagate() { 884 | this.trigger.apply(this, arguments); 885 | }, 886 | _allDatasetsEmpty: function allDatasetsEmpty() { 887 | return _.every(this.datasets, isDatasetEmpty); 888 | function isDatasetEmpty(dataset) { 889 | return dataset.isEmpty(); 890 | } 891 | }, 892 | _getSelectables: function getSelectables() { 893 | return this.$node.find(this.selectors.selectable); 894 | }, 895 | _removeCursor: function _removeCursor() { 896 | var $selectable = this.getActiveSelectable(); 897 | $selectable && $selectable.removeClass(this.classes.cursor); 898 | }, 899 | _ensureVisible: function ensureVisible($el) { 900 | var elTop, elBottom, nodeScrollTop, nodeHeight; 901 | elTop = $el.position().top; 902 | elBottom = elTop + $el.outerHeight(true); 903 | nodeScrollTop = this.$node.scrollTop(); 904 | nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10); 905 | if (elTop < 0) { 906 | this.$node.scrollTop(nodeScrollTop + elTop); 907 | } else if (nodeHeight < elBottom) { 908 | this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight)); 909 | } 910 | }, 911 | bind: function() { 912 | var that = this, onSelectableClick; 913 | onSelectableClick = _.bind(this._onSelectableClick, this); 914 | this.$node.on("click.tt", this.selectors.selectable, onSelectableClick); 915 | _.each(this.datasets, function(dataset) { 916 | dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that); 917 | }); 918 | return this; 919 | }, 920 | isOpen: function isOpen() { 921 | return this.$node.hasClass(this.classes.open); 922 | }, 923 | open: function open() { 924 | this.$node.addClass(this.classes.open); 925 | }, 926 | close: function close() { 927 | this.$node.removeClass(this.classes.open); 928 | this._removeCursor(); 929 | }, 930 | setLanguageDirection: function setLanguageDirection(dir) { 931 | this.$node.attr("dir", dir); 932 | }, 933 | selectableRelativeToCursor: function selectableRelativeToCursor(delta) { 934 | var $selectables, $oldCursor, oldIndex, newIndex; 935 | $oldCursor = this.getActiveSelectable(); 936 | $selectables = this._getSelectables(); 937 | oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1; 938 | newIndex = oldIndex + delta; 939 | newIndex = (newIndex + 1) % ($selectables.length + 1) - 1; 940 | newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex; 941 | return newIndex === -1 ? null : $selectables.eq(newIndex); 942 | }, 943 | setCursor: function setCursor($selectable) { 944 | this._removeCursor(); 945 | if ($selectable = $selectable && $selectable.first()) { 946 | $selectable.addClass(this.classes.cursor); 947 | this._ensureVisible($selectable); 948 | } 949 | }, 950 | getSelectableData: function getSelectableData($el) { 951 | return $el && $el.length ? Dataset.extractData($el) : null; 952 | }, 953 | getActiveSelectable: function getActiveSelectable() { 954 | var $selectable = this._getSelectables().filter(this.selectors.cursor).first(); 955 | return $selectable.length ? $selectable : null; 956 | }, 957 | getTopSelectable: function getTopSelectable() { 958 | var $selectable = this._getSelectables().first(); 959 | return $selectable.length ? $selectable : null; 960 | }, 961 | update: function update(query) { 962 | var isValidUpdate = query !== this.query; 963 | if (isValidUpdate) { 964 | this.query = query; 965 | _.each(this.datasets, updateDataset); 966 | } 967 | return isValidUpdate; 968 | function updateDataset(dataset) { 969 | dataset.update(query); 970 | } 971 | }, 972 | empty: function empty() { 973 | _.each(this.datasets, clearDataset); 974 | this.query = null; 975 | this.$node.addClass(this.classes.empty); 976 | function clearDataset(dataset) { 977 | dataset.clear(); 978 | } 979 | }, 980 | destroy: function destroy() { 981 | this.$node.off(".tt"); 982 | this.$node = $("
    "); 983 | _.each(this.datasets, destroyDataset); 984 | function destroyDataset(dataset) { 985 | dataset.destroy(); 986 | } 987 | } 988 | }); 989 | return Menu; 990 | }(); 991 | var DefaultMenu = function() { 992 | "use strict"; 993 | var s = Menu.prototype; 994 | function DefaultMenu() { 995 | Menu.apply(this, [].slice.call(arguments, 0)); 996 | } 997 | _.mixin(DefaultMenu.prototype, Menu.prototype, { 998 | open: function open() { 999 | !this._allDatasetsEmpty() && this._show(); 1000 | return s.open.apply(this, [].slice.call(arguments, 0)); 1001 | }, 1002 | close: function close() { 1003 | this._hide(); 1004 | return s.close.apply(this, [].slice.call(arguments, 0)); 1005 | }, 1006 | _onRendered: function onRendered() { 1007 | if (this._allDatasetsEmpty()) { 1008 | this._hide(); 1009 | } else { 1010 | this.isOpen() && this._show(); 1011 | } 1012 | return s._onRendered.apply(this, [].slice.call(arguments, 0)); 1013 | }, 1014 | _onCleared: function onCleared() { 1015 | if (this._allDatasetsEmpty()) { 1016 | this._hide(); 1017 | } else { 1018 | this.isOpen() && this._show(); 1019 | } 1020 | return s._onCleared.apply(this, [].slice.call(arguments, 0)); 1021 | }, 1022 | setLanguageDirection: function setLanguageDirection(dir) { 1023 | this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl); 1024 | return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0)); 1025 | }, 1026 | _hide: function hide() { 1027 | this.$node.hide(); 1028 | }, 1029 | _show: function show() { 1030 | this.$node.css("display", "block"); 1031 | } 1032 | }); 1033 | return DefaultMenu; 1034 | }(); 1035 | var Typeahead = function() { 1036 | "use strict"; 1037 | function Typeahead(o, www) { 1038 | var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged; 1039 | o = o || {}; 1040 | if (!o.input) { 1041 | $.error("missing input"); 1042 | } 1043 | if (!o.menu) { 1044 | $.error("missing menu"); 1045 | } 1046 | if (!o.eventBus) { 1047 | $.error("missing event bus"); 1048 | } 1049 | www.mixin(this); 1050 | this.eventBus = o.eventBus; 1051 | this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; 1052 | this.input = o.input; 1053 | this.menu = o.menu; 1054 | this.enabled = true; 1055 | this.active = false; 1056 | this.input.hasFocus() && this.activate(); 1057 | this.dir = this.input.getLangDir(); 1058 | this._hacks(); 1059 | this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this); 1060 | onFocused = c(this, "activate", "open", "_onFocused"); 1061 | onBlurred = c(this, "deactivate", "_onBlurred"); 1062 | onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed"); 1063 | onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed"); 1064 | onEscKeyed = c(this, "isActive", "_onEscKeyed"); 1065 | onUpKeyed = c(this, "isActive", "open", "_onUpKeyed"); 1066 | onDownKeyed = c(this, "isActive", "open", "_onDownKeyed"); 1067 | onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed"); 1068 | onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed"); 1069 | onQueryChanged = c(this, "_openIfActive", "_onQueryChanged"); 1070 | onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged"); 1071 | this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this); 1072 | } 1073 | _.mixin(Typeahead.prototype, { 1074 | _hacks: function hacks() { 1075 | var $input, $menu; 1076 | $input = this.input.$input || $("
    "); 1077 | $menu = this.menu.$node || $("
    "); 1078 | $input.on("blur.tt", function($e) { 1079 | var active, isActive, hasActive; 1080 | active = document.activeElement; 1081 | isActive = $menu.is(active); 1082 | hasActive = $menu.has(active).length > 0; 1083 | if (_.isMsie() && (isActive || hasActive)) { 1084 | $e.preventDefault(); 1085 | $e.stopImmediatePropagation(); 1086 | _.defer(function() { 1087 | $input.focus(); 1088 | }); 1089 | } 1090 | }); 1091 | $menu.on("mousedown.tt", function($e) { 1092 | $e.preventDefault(); 1093 | }); 1094 | }, 1095 | _onSelectableClicked: function onSelectableClicked(type, $el) { 1096 | this.select($el); 1097 | }, 1098 | _onDatasetCleared: function onDatasetCleared() { 1099 | this._updateHint(); 1100 | }, 1101 | _onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) { 1102 | this._updateHint(); 1103 | this.eventBus.trigger("render", suggestions, async, dataset); 1104 | }, 1105 | _onAsyncRequested: function onAsyncRequested(type, dataset, query) { 1106 | this.eventBus.trigger("asyncrequest", query, dataset); 1107 | }, 1108 | _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) { 1109 | this.eventBus.trigger("asynccancel", query, dataset); 1110 | }, 1111 | _onAsyncReceived: function onAsyncReceived(type, dataset, query) { 1112 | this.eventBus.trigger("asyncreceive", query, dataset); 1113 | }, 1114 | _onFocused: function onFocused() { 1115 | this._minLengthMet() && this.menu.update(this.input.getQuery()); 1116 | }, 1117 | _onBlurred: function onBlurred() { 1118 | if (this.input.hasQueryChangedSinceLastFocus()) { 1119 | this.eventBus.trigger("change", this.input.getQuery()); 1120 | } 1121 | }, 1122 | _onEnterKeyed: function onEnterKeyed(type, $e) { 1123 | var $selectable; 1124 | if ($selectable = this.menu.getActiveSelectable()) { 1125 | this.select($selectable) && $e.preventDefault(); 1126 | } 1127 | }, 1128 | _onTabKeyed: function onTabKeyed(type, $e) { 1129 | var $selectable; 1130 | if ($selectable = this.menu.getActiveSelectable()) { 1131 | this.select($selectable) && $e.preventDefault(); 1132 | } else if ($selectable = this.menu.getTopSelectable()) { 1133 | this.autocomplete($selectable) && $e.preventDefault(); 1134 | } 1135 | }, 1136 | _onEscKeyed: function onEscKeyed() { 1137 | this.close(); 1138 | }, 1139 | _onUpKeyed: function onUpKeyed() { 1140 | this.moveCursor(-1); 1141 | }, 1142 | _onDownKeyed: function onDownKeyed() { 1143 | this.moveCursor(+1); 1144 | }, 1145 | _onLeftKeyed: function onLeftKeyed() { 1146 | if (this.dir === "rtl" && this.input.isCursorAtEnd()) { 1147 | this.autocomplete(this.menu.getTopSelectable()); 1148 | } 1149 | }, 1150 | _onRightKeyed: function onRightKeyed() { 1151 | if (this.dir === "ltr" && this.input.isCursorAtEnd()) { 1152 | this.autocomplete(this.menu.getTopSelectable()); 1153 | } 1154 | }, 1155 | _onQueryChanged: function onQueryChanged(e, query) { 1156 | this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty(); 1157 | }, 1158 | _onWhitespaceChanged: function onWhitespaceChanged() { 1159 | this._updateHint(); 1160 | }, 1161 | _onLangDirChanged: function onLangDirChanged(e, dir) { 1162 | if (this.dir !== dir) { 1163 | this.dir = dir; 1164 | this.menu.setLanguageDirection(dir); 1165 | } 1166 | }, 1167 | _openIfActive: function openIfActive() { 1168 | this.isActive() && this.open(); 1169 | }, 1170 | _minLengthMet: function minLengthMet(query) { 1171 | query = _.isString(query) ? query : this.input.getQuery() || ""; 1172 | return query.length >= this.minLength; 1173 | }, 1174 | _updateHint: function updateHint() { 1175 | var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match; 1176 | $selectable = this.menu.getTopSelectable(); 1177 | data = this.menu.getSelectableData($selectable); 1178 | val = this.input.getInputValue(); 1179 | if (data && !_.isBlankString(val) && !this.input.hasOverflow()) { 1180 | query = Input.normalizeQuery(val); 1181 | escapedQuery = _.escapeRegExChars(query); 1182 | frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i"); 1183 | match = frontMatchRegEx.exec(data.val); 1184 | match && this.input.setHint(val + match[1]); 1185 | } else { 1186 | this.input.clearHint(); 1187 | } 1188 | }, 1189 | isEnabled: function isEnabled() { 1190 | return this.enabled; 1191 | }, 1192 | enable: function enable() { 1193 | this.enabled = true; 1194 | }, 1195 | disable: function disable() { 1196 | this.enabled = false; 1197 | }, 1198 | isActive: function isActive() { 1199 | return this.active; 1200 | }, 1201 | activate: function activate() { 1202 | if (this.isActive()) { 1203 | return true; 1204 | } else if (!this.isEnabled() || this.eventBus.before("active")) { 1205 | return false; 1206 | } else { 1207 | this.active = true; 1208 | this.eventBus.trigger("active"); 1209 | return true; 1210 | } 1211 | }, 1212 | deactivate: function deactivate() { 1213 | if (!this.isActive()) { 1214 | return true; 1215 | } else if (this.eventBus.before("idle")) { 1216 | return false; 1217 | } else { 1218 | this.active = false; 1219 | this.close(); 1220 | this.eventBus.trigger("idle"); 1221 | return true; 1222 | } 1223 | }, 1224 | isOpen: function isOpen() { 1225 | return this.menu.isOpen(); 1226 | }, 1227 | open: function open() { 1228 | if (!this.isOpen() && !this.eventBus.before("open")) { 1229 | this.menu.open(); 1230 | this._updateHint(); 1231 | this.eventBus.trigger("open"); 1232 | } 1233 | return this.isOpen(); 1234 | }, 1235 | close: function close() { 1236 | if (this.isOpen() && !this.eventBus.before("close")) { 1237 | this.menu.close(); 1238 | this.input.clearHint(); 1239 | this.input.resetInputValue(); 1240 | this.eventBus.trigger("close"); 1241 | } 1242 | return !this.isOpen(); 1243 | }, 1244 | setVal: function setVal(val) { 1245 | this.input.setQuery(_.toStr(val)); 1246 | }, 1247 | getVal: function getVal() { 1248 | return this.input.getQuery(); 1249 | }, 1250 | select: function select($selectable) { 1251 | var data = this.menu.getSelectableData($selectable); 1252 | if (data && !this.eventBus.before("select", data.obj)) { 1253 | this.input.setQuery(data.val, true); 1254 | this.eventBus.trigger("select", data.obj); 1255 | this.close(); 1256 | return true; 1257 | } 1258 | return false; 1259 | }, 1260 | autocomplete: function autocomplete($selectable) { 1261 | var query, data, isValid; 1262 | query = this.input.getQuery(); 1263 | data = this.menu.getSelectableData($selectable); 1264 | isValid = data && query !== data.val; 1265 | if (isValid && !this.eventBus.before("autocomplete", data.obj)) { 1266 | this.input.setQuery(data.val); 1267 | this.eventBus.trigger("autocomplete", data.obj); 1268 | return true; 1269 | } 1270 | return false; 1271 | }, 1272 | moveCursor: function moveCursor(delta) { 1273 | var query, $candidate, data, payload, cancelMove; 1274 | query = this.input.getQuery(); 1275 | $candidate = this.menu.selectableRelativeToCursor(delta); 1276 | data = this.menu.getSelectableData($candidate); 1277 | payload = data ? data.obj : null; 1278 | cancelMove = this._minLengthMet() && this.menu.update(query); 1279 | if (!cancelMove && !this.eventBus.before("cursorchange", payload)) { 1280 | this.menu.setCursor($candidate); 1281 | if (data) { 1282 | this.input.setInputValue(data.val); 1283 | } else { 1284 | this.input.resetInputValue(); 1285 | this._updateHint(); 1286 | } 1287 | this.eventBus.trigger("cursorchange", payload); 1288 | return true; 1289 | } 1290 | return false; 1291 | }, 1292 | destroy: function destroy() { 1293 | this.input.destroy(); 1294 | this.menu.destroy(); 1295 | } 1296 | }); 1297 | return Typeahead; 1298 | function c(ctx) { 1299 | var methods = [].slice.call(arguments, 1); 1300 | return function() { 1301 | var args = [].slice.call(arguments); 1302 | _.each(methods, function(method) { 1303 | return ctx[method].apply(ctx, args); 1304 | }); 1305 | }; 1306 | } 1307 | }(); 1308 | (function() { 1309 | "use strict"; 1310 | var old, keys, methods; 1311 | old = $.fn.typeahead; 1312 | keys = { 1313 | www: "tt-www", 1314 | attrs: "tt-attrs", 1315 | typeahead: "tt-typeahead" 1316 | }; 1317 | methods = { 1318 | initialize: function initialize(o, datasets) { 1319 | var www; 1320 | datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1); 1321 | o = o || {}; 1322 | www = WWW(o.classNames); 1323 | return this.each(attach); 1324 | function attach() { 1325 | var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor; 1326 | _.each(datasets, function(d) { 1327 | d.highlight = !!o.highlight; 1328 | }); 1329 | $input = $(this); 1330 | $wrapper = $(www.html.wrapper); 1331 | $hint = $elOrNull(o.hint); 1332 | $menu = $elOrNull(o.menu); 1333 | defaultHint = o.hint !== false && !$hint; 1334 | defaultMenu = o.menu !== false && !$menu; 1335 | defaultHint && ($hint = buildHintFromInput($input, www)); 1336 | defaultMenu && ($menu = $(www.html.menu).css(www.css.menu)); 1337 | $hint && $hint.val(""); 1338 | $input = prepInput($input, www); 1339 | if (defaultHint || defaultMenu) { 1340 | $wrapper.css(www.css.wrapper); 1341 | $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint); 1342 | $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null); 1343 | } 1344 | MenuConstructor = defaultMenu ? DefaultMenu : Menu; 1345 | eventBus = new EventBus({ 1346 | el: $input 1347 | }); 1348 | input = new Input({ 1349 | hint: $hint, 1350 | input: $input 1351 | }, www); 1352 | menu = new MenuConstructor({ 1353 | node: $menu, 1354 | datasets: datasets 1355 | }, www); 1356 | typeahead = new Typeahead({ 1357 | input: input, 1358 | menu: menu, 1359 | eventBus: eventBus, 1360 | minLength: o.minLength 1361 | }, www); 1362 | $input.data(keys.www, www); 1363 | $input.data(keys.typeahead, typeahead); 1364 | } 1365 | }, 1366 | isEnabled: function isEnabled() { 1367 | var enabled; 1368 | ttEach(this.first(), function(t) { 1369 | enabled = t.isEnabled(); 1370 | }); 1371 | return enabled; 1372 | }, 1373 | enable: function enable() { 1374 | ttEach(this, function(t) { 1375 | t.enable(); 1376 | }); 1377 | return this; 1378 | }, 1379 | disable: function disable() { 1380 | ttEach(this, function(t) { 1381 | t.disable(); 1382 | }); 1383 | return this; 1384 | }, 1385 | isActive: function isActive() { 1386 | var active; 1387 | ttEach(this.first(), function(t) { 1388 | active = t.isActive(); 1389 | }); 1390 | return active; 1391 | }, 1392 | activate: function activate() { 1393 | ttEach(this, function(t) { 1394 | t.activate(); 1395 | }); 1396 | return this; 1397 | }, 1398 | deactivate: function deactivate() { 1399 | ttEach(this, function(t) { 1400 | t.deactivate(); 1401 | }); 1402 | return this; 1403 | }, 1404 | isOpen: function isOpen() { 1405 | var open; 1406 | ttEach(this.first(), function(t) { 1407 | open = t.isOpen(); 1408 | }); 1409 | return open; 1410 | }, 1411 | open: function open() { 1412 | ttEach(this, function(t) { 1413 | t.open(); 1414 | }); 1415 | return this; 1416 | }, 1417 | close: function close() { 1418 | ttEach(this, function(t) { 1419 | t.close(); 1420 | }); 1421 | return this; 1422 | }, 1423 | select: function select(el) { 1424 | var success = false, $el = $(el); 1425 | ttEach(this.first(), function(t) { 1426 | success = t.select($el); 1427 | }); 1428 | return success; 1429 | }, 1430 | autocomplete: function autocomplete(el) { 1431 | var success = false, $el = $(el); 1432 | ttEach(this.first(), function(t) { 1433 | success = t.autocomplete($el); 1434 | }); 1435 | return success; 1436 | }, 1437 | moveCursor: function moveCursoe(delta) { 1438 | var success = false; 1439 | ttEach(this.first(), function(t) { 1440 | success = t.moveCursor(delta); 1441 | }); 1442 | return success; 1443 | }, 1444 | val: function val(newVal) { 1445 | var query; 1446 | if (!arguments.length) { 1447 | ttEach(this.first(), function(t) { 1448 | query = t.getVal(); 1449 | }); 1450 | return query; 1451 | } else { 1452 | ttEach(this, function(t) { 1453 | t.setVal(newVal); 1454 | }); 1455 | return this; 1456 | } 1457 | }, 1458 | destroy: function destroy() { 1459 | ttEach(this, function(typeahead, $input) { 1460 | revert($input); 1461 | typeahead.destroy(); 1462 | }); 1463 | return this; 1464 | } 1465 | }; 1466 | $.fn.typeahead = function(method) { 1467 | if (methods[method]) { 1468 | return methods[method].apply(this, [].slice.call(arguments, 1)); 1469 | } else { 1470 | return methods.initialize.apply(this, arguments); 1471 | } 1472 | }; 1473 | $.fn.typeahead.noConflict = function noConflict() { 1474 | $.fn.typeahead = old; 1475 | return this; 1476 | }; 1477 | function ttEach($els, fn) { 1478 | $els.each(function() { 1479 | var $input = $(this), typeahead; 1480 | (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input); 1481 | }); 1482 | } 1483 | function buildHintFromInput($input, www) { 1484 | return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({ 1485 | autocomplete: "off", 1486 | spellcheck: "false", 1487 | tabindex: -1 1488 | }); 1489 | } 1490 | function prepInput($input, www) { 1491 | $input.data(keys.attrs, { 1492 | dir: $input.attr("dir"), 1493 | autocomplete: $input.attr("autocomplete"), 1494 | spellcheck: $input.attr("spellcheck"), 1495 | style: $input.attr("style") 1496 | }); 1497 | $input.addClass(www.classes.input).attr({ 1498 | autocomplete: "off", 1499 | spellcheck: false 1500 | }); 1501 | try { 1502 | !$input.attr("dir") && $input.attr("dir", "auto"); 1503 | } catch (e) {} 1504 | return $input; 1505 | } 1506 | function getBackgroundStyles($el) { 1507 | return { 1508 | backgroundAttachment: $el.css("background-attachment"), 1509 | backgroundClip: $el.css("background-clip"), 1510 | backgroundColor: $el.css("background-color"), 1511 | backgroundImage: $el.css("background-image"), 1512 | backgroundOrigin: $el.css("background-origin"), 1513 | backgroundPosition: $el.css("background-position"), 1514 | backgroundRepeat: $el.css("background-repeat"), 1515 | backgroundSize: $el.css("background-size") 1516 | }; 1517 | } 1518 | function revert($input) { 1519 | var www, $wrapper; 1520 | www = $input.data(keys.www); 1521 | $wrapper = $input.parent().filter(www.selectors.wrapper); 1522 | _.each($input.data(keys.attrs), function(val, key) { 1523 | _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val); 1524 | }); 1525 | $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input); 1526 | if ($wrapper.length) { 1527 | $input.detach().insertAfter($wrapper); 1528 | $wrapper.remove(); 1529 | } 1530 | } 1531 | function $elOrNull(obj) { 1532 | var isValid, $el; 1533 | isValid = _.isJQuery(obj) || _.isElement(obj); 1534 | $el = isValid ? $(obj).first() : []; 1535 | return $el.length ? $el : null; 1536 | } 1537 | })(); 1538 | }); -------------------------------------------------------------------------------- /js/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* =================================================== 2 | * bootstrap-transition.js v2.3.2 3 | * http://twbs.github.com/bootstrap/javascript.html#transitions 4 | * =================================================== 5 | * Copyright 2013 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) 27 | * ======================================================= */ 28 | 29 | $(function () { 30 | 31 | $.support.transition = (function () { 32 | 33 | var transitionEnd = (function () { 34 | 35 | var el = document.createElement('bootstrap') 36 | , transEndEventNames = { 37 | 'WebkitTransition' : 'webkitTransitionEnd' 38 | , 'MozTransition' : 'transitionend' 39 | , 'OTransition' : 'oTransitionEnd otransitionend' 40 | , 'transition' : 'transitionend' 41 | } 42 | , name 43 | 44 | for (name in transEndEventNames){ 45 | if (el.style[name] !== undefined) { 46 | return transEndEventNames[name] 47 | } 48 | } 49 | 50 | }()) 51 | 52 | return transitionEnd && { 53 | end: transitionEnd 54 | } 55 | 56 | })() 57 | 58 | }) 59 | 60 | }(window.jQuery);/* ========================================================== 61 | * bootstrap-alert.js v2.3.2 62 | * http://twbs.github.com/bootstrap/javascript.html#alerts 63 | * ========================================================== 64 | * Copyright 2013 Twitter, Inc. 65 | * 66 | * Licensed under the Apache License, Version 2.0 (the "License"); 67 | * you may not use this file except in compliance with the License. 68 | * You may obtain a copy of the License at 69 | * 70 | * http://www.apache.org/licenses/LICENSE-2.0 71 | * 72 | * Unless required by applicable law or agreed to in writing, software 73 | * distributed under the License is distributed on an "AS IS" BASIS, 74 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 75 | * See the License for the specific language governing permissions and 76 | * limitations under the License. 77 | * ========================================================== */ 78 | 79 | 80 | !function ($) { 81 | 82 | "use strict"; // jshint ;_; 83 | 84 | 85 | /* ALERT CLASS DEFINITION 86 | * ====================== */ 87 | 88 | var dismiss = '[data-dismiss="alert"]' 89 | , Alert = function (el) { 90 | $(el).on('click', dismiss, this.close) 91 | } 92 | 93 | Alert.prototype.close = function (e) { 94 | var $this = $(this) 95 | , selector = $this.attr('data-target') 96 | , $parent 97 | 98 | if (!selector) { 99 | selector = $this.attr('href') 100 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 101 | } 102 | 103 | $parent = $(selector) 104 | 105 | e && e.preventDefault() 106 | 107 | $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) 108 | 109 | $parent.trigger(e = $.Event('close')) 110 | 111 | if (e.isDefaultPrevented()) return 112 | 113 | $parent.removeClass('in') 114 | 115 | function removeElement() { 116 | $parent 117 | .trigger('closed') 118 | .remove() 119 | } 120 | 121 | $.support.transition && $parent.hasClass('fade') ? 122 | $parent.on($.support.transition.end, removeElement) : 123 | removeElement() 124 | } 125 | 126 | 127 | /* ALERT PLUGIN DEFINITION 128 | * ======================= */ 129 | 130 | var old = $.fn.alert 131 | 132 | $.fn.alert = function (option) { 133 | return this.each(function () { 134 | var $this = $(this) 135 | , data = $this.data('alert') 136 | if (!data) $this.data('alert', (data = new Alert(this))) 137 | if (typeof option == 'string') data[option].call($this) 138 | }) 139 | } 140 | 141 | $.fn.alert.Constructor = Alert 142 | 143 | 144 | /* ALERT NO CONFLICT 145 | * ================= */ 146 | 147 | $.fn.alert.noConflict = function () { 148 | $.fn.alert = old 149 | return this 150 | } 151 | 152 | 153 | /* ALERT DATA-API 154 | * ============== */ 155 | 156 | $(document).on('click.alert.data-api', dismiss, Alert.prototype.close) 157 | 158 | }(window.jQuery);/* ============================================================ 159 | * bootstrap-button.js v2.3.2 160 | * http://twbs.github.com/bootstrap/javascript.html#buttons 161 | * ============================================================ 162 | * Copyright 2013 Twitter, Inc. 163 | * 164 | * Licensed under the Apache License, Version 2.0 (the "License"); 165 | * you may not use this file except in compliance with the License. 166 | * You may obtain a copy of the License at 167 | * 168 | * http://www.apache.org/licenses/LICENSE-2.0 169 | * 170 | * Unless required by applicable law or agreed to in writing, software 171 | * distributed under the License is distributed on an "AS IS" BASIS, 172 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 173 | * See the License for the specific language governing permissions and 174 | * limitations under the License. 175 | * ============================================================ */ 176 | 177 | 178 | !function ($) { 179 | 180 | "use strict"; // jshint ;_; 181 | 182 | 183 | /* BUTTON PUBLIC CLASS DEFINITION 184 | * ============================== */ 185 | 186 | var Button = function (element, options) { 187 | this.$element = $(element) 188 | this.options = $.extend({}, $.fn.button.defaults, options) 189 | } 190 | 191 | Button.prototype.setState = function (state) { 192 | var d = 'disabled' 193 | , $el = this.$element 194 | , data = $el.data() 195 | , val = $el.is('input') ? 'val' : 'html' 196 | 197 | state = state + 'Text' 198 | data.resetText || $el.data('resetText', $el[val]()) 199 | 200 | $el[val](data[state] || this.options[state]) 201 | 202 | // push to event loop to allow forms to submit 203 | setTimeout(function () { 204 | state == 'loadingText' ? 205 | $el.addClass(d).attr(d, d) : 206 | $el.removeClass(d).removeAttr(d) 207 | }, 0) 208 | } 209 | 210 | Button.prototype.toggle = function () { 211 | var $parent = this.$element.closest('[data-toggle="buttons-radio"]') 212 | 213 | $parent && $parent 214 | .find('.active') 215 | .removeClass('active') 216 | 217 | this.$element.toggleClass('active') 218 | } 219 | 220 | 221 | /* BUTTON PLUGIN DEFINITION 222 | * ======================== */ 223 | 224 | var old = $.fn.button 225 | 226 | $.fn.button = function (option) { 227 | return this.each(function () { 228 | var $this = $(this) 229 | , data = $this.data('button') 230 | , options = typeof option == 'object' && option 231 | if (!data) $this.data('button', (data = new Button(this, options))) 232 | if (option == 'toggle') data.toggle() 233 | else if (option) data.setState(option) 234 | }) 235 | } 236 | 237 | $.fn.button.defaults = { 238 | loadingText: 'loading...' 239 | } 240 | 241 | $.fn.button.Constructor = Button 242 | 243 | 244 | /* BUTTON NO CONFLICT 245 | * ================== */ 246 | 247 | $.fn.button.noConflict = function () { 248 | $.fn.button = old 249 | return this 250 | } 251 | 252 | 253 | /* BUTTON DATA-API 254 | * =============== */ 255 | 256 | $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) { 257 | var $btn = $(e.target) 258 | if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') 259 | $btn.button('toggle') 260 | }) 261 | 262 | }(window.jQuery);/* ========================================================== 263 | * bootstrap-carousel.js v2.3.2 264 | * http://twbs.github.com/bootstrap/javascript.html#carousel 265 | * ========================================================== 266 | * Copyright 2013 Twitter, Inc. 267 | * 268 | * Licensed under the Apache License, Version 2.0 (the "License"); 269 | * you may not use this file except in compliance with the License. 270 | * You may obtain a copy of the License at 271 | * 272 | * http://www.apache.org/licenses/LICENSE-2.0 273 | * 274 | * Unless required by applicable law or agreed to in writing, software 275 | * distributed under the License is distributed on an "AS IS" BASIS, 276 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 277 | * See the License for the specific language governing permissions and 278 | * limitations under the License. 279 | * ========================================================== */ 280 | 281 | 282 | !function ($) { 283 | 284 | "use strict"; // jshint ;_; 285 | 286 | 287 | /* CAROUSEL CLASS DEFINITION 288 | * ========================= */ 289 | 290 | var Carousel = function (element, options) { 291 | this.$element = $(element) 292 | this.$indicators = this.$element.find('.carousel-indicators') 293 | this.options = options 294 | this.options.pause == 'hover' && this.$element 295 | .on('mouseenter', $.proxy(this.pause, this)) 296 | .on('mouseleave', $.proxy(this.cycle, this)) 297 | } 298 | 299 | Carousel.prototype = { 300 | 301 | cycle: function (e) { 302 | if (!e) this.paused = false 303 | if (this.interval) clearInterval(this.interval); 304 | this.options.interval 305 | && !this.paused 306 | && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) 307 | return this 308 | } 309 | 310 | , getActiveIndex: function () { 311 | this.$active = this.$element.find('.item.active') 312 | this.$items = this.$active.parent().children() 313 | return this.$items.index(this.$active) 314 | } 315 | 316 | , to: function (pos) { 317 | var activeIndex = this.getActiveIndex() 318 | , that = this 319 | 320 | if (pos > (this.$items.length - 1) || pos < 0) return 321 | 322 | if (this.sliding) { 323 | return this.$element.one('slid', function () { 324 | that.to(pos) 325 | }) 326 | } 327 | 328 | if (activeIndex == pos) { 329 | return this.pause().cycle() 330 | } 331 | 332 | return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) 333 | } 334 | 335 | , pause: function (e) { 336 | if (!e) this.paused = true 337 | if (this.$element.find('.next, .prev').length && $.support.transition.end) { 338 | this.$element.trigger($.support.transition.end) 339 | this.cycle(true) 340 | } 341 | clearInterval(this.interval) 342 | this.interval = null 343 | return this 344 | } 345 | 346 | , next: function () { 347 | if (this.sliding) return 348 | return this.slide('next') 349 | } 350 | 351 | , prev: function () { 352 | if (this.sliding) return 353 | return this.slide('prev') 354 | } 355 | 356 | , slide: function (type, next) { 357 | var $active = this.$element.find('.item.active') 358 | , $next = next || $active[type]() 359 | , isCycling = this.interval 360 | , direction = type == 'next' ? 'left' : 'right' 361 | , fallback = type == 'next' ? 'first' : 'last' 362 | , that = this 363 | , e 364 | 365 | this.sliding = true 366 | 367 | isCycling && this.pause() 368 | 369 | $next = $next.length ? $next : this.$element.find('.item')[fallback]() 370 | 371 | e = $.Event('slide', { 372 | relatedTarget: $next[0] 373 | , direction: direction 374 | }) 375 | 376 | if ($next.hasClass('active')) return 377 | 378 | if (this.$indicators.length) { 379 | this.$indicators.find('.active').removeClass('active') 380 | this.$element.one('slid', function () { 381 | var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) 382 | $nextIndicator && $nextIndicator.addClass('active') 383 | }) 384 | } 385 | 386 | if ($.support.transition && this.$element.hasClass('slide')) { 387 | this.$element.trigger(e) 388 | if (e.isDefaultPrevented()) return 389 | $next.addClass(type) 390 | $next[0].offsetWidth // force reflow 391 | $active.addClass(direction) 392 | $next.addClass(direction) 393 | this.$element.one($.support.transition.end, function () { 394 | $next.removeClass([type, direction].join(' ')).addClass('active') 395 | $active.removeClass(['active', direction].join(' ')) 396 | that.sliding = false 397 | setTimeout(function () { that.$element.trigger('slid') }, 0) 398 | }) 399 | } else { 400 | this.$element.trigger(e) 401 | if (e.isDefaultPrevented()) return 402 | $active.removeClass('active') 403 | $next.addClass('active') 404 | this.sliding = false 405 | this.$element.trigger('slid') 406 | } 407 | 408 | isCycling && this.cycle() 409 | 410 | return this 411 | } 412 | 413 | } 414 | 415 | 416 | /* CAROUSEL PLUGIN DEFINITION 417 | * ========================== */ 418 | 419 | var old = $.fn.carousel 420 | 421 | $.fn.carousel = function (option) { 422 | return this.each(function () { 423 | var $this = $(this) 424 | , data = $this.data('carousel') 425 | , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option) 426 | , action = typeof option == 'string' ? option : options.slide 427 | if (!data) $this.data('carousel', (data = new Carousel(this, options))) 428 | if (typeof option == 'number') data.to(option) 429 | else if (action) data[action]() 430 | else if (options.interval) data.pause().cycle() 431 | }) 432 | } 433 | 434 | $.fn.carousel.defaults = { 435 | interval: 5000 436 | , pause: 'hover' 437 | } 438 | 439 | $.fn.carousel.Constructor = Carousel 440 | 441 | 442 | /* CAROUSEL NO CONFLICT 443 | * ==================== */ 444 | 445 | $.fn.carousel.noConflict = function () { 446 | $.fn.carousel = old 447 | return this 448 | } 449 | 450 | /* CAROUSEL DATA-API 451 | * ================= */ 452 | 453 | $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { 454 | var $this = $(this), href 455 | , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 456 | , options = $.extend({}, $target.data(), $this.data()) 457 | , slideIndex 458 | 459 | $target.carousel(options) 460 | 461 | if (slideIndex = $this.attr('data-slide-to')) { 462 | $target.data('carousel').pause().to(slideIndex).cycle() 463 | } 464 | 465 | e.preventDefault() 466 | }) 467 | 468 | }(window.jQuery);/* ============================================================= 469 | * bootstrap-collapse.js v2.3.2 470 | * http://twbs.github.com/bootstrap/javascript.html#collapse 471 | * ============================================================= 472 | * Copyright 2013 Twitter, Inc. 473 | * 474 | * Licensed under the Apache License, Version 2.0 (the "License"); 475 | * you may not use this file except in compliance with the License. 476 | * You may obtain a copy of the License at 477 | * 478 | * http://www.apache.org/licenses/LICENSE-2.0 479 | * 480 | * Unless required by applicable law or agreed to in writing, software 481 | * distributed under the License is distributed on an "AS IS" BASIS, 482 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 483 | * See the License for the specific language governing permissions and 484 | * limitations under the License. 485 | * ============================================================ */ 486 | 487 | 488 | !function ($) { 489 | 490 | "use strict"; // jshint ;_; 491 | 492 | 493 | /* COLLAPSE PUBLIC CLASS DEFINITION 494 | * ================================ */ 495 | 496 | var Collapse = function (element, options) { 497 | this.$element = $(element) 498 | this.options = $.extend({}, $.fn.collapse.defaults, options) 499 | 500 | if (this.options.parent) { 501 | this.$parent = $(this.options.parent) 502 | } 503 | 504 | this.options.toggle && this.toggle() 505 | } 506 | 507 | Collapse.prototype = { 508 | 509 | constructor: Collapse 510 | 511 | , dimension: function () { 512 | var hasWidth = this.$element.hasClass('width') 513 | return hasWidth ? 'width' : 'height' 514 | } 515 | 516 | , show: function () { 517 | var dimension 518 | , scroll 519 | , actives 520 | , hasData 521 | 522 | if (this.transitioning || this.$element.hasClass('in')) return 523 | 524 | dimension = this.dimension() 525 | scroll = $.camelCase(['scroll', dimension].join('-')) 526 | actives = this.$parent && this.$parent.find('> .accordion-group > .in') 527 | 528 | if (actives && actives.length) { 529 | hasData = actives.data('collapse') 530 | if (hasData && hasData.transitioning) return 531 | actives.collapse('hide') 532 | hasData || actives.data('collapse', null) 533 | } 534 | 535 | this.$element[dimension](0) 536 | this.transition('addClass', $.Event('show'), 'shown') 537 | $.support.transition && this.$element[dimension](this.$element[0][scroll]) 538 | } 539 | 540 | , hide: function () { 541 | var dimension 542 | if (this.transitioning || !this.$element.hasClass('in')) return 543 | dimension = this.dimension() 544 | this.reset(this.$element[dimension]()) 545 | this.transition('removeClass', $.Event('hide'), 'hidden') 546 | this.$element[dimension](0) 547 | } 548 | 549 | , reset: function (size) { 550 | var dimension = this.dimension() 551 | 552 | this.$element 553 | .removeClass('collapse') 554 | [dimension](size || 'auto') 555 | [0].offsetWidth 556 | 557 | this.$element[size !== null ? 'addClass' : 'removeClass']('collapse') 558 | 559 | return this 560 | } 561 | 562 | , transition: function (method, startEvent, completeEvent) { 563 | var that = this 564 | , complete = function () { 565 | if (startEvent.type == 'show') that.reset() 566 | that.transitioning = 0 567 | that.$element.trigger(completeEvent) 568 | } 569 | 570 | this.$element.trigger(startEvent) 571 | 572 | if (startEvent.isDefaultPrevented()) return 573 | 574 | this.transitioning = 1 575 | 576 | this.$element[method]('in') 577 | 578 | $.support.transition && this.$element.hasClass('collapse') ? 579 | this.$element.one($.support.transition.end, complete) : 580 | complete() 581 | } 582 | 583 | , toggle: function () { 584 | this[this.$element.hasClass('in') ? 'hide' : 'show']() 585 | } 586 | 587 | } 588 | 589 | 590 | /* COLLAPSE PLUGIN DEFINITION 591 | * ========================== */ 592 | 593 | var old = $.fn.collapse 594 | 595 | $.fn.collapse = function (option) { 596 | return this.each(function () { 597 | var $this = $(this) 598 | , data = $this.data('collapse') 599 | , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option) 600 | if (!data) $this.data('collapse', (data = new Collapse(this, options))) 601 | if (typeof option == 'string') data[option]() 602 | }) 603 | } 604 | 605 | $.fn.collapse.defaults = { 606 | toggle: true 607 | } 608 | 609 | $.fn.collapse.Constructor = Collapse 610 | 611 | 612 | /* COLLAPSE NO CONFLICT 613 | * ==================== */ 614 | 615 | $.fn.collapse.noConflict = function () { 616 | $.fn.collapse = old 617 | return this 618 | } 619 | 620 | 621 | /* COLLAPSE DATA-API 622 | * ================= */ 623 | 624 | $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) { 625 | var $this = $(this), href 626 | , target = $this.attr('data-target') 627 | || e.preventDefault() 628 | || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 629 | , option = $(target).data('collapse') ? 'toggle' : $this.data() 630 | $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 631 | $(target).collapse(option) 632 | }) 633 | 634 | }(window.jQuery);/* ============================================================ 635 | * bootstrap-dropdown.js v2.3.2 636 | * http://twbs.github.com/bootstrap/javascript.html#dropdowns 637 | * ============================================================ 638 | * Copyright 2013 Twitter, Inc. 639 | * 640 | * Licensed under the Apache License, Version 2.0 (the "License"); 641 | * you may not use this file except in compliance with the License. 642 | * You may obtain a copy of the License at 643 | * 644 | * http://www.apache.org/licenses/LICENSE-2.0 645 | * 646 | * Unless required by applicable law or agreed to in writing, software 647 | * distributed under the License is distributed on an "AS IS" BASIS, 648 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 649 | * See the License for the specific language governing permissions and 650 | * limitations under the License. 651 | * ============================================================ */ 652 | 653 | 654 | !function ($) { 655 | 656 | "use strict"; // jshint ;_; 657 | 658 | 659 | /* DROPDOWN CLASS DEFINITION 660 | * ========================= */ 661 | 662 | var toggle = '[data-toggle=dropdown]' 663 | , Dropdown = function (element) { 664 | var $el = $(element).on('click.dropdown.data-api', this.toggle) 665 | $('html').on('click.dropdown.data-api', function () { 666 | $el.parent().removeClass('open') 667 | }) 668 | } 669 | 670 | Dropdown.prototype = { 671 | 672 | constructor: Dropdown 673 | 674 | , toggle: function (e) { 675 | var $this = $(this) 676 | , $parent 677 | , isActive 678 | 679 | if ($this.is('.disabled, :disabled')) return 680 | 681 | $parent = getParent($this) 682 | 683 | isActive = $parent.hasClass('open') 684 | 685 | clearMenus() 686 | 687 | if (!isActive) { 688 | if ('ontouchstart' in document.documentElement) { 689 | // if mobile we we use a backdrop because click events don't delegate 690 | $('