├── LICENSE ├── README.md ├── _site ├── LICENSE ├── README.md ├── assets │ ├── css │ │ └── app.css │ ├── js │ │ └── app.js │ └── vendor │ │ ├── jQuery-QueryBuilder │ │ ├── LICENSE.txt │ │ ├── query-builder.default.min.css │ │ └── query-builder.standalone.min.js │ │ └── tableExport │ │ ├── README.md │ │ ├── libs │ │ ├── FileSaver │ │ │ ├── FileSaver.min.js │ │ │ └── LICENSE.md │ │ ├── html2canvas │ │ │ ├── LICENSE │ │ │ └── html2canvas.min.js │ │ ├── jsPDF-AutoTable │ │ │ ├── LICENSE.txt │ │ │ └── jspdf.plugin.autotable.js │ │ └── jsPDF │ │ │ ├── MIT-LICENSE.txt │ │ │ └── jspdf.min.js │ │ ├── tableExport.js │ │ └── tableExport.min.js ├── index.html └── screenshots │ ├── charts.png │ ├── filter.png │ ├── info.png │ └── map.png ├── assets ├── css │ └── app.css ├── js │ └── app.js └── vendor │ ├── jQuery-QueryBuilder │ ├── LICENSE.txt │ ├── query-builder.default.min.css │ └── query-builder.standalone.min.js │ └── tableExport │ ├── .gitignore │ ├── README.md │ ├── libs │ ├── FileSaver │ │ ├── FileSaver.min.js │ │ └── LICENSE.md │ ├── html2canvas │ │ ├── LICENSE │ │ └── html2canvas.min.js │ ├── jsPDF-AutoTable │ │ ├── LICENSE.txt │ │ └── jspdf.plugin.autotable.js │ └── jsPDF │ │ ├── MIT-LICENSE.txt │ │ └── jspdf.min.js │ ├── tableExport.js │ └── tableExport.min.js ├── index.html └── screenshots ├── charts.png ├── filter.png ├── info.png └── map.png /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Fulcrum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # geojson-dashboard 2 | A configurable framework for building a geographic "data dashboard" from a GeoJSON file. 3 | 4 | ## Features 5 | 6 | * Flexible template built on active open source components 7 | * Entirely client-side, can be hosted for free on [GitHub Pages](https://pages.github.com/) 8 | * Built on the incredibly popular [Bootstrap](http://getbootstrap.com/) UI framework 9 | * Maps via [Leaflet](http://leafletjs.com/), the leading open source JavaScript mapping library 10 | * Interactive data table with sorting, searching, column toggling, and data export via the [Bootstrap Table](http://bootstrap-table.wenzhixin.net.cn/) plugin 11 | * Advanced, interactive GeoJSON data querying that integrates [jQuery QueryBuilder](http://mistic100.github.io/jQuery-QueryBuilder/index.html) with [AlaSQL](http://alasql.org/) 12 | * Advanced charting via [C3.js](http://c3js.org/), the D3-based reusable chart library 13 | 14 | ## Screenshots 15 | 16 | Split screen view 17 | 18 | ![Map](https://raw.githubusercontent.com/fulcrumapp/geojson-dashboard/gh-pages/screenshots/map.png) 19 | 20 | Feature Info popup 21 | 22 | ![Info](https://raw.githubusercontent.com/fulcrumapp/geojson-dashboard/gh-pages/screenshots/info.png) 23 | 24 | Interactive charts 25 | 26 | ![Charts](https://raw.githubusercontent.com/fulcrumapp/geojson-dashboard/gh-pages/screenshots/charts.png) 27 | 28 | SQL query filters 29 | 30 | ![Filter](https://raw.githubusercontent.com/fulcrumapp/geojson-dashboard/gh-pages/screenshots/filter.png) 31 | -------------------------------------------------------------------------------- /_site/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Fulcrum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /_site/README.md: -------------------------------------------------------------------------------- 1 | # geojson-dashboard 2 | A configurable framework for building a geographic "data dashboard" from a GeoJSON file. 3 | 4 | ## Features 5 | 6 | * Flexible template built on active open source components 7 | * Entirely client-side, can be hosted for free on [GitHub Pages](https://pages.github.com/) 8 | * Built on the incredibly popular [Bootstrap](http://getbootstrap.com/) UI framework 9 | * Maps via [Leaflet](http://leafletjs.com/), the leading open source JavaScript mapping library 10 | * Interactive data table with sorting, searching, column toggling, and data export via the [Bootstrap Table](http://bootstrap-table.wenzhixin.net.cn/) plugin 11 | * Advanced, interactive GeoJSON data querying that integrates [jQuery QueryBuilder](http://mistic100.github.io/jQuery-QueryBuilder/index.html) with [AlaSQL](http://alasql.org/) 12 | * Advanced charting via [C3.js](http://c3js.org/), the D3-based reusable chart library 13 | 14 | ## Screenshots 15 | 16 | Split screen view 17 | 18 | ![Map](https://raw.githubusercontent.com/fulcrumapp/geojson-dashboard/gh-pages/screenshots/map.png) 19 | 20 | Feature Info popup 21 | 22 | ![Info](https://raw.githubusercontent.com/fulcrumapp/geojson-dashboard/gh-pages/screenshots/info.png) 23 | 24 | Interactive charts 25 | 26 | ![Charts](https://raw.githubusercontent.com/fulcrumapp/geojson-dashboard/gh-pages/screenshots/charts.png) 27 | 28 | SQL query filters 29 | 30 | ![Filter](https://raw.githubusercontent.com/fulcrumapp/geojson-dashboard/gh-pages/screenshots/filter.png) 31 | -------------------------------------------------------------------------------- /_site/assets/css/app.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | width: 100%; 4 | overflow: hidden; 5 | } 6 | body { 7 | padding-top: 50px; 8 | } 9 | #map-container { 10 | height: 45%; 11 | padding: 0; 12 | } 13 | #table-container { 14 | height: 55%; 15 | padding: 5px; 16 | position: relative; 17 | box-shadow: inset 0 8px 8px -8px #696868; 18 | } 19 | #map { 20 | height: 100%; 21 | } 22 | #table tr { 23 | cursor: pointer; 24 | } 25 | #loading-mask { 26 | background-color: rgba(0, 0, 0, 0.5); 27 | } 28 | .loading-indicator { 29 | position: absolute; 30 | width: 220px; 31 | height: 19px; 32 | top: 50%; 33 | left: 50%; 34 | margin: -10px 0 0 -110px; 35 | z-index: 20001; 36 | } 37 | .loading-bar { 38 | width: 100%; 39 | } 40 | .rule-value-container { 41 | max-height: 100px; 42 | width: 350px; 43 | overflow: auto; 44 | } 45 | .tab-content { 46 | padding-top: 10px; 47 | } 48 | .fa-white { 49 | color: white; 50 | } 51 | .info-control { 52 | padding: 6px 8px; 53 | font: 14px/16px Arial, Helvetica, sans-serif; 54 | background: white; 55 | background: rgba(255,255,255,0.9); 56 | box-shadow: 0 0 15px rgba(0,0,0,0.2); 57 | border-radius: 5px; 58 | } 59 | .leaflet-control-layers { 60 | overflow: auto; 61 | } 62 | .leaflet-control-layers label { 63 | font-weight: normal; 64 | margin-bottom: 0px; 65 | } 66 | .leaflet-control-layers-selector { 67 | top: 0px; 68 | } 69 | .navbar .navbar-brand { 70 | font-weight: bold; 71 | font-size: 25px; 72 | color: white; 73 | } 74 | .navbar-brand img { 75 | height: 100%; 76 | margin-top: -5px; 77 | margin-right: 15px; 78 | display: inline; 79 | } 80 | .navbar-nav img { 81 | height: 40px; 82 | margin-top: -12px; 83 | margin-bottom: -10px; 84 | } 85 | @media (max-width: 992px) { 86 | .navbar .navbar-brand { 87 | font-size: 18px; 88 | } 89 | body { 90 | overflow-y: auto; 91 | } 92 | .fixed-table-toolbar { 93 | display: none; 94 | } 95 | .fixed-table-container { 96 | padding-bottom: 15px !important; 97 | } 98 | } 99 | @media print { 100 | .navbar { 101 | display: none !important; 102 | } 103 | .leaflet-control-container { 104 | display: none !important; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /_site/assets/js/app.js: -------------------------------------------------------------------------------- 1 | var config = { 2 | geojson: "https://gist.githubusercontent.com/JJediny/b238fc15e3b31a2e3432/raw/3d73dbd7d4c950c8e85fdb7485567e84eca90772/CitizenScienceandCrowdsourcing_WWilson.geojson", 3 | title: "Federal Citizen Science and Crowdsourcing Projects", 4 | layerName: "Projects", 5 | hoverProperty: "project_name", 6 | sortProperty: "agency_sponsor", 7 | sortOrder: "desc" 8 | }; 9 | 10 | var properties = [{ 11 | value: "project_name", 12 | label: "Project Name", 13 | table: { 14 | visible: true, 15 | sortable: true 16 | }, 17 | filter: { 18 | type: "string" 19 | }, 20 | info: false 21 | }, { 22 | value: "status", 23 | label: "Status", 24 | table: { 25 | visible: true, 26 | sortable: true 27 | }, 28 | filter: { 29 | type: "string", 30 | input: "checkbox", 31 | vertical: true, 32 | multiple: true, 33 | operators: ["in", "not_in", "equal", "not_equal"], 34 | values: [] 35 | } 36 | }, { 37 | value: "agency_sponsor", 38 | label: "Federal Sponsor(s)", 39 | table: { 40 | visible: true, 41 | sortable: true 42 | }, 43 | filter: { 44 | type: "string" 45 | } 46 | }, { 47 | value: "agency_partner", 48 | label: "Agency Partner", 49 | table: { 50 | visible: true, 51 | sortable: true 52 | }, 53 | filter: { 54 | type: "string" 55 | } 56 | }, { 57 | value: "project_topic", 58 | label: "Topic(s)", 59 | table: { 60 | visible: true, 61 | sortable: true 62 | }, 63 | filter: { 64 | type: "integer" 65 | } 66 | }, { 67 | value: "project_description", 68 | label: "Description", 69 | table: { 70 | visible: true, 71 | sortable: true 72 | }, 73 | filter: { 74 | type: "integer" 75 | } 76 | }, { 77 | value: "project_url", 78 | label: "URL", 79 | table: { 80 | visible: false, 81 | sortable: true 82 | }, 83 | filter: { 84 | type: "integer" 85 | } 86 | }, { 87 | value: "participation_tasks", 88 | label: "Participation", 89 | table: { 90 | visible: true, 91 | sortable: true 92 | }, 93 | filter: { 94 | type: "integer" 95 | } 96 | }]; 97 | 98 | function drawCharts() { 99 | // Status 100 | $(function() { 101 | var result = alasql( 102 | "SELECT status AS label, COUNT(*) AS total FROM ? GROUP BY status", [ 103 | features 104 | ]); 105 | var columns = $.map(result, function(status) { 106 | return [ 107 | [status.label, status.total] 108 | ]; 109 | }); 110 | var chart = c3.generate({ 111 | bindto: "#status-chart", 112 | data: { 113 | type: "pie", 114 | columns: columns 115 | } 116 | }); 117 | }); 118 | 119 | // Agencies 120 | $(function() { 121 | var result = alasql( 122 | "SELECT agency_sponsor AS label, COUNT(*) AS total FROM ? GROUP BY agency_sponsor", [ 123 | features 124 | ]); 125 | var columns = $.map(result, function(zone) { 126 | return [ 127 | [zone.label, zone.total] 128 | ]; 129 | }); 130 | var chart = c3.generate({ 131 | bindto: "#zone-chart", 132 | data: { 133 | type: "pie", 134 | columns: columns 135 | } 136 | }); 137 | }); 138 | 139 | // Species 140 | $(function() { 141 | var result = alasql( 142 | "SELECT agency_partner AS label, COUNT(*) AS total FROM ? GROUP BY agency_partner ORDER BY label ASC", [ 143 | features 144 | ]); 145 | var chart = c3.generate({ 146 | bindto: "#species-chart", 147 | size: { 148 | height: 2000 149 | }, 150 | data: { 151 | json: result, 152 | keys: { 153 | x: "label", 154 | value: ["total"] 155 | }, 156 | type: "bar" 157 | }, 158 | axis: { 159 | rotated: true, 160 | x: { 161 | type: "category" 162 | } 163 | }, 164 | legend: { 165 | show: false 166 | } 167 | }); 168 | }); 169 | } 170 | 171 | $(function() { 172 | $(".title").html(config.title); 173 | $("#layer-name").html(config.layerName); 174 | }); 175 | 176 | function buildConfig() { 177 | filters = []; 178 | table = [{ 179 | field: "action", 180 | title: " Action", 181 | align: "center", 182 | valign: "middle", 183 | width: "75px", 184 | cardVisible: false, 185 | switchable: false, 186 | formatter: function(value, row, index) { 187 | return [ 188 | '', 189 | '', 190 | '', 191 | '', 192 | '', 193 | '' 194 | ].join(""); 195 | }, 196 | events: { 197 | "click .zoom": function(e, value, row, index) { 198 | map.fitBounds(featureLayer.getLayer(row.leaflet_stamp).getBounds()); 199 | highlightLayer.clearLayers(); 200 | highlightLayer.addData(featureLayer.getLayer(row.leaflet_stamp).toGeoJSON()); 201 | }, 202 | "click .identify": function(e, value, row, index) { 203 | identifyFeature(row.leaflet_stamp); 204 | highlightLayer.clearLayers(); 205 | highlightLayer.addData(featureLayer.getLayer(row.leaflet_stamp).toGeoJSON()); 206 | } 207 | } 208 | }]; 209 | 210 | 211 | 212 | $.each(properties, function(index, value) { 213 | // Filter config 214 | if (value.filter) { 215 | var id; 216 | if (value.filter.type == "integer") { 217 | id = "cast(properties->" + value.value + " as int)"; 218 | } else if (value.filter.type == "double") { 219 | id = "cast(properties->" + value.value + " as double)"; 220 | } else { 221 | id = "properties->" + value.value; 222 | } 223 | filters.push({ 224 | id: id, 225 | label: value.label 226 | }); 227 | $.each(value.filter, function(key, val) { 228 | if (filters[index]) { 229 | // If values array is empty, fetch all distinct values 230 | if (key == "values" && val.length === 0) { 231 | alasql("SELECT DISTINCT(properties->" + value.value + 232 | ") AS field FROM ? ORDER BY field ASC", [geojson.features], 233 | function(results) { 234 | distinctValues = []; 235 | $.each(results, function(index, value) { 236 | distinctValues.push(value.field); 237 | }); 238 | }); 239 | filters[index].values = distinctValues; 240 | } else { 241 | filters[index][key] = val; 242 | } 243 | } 244 | }); 245 | } 246 | // Table config 247 | if (value.table) { 248 | table.push({ 249 | field: value.value, 250 | title: value.label 251 | }); 252 | $.each(value.table, function(key, val) { 253 | if (table[index + 1]) { 254 | table[index + 1][key] = val; 255 | } 256 | }); 257 | } 258 | }); 259 | 260 | buildFilters(); 261 | buildTable(); 262 | } 263 | 264 | // Basemap Layers 265 | var mapboxTerrian = L.tileLayer( 266 | "http://{s}.tiles.mapbox.com/v3/energy.map-ayrdk7iy/{z}/{x}/{y}.png", { 267 | maxZoom: 18, 268 | subdomains: ["a", "b", "c"], 269 | attribution: 'Tiles courtesy of Mapbox Team. Map data (c) OpenStreetMap contributors, CC-BY-SA.' 270 | }); 271 | 272 | var humanitarianOSM = L.tileLayer( 273 | "http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png", { 274 | maxZoom: 19, 275 | subdomains: ["a", "b", "c"], 276 | attribution: 'Tiles courtesy of Humanitarian OpenStreetMap Team. Map data (c) OpenStreetMap contributors, CC-BY-SA.' 277 | }); 278 | 279 | var stamenToner = L.tileLayer( 280 | "http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png", { 281 | maxZoom: 19, 282 | subdomains: ["a", "b", "c"], 283 | attribution: 'Labels courtesy of Stamen Design. Map data (c) OpenStreetMap contributors, CC-BY-3.0.' 284 | }); 285 | 286 | var highlightLayer = L.geoJson(null, { 287 | pointToLayer: function(feature, latlng) { 288 | return L.circleMarker(latlng, { 289 | radius: 5, 290 | color: "#FFF", 291 | weight: 2, 292 | opacity: 1, 293 | fillColor: "#00FFFF", 294 | fillOpacity: 1, 295 | clickable: false 296 | }); 297 | }, 298 | style: function(feature) { 299 | return { 300 | color: "#00FFFF", 301 | weight: 2, 302 | opacity: 1, 303 | fillColor: "#00FFFF", 304 | fillOpacity: 0.5, 305 | clickable: false 306 | }; 307 | } 308 | }); 309 | 310 | var featureLayer = L.geoJson(null, { 311 | filter: function(feature, layer) { 312 | return feature.geometry.coordinates[0] !== 0 && feature.geometry.coordinates[ 313 | 1] !== 0; 314 | }, 315 | /*style: function (feature) { 316 | return { 317 | color: feature.properties.color 318 | }; 319 | },*/ 320 | pointToLayer: function(feature, latlng) { 321 | if (feature.properties && feature.properties["marker-color"]) { 322 | markerColor = feature.properties["marker-color"]; 323 | } else { 324 | markerColor = "#FF0000"; 325 | } 326 | return L.circleMarker(latlng, { 327 | radius: 3, 328 | weight: 1, 329 | fillColor: markerColor, 330 | color: markerColor, 331 | opacity: 1, 332 | fillOpacity: 0.5 333 | }); 334 | }, 335 | onEachFeature: function(feature, layer) { 336 | if (feature.properties) { 337 | layer.on({ 338 | click: function(e) { 339 | identifyFeature(L.stamp(layer)); 340 | highlightLayer.clearLayers(); 341 | highlightLayer.addData(featureLayer.getLayer(L.stamp( 342 | layer)).toGeoJSON()); 343 | }, 344 | mouseover: function(e) { 345 | if (config.hoverProperty) { 346 | $(".info-control").html(feature.properties[config.hoverProperty]); 347 | $(".info-control").show(); 348 | } 349 | }, 350 | mouseout: function(e) { 351 | $(".info-control").hide(); 352 | } 353 | }); 354 | } 355 | } 356 | }); 357 | 358 | // Fetch the GeoJSON file 359 | $.getJSON(config.geojson, function(data) { 360 | geojson = data; 361 | features = $.map(geojson.features, function(feature) { 362 | return feature.properties; 363 | }); 364 | featureLayer.addData(data); 365 | buildConfig(); 366 | $("#loading-mask").hide(); 367 | }); 368 | 369 | var map = L.map("map", { 370 | layers: [mapboxTerrian, featureLayer, highlightLayer] 371 | }).fitWorld(); 372 | 373 | // ESRI geocoder 374 | var searchControl = L.esri.Geocoding.Controls.geosearch({ 375 | useMapBounds: 17 376 | }).addTo(map); 377 | 378 | // Info control 379 | var info = L.control({ 380 | position: "bottomleft" 381 | }); 382 | 383 | // Custom info hover control 384 | info.onAdd = function(map) { 385 | this._div = L.DomUtil.create("div", "info-control"); 386 | this.update(); 387 | return this._div; 388 | }; 389 | info.update = function(props) { 390 | this._div.innerHTML = ""; 391 | }; 392 | info.addTo(map); 393 | $(".info-control").hide(); 394 | 395 | // Larger screens get expanded layer control 396 | if (document.body.clientWidth <= 767) { 397 | isCollapsed = true; 398 | } else { 399 | isCollapsed = false; 400 | } 401 | var baseLayers = { 402 | "Humanitarian OpenStreetMap": humanitarianOSM, 403 | "Mapbox Terrian": mapboxTerrian, 404 | "Stamen Toner": stamenToner 405 | }; 406 | var overlayLayers = { 407 | "GeoJSON Layer": featureLayer 408 | }; 409 | var layerControl = L.control.layers(baseLayers, overlayLayers, { 410 | collapsed: isCollapsed 411 | }).addTo(map); 412 | 413 | // Filter table to only show features in current map bounds 414 | map.on("moveend", function(e) { 415 | syncTable(); 416 | }); 417 | 418 | map.on("click", function(e) { 419 | highlightLayer.clearLayers(); 420 | }); 421 | 422 | // Table formatter to make links clickable 423 | function urlFormatter(value, row, index) { 424 | if (typeof value == "string" && (value.indexOf("http") === 0 || value.indexOf( 425 | "https") === 0)) { 426 | return "" + value + ""; 427 | } 428 | } 429 | 430 | function buildFilters() { 431 | $("#query-builder").queryBuilder({ 432 | allow_empty: true, 433 | filters: filters 434 | }); 435 | } 436 | 437 | function applyFilter() { 438 | var query = "SELECT * FROM ?"; 439 | var sql = $("#query-builder").queryBuilder("getSQL", false, false).sql; 440 | if (sql.length > 0) { 441 | query += " WHERE " + sql; 442 | } 443 | alasql(query, [geojson.features], function(features) { 444 | featureLayer.clearLayers(); 445 | featureLayer.addData(features); 446 | syncTable(); 447 | }); 448 | } 449 | 450 | function buildTable() { 451 | $("#table").bootstrapTable({ 452 | cache: false, 453 | height: $("#table-container").height(), 454 | undefinedText: "", 455 | striped: false, 456 | pagination: false, 457 | minimumCountColumns: 1, 458 | sortName: config.sortProperty, 459 | sortOrder: config.sortOrder, 460 | toolbar: "#toolbar", 461 | search: true, 462 | trimOnSearch: false, 463 | showColumns: true, 464 | showToggle: true, 465 | columns: table, 466 | onClickRow: function(row) { 467 | // do something! 468 | }, 469 | onDblClickRow: function(row) { 470 | // do something! 471 | } 472 | }); 473 | 474 | map.fitBounds(featureLayer.getBounds()); 475 | 476 | $(window).resize(function() { 477 | $("#table").bootstrapTable("resetView", { 478 | height: $("#table-container").height() 479 | }); 480 | }); 481 | } 482 | 483 | function syncTable() { 484 | tableFeatures = []; 485 | featureLayer.eachLayer(function(layer) { 486 | layer.feature.properties.leaflet_stamp = L.stamp(layer); 487 | if (map.hasLayer(featureLayer)) { 488 | if (map.getBounds().contains(layer.getBounds())) { 489 | tableFeatures.push(layer.feature.properties); 490 | } 491 | } 492 | }); 493 | $("#table").bootstrapTable("load", JSON.parse(JSON.stringify(tableFeatures))); 494 | var featureCount = $("#table").bootstrapTable("getData").length; 495 | if (featureCount == 1) { 496 | $("#feature-count").html($("#table").bootstrapTable("getData").length + 497 | " visible feature"); 498 | } else { 499 | $("#feature-count").html($("#table").bootstrapTable("getData").length + 500 | " visible features"); 501 | } 502 | } 503 | 504 | function identifyFeature(id) { 505 | var featureProperties = featureLayer.getLayer(id).feature.properties; 506 | var content = 507 | ""; 508 | $.each(featureProperties, function(key, value) { 509 | if (!value) { 510 | value = ""; 511 | } 512 | if (typeof value == "string" && (value.indexOf("http") === 0 || value.indexOf( 513 | "https") === 0)) { 514 | value = "" + value + ""; 515 | } 516 | $.each(properties, function(index, property) { 517 | if (key == property.value) { 518 | if (property.info !== false) { 519 | content += ""; 521 | } 522 | } 523 | }); 524 | }); 525 | content += "
" + property.label + "" + value + 520 | "
"; 526 | $("#feature-info").html(content); 527 | $("#featureModal").modal("show"); 528 | } 529 | 530 | function switchView(view) { 531 | if (view == "split") { 532 | $("#view").html("Split View"); 533 | location.hash = "#split"; 534 | $("#table-container").show(); 535 | $("#table-container").css("height", "55%"); 536 | $("#map-container").show(); 537 | $("#map-container").css("height", "45%"); 538 | $(window).resize(); 539 | if (map) { 540 | map.invalidateSize(); 541 | } 542 | } else if (view == "map") { 543 | $("#view").html("Map View"); 544 | location.hash = "#map"; 545 | $("#map-container").show(); 546 | $("#map-container").css("height", "100%"); 547 | $("#table-container").hide(); 548 | if (map) { 549 | map.invalidateSize(); 550 | } 551 | } else if (view == "table") { 552 | $("#view").html("Table View"); 553 | location.hash = "#table"; 554 | $("#table-container").show(); 555 | $("#table-container").css("height", "100%"); 556 | $("#map-container").hide(); 557 | $(window).resize(); 558 | } 559 | } 560 | 561 | $("[name='view']").click(function() { 562 | $(".in,.open").removeClass("in open"); 563 | if (this.id === "map-graph") { 564 | switchView("split"); 565 | return false; 566 | } else if (this.id === "map-only") { 567 | switchView("map"); 568 | return false; 569 | } else if (this.id === "graph-only") { 570 | switchView("table"); 571 | return false; 572 | } 573 | }); 574 | 575 | $("#about-btn").click(function() { 576 | $("#aboutModal").modal("show"); 577 | $(".navbar-collapse.in").collapse("hide"); 578 | return false; 579 | }); 580 | 581 | $("#filter-btn").click(function() { 582 | $("#filterModal").modal("show"); 583 | $(".navbar-collapse.in").collapse("hide"); 584 | return false; 585 | }); 586 | 587 | $("#chart-btn").click(function() { 588 | $("#chartModal").modal("show"); 589 | $(".navbar-collapse.in").collapse("hide"); 590 | return false; 591 | }); 592 | 593 | $("#view-sql-btn").click(function() { 594 | alert($("#query-builder").queryBuilder("getSQL", false, false).sql); 595 | }); 596 | 597 | $("#apply-filter-btn").click(function() { 598 | applyFilter(); 599 | }); 600 | 601 | $("#reset-filter-btn").click(function() { 602 | $("#query-builder").queryBuilder("reset"); 603 | applyFilter(); 604 | }); 605 | 606 | $("#extent-btn").click(function() { 607 | map.fitBounds(featureLayer.getBounds()); 608 | $(".navbar-collapse.in").collapse("hide"); 609 | return false; 610 | }); 611 | 612 | $("#download-csv-btn").click(function() { 613 | $("#table").tableExport({ 614 | type: "csv", 615 | ignoreColumn: [0], 616 | fileName: "data" 617 | }); 618 | $(".navbar-collapse.in").collapse("hide"); 619 | return false; 620 | }); 621 | 622 | $("#download-excel-btn").click(function() { 623 | $("#table").tableExport({ 624 | type: "excel", 625 | ignoreColumn: [0], 626 | fileName: "data" 627 | }); 628 | $(".navbar-collapse.in").collapse("hide"); 629 | return false; 630 | }); 631 | 632 | $("#download-pdf-btn").click(function() { 633 | $("#table").tableExport({ 634 | type: "pdf", 635 | ignoreColumn: [0], 636 | fileName: "data", 637 | jspdf: { 638 | format: "bestfit", 639 | margins: { 640 | left: 20, 641 | right: 10, 642 | top: 20, 643 | bottom: 20 644 | }, 645 | autotable: { 646 | extendWidth: false, 647 | overflow: "linebreak" 648 | } 649 | } 650 | }); 651 | $(".navbar-collapse.in").collapse("hide"); 652 | return false; 653 | }); 654 | 655 | $("#chartModal").on("shown.bs.modal", function(e) { 656 | drawCharts(); 657 | }); 658 | -------------------------------------------------------------------------------- /_site/assets/vendor/jQuery-QueryBuilder/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2015 Damien Sorel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /_site/assets/vendor/jQuery-QueryBuilder/query-builder.default.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery QueryBuilder 2.2.0 3 | * Copyright 2014-2015 Damien "Mistic" Sorel (http://www.strangeplanet.fr) 4 | * Licensed under MIT (http://opensource.org/licenses/MIT) 5 | */ 6 | 7 | .query-builder .rule-container,.query-builder .rule-placeholder,.query-builder .rules-group-container{position:relative;margin:4px 0;border-radius:5px;padding:5px;border:1px solid #EEE;background:rgba(255,255,255,.9)}.query-builder .drag-handle,.query-builder .error-container,.query-builder .rule-container .rule-filter-container,.query-builder .rule-container .rule-operator-container,.query-builder .rule-container .rule-value-container{display:inline-block;margin:0 5px 0 0;vertical-align:middle}.query-builder .rules-group-container{padding:10px 10px 6px;border:1px solid #DCC896;background:rgba(250,240,210,.5)}.query-builder .rules-group-container .rules-group-header{margin-bottom:10px}.query-builder .rules-group-container .rules-group-header input[name$=_cond]{display:none}.query-builder .rules-group-container .rules-list{list-style:none;padding:0 0 0 15px;margin:0}.query-builder .rule-container .rule-value-container{border-left:1px solid #ddd;padding-left:5px}.query-builder .rule-container .rule-value-container label{margin-bottom:0;font-weight:400}.query-builder .rule-container .rule-value-container label.block{display:block}.query-builder .rule-container input[type=number],.query-builder .rule-container input[type=text],.query-builder .rule-container select{padding:1px}.query-builder .error-container{display:none;cursor:help;color:red}.query-builder .has-error{background-color:#FDD;border-color:#F99}.query-builder .has-error .error-container{display:inline-block!important}.query-builder .rules-list>:after,.query-builder .rules-list>:before{content:'';position:absolute;left:-10px;width:10px;height:calc(50% + 4px);border-color:#CCC;border-style:solid}.query-builder .rules-list>:before{top:-4px;border-width:0 0 2px 2px}.query-builder .rules-list>:after{top:50%;border-width:0 0 0 2px}.query-builder .rules-list>:first-child:before{top:-12px;height:calc(50% + 14px)}.query-builder .rules-list>:last-child:before{border-radius:0 0 0 4px}.query-builder .rules-list>:last-child:after{display:none}.query-builder .error-container+.tooltip .tooltip-inner{color:#F99!important}.query-builder p.filter-description{margin:5px 0 0;background:#D9EDF7;border:1px solid #BCE8F1;color:#31708F;border-radius:5px;padding:2.5px 5px;font-size:.8em}.query-builder .drag-handle{cursor:move;vertical-align:middle;margin-left:5px}.query-builder .dragged{opacity:.5}.query-builder .rule-placeholder{border:1px dashed #BBB;opacity:.7} -------------------------------------------------------------------------------- /_site/assets/vendor/tableExport/README.md: -------------------------------------------------------------------------------- 1 | tableExport.jquery.plugin 2 | ========================= 3 | 4 |

Export HTML Table to

5 | 16 | 17 | Installation 18 | ============ 19 | To export a html table in CSV, TXT, JSON, XML, SQL, XLS or DOC formats include: 20 | 21 | ```javascript 22 | 23 | 24 | ``` 25 | 26 | To export the table in PNG format additionally include : 27 | 28 | ```javascript 29 | 30 | ``` 31 | 32 | To export the table as a PDF file the following includes are required : 33 | 34 | ```javascript 35 | 36 | 37 | 38 | ``` 39 | 40 | Examples 41 | ======== 42 | 43 | ```javascript 44 | $('#tableID').tableExport({type:'csv'}); 45 | ``` 46 | 47 | ```javascript 48 | $('#tableID').tableExport({type:'pdf', 49 | jspdf: {orientation: 'p', 50 | margins: {left:20, top:10}, 51 | autotable: false} 52 | }); 53 | ``` 54 | 55 | ```javascript 56 | $('#tableID').tableExport({type:'pdf', 57 | jspdf: {orientation: 'l', 58 | format: 'a3', 59 | margins: {left:10, right:10, top:20, bottom:20}, 60 | autotable: {extendWidth: true} 61 | }); 62 | ``` 63 | 64 | ```javascript 65 | function DoCellData(cell, row, col, data) {} 66 | function DoBeforeAutotable(table, headers, rows, AutotableSettings) {} 67 | 68 | $('table').tableExport({fileName: sFileName, 69 | type: 'pdf', 70 | jspdf: { format: 'bestfit', 71 | margins: {left:20, right:10, top:20, bottom:20}, 72 | autotable: {extendWidth: false, 73 | overflow: 'linebreak', 74 | tableExport: {onBeforeAutotable: DoBeforeAutotable, 75 | onCellData: DoCellData}}} 76 | }); 77 | ``` 78 | 79 | Options 80 | ======= 81 | 82 | ```javascript 83 | csvSeparator: ',' 84 | csvEnclosure: '"' 85 | consoleLog: false 86 | displayTableName: false 87 | escape: false 88 | excelstyles: ['css','properties','to','export','to','excel'] 89 | fileName: 'tableExport' 90 | htmlContent: false 91 | ignoreColumn: [] 92 | jspdf: orientation: 'p' 93 | unit:'pt' 94 | format: 'bestfit' 95 | margins: { left: 20, right: 10, top: 10, bottom: 10 } 96 | autotable: padding: 2 97 | lineHeight: 12 98 | fontSize: 8 99 | tableExport: onAfterAutotable: null 100 | onBeforeAutotable: null 101 | onTable: null 102 | onCellData: null 103 | outputMode: 'file' 104 | tbodySelector: 'tr' 105 | theadSelector: 'tr' 106 | tableName: 'myTableName' 107 | type: 'csv' 108 | worksheetName: 'xlsWorksheetName' 109 | ``` 110 | 111 | For jspdf options see the documentation of [jsPDF](https://github.com/MrRio/jsPDF) and [jsPDF-AutoTable](https://github.com/someatoms/jsPDF-AutoTable) resp. 112 | 113 | Optional html data attributes 114 | ============================= 115 | (can be set while generating the table you want to export) 116 | 117 | ```html 118 | -> cell will not be exported 119 | ``` 120 | -------------------------------------------------------------------------------- /_site/assets/vendor/tableExport/libs/FileSaver/FileSaver.min.js: -------------------------------------------------------------------------------- 1 | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ 2 | var saveAs=saveAs||function(e){"use strict";if("undefined"==typeof navigator||!/MSIE [1-9]\./.test(navigator.userAgent)){var t=e.document,n=function(){return e.URL||e.webkitURL||e},o=t.createElementNS("http://www.w3.org/1999/xhtml","a"),r="download"in o,i=function(n){var o=t.createEvent("MouseEvents");o.initMouseEvent("click",!0,!1,e,0,0,0,0,0,!1,!1,!1,!1,0,null),n.dispatchEvent(o)},a=e.webkitRequestFileSystem,c=e.requestFileSystem||a||e.mozRequestFileSystem,u=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},f="application/octet-stream",s=0,d=500,l=function(t){var o=function(){"string"==typeof t?n().revokeObjectURL(t):t.remove()};e.chrome?o():setTimeout(o,d)},v=function(e,t,n){t=[].concat(t);for(var o=t.length;o--;){var r=e["on"+t[o]];if("function"==typeof r)try{r.call(e,n||e)}catch(i){u(i)}}},p=function(e){return/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)?new Blob(["\ufeff",e],{type:e.type}):e},w=function(t,u){t=p(t);var d,w,y,m=this,S=t.type,h=!1,O=function(){v(m,"writestart progress write writeend".split(" "))},E=function(){if((h||!d)&&(d=n().createObjectURL(t)),w)w.location.href=d;else{var o=e.open(d,"_blank");void 0==o&&"undefined"!=typeof safari&&(e.location.href=d)}m.readyState=m.DONE,O(),l(d)},R=function(e){return function(){return m.readyState!==m.DONE?e.apply(this,arguments):void 0}},b={create:!0,exclusive:!1};return m.readyState=m.INIT,u||(u="download"),r?(d=n().createObjectURL(t),o.href=d,o.download=u,i(o),m.readyState=m.DONE,O(),void l(d)):(e.chrome&&S&&S!==f&&(y=t.slice||t.webkitSlice,t=y.call(t,0,t.size,f),h=!0),a&&"download"!==u&&(u+=".download"),(S===f||a)&&(w=e),c?(s+=t.size,void c(e.TEMPORARY,s,R(function(e){e.root.getDirectory("saved",b,R(function(e){var n=function(){e.getFile(u,b,R(function(e){e.createWriter(R(function(n){n.onwriteend=function(t){w.location.href=e.toURL(),m.readyState=m.DONE,v(m,"writeend",t),l(e)},n.onerror=function(){var e=n.error;e.code!==e.ABORT_ERR&&E()},"writestart progress write abort".split(" ").forEach(function(e){n["on"+e]=m["on"+e]}),n.write(t),m.abort=function(){n.abort(),m.readyState=m.DONE},m.readyState=m.WRITING}),E)}),E)};e.getFile(u,{create:!1},R(function(e){e.remove(),n()}),R(function(e){e.code===e.NOT_FOUND_ERR?n():E()}))}),E)}),E)):void E())},y=w.prototype,m=function(e,t){return new w(e,t)};return"undefined"!=typeof navigator&&navigator.msSaveOrOpenBlob?function(e,t){return navigator.msSaveOrOpenBlob(p(e),t)}:(y.abort=function(){var e=this;e.readyState=e.DONE,v(e,"abort")},y.readyState=y.INIT=0,y.WRITING=1,y.DONE=2,y.error=y.onwritestart=y.onprogress=y.onwrite=y.onabort=y.onerror=y.onwriteend=null,m)}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content);"undefined"!=typeof module&&module.exports?module.exports.saveAs=saveAs:"undefined"!=typeof define&&null!==define&&null!=define.amd&&define([],function(){return saveAs}); -------------------------------------------------------------------------------- /_site/assets/vendor/tableExport/libs/FileSaver/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2015 [Eli Grey][1]. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | [1]: http://eligrey.com 10 | -------------------------------------------------------------------------------- /_site/assets/vendor/tableExport/libs/html2canvas/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Niklas von Hertzen 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /_site/assets/vendor/tableExport/libs/jsPDF-AutoTable/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Simon Bengtsson, https://github.com/someatoms/jspdf-autotable 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /_site/assets/vendor/tableExport/libs/jsPDF-AutoTable/jspdf.plugin.autotable.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jsPDF AutoTable plugin 3 | * Copyright (c) 2014 Simon Bengtsson, https://github.com/someatoms/jsPDF-AutoTable 4 | * 5 | * Licensed under the MIT License. 6 | * http://opensource.org/licenses/mit-license 7 | */ 8 | (function (API) { 9 | 'use strict'; 10 | 11 | // On every new jsPDF object, clear variables 12 | API.events.push(['initialized', function () { 13 | doc = undefined; 14 | cellPos = undefined; 15 | pageCount = 1; 16 | settings = undefined; 17 | }], false); 18 | 19 | var MIN_COLUMN_WIDTH = 25; 20 | 21 | var doc, cellPos, pageCount = 1, settings; 22 | 23 | // See README.md or examples for documentation of the options 24 | // return a new instance every time to avoid references issues 25 | var defaultOptions = function () { 26 | return { 27 | padding: 5, 28 | fontSize: 10, 29 | lineHeight: 20, 30 | renderHeader: function (doc, pageNumber, settings) { 31 | }, 32 | renderFooter: function (doc, lastCellPos, pageNumber, settings) { 33 | }, 34 | renderHeaderCell: function (x, y, width, height, key, value, settings) { 35 | doc.setFillColor(52, 73, 94); // Asphalt 36 | doc.setTextColor(255, 255, 255); 37 | doc.setFontStyle('bold'); 38 | doc.rect(x, y, width, height, 'F'); 39 | y += settings.lineHeight / 2 + API.autoTableTextHeight() / 2; 40 | doc.text(value, x + settings.padding, y); 41 | }, 42 | renderCell: function (x, y, width, height, key, value, row, settings) { 43 | doc.setFillColor(row % 2 === 0 ? 245 : 255); 44 | doc.setTextColor(50); 45 | doc.rect(x, y, width, height, 'F'); 46 | y += settings.lineHeight / 2 + API.autoTableTextHeight() / 2 - 2.5; 47 | doc.text(value, x + settings.padding, y); 48 | }, 49 | margins: {right: 40, left: 40, top: 50, bottom: 40}, 50 | startY: false, 51 | overflow: 'ellipsize', // false, ellipsize or linebreak (false passes the raw text to renderCell) 52 | overflowColumns: false, // Specify which colums that gets subjected to the overflow method chosen. false indicates all 53 | avoidPageSplit: false, 54 | extendWidth: true 55 | } 56 | }; 57 | 58 | /** 59 | * Create a table from a set of rows and columns. 60 | * 61 | * @param {Object[]|String[]} columns Either as an array of objects or array of strings 62 | * @param {Object[][]|String[][]} data Either as an array of objects or array of strings 63 | * @param {Object} [options={}] Options that will override the default ones (above) 64 | */ 65 | API.autoTable = function (columns, data, options) { 66 | options = options || {}; 67 | columns = columns || []; 68 | doc = this; 69 | 70 | var userFontSize = doc.internal.getFontSize(); 71 | 72 | initData({columns: columns, data: data}); 73 | initOptions(options); 74 | 75 | cellPos = { 76 | x: settings.margins.left, 77 | y: settings.startY === false ? settings.margins.top : settings.startY 78 | }; 79 | 80 | var tableHeight = settings.margins.bottom + settings.margins.top + settings.lineHeight * (data.length + 1) + 5 + settings.startY; 81 | if (settings.startY !== false && settings.avoidPageSplit && tableHeight > doc.internal.pageSize.height) { 82 | pageCount++; 83 | doc.addPage(); 84 | cellPos.y = settings.margins.top; 85 | } 86 | 87 | settings.renderHeader(doc, pageCount, settings); 88 | var columnWidths = calculateColumnWidths(data, columns); 89 | printHeader(columns, columnWidths); 90 | printRows(columns, data, columnWidths); 91 | settings.renderFooter(doc, cellPos, pageCount, settings); 92 | 93 | doc.setFontSize(userFontSize); 94 | 95 | return this; 96 | }; 97 | 98 | /** 99 | * Returns the Y position of the last drawn cell 100 | * @returns int 101 | */ 102 | API.autoTableEndPosY = function () { 103 | // If cellPos is not set, autoTable() has probably not been called 104 | return cellPos ? cellPos.y : false; 105 | }; 106 | 107 | /** 108 | * @deprecated Use autoTableEndPosY() 109 | */ 110 | API.autoTableEndPos = function () { 111 | return cellPos; 112 | }; 113 | 114 | /** 115 | * Parses an html table. To draw a table, use it like this: 116 | * `doc.autoTable(false, doc.autoTableHtmlToJson(tableDomElem))` 117 | * 118 | * @param table Html table element 119 | * @param indexBased Boolean flag if result should be returned as seperate cols and data 120 | * @returns []|{} Array of objects with object keys as headers or based on indexes if indexBased is set to true 121 | */ 122 | API.autoTableHtmlToJson = function (table, indexBased) { 123 | var data = [], headers = {}, header = table.rows[0], i, tableRow, rowData, j; 124 | if (indexBased) { 125 | headers = []; 126 | for (i = 0; i < header.cells.length; i++) { 127 | headers.push(header.cells[i] ? header.cells[i].textContent : ''); 128 | } 129 | 130 | for (i = 1; i < table.rows.length; i++) { 131 | tableRow = table.rows[i]; 132 | rowData = []; 133 | for (j = 0; j < header.cells.length; j++) { 134 | rowData.push(tableRow.cells[j] ? tableRow.cells[j].textContent : ''); 135 | } 136 | data.push(rowData); 137 | } 138 | return {columns: headers, data: data}; 139 | } else { 140 | for (i = 0; i < header.cells.length; i++) { 141 | headers[i] = header.cells[i] ? header.cells[i].textContent : ''; 142 | } 143 | 144 | for (i = 1; i < table.rows.length; i++) { 145 | tableRow = table.rows[i]; 146 | rowData = {}; 147 | for (j = 0; j < header.cells.length; j++) { 148 | rowData[headers[j]] = tableRow.cells[j] ? tableRow.cells[j].textContent : ''; 149 | } 150 | data.push(rowData); 151 | } 152 | 153 | return data; 154 | } 155 | }; 156 | 157 | /** 158 | * Basically the same as getLineHeight() in 1.0+ versions of jsPDF, however 159 | * added here for backwards compatibility with version 0.9 160 | * 161 | * Export it to make it available in drawCell and drawHeaderCell 162 | */ 163 | API.autoTableTextHeight = function() { 164 | // The value 1.15 comes from from the jsPDF source code and looks about right 165 | return doc.internal.getFontSize() * 1.15; 166 | }; 167 | 168 | /** 169 | * Transform all to the object initialization form 170 | * @param params 171 | */ 172 | function initData(params) { 173 | 174 | // Object only initial 175 | if (!params.columns || params.columns.length === 0) { 176 | var keys = Object.keys(params.data[0]); 177 | Array.prototype.push.apply(params.columns, keys); 178 | params.columns.forEach(function (title, i) { 179 | params.columns[i] = {title: title, key: keys[i]}; 180 | }); 181 | } 182 | // Array initialization form 183 | else if (typeof params.columns[0] === 'string') { 184 | params.data.forEach(function (row, i) { 185 | var obj = {}; 186 | for (var j = 0; j < row.length; j++) { 187 | obj[j] = params.data[i][j]; 188 | } 189 | params.data[i] = obj; 190 | }); 191 | params.columns.forEach(function (title, i) { 192 | params.columns[i] = {title: title, key: i}; 193 | }); 194 | } else { 195 | // Use options as is 196 | } 197 | } 198 | 199 | function initOptions(raw) { 200 | settings = defaultOptions(); 201 | Object.keys(raw).forEach(function (key) { 202 | settings[key] = raw[key]; 203 | }); 204 | doc.setFontSize(settings.fontSize); 205 | 206 | // Backwards compatibility 207 | if(settings.margins.horizontal !== undefined) { 208 | settings.margins.left = settings.margins.horizontal; 209 | settings.margins.right = settings.margins.horizontal; 210 | } else { 211 | settings.margins.horizontal = settings.margins.left; 212 | } 213 | } 214 | 215 | function calculateColumnWidths(rows, columns) { 216 | var widths = {}; 217 | 218 | // Optimal widths 219 | var optimalTableWidth = 0; 220 | columns.forEach(function (header) { 221 | var widest = getStringWidth(header.title || '', true); 222 | if(typeof header.width == "number") { 223 | widest = header.width; 224 | } else { 225 | rows.forEach(function (row) { 226 | if (!header.hasOwnProperty('key')) 227 | throw new Error("The key attribute is required in every header"); 228 | var w = getStringWidth(stringify(row, header.key)); 229 | if (w > widest) { 230 | widest = w; 231 | } 232 | }); 233 | } 234 | widths[header.key] = widest; 235 | optimalTableWidth += widest; 236 | }); 237 | 238 | var paddingAndMargin = settings.padding * 2 * columns.length + settings.margins.left + settings.margins.right; 239 | var spaceDiff = doc.internal.pageSize.width - optimalTableWidth - paddingAndMargin; 240 | 241 | var keys = Object.keys(widths); 242 | if (spaceDiff < 0) { 243 | // Shrink columns 244 | var shrinkableColumns = []; 245 | var shrinkableColumnWidths = 0; 246 | if (settings.overflowColumns === false) { 247 | keys.forEach(function (key) { 248 | if (widths[key] > MIN_COLUMN_WIDTH) { 249 | shrinkableColumns.push(key); 250 | shrinkableColumnWidths += widths[key]; 251 | } 252 | }); 253 | } else { 254 | shrinkableColumns = settings.overflowColumns; 255 | shrinkableColumns.forEach(function (col) { 256 | shrinkableColumnWidths += widths[col]; 257 | }); 258 | } 259 | 260 | shrinkableColumns.forEach(function (key) { 261 | widths[key] += spaceDiff * (widths[key] / shrinkableColumnWidths); 262 | }); 263 | } else if (spaceDiff > 0 && settings.extendWidth) { 264 | // Fill page horizontally 265 | keys.forEach(function (key) { 266 | widths[key] += spaceDiff / keys.length; 267 | }); 268 | } 269 | 270 | return widths; 271 | } 272 | 273 | function printHeader(headers, columnWidths) { 274 | if (!headers) return; 275 | 276 | // First calculate the height of the row 277 | // (to do that the maxium amount of rows first need to be found) 278 | var maxRows = 1; 279 | if (settings.overflow === 'linebreak') { 280 | // Font style must be the same as in function renderHeaderCell() 281 | doc.setFontStyle('bold'); 282 | 283 | headers.forEach(function (header) { 284 | if (isOverflowColumn(header)) { 285 | var value = header.title || ''; 286 | var arr = doc.splitTextToSize(value, columnWidths[header.key]); 287 | if (arr.length > maxRows) { 288 | maxRows = arr.length; 289 | } 290 | } 291 | }); 292 | } 293 | var rowHeight = settings.lineHeight + (maxRows - 1) * API.autoTableTextHeight() + 5; 294 | 295 | // Avoid isolated table headers when drawing multiple tables. Add a new page 296 | // if cellpos would be at the end of page after drawing the header row 297 | var newPage = (cellPos.y + settings.margins.bottom + rowHeight * 2) >= doc.internal.pageSize.height; 298 | if (newPage) { 299 | settings.renderFooter(doc, cellPos, pageCount, settings); 300 | doc.addPage(); 301 | cellPos = {x: settings.margins.left, y: settings.margins.top}; 302 | pageCount++; 303 | settings.renderHeader(doc, pageCount, settings); 304 | } 305 | 306 | headers.forEach(function (header) { 307 | var width = columnWidths[header.key] + settings.padding * 2; 308 | var value = header.title || ''; 309 | if (settings.overflow === 'linebreak') { 310 | if (isOverflowColumn(header)) { 311 | value = doc.splitTextToSize(value, columnWidths[header.key]); 312 | } 313 | } else if (settings.overflow === 'ellipsize') { 314 | value = ellipsize(columnWidths[header.key], value); 315 | } 316 | settings.renderHeaderCell(cellPos.x, cellPos.y, width, rowHeight, header.key, value, settings); 317 | cellPos.x += width; 318 | }); 319 | doc.setTextColor(70, 70, 70); 320 | doc.setFontStyle('normal'); 321 | 322 | cellPos.y += rowHeight; 323 | cellPos.x = settings.margins.left; 324 | } 325 | 326 | function printRows(headers, rows, columnWidths) { 327 | for (var i = 0; i < rows.length; i++) { 328 | var row = rows[i]; 329 | 330 | // First calculate the height of the row 331 | // (to do that the maxium amount of rows first need to be found) 332 | var maxRows = 1; 333 | if (settings.overflow === 'linebreak') { 334 | headers.forEach(function (header) { 335 | if (isOverflowColumn(header)) { 336 | var value = stringify(row, header.key); 337 | var arr = doc.splitTextToSize(value, columnWidths[header.key]); 338 | if (arr.length > maxRows) { 339 | maxRows = arr.length; 340 | } 341 | } 342 | }); 343 | } 344 | var rowHeight = settings.lineHeight + (maxRows - 1) * API.autoTableTextHeight(); 345 | 346 | 347 | // Render the cell 348 | headers.forEach(function (header) { 349 | var value = stringify(row, header.key); 350 | if (settings.overflow === 'linebreak') { 351 | if (isOverflowColumn(header)) { 352 | value = doc.splitTextToSize(value, columnWidths[header.key]); 353 | } 354 | } else if (settings.overflow === 'ellipsize') { 355 | value = ellipsize(columnWidths[header.key], value); 356 | } 357 | var width = columnWidths[header.key] + settings.padding * 2; 358 | settings.renderCell(cellPos.x, cellPos.y, width, rowHeight, header.key, value, i, settings); 359 | cellPos.x = cellPos.x + columnWidths[header.key] + settings.padding * 2; 360 | }); 361 | 362 | // Add a new page if cellpos is at the end of page 363 | var newPage = (cellPos.y + settings.margins.bottom + rowHeight * 2) >= doc.internal.pageSize.height; 364 | if (newPage) { 365 | if (i+1 < rows.length) { 366 | settings.renderFooter(doc, cellPos, pageCount, settings); 367 | doc.addPage(); 368 | cellPos = {x: settings.margins.left, y: settings.margins.top}; 369 | pageCount++; 370 | settings.renderHeader(doc, pageCount, settings); 371 | printHeader(headers, columnWidths); 372 | } 373 | } else { 374 | cellPos.y += rowHeight; 375 | cellPos.x = settings.margins.left; 376 | } 377 | } 378 | } 379 | 380 | function isOverflowColumn(header) { 381 | return settings.overflowColumns === false || settings.overflowColumns.indexOf(header.key) !== -1; 382 | } 383 | 384 | /** 385 | * Ellipsize the text to fit in the width 386 | * @param width 387 | * @param text 388 | */ 389 | function ellipsize(width, text) { 390 | if (width >= getStringWidth(text)) { 391 | return text; 392 | } 393 | while (width < getStringWidth(text + "...")) { 394 | if (text.length < 2) { 395 | break; 396 | } 397 | text = text.substring(0, text.length - 1); 398 | } 399 | text += "..."; 400 | return text; 401 | } 402 | 403 | function stringify(row, key) { 404 | return row.hasOwnProperty(key) ? '' + row[key] : ''; 405 | } 406 | 407 | function getStringWidth(txt, isBold) { 408 | if(isBold) { 409 | doc.setFontStyle('bold'); 410 | } 411 | var strWidth = doc.getStringUnitWidth(txt) * doc.internal.getFontSize(); 412 | if(isBold) { 413 | doc.setFontStyle('normal'); 414 | } 415 | return strWidth; 416 | } 417 | 418 | })(jsPDF.API); 419 | -------------------------------------------------------------------------------- /_site/assets/vendor/tableExport/libs/jsPDF/MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2014 James Hall, https://github.com/MrRio/jsPDF 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /_site/assets/vendor/tableExport/tableExport.min.js: -------------------------------------------------------------------------------- 1 | (function(f){f.fn.extend({tableExport:function(q){function t(l,e,d,h){f(l).filter(":visible").find(e).each(function(l){if("none"!=f(this).css("display")&&"none"!=f(this).data("tableexport-display")&&-1==a.ignoreColumn.indexOf(l)&&"function"===typeof h){var e=0;if("undefined"!=typeof w[d]&&0f?h+=String.fromCharCode(f):(127f?h+=String.fromCharCode(f>>6|192):(h+=String.fromCharCode(f>>12|224),h+=String.fromCharCode(f>>6&63|128)),h+=String.fromCharCode(f&63|128));for(a=h;m>2,d=(d&3)<<4|h>>4,g=(h&15)<<2|b>>6,k=b&63,isNaN(h)?g=k=64:isNaN(b)&&(k=64),e=e+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(f)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(d)+ 7 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(g)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(k);return e}var a={csvSeparator:",",csvEnclosure:'"',consoleLog:!1,displayTableName:!1,escape:!1,excelstyles:["border-bottom","border-top","border-left","border-right"],fileName:"tableExport",htmlContent:!1,ignoreColumn:[],jspdf:{orientation:"p",unit:"pt",format:"a4",margins:{left:20,right:10,top:10,bottom:10},autotable:{padding:2,lineHeight:12,fontSize:8, 8 | tableExport:{onAfterAutotable:null,onBeforeAutotable:null,onTable:null}}},onCellData:null,outputMode:"file",tbodySelector:"tr",theadSelector:"tr",tableName:"myTableName",type:"csv",worksheetName:"xlsWorksheetName"},C=null,w=[];f.extend(!0,a,q);if("csv"==a.type||"txt"==a.type){var g="",n=0;f(this).find("thead").first().find(a.theadSelector).each(function(){g+="\n";t(this,"th,td",n,function(l,e,d){g+=H(l,e,d)+a.csvSeparator});n++;g=f.trim(g);g=f.trim(g).substring(0,g.length-1)});f(this).find("tbody").first().find(a.tbodySelector).each(function(){trData= 9 | "";t(this,"td",n,function(l,e,d){trData+=H(l,e,d)+a.csvSeparator});trData.length>a.csvSeparator.length&&(g+="\n"+trData);n++;g=f.trim(g).substring(0,g.length-1)});g+="\n";!0===a.consoleLog&&console.log(g);if("string"===a.outputMode)return g;if("base64"===a.outputMode)return x(g);try{var v=new Blob([("csv"==a.type?"\ufeff":"")+g],{type:"text/"+("csv"==a.type?"csv":"plain")+";charset=utf-8"});saveAs(v,a.fileName+"."+a.type)}catch(O){y(a.fileName+"."+a.type,"data:text/"+("csv"==a.type?"csv":"plain")+ 10 | ";charset=utf-8,"+("csv"==a.type?"\ufeff":"")+encodeURIComponent(g))}}else if("sql"==a.type){n=0;g="INSERT INTO `"+a.tableName+"` (";f(this).find("thead").first().find(a.theadSelector).each(function(){t(this,"th,td",n,function(a,e,d){g+="'"+u(a,e,d)+"',"});n++;g=f.trim(g);g=f.trim(g).substring(0,g.length-1)});g+=") VALUES ";f(this).find("tbody").first().find(a.tbodySelector).each(function(){trData="";t(this,"td",n,function(a,e,d){trData+="'"+u(a,e,d)+"',"});3',p=p+"";f(this).find("thead").first().find(a.theadSelector).each(function(){t(this,"th,td",n,function(a,e,d){p+=""+u(a,e,d)+""});n++});var p=p+"",D=1;f(this).find("tbody").first().find(a.tbodySelector).each(function(){var a=1,e="";t(this,"td",n,function(d,h,b){e+=""+u(d,h,b)+"";a++});""!=e&&(p+=''+e+"", 14 | D++);n++});p+="";!0===a.consoleLog&&console.log(p);if("string"==a.outputMode)return p;q=x(p);if("base64"==a.outputMode)return q;try{v=new Blob([p],{type:"application/xml;charset=utf-8"}),saveAs(v,a.fileName+".xml")}catch(R){y(a.fileName+".xml","data:application/xml;charset=utf-8;base64,"+q)}}else if("excel"==a.type||"doc"==a.type){var n=0,k="
...
";f(this).find("thead").first().find(a.theadSelector).each(function(){k+="";t(this,"th,td",n,function(b,e,d){if(null!=b){k+=""}});n++;k+=""});D=1;f(this).find("tbody").first().find(a.tbodySelector).each(function(){k+="";t(this,"td",n,function(b,e,d){if(null!=b){k+=""}});D++;n++;k+=""});a.displayTableName&&(k+="");k+="
"+u(b,e,d)+"
"+u(b,e,d)+"
"+u(f("

"+a.tableName+"

"))+"
";!0===a.consoleLog&&console.log(k);b="";b+=''; 17 | b=b+'';b+="";"excel"===a.type&&(b+="\x3c!--[if gte mso 9]>",b+="",b+="",b+="",b+="",b+="",b+=a.worksheetName,b+="",b+="",b+="",b+="",b+="",b+="",b+="",b+="",b+="";b+="";b+=k;b+="";b+="";if("string"==a.outputMode)return b;q=x(b);if("base64"===a.outputMode)return q;var K="excel"===a.type?"xls":"doc";try{v=new Blob([b],{type:"application/vnd.ms-"+a.type}),saveAs(v,a.fileName+"."+K)}catch(S){y(a.fileName+"."+K,"data:application/vnd.ms-"+a.type+";base64,"+q)}}else if("png"==a.type)html2canvas(f(this),{onrendered:function(b){b=b.toDataURL();b=b.substring(22);for(var e=atob(b),d=new ArrayBuffer(e.length),h=new Uint8Array(d),f=0;f< 19 | e.length;f++)h[f]=e.charCodeAt(f);try{var g=new Blob([d],{type:"image/png"});saveAs(g,a.fileName+".png")}catch(k){y(a.fileName+".png","data:image/png;base64,"+b)}}});else if("pdf"==a.type)if(!1===a.jspdf.autotable){var v={dim:{w:F(f(this).first().get(0),"width","mm"),h:F(f(this).first().get(0),"height","mm")},pagesplit:!1},L=new jsPDF(a.jspdf.orientation,a.jspdf.unit,a.jspdf.format);L.addHTML(f(this).first(),a.jspdf.margins.left,a.jspdf.margins.top,v,function(){G(L)})}else{var m=a.jspdf.autotable.tableExport; 20 | if("string"===typeof a.jspdf.format&&"bestfit"===a.jspdf.format.toLowerCase()){var A={a0:[2383.94,3370.39],a1:[1683.78,2383.94],a2:[1190.55,1683.78],a3:[841.89,1190.55],a4:[595.28,841.89]},E="",B="",M=0;f(this).filter(":visible").each(function(){if("none"!=f(this).css("display")){var a=F(f(this).get(0),"width","pt");if(a>M){a>A.a0[0]&&(E="a0",B="l");for(var b in A)A.hasOwnProperty(b)&&A[b][1]>a&&(E=b,B="l",A[b][0]>a&&(B="p"));M=a}}});a.jspdf.format=""==E?"a4":E;a.jspdf.orientation=""==B?"w":B}m.doc= 21 | new jsPDF(a.jspdf.orientation,a.jspdf.unit,a.jspdf.format);f(this).filter(":visible").each(function(){if("none"!=f(this).css("display")){var b,e=0,d={};m.columns=[];m.rows=[];m.rowoptions={};if("function"===typeof m.onTable&&!1===m.onTable(f(this),a))return!0;Object.keys(a.jspdf.autotable).forEach(function(b){d[b]=a.jspdf.autotable[b]});d.margins={};f.extend(!0,d.margins,a.jspdf.margins);"function"!==typeof d.renderCell&&(d.renderCell=function(a,b,e,d,f,g,k,l){var m=l.tableExport.doc,n=0;m.setFillColor(0=== 22 | k%2?245:255);m.setTextColor(50);m.rect(a,b,e,d,"F");b+=l.lineHeight/2+m.autoTableTextHeight()/2-2.5;"undefined"!=typeof l.tableExport.columns[f]&&(d=l.tableExport.columns[f].style.align,f=l.tableExport.rowoptions[k+1+":"+f],void 0!==f&&(d=f.style.align),"right"==d?n=e-m.getStringUnitWidth(""+g)*m.internal.getFontSize()-l.padding:"center"==d&&(n=(e-m.getStringUnitWidth(""+g)*m.internal.getFontSize())/2));n 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | GeoJSON Dashboard 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | 37 | 38 | 66 | 67 |
68 |
69 |
70 | 71 |
72 |
73 |
74 | 77 |
78 | 81 | 86 |
87 |
88 | 89 |
90 |
91 |
92 | 93 | 146 | 147 | 176 | 177 | 195 | 196 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | -------------------------------------------------------------------------------- /_site/screenshots/charts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-open-data/geojson-dashboard/d04f7f1ed476b66af87f05085df2b2b1ba005b9b/_site/screenshots/charts.png -------------------------------------------------------------------------------- /_site/screenshots/filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-open-data/geojson-dashboard/d04f7f1ed476b66af87f05085df2b2b1ba005b9b/_site/screenshots/filter.png -------------------------------------------------------------------------------- /_site/screenshots/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-open-data/geojson-dashboard/d04f7f1ed476b66af87f05085df2b2b1ba005b9b/_site/screenshots/info.png -------------------------------------------------------------------------------- /_site/screenshots/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-open-data/geojson-dashboard/d04f7f1ed476b66af87f05085df2b2b1ba005b9b/_site/screenshots/map.png -------------------------------------------------------------------------------- /assets/css/app.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | width: 100%; 4 | overflow: hidden; 5 | } 6 | body { 7 | padding-top: 50px; 8 | } 9 | #map-container { 10 | height: 45%; 11 | padding: 0; 12 | } 13 | #table-container { 14 | height: 55%; 15 | padding: 5px; 16 | position: relative; 17 | box-shadow: inset 0 8px 8px -8px #696868; 18 | } 19 | #map { 20 | height: 100%; 21 | } 22 | #table tr { 23 | cursor: pointer; 24 | } 25 | #loading-mask { 26 | background-color: rgba(0, 0, 0, 0.5); 27 | } 28 | .loading-indicator { 29 | position: absolute; 30 | width: 220px; 31 | height: 19px; 32 | top: 50%; 33 | left: 50%; 34 | margin: -10px 0 0 -110px; 35 | z-index: 20001; 36 | } 37 | .loading-bar { 38 | width: 100%; 39 | } 40 | .rule-value-container { 41 | max-height: 100px; 42 | width: 350px; 43 | overflow: auto; 44 | } 45 | .tab-content { 46 | padding-top: 10px; 47 | } 48 | .fa-white { 49 | color: white; 50 | } 51 | .info-control { 52 | padding: 6px 8px; 53 | font: 14px/16px Arial, Helvetica, sans-serif; 54 | background: white; 55 | background: rgba(255,255,255,0.9); 56 | box-shadow: 0 0 15px rgba(0,0,0,0.2); 57 | border-radius: 5px; 58 | } 59 | .leaflet-control-layers { 60 | overflow: auto; 61 | } 62 | .leaflet-control-layers label { 63 | font-weight: normal; 64 | margin-bottom: 0px; 65 | } 66 | .leaflet-control-layers-selector { 67 | top: 0px; 68 | } 69 | .navbar .navbar-brand { 70 | font-weight: bold; 71 | font-size: 25px; 72 | color: white; 73 | } 74 | .navbar-brand img { 75 | height: 100%; 76 | margin-top: -5px; 77 | margin-right: 15px; 78 | display: inline; 79 | } 80 | .navbar-nav img { 81 | height: 40px; 82 | margin-top: -12px; 83 | margin-bottom: -10px; 84 | } 85 | @media (max-width: 992px) { 86 | .navbar .navbar-brand { 87 | font-size: 18px; 88 | } 89 | body { 90 | overflow-y: auto; 91 | } 92 | .fixed-table-toolbar { 93 | display: none; 94 | } 95 | .fixed-table-container { 96 | padding-bottom: 15px !important; 97 | } 98 | } 99 | @media print { 100 | .navbar { 101 | display: none !important; 102 | } 103 | .leaflet-control-container { 104 | display: none !important; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /assets/js/app.js: -------------------------------------------------------------------------------- 1 | var config = { 2 | geojson: "https://gist.githubusercontent.com/JJediny/b238fc15e3b31a2e3432/raw/3d73dbd7d4c950c8e85fdb7485567e84eca90772/CitizenScienceandCrowdsourcing_WWilson.geojson", 3 | title: "Federal Citizen Science and Crowdsourcing Projects", 4 | layerName: "Projects", 5 | hoverProperty: "project_name", 6 | sortProperty: "agency_sponsor", 7 | sortOrder: "desc" 8 | }; 9 | 10 | var properties = [{ 11 | value: "project_name", 12 | label: "Project Name", 13 | table: { 14 | visible: true, 15 | sortable: true 16 | }, 17 | filter: { 18 | type: "string" 19 | }, 20 | info: false 21 | }, { 22 | value: "status", 23 | label: "Status", 24 | table: { 25 | visible: true, 26 | sortable: true 27 | }, 28 | filter: { 29 | type: "string", 30 | input: "checkbox", 31 | vertical: true, 32 | multiple: true, 33 | operators: ["in", "not_in", "equal", "not_equal"], 34 | values: [] 35 | } 36 | }, { 37 | value: "agency_sponsor", 38 | label: "Federal Sponsor(s)", 39 | table: { 40 | visible: true, 41 | sortable: true 42 | }, 43 | filter: { 44 | type: "string" 45 | } 46 | }, { 47 | value: "agency_partner", 48 | label: "Agency Partner", 49 | table: { 50 | visible: true, 51 | sortable: true 52 | }, 53 | filter: { 54 | type: "string" 55 | } 56 | }, { 57 | value: "project_topic", 58 | label: "Topic(s)", 59 | table: { 60 | visible: true, 61 | sortable: true 62 | }, 63 | filter: { 64 | type: "integer" 65 | } 66 | }, { 67 | value: "project_description", 68 | label: "Description", 69 | table: { 70 | visible: true, 71 | sortable: true 72 | }, 73 | filter: { 74 | type: "integer" 75 | } 76 | }, { 77 | value: "project_url", 78 | label: "URL", 79 | table: { 80 | visible: false, 81 | sortable: true 82 | }, 83 | filter: { 84 | type: "integer" 85 | } 86 | }, { 87 | value: "participation_tasks", 88 | label: "Participation", 89 | table: { 90 | visible: true, 91 | sortable: true 92 | }, 93 | filter: { 94 | type: "integer" 95 | } 96 | }]; 97 | 98 | function drawCharts() { 99 | // Status 100 | $(function() { 101 | var result = alasql( 102 | "SELECT status AS label, COUNT(*) AS total FROM ? GROUP BY status", [ 103 | features 104 | ]); 105 | var columns = $.map(result, function(status) { 106 | return [ 107 | [status.label, status.total] 108 | ]; 109 | }); 110 | var chart = c3.generate({ 111 | bindto: "#status-chart", 112 | data: { 113 | type: "pie", 114 | columns: columns 115 | } 116 | }); 117 | }); 118 | 119 | // Agencies 120 | $(function() { 121 | var result = alasql( 122 | "SELECT agency_sponsor AS label, COUNT(*) AS total FROM ? GROUP BY agency_sponsor", [ 123 | features 124 | ]); 125 | var columns = $.map(result, function(zone) { 126 | return [ 127 | [zone.label, zone.total] 128 | ]; 129 | }); 130 | var chart = c3.generate({ 131 | bindto: "#zone-chart", 132 | data: { 133 | type: "pie", 134 | columns: columns 135 | } 136 | }); 137 | }); 138 | 139 | // Species 140 | $(function() { 141 | var result = alasql( 142 | "SELECT agency_partner AS label, COUNT(*) AS total FROM ? GROUP BY agency_partner ORDER BY label ASC", [ 143 | features 144 | ]); 145 | var chart = c3.generate({ 146 | bindto: "#species-chart", 147 | size: { 148 | height: 2000 149 | }, 150 | data: { 151 | json: result, 152 | keys: { 153 | x: "label", 154 | value: ["total"] 155 | }, 156 | type: "bar" 157 | }, 158 | axis: { 159 | rotated: true, 160 | x: { 161 | type: "category" 162 | } 163 | }, 164 | legend: { 165 | show: false 166 | } 167 | }); 168 | }); 169 | } 170 | 171 | $(function() { 172 | $(".title").html(config.title); 173 | $("#layer-name").html(config.layerName); 174 | }); 175 | 176 | function buildConfig() { 177 | filters = []; 178 | table = [{ 179 | field: "action", 180 | title: " Action", 181 | align: "center", 182 | valign: "middle", 183 | width: "75px", 184 | cardVisible: false, 185 | switchable: false, 186 | formatter: function(value, row, index) { 187 | return [ 188 | '', 189 | '', 190 | '', 191 | '', 192 | '', 193 | '' 194 | ].join(""); 195 | }, 196 | events: { 197 | "click .zoom": function(e, value, row, index) { 198 | map.fitBounds(featureLayer.getLayer(row.leaflet_stamp).getBounds()); 199 | highlightLayer.clearLayers(); 200 | highlightLayer.addData(featureLayer.getLayer(row.leaflet_stamp).toGeoJSON()); 201 | }, 202 | "click .identify": function(e, value, row, index) { 203 | identifyFeature(row.leaflet_stamp); 204 | highlightLayer.clearLayers(); 205 | highlightLayer.addData(featureLayer.getLayer(row.leaflet_stamp).toGeoJSON()); 206 | } 207 | } 208 | }]; 209 | 210 | 211 | 212 | $.each(properties, function(index, value) { 213 | // Filter config 214 | if (value.filter) { 215 | var id; 216 | if (value.filter.type == "integer") { 217 | id = "cast(properties->" + value.value + " as int)"; 218 | } else if (value.filter.type == "double") { 219 | id = "cast(properties->" + value.value + " as double)"; 220 | } else { 221 | id = "properties->" + value.value; 222 | } 223 | filters.push({ 224 | id: id, 225 | label: value.label 226 | }); 227 | $.each(value.filter, function(key, val) { 228 | if (filters[index]) { 229 | // If values array is empty, fetch all distinct values 230 | if (key == "values" && val.length === 0) { 231 | alasql("SELECT DISTINCT(properties->" + value.value + 232 | ") AS field FROM ? ORDER BY field ASC", [geojson.features], 233 | function(results) { 234 | distinctValues = []; 235 | $.each(results, function(index, value) { 236 | distinctValues.push(value.field); 237 | }); 238 | }); 239 | filters[index].values = distinctValues; 240 | } else { 241 | filters[index][key] = val; 242 | } 243 | } 244 | }); 245 | } 246 | // Table config 247 | if (value.table) { 248 | table.push({ 249 | field: value.value, 250 | title: value.label 251 | }); 252 | $.each(value.table, function(key, val) { 253 | if (table[index + 1]) { 254 | table[index + 1][key] = val; 255 | } 256 | }); 257 | } 258 | }); 259 | 260 | buildFilters(); 261 | buildTable(); 262 | } 263 | 264 | // Basemap Layers 265 | var mapboxTerrian = L.tileLayer( 266 | "http://{s}.tiles.mapbox.com/v3/energy.map-ayrdk7iy/{z}/{x}/{y}.png", { 267 | maxZoom: 18, 268 | subdomains: ["a", "b", "c"], 269 | attribution: 'Tiles courtesy of Mapbox Team. Map data (c) OpenStreetMap contributors, CC-BY-SA.' 270 | }); 271 | 272 | var humanitarianOSM = L.tileLayer( 273 | "http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png", { 274 | maxZoom: 19, 275 | subdomains: ["a", "b", "c"], 276 | attribution: 'Tiles courtesy of Humanitarian OpenStreetMap Team. Map data (c) OpenStreetMap contributors, CC-BY-SA.' 277 | }); 278 | 279 | var stamenToner = L.tileLayer( 280 | "http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png", { 281 | maxZoom: 19, 282 | subdomains: ["a", "b", "c"], 283 | attribution: 'Labels courtesy of Stamen Design. Map data (c) OpenStreetMap contributors, CC-BY-3.0.' 284 | }); 285 | 286 | var highlightLayer = L.geoJson(null, { 287 | pointToLayer: function(feature, latlng) { 288 | return L.circleMarker(latlng, { 289 | radius: 5, 290 | color: "#FFF", 291 | weight: 2, 292 | opacity: 1, 293 | fillColor: "#00FFFF", 294 | fillOpacity: 1, 295 | clickable: false 296 | }); 297 | }, 298 | style: function(feature) { 299 | return { 300 | color: "#00FFFF", 301 | weight: 2, 302 | opacity: 1, 303 | fillColor: "#00FFFF", 304 | fillOpacity: 0.5, 305 | clickable: false 306 | }; 307 | } 308 | }); 309 | 310 | var featureLayer = L.geoJson(null, { 311 | filter: function(feature, layer) { 312 | return feature.geometry.coordinates[0] !== 0 && feature.geometry.coordinates[ 313 | 1] !== 0; 314 | }, 315 | /*style: function (feature) { 316 | return { 317 | color: feature.properties.color 318 | }; 319 | },*/ 320 | pointToLayer: function(feature, latlng) { 321 | if (feature.properties && feature.properties["marker-color"]) { 322 | markerColor = feature.properties["marker-color"]; 323 | } else { 324 | markerColor = "#FF0000"; 325 | } 326 | return L.circleMarker(latlng, { 327 | radius: 3, 328 | weight: 1, 329 | fillColor: markerColor, 330 | color: markerColor, 331 | opacity: 1, 332 | fillOpacity: 0.5 333 | }); 334 | }, 335 | onEachFeature: function(feature, layer) { 336 | if (feature.properties) { 337 | layer.on({ 338 | click: function(e) { 339 | identifyFeature(L.stamp(layer)); 340 | highlightLayer.clearLayers(); 341 | highlightLayer.addData(featureLayer.getLayer(L.stamp( 342 | layer)).toGeoJSON()); 343 | }, 344 | mouseover: function(e) { 345 | if (config.hoverProperty) { 346 | $(".info-control").html(feature.properties[config.hoverProperty]); 347 | $(".info-control").show(); 348 | } 349 | }, 350 | mouseout: function(e) { 351 | $(".info-control").hide(); 352 | } 353 | }); 354 | } 355 | } 356 | }); 357 | 358 | // Fetch the GeoJSON file 359 | $.getJSON(config.geojson, function(data) { 360 | geojson = data; 361 | features = $.map(geojson.features, function(feature) { 362 | return feature.properties; 363 | }); 364 | featureLayer.addData(data); 365 | buildConfig(); 366 | $("#loading-mask").hide(); 367 | }); 368 | 369 | var map = L.map("map", { 370 | layers: [mapboxTerrian, featureLayer, highlightLayer] 371 | }).fitWorld(); 372 | 373 | // ESRI geocoder 374 | var searchControl = L.esri.Geocoding.Controls.geosearch({ 375 | useMapBounds: 17 376 | }).addTo(map); 377 | 378 | // Info control 379 | var info = L.control({ 380 | position: "bottomleft" 381 | }); 382 | 383 | // Custom info hover control 384 | info.onAdd = function(map) { 385 | this._div = L.DomUtil.create("div", "info-control"); 386 | this.update(); 387 | return this._div; 388 | }; 389 | info.update = function(props) { 390 | this._div.innerHTML = ""; 391 | }; 392 | info.addTo(map); 393 | $(".info-control").hide(); 394 | 395 | // Larger screens get expanded layer control 396 | if (document.body.clientWidth <= 767) { 397 | isCollapsed = true; 398 | } else { 399 | isCollapsed = false; 400 | } 401 | var baseLayers = { 402 | "Humanitarian OpenStreetMap": humanitarianOSM, 403 | "Mapbox Terrian": mapboxTerrian, 404 | "Stamen Toner": stamenToner 405 | }; 406 | var overlayLayers = { 407 | "GeoJSON Layer": featureLayer 408 | }; 409 | var layerControl = L.control.layers(baseLayers, overlayLayers, { 410 | collapsed: isCollapsed 411 | }).addTo(map); 412 | 413 | // Filter table to only show features in current map bounds 414 | map.on("moveend", function(e) { 415 | syncTable(); 416 | }); 417 | 418 | map.on("click", function(e) { 419 | highlightLayer.clearLayers(); 420 | }); 421 | 422 | // Table formatter to make links clickable 423 | function urlFormatter(value, row, index) { 424 | if (typeof value == "string" && (value.indexOf("http") === 0 || value.indexOf( 425 | "https") === 0)) { 426 | return "" + value + ""; 427 | } 428 | } 429 | 430 | function buildFilters() { 431 | $("#query-builder").queryBuilder({ 432 | allow_empty: true, 433 | filters: filters 434 | }); 435 | } 436 | 437 | function applyFilter() { 438 | var query = "SELECT * FROM ?"; 439 | var sql = $("#query-builder").queryBuilder("getSQL", false, false).sql; 440 | if (sql.length > 0) { 441 | query += " WHERE " + sql; 442 | } 443 | alasql(query, [geojson.features], function(features) { 444 | featureLayer.clearLayers(); 445 | featureLayer.addData(features); 446 | syncTable(); 447 | }); 448 | } 449 | 450 | function buildTable() { 451 | $("#table").bootstrapTable({ 452 | cache: false, 453 | height: $("#table-container").height(), 454 | undefinedText: "", 455 | striped: false, 456 | pagination: false, 457 | minimumCountColumns: 1, 458 | sortName: config.sortProperty, 459 | sortOrder: config.sortOrder, 460 | toolbar: "#toolbar", 461 | search: true, 462 | trimOnSearch: false, 463 | showColumns: true, 464 | showToggle: true, 465 | columns: table, 466 | onClickRow: function(row) { 467 | // do something! 468 | }, 469 | onDblClickRow: function(row) { 470 | // do something! 471 | } 472 | }); 473 | 474 | map.fitBounds(featureLayer.getBounds()); 475 | 476 | $(window).resize(function() { 477 | $("#table").bootstrapTable("resetView", { 478 | height: $("#table-container").height() 479 | }); 480 | }); 481 | } 482 | 483 | function syncTable() { 484 | tableFeatures = []; 485 | featureLayer.eachLayer(function(layer) { 486 | layer.feature.properties.leaflet_stamp = L.stamp(layer); 487 | if (map.hasLayer(featureLayer)) { 488 | if (map.getBounds().contains(layer.getBounds())) { 489 | tableFeatures.push(layer.feature.properties); 490 | } 491 | } 492 | }); 493 | $("#table").bootstrapTable("load", JSON.parse(JSON.stringify(tableFeatures))); 494 | var featureCount = $("#table").bootstrapTable("getData").length; 495 | if (featureCount == 1) { 496 | $("#feature-count").html($("#table").bootstrapTable("getData").length + 497 | " visible feature"); 498 | } else { 499 | $("#feature-count").html($("#table").bootstrapTable("getData").length + 500 | " visible features"); 501 | } 502 | } 503 | 504 | function identifyFeature(id) { 505 | var featureProperties = featureLayer.getLayer(id).feature.properties; 506 | var content = 507 | ""; 508 | $.each(featureProperties, function(key, value) { 509 | if (!value) { 510 | value = ""; 511 | } 512 | if (typeof value == "string" && (value.indexOf("http") === 0 || value.indexOf( 513 | "https") === 0)) { 514 | value = "" + value + ""; 515 | } 516 | $.each(properties, function(index, property) { 517 | if (key == property.value) { 518 | if (property.info !== false) { 519 | content += ""; 521 | } 522 | } 523 | }); 524 | }); 525 | content += "
" + property.label + "" + value + 520 | "
"; 526 | $("#feature-info").html(content); 527 | $("#featureModal").modal("show"); 528 | } 529 | 530 | function switchView(view) { 531 | if (view == "split") { 532 | $("#view").html("Split View"); 533 | location.hash = "#split"; 534 | $("#table-container").show(); 535 | $("#table-container").css("height", "55%"); 536 | $("#map-container").show(); 537 | $("#map-container").css("height", "45%"); 538 | $(window).resize(); 539 | if (map) { 540 | map.invalidateSize(); 541 | } 542 | } else if (view == "map") { 543 | $("#view").html("Map View"); 544 | location.hash = "#map"; 545 | $("#map-container").show(); 546 | $("#map-container").css("height", "100%"); 547 | $("#table-container").hide(); 548 | if (map) { 549 | map.invalidateSize(); 550 | } 551 | } else if (view == "table") { 552 | $("#view").html("Table View"); 553 | location.hash = "#table"; 554 | $("#table-container").show(); 555 | $("#table-container").css("height", "100%"); 556 | $("#map-container").hide(); 557 | $(window).resize(); 558 | } 559 | } 560 | 561 | $("[name='view']").click(function() { 562 | $(".in,.open").removeClass("in open"); 563 | if (this.id === "map-graph") { 564 | switchView("split"); 565 | return false; 566 | } else if (this.id === "map-only") { 567 | switchView("map"); 568 | return false; 569 | } else if (this.id === "graph-only") { 570 | switchView("table"); 571 | return false; 572 | } 573 | }); 574 | 575 | $("#about-btn").click(function() { 576 | $("#aboutModal").modal("show"); 577 | $(".navbar-collapse.in").collapse("hide"); 578 | return false; 579 | }); 580 | 581 | $("#filter-btn").click(function() { 582 | $("#filterModal").modal("show"); 583 | $(".navbar-collapse.in").collapse("hide"); 584 | return false; 585 | }); 586 | 587 | $("#chart-btn").click(function() { 588 | $("#chartModal").modal("show"); 589 | $(".navbar-collapse.in").collapse("hide"); 590 | return false; 591 | }); 592 | 593 | $("#view-sql-btn").click(function() { 594 | alert($("#query-builder").queryBuilder("getSQL", false, false).sql); 595 | }); 596 | 597 | $("#apply-filter-btn").click(function() { 598 | applyFilter(); 599 | }); 600 | 601 | $("#reset-filter-btn").click(function() { 602 | $("#query-builder").queryBuilder("reset"); 603 | applyFilter(); 604 | }); 605 | 606 | $("#extent-btn").click(function() { 607 | map.fitBounds(featureLayer.getBounds()); 608 | $(".navbar-collapse.in").collapse("hide"); 609 | return false; 610 | }); 611 | 612 | $("#download-csv-btn").click(function() { 613 | $("#table").tableExport({ 614 | type: "csv", 615 | ignoreColumn: [0], 616 | fileName: "data" 617 | }); 618 | $(".navbar-collapse.in").collapse("hide"); 619 | return false; 620 | }); 621 | 622 | $("#download-excel-btn").click(function() { 623 | $("#table").tableExport({ 624 | type: "excel", 625 | ignoreColumn: [0], 626 | fileName: "data" 627 | }); 628 | $(".navbar-collapse.in").collapse("hide"); 629 | return false; 630 | }); 631 | 632 | $("#download-pdf-btn").click(function() { 633 | $("#table").tableExport({ 634 | type: "pdf", 635 | ignoreColumn: [0], 636 | fileName: "data", 637 | jspdf: { 638 | format: "bestfit", 639 | margins: { 640 | left: 20, 641 | right: 10, 642 | top: 20, 643 | bottom: 20 644 | }, 645 | autotable: { 646 | extendWidth: false, 647 | overflow: "linebreak" 648 | } 649 | } 650 | }); 651 | $(".navbar-collapse.in").collapse("hide"); 652 | return false; 653 | }); 654 | 655 | $("#chartModal").on("shown.bs.modal", function(e) { 656 | drawCharts(); 657 | }); 658 | -------------------------------------------------------------------------------- /assets/vendor/jQuery-QueryBuilder/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2015 Damien Sorel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /assets/vendor/jQuery-QueryBuilder/query-builder.default.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery QueryBuilder 2.2.0 3 | * Copyright 2014-2015 Damien "Mistic" Sorel (http://www.strangeplanet.fr) 4 | * Licensed under MIT (http://opensource.org/licenses/MIT) 5 | */ 6 | 7 | .query-builder .rule-container,.query-builder .rule-placeholder,.query-builder .rules-group-container{position:relative;margin:4px 0;border-radius:5px;padding:5px;border:1px solid #EEE;background:rgba(255,255,255,.9)}.query-builder .drag-handle,.query-builder .error-container,.query-builder .rule-container .rule-filter-container,.query-builder .rule-container .rule-operator-container,.query-builder .rule-container .rule-value-container{display:inline-block;margin:0 5px 0 0;vertical-align:middle}.query-builder .rules-group-container{padding:10px 10px 6px;border:1px solid #DCC896;background:rgba(250,240,210,.5)}.query-builder .rules-group-container .rules-group-header{margin-bottom:10px}.query-builder .rules-group-container .rules-group-header input[name$=_cond]{display:none}.query-builder .rules-group-container .rules-list{list-style:none;padding:0 0 0 15px;margin:0}.query-builder .rule-container .rule-value-container{border-left:1px solid #ddd;padding-left:5px}.query-builder .rule-container .rule-value-container label{margin-bottom:0;font-weight:400}.query-builder .rule-container .rule-value-container label.block{display:block}.query-builder .rule-container input[type=number],.query-builder .rule-container input[type=text],.query-builder .rule-container select{padding:1px}.query-builder .error-container{display:none;cursor:help;color:red}.query-builder .has-error{background-color:#FDD;border-color:#F99}.query-builder .has-error .error-container{display:inline-block!important}.query-builder .rules-list>:after,.query-builder .rules-list>:before{content:'';position:absolute;left:-10px;width:10px;height:calc(50% + 4px);border-color:#CCC;border-style:solid}.query-builder .rules-list>:before{top:-4px;border-width:0 0 2px 2px}.query-builder .rules-list>:after{top:50%;border-width:0 0 0 2px}.query-builder .rules-list>:first-child:before{top:-12px;height:calc(50% + 14px)}.query-builder .rules-list>:last-child:before{border-radius:0 0 0 4px}.query-builder .rules-list>:last-child:after{display:none}.query-builder .error-container+.tooltip .tooltip-inner{color:#F99!important}.query-builder p.filter-description{margin:5px 0 0;background:#D9EDF7;border:1px solid #BCE8F1;color:#31708F;border-radius:5px;padding:2.5px 5px;font-size:.8em}.query-builder .drag-handle{cursor:move;vertical-align:middle;margin-left:5px}.query-builder .dragged{opacity:.5}.query-builder .rule-placeholder{border:1px dashed #BBB;opacity:.7} -------------------------------------------------------------------------------- /assets/vendor/tableExport/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | tableExport.jquery.plugin.iml -------------------------------------------------------------------------------- /assets/vendor/tableExport/README.md: -------------------------------------------------------------------------------- 1 | tableExport.jquery.plugin 2 | ========================= 3 | 4 |

Export HTML Table to

5 | 16 | 17 | Installation 18 | ============ 19 | To export a html table in CSV, TXT, JSON, XML, SQL, XLS or DOC formats include: 20 | 21 | ```javascript 22 | 23 | 24 | ``` 25 | 26 | To export the table in PNG format additionally include : 27 | 28 | ```javascript 29 | 30 | ``` 31 | 32 | To export the table as a PDF file the following includes are required : 33 | 34 | ```javascript 35 | 36 | 37 | 38 | ``` 39 | 40 | Examples 41 | ======== 42 | 43 | ```javascript 44 | $('#tableID').tableExport({type:'csv'}); 45 | ``` 46 | 47 | ```javascript 48 | $('#tableID').tableExport({type:'pdf', 49 | jspdf: {orientation: 'p', 50 | margins: {left:20, top:10}, 51 | autotable: false} 52 | }); 53 | ``` 54 | 55 | ```javascript 56 | $('#tableID').tableExport({type:'pdf', 57 | jspdf: {orientation: 'l', 58 | format: 'a3', 59 | margins: {left:10, right:10, top:20, bottom:20}, 60 | autotable: {extendWidth: true} 61 | }); 62 | ``` 63 | 64 | ```javascript 65 | function DoCellData(cell, row, col, data) {} 66 | function DoBeforeAutotable(table, headers, rows, AutotableSettings) {} 67 | 68 | $('table').tableExport({fileName: sFileName, 69 | type: 'pdf', 70 | jspdf: { format: 'bestfit', 71 | margins: {left:20, right:10, top:20, bottom:20}, 72 | autotable: {extendWidth: false, 73 | overflow: 'linebreak', 74 | tableExport: {onBeforeAutotable: DoBeforeAutotable, 75 | onCellData: DoCellData}}} 76 | }); 77 | ``` 78 | 79 | Options 80 | ======= 81 | 82 | ```javascript 83 | csvSeparator: ',' 84 | csvEnclosure: '"' 85 | consoleLog: false 86 | displayTableName: false 87 | escape: false 88 | excelstyles: ['css','properties','to','export','to','excel'] 89 | fileName: 'tableExport' 90 | htmlContent: false 91 | ignoreColumn: [] 92 | jspdf: orientation: 'p' 93 | unit:'pt' 94 | format: 'bestfit' 95 | margins: { left: 20, right: 10, top: 10, bottom: 10 } 96 | autotable: padding: 2 97 | lineHeight: 12 98 | fontSize: 8 99 | tableExport: onAfterAutotable: null 100 | onBeforeAutotable: null 101 | onTable: null 102 | onCellData: null 103 | outputMode: 'file' 104 | tbodySelector: 'tr' 105 | theadSelector: 'tr' 106 | tableName: 'myTableName' 107 | type: 'csv' 108 | worksheetName: 'xlsWorksheetName' 109 | ``` 110 | 111 | For jspdf options see the documentation of [jsPDF](https://github.com/MrRio/jsPDF) and [jsPDF-AutoTable](https://github.com/someatoms/jsPDF-AutoTable) resp. 112 | 113 | Optional html data attributes 114 | ============================= 115 | (can be set while generating the table you want to export) 116 | 117 | ```html 118 | -> cell will not be exported 119 | ``` 120 | -------------------------------------------------------------------------------- /assets/vendor/tableExport/libs/FileSaver/FileSaver.min.js: -------------------------------------------------------------------------------- 1 | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ 2 | var saveAs=saveAs||function(e){"use strict";if("undefined"==typeof navigator||!/MSIE [1-9]\./.test(navigator.userAgent)){var t=e.document,n=function(){return e.URL||e.webkitURL||e},o=t.createElementNS("http://www.w3.org/1999/xhtml","a"),r="download"in o,i=function(n){var o=t.createEvent("MouseEvents");o.initMouseEvent("click",!0,!1,e,0,0,0,0,0,!1,!1,!1,!1,0,null),n.dispatchEvent(o)},a=e.webkitRequestFileSystem,c=e.requestFileSystem||a||e.mozRequestFileSystem,u=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},f="application/octet-stream",s=0,d=500,l=function(t){var o=function(){"string"==typeof t?n().revokeObjectURL(t):t.remove()};e.chrome?o():setTimeout(o,d)},v=function(e,t,n){t=[].concat(t);for(var o=t.length;o--;){var r=e["on"+t[o]];if("function"==typeof r)try{r.call(e,n||e)}catch(i){u(i)}}},p=function(e){return/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)?new Blob(["\ufeff",e],{type:e.type}):e},w=function(t,u){t=p(t);var d,w,y,m=this,S=t.type,h=!1,O=function(){v(m,"writestart progress write writeend".split(" "))},E=function(){if((h||!d)&&(d=n().createObjectURL(t)),w)w.location.href=d;else{var o=e.open(d,"_blank");void 0==o&&"undefined"!=typeof safari&&(e.location.href=d)}m.readyState=m.DONE,O(),l(d)},R=function(e){return function(){return m.readyState!==m.DONE?e.apply(this,arguments):void 0}},b={create:!0,exclusive:!1};return m.readyState=m.INIT,u||(u="download"),r?(d=n().createObjectURL(t),o.href=d,o.download=u,i(o),m.readyState=m.DONE,O(),void l(d)):(e.chrome&&S&&S!==f&&(y=t.slice||t.webkitSlice,t=y.call(t,0,t.size,f),h=!0),a&&"download"!==u&&(u+=".download"),(S===f||a)&&(w=e),c?(s+=t.size,void c(e.TEMPORARY,s,R(function(e){e.root.getDirectory("saved",b,R(function(e){var n=function(){e.getFile(u,b,R(function(e){e.createWriter(R(function(n){n.onwriteend=function(t){w.location.href=e.toURL(),m.readyState=m.DONE,v(m,"writeend",t),l(e)},n.onerror=function(){var e=n.error;e.code!==e.ABORT_ERR&&E()},"writestart progress write abort".split(" ").forEach(function(e){n["on"+e]=m["on"+e]}),n.write(t),m.abort=function(){n.abort(),m.readyState=m.DONE},m.readyState=m.WRITING}),E)}),E)};e.getFile(u,{create:!1},R(function(e){e.remove(),n()}),R(function(e){e.code===e.NOT_FOUND_ERR?n():E()}))}),E)}),E)):void E())},y=w.prototype,m=function(e,t){return new w(e,t)};return"undefined"!=typeof navigator&&navigator.msSaveOrOpenBlob?function(e,t){return navigator.msSaveOrOpenBlob(p(e),t)}:(y.abort=function(){var e=this;e.readyState=e.DONE,v(e,"abort")},y.readyState=y.INIT=0,y.WRITING=1,y.DONE=2,y.error=y.onwritestart=y.onprogress=y.onwrite=y.onabort=y.onerror=y.onwriteend=null,m)}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content);"undefined"!=typeof module&&module.exports?module.exports.saveAs=saveAs:"undefined"!=typeof define&&null!==define&&null!=define.amd&&define([],function(){return saveAs}); -------------------------------------------------------------------------------- /assets/vendor/tableExport/libs/FileSaver/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2015 [Eli Grey][1]. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | [1]: http://eligrey.com 10 | -------------------------------------------------------------------------------- /assets/vendor/tableExport/libs/html2canvas/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Niklas von Hertzen 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /assets/vendor/tableExport/libs/jsPDF-AutoTable/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Simon Bengtsson, https://github.com/someatoms/jspdf-autotable 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /assets/vendor/tableExport/libs/jsPDF-AutoTable/jspdf.plugin.autotable.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jsPDF AutoTable plugin 3 | * Copyright (c) 2014 Simon Bengtsson, https://github.com/someatoms/jsPDF-AutoTable 4 | * 5 | * Licensed under the MIT License. 6 | * http://opensource.org/licenses/mit-license 7 | */ 8 | (function (API) { 9 | 'use strict'; 10 | 11 | // On every new jsPDF object, clear variables 12 | API.events.push(['initialized', function () { 13 | doc = undefined; 14 | cellPos = undefined; 15 | pageCount = 1; 16 | settings = undefined; 17 | }], false); 18 | 19 | var MIN_COLUMN_WIDTH = 25; 20 | 21 | var doc, cellPos, pageCount = 1, settings; 22 | 23 | // See README.md or examples for documentation of the options 24 | // return a new instance every time to avoid references issues 25 | var defaultOptions = function () { 26 | return { 27 | padding: 5, 28 | fontSize: 10, 29 | lineHeight: 20, 30 | renderHeader: function (doc, pageNumber, settings) { 31 | }, 32 | renderFooter: function (doc, lastCellPos, pageNumber, settings) { 33 | }, 34 | renderHeaderCell: function (x, y, width, height, key, value, settings) { 35 | doc.setFillColor(52, 73, 94); // Asphalt 36 | doc.setTextColor(255, 255, 255); 37 | doc.setFontStyle('bold'); 38 | doc.rect(x, y, width, height, 'F'); 39 | y += settings.lineHeight / 2 + API.autoTableTextHeight() / 2; 40 | doc.text(value, x + settings.padding, y); 41 | }, 42 | renderCell: function (x, y, width, height, key, value, row, settings) { 43 | doc.setFillColor(row % 2 === 0 ? 245 : 255); 44 | doc.setTextColor(50); 45 | doc.rect(x, y, width, height, 'F'); 46 | y += settings.lineHeight / 2 + API.autoTableTextHeight() / 2 - 2.5; 47 | doc.text(value, x + settings.padding, y); 48 | }, 49 | margins: {right: 40, left: 40, top: 50, bottom: 40}, 50 | startY: false, 51 | overflow: 'ellipsize', // false, ellipsize or linebreak (false passes the raw text to renderCell) 52 | overflowColumns: false, // Specify which colums that gets subjected to the overflow method chosen. false indicates all 53 | avoidPageSplit: false, 54 | extendWidth: true 55 | } 56 | }; 57 | 58 | /** 59 | * Create a table from a set of rows and columns. 60 | * 61 | * @param {Object[]|String[]} columns Either as an array of objects or array of strings 62 | * @param {Object[][]|String[][]} data Either as an array of objects or array of strings 63 | * @param {Object} [options={}] Options that will override the default ones (above) 64 | */ 65 | API.autoTable = function (columns, data, options) { 66 | options = options || {}; 67 | columns = columns || []; 68 | doc = this; 69 | 70 | var userFontSize = doc.internal.getFontSize(); 71 | 72 | initData({columns: columns, data: data}); 73 | initOptions(options); 74 | 75 | cellPos = { 76 | x: settings.margins.left, 77 | y: settings.startY === false ? settings.margins.top : settings.startY 78 | }; 79 | 80 | var tableHeight = settings.margins.bottom + settings.margins.top + settings.lineHeight * (data.length + 1) + 5 + settings.startY; 81 | if (settings.startY !== false && settings.avoidPageSplit && tableHeight > doc.internal.pageSize.height) { 82 | pageCount++; 83 | doc.addPage(); 84 | cellPos.y = settings.margins.top; 85 | } 86 | 87 | settings.renderHeader(doc, pageCount, settings); 88 | var columnWidths = calculateColumnWidths(data, columns); 89 | printHeader(columns, columnWidths); 90 | printRows(columns, data, columnWidths); 91 | settings.renderFooter(doc, cellPos, pageCount, settings); 92 | 93 | doc.setFontSize(userFontSize); 94 | 95 | return this; 96 | }; 97 | 98 | /** 99 | * Returns the Y position of the last drawn cell 100 | * @returns int 101 | */ 102 | API.autoTableEndPosY = function () { 103 | // If cellPos is not set, autoTable() has probably not been called 104 | return cellPos ? cellPos.y : false; 105 | }; 106 | 107 | /** 108 | * @deprecated Use autoTableEndPosY() 109 | */ 110 | API.autoTableEndPos = function () { 111 | return cellPos; 112 | }; 113 | 114 | /** 115 | * Parses an html table. To draw a table, use it like this: 116 | * `doc.autoTable(false, doc.autoTableHtmlToJson(tableDomElem))` 117 | * 118 | * @param table Html table element 119 | * @param indexBased Boolean flag if result should be returned as seperate cols and data 120 | * @returns []|{} Array of objects with object keys as headers or based on indexes if indexBased is set to true 121 | */ 122 | API.autoTableHtmlToJson = function (table, indexBased) { 123 | var data = [], headers = {}, header = table.rows[0], i, tableRow, rowData, j; 124 | if (indexBased) { 125 | headers = []; 126 | for (i = 0; i < header.cells.length; i++) { 127 | headers.push(header.cells[i] ? header.cells[i].textContent : ''); 128 | } 129 | 130 | for (i = 1; i < table.rows.length; i++) { 131 | tableRow = table.rows[i]; 132 | rowData = []; 133 | for (j = 0; j < header.cells.length; j++) { 134 | rowData.push(tableRow.cells[j] ? tableRow.cells[j].textContent : ''); 135 | } 136 | data.push(rowData); 137 | } 138 | return {columns: headers, data: data}; 139 | } else { 140 | for (i = 0; i < header.cells.length; i++) { 141 | headers[i] = header.cells[i] ? header.cells[i].textContent : ''; 142 | } 143 | 144 | for (i = 1; i < table.rows.length; i++) { 145 | tableRow = table.rows[i]; 146 | rowData = {}; 147 | for (j = 0; j < header.cells.length; j++) { 148 | rowData[headers[j]] = tableRow.cells[j] ? tableRow.cells[j].textContent : ''; 149 | } 150 | data.push(rowData); 151 | } 152 | 153 | return data; 154 | } 155 | }; 156 | 157 | /** 158 | * Basically the same as getLineHeight() in 1.0+ versions of jsPDF, however 159 | * added here for backwards compatibility with version 0.9 160 | * 161 | * Export it to make it available in drawCell and drawHeaderCell 162 | */ 163 | API.autoTableTextHeight = function() { 164 | // The value 1.15 comes from from the jsPDF source code and looks about right 165 | return doc.internal.getFontSize() * 1.15; 166 | }; 167 | 168 | /** 169 | * Transform all to the object initialization form 170 | * @param params 171 | */ 172 | function initData(params) { 173 | 174 | // Object only initial 175 | if (!params.columns || params.columns.length === 0) { 176 | var keys = Object.keys(params.data[0]); 177 | Array.prototype.push.apply(params.columns, keys); 178 | params.columns.forEach(function (title, i) { 179 | params.columns[i] = {title: title, key: keys[i]}; 180 | }); 181 | } 182 | // Array initialization form 183 | else if (typeof params.columns[0] === 'string') { 184 | params.data.forEach(function (row, i) { 185 | var obj = {}; 186 | for (var j = 0; j < row.length; j++) { 187 | obj[j] = params.data[i][j]; 188 | } 189 | params.data[i] = obj; 190 | }); 191 | params.columns.forEach(function (title, i) { 192 | params.columns[i] = {title: title, key: i}; 193 | }); 194 | } else { 195 | // Use options as is 196 | } 197 | } 198 | 199 | function initOptions(raw) { 200 | settings = defaultOptions(); 201 | Object.keys(raw).forEach(function (key) { 202 | settings[key] = raw[key]; 203 | }); 204 | doc.setFontSize(settings.fontSize); 205 | 206 | // Backwards compatibility 207 | if(settings.margins.horizontal !== undefined) { 208 | settings.margins.left = settings.margins.horizontal; 209 | settings.margins.right = settings.margins.horizontal; 210 | } else { 211 | settings.margins.horizontal = settings.margins.left; 212 | } 213 | } 214 | 215 | function calculateColumnWidths(rows, columns) { 216 | var widths = {}; 217 | 218 | // Optimal widths 219 | var optimalTableWidth = 0; 220 | columns.forEach(function (header) { 221 | var widest = getStringWidth(header.title || '', true); 222 | if(typeof header.width == "number") { 223 | widest = header.width; 224 | } else { 225 | rows.forEach(function (row) { 226 | if (!header.hasOwnProperty('key')) 227 | throw new Error("The key attribute is required in every header"); 228 | var w = getStringWidth(stringify(row, header.key)); 229 | if (w > widest) { 230 | widest = w; 231 | } 232 | }); 233 | } 234 | widths[header.key] = widest; 235 | optimalTableWidth += widest; 236 | }); 237 | 238 | var paddingAndMargin = settings.padding * 2 * columns.length + settings.margins.left + settings.margins.right; 239 | var spaceDiff = doc.internal.pageSize.width - optimalTableWidth - paddingAndMargin; 240 | 241 | var keys = Object.keys(widths); 242 | if (spaceDiff < 0) { 243 | // Shrink columns 244 | var shrinkableColumns = []; 245 | var shrinkableColumnWidths = 0; 246 | if (settings.overflowColumns === false) { 247 | keys.forEach(function (key) { 248 | if (widths[key] > MIN_COLUMN_WIDTH) { 249 | shrinkableColumns.push(key); 250 | shrinkableColumnWidths += widths[key]; 251 | } 252 | }); 253 | } else { 254 | shrinkableColumns = settings.overflowColumns; 255 | shrinkableColumns.forEach(function (col) { 256 | shrinkableColumnWidths += widths[col]; 257 | }); 258 | } 259 | 260 | shrinkableColumns.forEach(function (key) { 261 | widths[key] += spaceDiff * (widths[key] / shrinkableColumnWidths); 262 | }); 263 | } else if (spaceDiff > 0 && settings.extendWidth) { 264 | // Fill page horizontally 265 | keys.forEach(function (key) { 266 | widths[key] += spaceDiff / keys.length; 267 | }); 268 | } 269 | 270 | return widths; 271 | } 272 | 273 | function printHeader(headers, columnWidths) { 274 | if (!headers) return; 275 | 276 | // First calculate the height of the row 277 | // (to do that the maxium amount of rows first need to be found) 278 | var maxRows = 1; 279 | if (settings.overflow === 'linebreak') { 280 | // Font style must be the same as in function renderHeaderCell() 281 | doc.setFontStyle('bold'); 282 | 283 | headers.forEach(function (header) { 284 | if (isOverflowColumn(header)) { 285 | var value = header.title || ''; 286 | var arr = doc.splitTextToSize(value, columnWidths[header.key]); 287 | if (arr.length > maxRows) { 288 | maxRows = arr.length; 289 | } 290 | } 291 | }); 292 | } 293 | var rowHeight = settings.lineHeight + (maxRows - 1) * API.autoTableTextHeight() + 5; 294 | 295 | // Avoid isolated table headers when drawing multiple tables. Add a new page 296 | // if cellpos would be at the end of page after drawing the header row 297 | var newPage = (cellPos.y + settings.margins.bottom + rowHeight * 2) >= doc.internal.pageSize.height; 298 | if (newPage) { 299 | settings.renderFooter(doc, cellPos, pageCount, settings); 300 | doc.addPage(); 301 | cellPos = {x: settings.margins.left, y: settings.margins.top}; 302 | pageCount++; 303 | settings.renderHeader(doc, pageCount, settings); 304 | } 305 | 306 | headers.forEach(function (header) { 307 | var width = columnWidths[header.key] + settings.padding * 2; 308 | var value = header.title || ''; 309 | if (settings.overflow === 'linebreak') { 310 | if (isOverflowColumn(header)) { 311 | value = doc.splitTextToSize(value, columnWidths[header.key]); 312 | } 313 | } else if (settings.overflow === 'ellipsize') { 314 | value = ellipsize(columnWidths[header.key], value); 315 | } 316 | settings.renderHeaderCell(cellPos.x, cellPos.y, width, rowHeight, header.key, value, settings); 317 | cellPos.x += width; 318 | }); 319 | doc.setTextColor(70, 70, 70); 320 | doc.setFontStyle('normal'); 321 | 322 | cellPos.y += rowHeight; 323 | cellPos.x = settings.margins.left; 324 | } 325 | 326 | function printRows(headers, rows, columnWidths) { 327 | for (var i = 0; i < rows.length; i++) { 328 | var row = rows[i]; 329 | 330 | // First calculate the height of the row 331 | // (to do that the maxium amount of rows first need to be found) 332 | var maxRows = 1; 333 | if (settings.overflow === 'linebreak') { 334 | headers.forEach(function (header) { 335 | if (isOverflowColumn(header)) { 336 | var value = stringify(row, header.key); 337 | var arr = doc.splitTextToSize(value, columnWidths[header.key]); 338 | if (arr.length > maxRows) { 339 | maxRows = arr.length; 340 | } 341 | } 342 | }); 343 | } 344 | var rowHeight = settings.lineHeight + (maxRows - 1) * API.autoTableTextHeight(); 345 | 346 | 347 | // Render the cell 348 | headers.forEach(function (header) { 349 | var value = stringify(row, header.key); 350 | if (settings.overflow === 'linebreak') { 351 | if (isOverflowColumn(header)) { 352 | value = doc.splitTextToSize(value, columnWidths[header.key]); 353 | } 354 | } else if (settings.overflow === 'ellipsize') { 355 | value = ellipsize(columnWidths[header.key], value); 356 | } 357 | var width = columnWidths[header.key] + settings.padding * 2; 358 | settings.renderCell(cellPos.x, cellPos.y, width, rowHeight, header.key, value, i, settings); 359 | cellPos.x = cellPos.x + columnWidths[header.key] + settings.padding * 2; 360 | }); 361 | 362 | // Add a new page if cellpos is at the end of page 363 | var newPage = (cellPos.y + settings.margins.bottom + rowHeight * 2) >= doc.internal.pageSize.height; 364 | if (newPage) { 365 | if (i+1 < rows.length) { 366 | settings.renderFooter(doc, cellPos, pageCount, settings); 367 | doc.addPage(); 368 | cellPos = {x: settings.margins.left, y: settings.margins.top}; 369 | pageCount++; 370 | settings.renderHeader(doc, pageCount, settings); 371 | printHeader(headers, columnWidths); 372 | } 373 | } else { 374 | cellPos.y += rowHeight; 375 | cellPos.x = settings.margins.left; 376 | } 377 | } 378 | } 379 | 380 | function isOverflowColumn(header) { 381 | return settings.overflowColumns === false || settings.overflowColumns.indexOf(header.key) !== -1; 382 | } 383 | 384 | /** 385 | * Ellipsize the text to fit in the width 386 | * @param width 387 | * @param text 388 | */ 389 | function ellipsize(width, text) { 390 | if (width >= getStringWidth(text)) { 391 | return text; 392 | } 393 | while (width < getStringWidth(text + "...")) { 394 | if (text.length < 2) { 395 | break; 396 | } 397 | text = text.substring(0, text.length - 1); 398 | } 399 | text += "..."; 400 | return text; 401 | } 402 | 403 | function stringify(row, key) { 404 | return row.hasOwnProperty(key) ? '' + row[key] : ''; 405 | } 406 | 407 | function getStringWidth(txt, isBold) { 408 | if(isBold) { 409 | doc.setFontStyle('bold'); 410 | } 411 | var strWidth = doc.getStringUnitWidth(txt) * doc.internal.getFontSize(); 412 | if(isBold) { 413 | doc.setFontStyle('normal'); 414 | } 415 | return strWidth; 416 | } 417 | 418 | })(jsPDF.API); 419 | -------------------------------------------------------------------------------- /assets/vendor/tableExport/libs/jsPDF/MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2014 James Hall, https://github.com/MrRio/jsPDF 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /assets/vendor/tableExport/tableExport.js: -------------------------------------------------------------------------------- 1 | /*The MIT License (MIT) 2 | 3 | Original work Copyright (c) 2014 https://github.com/kayalshri/ 4 | Modified work Copyright (c) 2015 https://github.com/hhurz/ 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE.*/ 23 | 24 | (function ($) { 25 | $.fn.extend({ 26 | tableExport: function (options) { 27 | var defaults = { 28 | csvSeparator: ',', 29 | csvEnclosure: '"', 30 | consoleLog: false, 31 | displayTableName: false, 32 | escape: false, 33 | excelstyles: ['border-bottom', 'border-top', 'border-left', 'border-right'], 34 | fileName: 'tableExport', 35 | htmlContent: false, 36 | ignoreColumn: [], 37 | jspdf: {orientation: 'p', 38 | unit: 'pt', 39 | format: 'a4', 40 | margins: {left: 20, right: 10, top: 10, bottom: 10}, 41 | autotable: {padding: 2, 42 | lineHeight: 12, 43 | fontSize: 8, 44 | tableExport: {onAfterAutotable: null, 45 | onBeforeAutotable: null, 46 | onTable: null 47 | } 48 | } 49 | }, 50 | onCellData: null, 51 | outputMode: 'file', // file|string|base64 52 | tbodySelector: 'tr', 53 | theadSelector: 'tr', 54 | tableName: 'myTableName', 55 | type: 'csv', 56 | worksheetName: 'xlsWorksheetName' 57 | }; 58 | 59 | var el = this; 60 | var DownloadEvt = null; 61 | var rowspans = []; 62 | 63 | $.extend(true, defaults, options); 64 | 65 | if (defaults.type == 'csv' || defaults.type == 'txt') { 66 | 67 | // Header 68 | var tdData = ""; 69 | var rowIndex = 0; 70 | $(el).find('thead').first().find(defaults.theadSelector).each(function () { 71 | tdData += "\n"; 72 | ForEachVisibleCell(this, 'th,td', rowIndex, 73 | function (cell, row, col) { 74 | tdData += csvString(cell, row, col) + defaults.csvSeparator; 75 | }); 76 | rowIndex++; 77 | tdData = $.trim(tdData); 78 | tdData = $.trim(tdData).substring(0, tdData.length - 1); 79 | }); 80 | 81 | // Row vs Column 82 | $(el).find('tbody').first().find(defaults.tbodySelector).each(function () { 83 | trData = ""; 84 | ForEachVisibleCell(this, 'td', rowIndex, 85 | function (cell, row, col) { 86 | trData += csvString(cell, row, col) + defaults.csvSeparator; 87 | }); 88 | if (trData.length > defaults.csvSeparator.length) 89 | tdData += "\n" + trData; 90 | rowIndex++; 91 | //tdData = $.trim(tdData); 92 | tdData = $.trim(tdData).substring(0, tdData.length - 1); 93 | }); 94 | 95 | tdData += "\n"; 96 | 97 | //output 98 | if (defaults.consoleLog === true) 99 | console.log(tdData); 100 | 101 | if (defaults.outputMode === 'string') 102 | return tdData; 103 | 104 | if (defaults.outputMode === 'base64') 105 | return base64encode(tdData); 106 | 107 | try { 108 | var blob = new Blob([(defaults.type == 'csv' ? '\ufeff' : '') + tdData], {type: "text/" + (defaults.type == 'csv' ? 'csv' : 'plain') + ";charset=utf-8"}); 109 | saveAs(blob, defaults.fileName + '.' + defaults.type); 110 | } 111 | catch (e) { 112 | downloadFile(defaults.fileName + '.' + defaults.type, 113 | 'data:text/' + (defaults.type == 'csv' ? 'csv' : 'plain') + ';charset=utf-8,' + (defaults.type == 'csv' ? '\ufeff' : '') + 114 | encodeURIComponent(tdData)); 115 | } 116 | 117 | } else if (defaults.type == 'sql') { 118 | 119 | // Header 120 | var rowIndex = 0; 121 | var tdData = "INSERT INTO `" + defaults.tableName + "` ("; 122 | $(el).find('thead').first().find(defaults.theadSelector).each(function () { 123 | 124 | ForEachVisibleCell(this, 'th,td', rowIndex, 125 | function (cell, row, col) { 126 | tdData += "'" + parseString(cell, row, col) + "',"; 127 | }); 128 | rowIndex++; 129 | tdData = $.trim(tdData); 130 | tdData = $.trim(tdData).substring(0, tdData.length - 1); 131 | }); 132 | tdData += ") VALUES "; 133 | // Row vs Column 134 | $(el).find('tbody').first().find(defaults.tbodySelector).each(function () { 135 | trData = ""; 136 | ForEachVisibleCell(this, 'td', rowIndex, 137 | function (cell, row, col) { 138 | trData += "'" + parseString(cell, row, col) + "',"; 139 | }); 140 | if (trData.length > 3) { 141 | tdData += "(" + trData; 142 | tdData = $.trim(tdData).substring(0, tdData.length - 1); 143 | tdData += "),"; 144 | } 145 | rowIndex++; 146 | }); 147 | 148 | tdData = $.trim(tdData).substring(0, tdData.length - 1); 149 | tdData += ";"; 150 | 151 | //output 152 | if (defaults.consoleLog === true) 153 | console.log(tdData); 154 | 155 | if (defaults.outputMode == 'string') 156 | return tdData; 157 | 158 | if (defaults.outputMode == 'base64') 159 | return base64encode(tdData); 160 | 161 | try { 162 | var blob = new Blob([tdData], {type: "text/plain;charset=utf-8"}); 163 | saveAs(blob, defaults.fileName + '.sql'); 164 | } 165 | catch (e) { 166 | downloadFile(defaults.fileName + '.sql', 'data:application/sql;charset=utf-8,' + encodeURIComponent(tdData)); 167 | } 168 | 169 | } else if (defaults.type == 'json') { 170 | 171 | var jsonHeaderArray = []; 172 | $(el).find('thead').first().find(defaults.theadSelector).each(function () { 173 | var jsonArrayTd = []; 174 | 175 | ForEachVisibleCell(this, 'th,td', rowIndex, 176 | function (cell, row, col) { 177 | jsonArrayTd.push(parseString(cell, row, col)); 178 | }); 179 | jsonHeaderArray.push(jsonArrayTd); 180 | }); 181 | 182 | var jsonArray = []; 183 | $(el).find('tbody').first().find(defaults.tbodySelector).each(function () { 184 | var jsonArrayTd = []; 185 | 186 | ForEachVisibleCell(this, 'td', rowIndex, 187 | function (cell, row, col) { 188 | jsonArrayTd.push(parseString(cell, row, col)); 189 | }); 190 | 191 | if (jsonArrayTd.length > 0 && (jsonArrayTd.length != 1 || jsonArrayTd[0] != "")) 192 | jsonArray.push(jsonArrayTd); 193 | 194 | rowIndex++; 195 | }); 196 | 197 | var jsonExportArray = []; 198 | jsonExportArray.push({header: jsonHeaderArray, data: jsonArray}); 199 | 200 | var sdata = JSON.stringify(jsonExportArray); 201 | 202 | if (defaults.consoleLog === true) 203 | console.log(sdata); 204 | 205 | if (defaults.outputMode == 'string') 206 | return sdata; 207 | 208 | var base64data = base64encode(sdata); 209 | 210 | if (defaults.outputMode == 'base64') 211 | return base64data; 212 | 213 | try { 214 | var blob = new Blob([sdata], {type: "application/json;charset=utf-8"}); 215 | saveAs(blob, defaults.fileName + '.json'); 216 | } 217 | catch (e) { 218 | downloadFile(defaults.fileName + '.json', 'data:application/json;charset=utf-8;base64,' + base64data); 219 | } 220 | 221 | } else if (defaults.type === 'xml') { 222 | 223 | var rowIndex = 0; 224 | var xml = ''; 225 | xml += ''; 226 | 227 | // Header 228 | $(el).find('thead').first().find(defaults.theadSelector).each(function () { 229 | 230 | ForEachVisibleCell(this, 'th,td', rowIndex, 231 | function (cell, row, col) { 232 | xml += "" + parseString(cell, row, col) + ""; 233 | }); 234 | rowIndex++; 235 | }); 236 | xml += ''; 237 | 238 | // Row Vs Column 239 | var rowCount = 1; 240 | $(el).find('tbody').first().find(defaults.tbodySelector).each(function () { 241 | var colCount = 1; 242 | var rxml = ""; 243 | ForEachVisibleCell(this, 'td', rowIndex, 244 | function (cell, row, col) { 245 | rxml += "" + parseString(cell, row, col) + ""; 246 | colCount++; 247 | }); 248 | if (rxml != "") { 249 | xml += '' + rxml + ''; 250 | rowCount++; 251 | } 252 | 253 | rowIndex++; 254 | }); 255 | xml += ''; 256 | 257 | //output 258 | if (defaults.consoleLog === true) 259 | console.log(xml); 260 | 261 | if (defaults.outputMode == 'string') 262 | return xml; 263 | 264 | var base64data = base64encode(xml); 265 | 266 | if (defaults.outputMode == 'base64') 267 | return base64data; 268 | 269 | try { 270 | var blob = new Blob([xml], {type: "application/xml;charset=utf-8"}); 271 | saveAs(blob, defaults.fileName + '.xml'); 272 | } 273 | catch (e) { 274 | downloadFile(defaults.fileName + '.xml', 'data:application/xml;charset=utf-8;base64,' + base64data); 275 | } 276 | 277 | } else if (defaults.type == 'excel' || defaults.type == 'doc') { 278 | //console.log($(this).html()); 279 | 280 | var rowIndex = 0; 281 | var excel = "
...
"; 282 | // Header 283 | $(el).find('thead').first().find(defaults.theadSelector).each(function () { 284 | excel += ""; 285 | ForEachVisibleCell(this, 'th,td', rowIndex, 286 | function (cell, row, col) { 287 | if (cell != null) { 288 | excel += ""; 295 | } 296 | }); 297 | rowIndex++; 298 | excel += ''; 299 | }); 300 | 301 | // Row Vs Column 302 | var rowCount = 1; 303 | $(el).find('tbody').first().find(defaults.tbodySelector).each(function () { 304 | excel += ""; 305 | ForEachVisibleCell(this, 'td', rowIndex, 306 | function (cell, row, col) { 307 | if (cell != null) { 308 | excel += "'; 324 | }); 325 | 326 | if (defaults.displayTableName) 327 | excel += ""; 328 | 329 | excel += '
" + parseString(cell, row, col) + "
"; 319 | } 320 | }); 321 | rowCount++; 322 | rowIndex++; 323 | excel += '
" + parseString($('

' + defaults.tableName + '

')) + "
'; 330 | 331 | if (defaults.consoleLog === true) 332 | console.log(excel); 333 | 334 | var excelFile = ""; 335 | excelFile += ''; 336 | excelFile += ''; 339 | excelFile += ""; 340 | if (defaults.type === 'excel') { 341 | excelFile += ""; 357 | } 358 | excelFile += ""; 359 | excelFile += ""; 360 | excelFile += excel; 361 | excelFile += ""; 362 | excelFile += ""; 363 | 364 | if (defaults.outputMode == 'string') 365 | return excelFile; 366 | 367 | var base64data = base64encode(excelFile); 368 | 369 | if (defaults.outputMode === 'base64') 370 | return base64data; 371 | 372 | var extension = (defaults.type === 'excel') ? 'xls' : 'doc'; 373 | try { 374 | var blob = new Blob([excelFile], {type: 'application/vnd.ms-' + defaults.type}); 375 | saveAs(blob, defaults.fileName + '.' + extension); 376 | } 377 | catch (e) { 378 | downloadFile(defaults.fileName + '.' + extension, 'data:application/vnd.ms-' + defaults.type + ';base64,' + base64data); 379 | } 380 | 381 | } else if (defaults.type == 'png') { 382 | html2canvas($(el), { 383 | onrendered: function (canvas) { 384 | 385 | var image = canvas.toDataURL(); 386 | image = image.substring(22); // remove data stuff 387 | 388 | var byteString = atob(image); 389 | var buffer = new ArrayBuffer(byteString.length); 390 | var intArray = new Uint8Array(buffer); 391 | 392 | for (var i = 0; i < byteString.length; i++) 393 | intArray[i] = byteString.charCodeAt(i); 394 | 395 | try { 396 | var blob = new Blob([buffer], {type: "image/png"}); 397 | saveAs(blob, defaults.fileName + '.png'); 398 | } 399 | catch (e) { 400 | downloadFile(defaults.fileName + '.png', 'data:image/png;base64,' + image); 401 | } 402 | } 403 | }); 404 | 405 | } else if (defaults.type == 'pdf') { 406 | if (defaults.jspdf.autotable === false) { 407 | var addHtmlOptions = { 408 | dim: { 409 | w: getPropertyUnitValue($(el).first().get(0), 'width', 'mm'), 410 | h: getPropertyUnitValue($(el).first().get(0), 'height', 'mm') 411 | }, 412 | pagesplit: false 413 | }; 414 | 415 | var doc = new jsPDF(defaults.jspdf.orientation, defaults.jspdf.unit, defaults.jspdf.format); 416 | doc.addHTML($(el).first(), 417 | defaults.jspdf.margins.left, 418 | defaults.jspdf.margins.top, 419 | addHtmlOptions, 420 | function () { 421 | jsPdfOutput(doc); 422 | }); 423 | //delete doc; 424 | } 425 | else { 426 | // pdf output using jsPDF AutoTable plugin 427 | // https://github.com/someatoms/jsPDF-AutoTable 428 | 429 | var teOptions = defaults.jspdf.autotable.tableExport; 430 | 431 | // When setting jspdf.format to 'bestfit' tableExport tries to choose 432 | // the minimum required paper format and orientation in which the table 433 | // (or tables in multitable mode) completely fit without column adjustment 434 | if (typeof defaults.jspdf.format === 'string' && defaults.jspdf.format.toLowerCase() === 'bestfit') { 435 | var pageFormats = { 436 | 'a0': [2383.94, 3370.39], 'a1': [1683.78, 2383.94], 437 | 'a2': [1190.55, 1683.78], 'a3': [841.89, 1190.55], 438 | 'a4': [595.28, 841.89] 439 | }; 440 | var rk = '', ro = ''; 441 | var mw = 0; 442 | 443 | $(el).filter(':visible').each(function () { 444 | if ($(this).css('display') != 'none') { 445 | var w = getPropertyUnitValue($(this).get(0), 'width', 'pt'); 446 | 447 | if (w > mw) { 448 | if (w > pageFormats['a0'][0]) { 449 | rk = 'a0'; 450 | ro = 'l'; 451 | } 452 | for (var key in pageFormats) { 453 | if (pageFormats.hasOwnProperty(key)) { 454 | if (pageFormats[key][1] > w) { 455 | rk = key; 456 | ro = 'l'; 457 | if (pageFormats[key][0] > w) 458 | ro = 'p'; 459 | } 460 | } 461 | } 462 | mw = w; 463 | } 464 | } 465 | }); 466 | defaults.jspdf.format = (rk == '' ? 'a4' : rk); 467 | defaults.jspdf.orientation = (ro == '' ? 'w' : ro); 468 | } 469 | 470 | // The jsPDF doc object is stored in defaults.jspdf.autotable.tableExport, 471 | // thus it can be accessed from any callback function from below 472 | teOptions.doc = new jsPDF(defaults.jspdf.orientation, 473 | defaults.jspdf.unit, 474 | defaults.jspdf.format); 475 | 476 | $(el).filter(':visible').each(function () { 477 | if ($(this).css('display') != 'none') { 478 | var colKey; 479 | var rowIndex = 0; 480 | var atOptions = {}; 481 | 482 | teOptions.columns = []; 483 | teOptions.rows = []; 484 | teOptions.rowoptions = {}; 485 | 486 | // onTable: optional callback function for every matching table that can be used 487 | // to modify the tableExport options or to skip the output of a particular table 488 | // when the table selector targets multiple tables 489 | if (typeof teOptions.onTable === 'function') 490 | if (teOptions.onTable($(this), defaults) === false) 491 | return true; // continue to next iteration step (table) 492 | 493 | // each table works with an own copy of AutoTable options 494 | Object.keys(defaults.jspdf.autotable).forEach(function (key) { 495 | atOptions[key] = defaults.jspdf.autotable[key]; 496 | }); 497 | atOptions.margins = {}; 498 | $.extend(true, atOptions.margins, defaults.jspdf.margins); 499 | 500 | if (typeof atOptions.renderCell !== 'function') { 501 | 502 | // draw cell text with original alignment 503 | atOptions.renderCell = function (x, y, width, height, key, value, row, settings) { 504 | var doc = settings.tableExport.doc; 505 | var xoffset = 0; 506 | 507 | doc.setFillColor(row % 2 === 0 ? 245 : 255); 508 | doc.setTextColor(50); 509 | doc.rect(x, y, width, height, 'F'); 510 | y += settings.lineHeight / 2 + doc.autoTableTextHeight() / 2 - 2.5; 511 | 512 | if (typeof settings.tableExport.columns [key] != 'undefined') { 513 | var col = settings.tableExport.columns [key]; 514 | var alignment = col.style.align; 515 | var rowopt = settings.tableExport.rowoptions [(row+1) + ":" + key]; 516 | 517 | if (rowopt !== undefined) 518 | alignment = rowopt.style.align; 519 | 520 | if (alignment == 'right') 521 | xoffset = width - doc.getStringUnitWidth(('' + value)) * doc.internal.getFontSize() - settings.padding; 522 | else if (alignment == 'center') 523 | xoffset = (width - doc.getStringUnitWidth(('' + value)) * doc.internal.getFontSize()) / 2; 524 | } 525 | 526 | if (xoffset < settings.padding) 527 | xoffset = settings.padding; 528 | 529 | doc.text(value, x + xoffset, y); 530 | } 531 | } 532 | 533 | // collect header and data rows 534 | $(this).find('thead').find(defaults.theadSelector).each(function () { 535 | colKey = 0; 536 | 537 | ForEachVisibleCell(this, 'th,td', rowIndex, 538 | function (cell, row, col) { 539 | var obj = { 540 | title: parseString(cell, row, col), 541 | key: colKey++, 542 | style: { 543 | align: getStyle(cell, 'text-align'), 544 | bcolor: getStyle(cell, 'background-color') 545 | } 546 | }; 547 | teOptions.columns.push(obj); 548 | }); 549 | rowIndex++; 550 | }); 551 | 552 | $(this).find('tbody').find(defaults.tbodySelector).each(function () { 553 | var rowData = []; 554 | colKey = 0; 555 | 556 | ForEachVisibleCell(this, 'td', rowIndex, 557 | function (cell, row, col) { 558 | var obj = { 559 | style: { 560 | align: getStyle(cell, 'text-align'), 561 | bcolor: getStyle(cell, 'background-color') 562 | } 563 | }; 564 | teOptions.rowoptions [rowIndex + ":" + colKey++] = obj; 565 | 566 | rowData.push(parseString(cell, row, col)); 567 | }); 568 | rowIndex++; 569 | teOptions.rows.push(rowData); 570 | }); 571 | 572 | // onBeforeAutotable: optional callback function before calling 573 | // jsPDF AutoTable that can be used to modify the AutoTable options 574 | if (typeof teOptions.onBeforeAutotable === 'function') 575 | teOptions.onBeforeAutotable($(this), teOptions.columns, teOptions.rows, atOptions); 576 | 577 | teOptions.doc.autoTable(teOptions.columns, teOptions.rows, atOptions); 578 | 579 | // onAfterAutotable: optional callback function after returning 580 | // from jsPDF AutoTable that can be used to modify the AutoTable options 581 | if (typeof teOptions.onAfterAutotable === 'function') 582 | teOptions.onAfterAutotable($(this), atOptions); 583 | 584 | // set the start position for the next table (in case there is one) 585 | defaults.jspdf.autotable.startY = teOptions.doc.autoTableEndPosY() + atOptions.margins.top; 586 | } 587 | }); 588 | 589 | jsPdfOutput(teOptions.doc); 590 | 591 | teOptions.columns.length = 0; 592 | teOptions.rows.length = 0; 593 | delete teOptions.doc; 594 | teOptions.doc = null; 595 | } 596 | } 597 | 598 | function ForEachVisibleCell(tableRow, selector, rowIndex, cellcallback) { 599 | 600 | $(tableRow).filter(':visible').find(selector).each(function (colIndex) { 601 | if ($(this).css('display') != 'none' && 602 | $(this).data("tableexport-display") != 'none') { 603 | if (defaults.ignoreColumn.indexOf(colIndex) == -1) { 604 | if (typeof (cellcallback) === "function") { 605 | var cs = 0; // colspan value 606 | 607 | // handle previously detected rowspans 608 | if (typeof rowspans[rowIndex] != 'undefined' && rowspans[rowIndex].length > 0) { 609 | for (c = 0; c <= colIndex; c++) { 610 | if (typeof rowspans[rowIndex][c] != 'undefined') { 611 | cellcallback(null, rowIndex, c); 612 | delete rowspans[rowIndex][c]; 613 | colIndex++; 614 | } 615 | } 616 | } 617 | 618 | // output content of current cell 619 | cellcallback(this, rowIndex, colIndex); 620 | 621 | // handle colspan of current cell 622 | if ($(this).is("[colspan]")) { 623 | cs = $(this).attr('colspan'); 624 | for (c = 0; c < cs - 1; c++) 625 | cellcallback(null, rowIndex, colIndex + c); 626 | } 627 | 628 | // store rowspan for following rows 629 | if ($(this).is("[rowspan]")) { 630 | var rs = parseInt($(this).attr('rowspan')); 631 | 632 | for (r = 1; r < rs; r++) { 633 | if (typeof rowspans[rowIndex + r] == 'undefined') 634 | rowspans[rowIndex + r] = []; 635 | rowspans[rowIndex + r][colIndex] = ""; 636 | 637 | for (c = 1; c < cs; c++) 638 | rowspans[rowIndex + r][colIndex + c] = ""; 639 | } 640 | } 641 | } 642 | } 643 | } 644 | }); 645 | } 646 | 647 | function jsPdfOutput(doc) { 648 | if (defaults.consoleLog === true) 649 | console.log(doc.output()); 650 | 651 | if (defaults.outputMode == 'string') 652 | return doc.output(); 653 | 654 | if (defaults.outputMode == 'base64') 655 | return base64encode(doc.output()); 656 | 657 | try { 658 | var blob = doc.output('blob'); 659 | saveAs(blob, defaults.fileName + '.pdf'); 660 | } 661 | catch (e) { 662 | downloadFile(defaults.fileName + '.pdf', 'data:application/pdf;base64,' + base64encode(doc.output())); 663 | } 664 | } 665 | 666 | function escapeRegExp(string) { 667 | return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); 668 | } 669 | 670 | function replaceAll(string, find, replace) { 671 | return string.replace(new RegExp(escapeRegExp(find), 'g'), replace); 672 | } 673 | 674 | function csvString(cell, rowIndex, colIndex) { 675 | var result = ''; 676 | 677 | if (cell != null) { 678 | var dataString = parseString(cell, rowIndex, colIndex); 679 | 680 | var csvValue = (dataString === null || dataString == '') ? '' : dataString.toString(); 681 | 682 | if (dataString instanceof Date) 683 | result = defaults.csvEnclosure + dataString.toLocaleString() + defaults.csvEnclosure; 684 | else { 685 | result = replaceAll(csvValue, defaults.csvEnclosure, defaults.csvEnclosure + defaults.csvEnclosure); 686 | 687 | if (result.indexOf(defaults.csvSeparator) >= 0 || /[\r\n ]/g.test(result)) 688 | result = defaults.csvEnclosure + result + defaults.csvEnclosure; 689 | } 690 | } 691 | 692 | return result; 693 | } 694 | 695 | function parseString(cell, rowIndex, colIndex) { 696 | var result = ''; 697 | 698 | if (cell != null) { 699 | var $cell = $(cell); 700 | 701 | if (defaults.htmlContent === true) { 702 | result = $cell.html().trim(); 703 | } else { 704 | result = $cell.text().trim().replace(/\u00AD/g, ""); // remove soft hyphens 705 | } 706 | 707 | if (defaults.escape === true) { 708 | result = escape(result); 709 | } 710 | 711 | if (typeof defaults.onCellData === 'function') { 712 | result = defaults.onCellData($cell, rowIndex, colIndex, result); 713 | } 714 | } 715 | 716 | return result; 717 | } 718 | 719 | function hyphenate(a, b, c) { 720 | return b + "-" + c.toLowerCase(); 721 | } 722 | 723 | // get computed style property 724 | function getStyle(target, prop) { 725 | try { 726 | if (window.getComputedStyle) { // gecko and webkit 727 | prop = prop.replace(/([a-z])([A-Z])/, hyphenate); // requires hyphenated, not camel 728 | return window.getComputedStyle(target, null).getPropertyValue(prop); 729 | } 730 | if (target.currentStyle) { // ie 731 | return target.currentStyle[prop]; 732 | } 733 | return target.style[prop]; 734 | } 735 | catch (e) { 736 | } 737 | return ""; 738 | } 739 | 740 | function getPropertyUnitValue(target, prop, unit) { 741 | var baseline = 100; // any number serves 742 | 743 | var value = getStyle(target, prop); // get the computed style value 744 | 745 | var numeric = value.match(/\d+/); // get the numeric component 746 | if (numeric !== null) { 747 | numeric = numeric[0]; // get the string 748 | 749 | var temp = document.createElement("div"); // create temporary element 750 | temp.style.overflow = "hidden"; // in case baseline is set too low 751 | temp.style.visibility = "hidden"; // no need to show it 752 | 753 | target.parentElement.appendChild(temp); // insert it into the parent for em, ex and % 754 | 755 | temp.style.width = baseline + unit; 756 | var factor = baseline / temp.offsetWidth; 757 | 758 | target.parentElement.removeChild(temp); // clean up 759 | 760 | return (numeric * factor); 761 | } 762 | return 0; 763 | } 764 | 765 | function downloadFile(filename, data) { 766 | var DownloadLink = document.createElement('a'); 767 | 768 | if (DownloadLink) { 769 | document.body.appendChild(DownloadLink); 770 | DownloadLink.style = 'display: none'; 771 | DownloadLink.download = filename; 772 | DownloadLink.href = data; 773 | 774 | if (document.createEvent) { 775 | if (DownloadEvt == null) 776 | DownloadEvt = document.createEvent('MouseEvents'); 777 | 778 | DownloadEvt.initEvent('click', true, false); 779 | DownloadLink.dispatchEvent(DownloadEvt); 780 | } 781 | else if (document.createEventObject) 782 | DownloadLink.fireEvent('onclick'); 783 | else if (typeof DownloadLink.onclick == 'function') 784 | DownloadLink.onclick(); 785 | 786 | document.body.removeChild(DownloadLink); 787 | } 788 | } 789 | 790 | function utf8Encode(string) { 791 | string = string.replace(/\x0d\x0a/g, "\x0a"); 792 | var utftext = ""; 793 | for (var n = 0; n < string.length; n++) { 794 | var c = string.charCodeAt(n); 795 | if (c < 128) { 796 | utftext += String.fromCharCode(c); 797 | } 798 | else if ((c > 127) && (c < 2048)) { 799 | utftext += String.fromCharCode((c >> 6) | 192); 800 | utftext += String.fromCharCode((c & 63) | 128); 801 | } 802 | else { 803 | utftext += String.fromCharCode((c >> 12) | 224); 804 | utftext += String.fromCharCode(((c >> 6) & 63) | 128); 805 | utftext += String.fromCharCode((c & 63) | 128); 806 | } 807 | } 808 | return utftext; 809 | } 810 | 811 | function base64encode(input) { 812 | var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 813 | var output = ""; 814 | var chr1, chr2, chr3, enc1, enc2, enc3, enc4; 815 | var i = 0; 816 | input = utf8Encode(input); 817 | while (i < input.length) { 818 | chr1 = input.charCodeAt(i++); 819 | chr2 = input.charCodeAt(i++); 820 | chr3 = input.charCodeAt(i++); 821 | enc1 = chr1 >> 2; 822 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); 823 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); 824 | enc4 = chr3 & 63; 825 | if (isNaN(chr2)) { 826 | enc3 = enc4 = 64; 827 | } else if (isNaN(chr3)) { 828 | enc4 = 64; 829 | } 830 | output = output + 831 | keyStr.charAt(enc1) + keyStr.charAt(enc2) + 832 | keyStr.charAt(enc3) + keyStr.charAt(enc4); 833 | } 834 | return output; 835 | } 836 | 837 | return this; 838 | } 839 | }); 840 | })(jQuery); 841 | -------------------------------------------------------------------------------- /assets/vendor/tableExport/tableExport.min.js: -------------------------------------------------------------------------------- 1 | (function(f){f.fn.extend({tableExport:function(q){function t(l,e,d,h){f(l).filter(":visible").find(e).each(function(l){if("none"!=f(this).css("display")&&"none"!=f(this).data("tableexport-display")&&-1==a.ignoreColumn.indexOf(l)&&"function"===typeof h){var e=0;if("undefined"!=typeof w[d]&&0f?h+=String.fromCharCode(f):(127f?h+=String.fromCharCode(f>>6|192):(h+=String.fromCharCode(f>>12|224),h+=String.fromCharCode(f>>6&63|128)),h+=String.fromCharCode(f&63|128));for(a=h;m>2,d=(d&3)<<4|h>>4,g=(h&15)<<2|b>>6,k=b&63,isNaN(h)?g=k=64:isNaN(b)&&(k=64),e=e+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(f)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(d)+ 7 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(g)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(k);return e}var a={csvSeparator:",",csvEnclosure:'"',consoleLog:!1,displayTableName:!1,escape:!1,excelstyles:["border-bottom","border-top","border-left","border-right"],fileName:"tableExport",htmlContent:!1,ignoreColumn:[],jspdf:{orientation:"p",unit:"pt",format:"a4",margins:{left:20,right:10,top:10,bottom:10},autotable:{padding:2,lineHeight:12,fontSize:8, 8 | tableExport:{onAfterAutotable:null,onBeforeAutotable:null,onTable:null}}},onCellData:null,outputMode:"file",tbodySelector:"tr",theadSelector:"tr",tableName:"myTableName",type:"csv",worksheetName:"xlsWorksheetName"},C=null,w=[];f.extend(!0,a,q);if("csv"==a.type||"txt"==a.type){var g="",n=0;f(this).find("thead").first().find(a.theadSelector).each(function(){g+="\n";t(this,"th,td",n,function(l,e,d){g+=H(l,e,d)+a.csvSeparator});n++;g=f.trim(g);g=f.trim(g).substring(0,g.length-1)});f(this).find("tbody").first().find(a.tbodySelector).each(function(){trData= 9 | "";t(this,"td",n,function(l,e,d){trData+=H(l,e,d)+a.csvSeparator});trData.length>a.csvSeparator.length&&(g+="\n"+trData);n++;g=f.trim(g).substring(0,g.length-1)});g+="\n";!0===a.consoleLog&&console.log(g);if("string"===a.outputMode)return g;if("base64"===a.outputMode)return x(g);try{var v=new Blob([("csv"==a.type?"\ufeff":"")+g],{type:"text/"+("csv"==a.type?"csv":"plain")+";charset=utf-8"});saveAs(v,a.fileName+"."+a.type)}catch(O){y(a.fileName+"."+a.type,"data:text/"+("csv"==a.type?"csv":"plain")+ 10 | ";charset=utf-8,"+("csv"==a.type?"\ufeff":"")+encodeURIComponent(g))}}else if("sql"==a.type){n=0;g="INSERT INTO `"+a.tableName+"` (";f(this).find("thead").first().find(a.theadSelector).each(function(){t(this,"th,td",n,function(a,e,d){g+="'"+u(a,e,d)+"',"});n++;g=f.trim(g);g=f.trim(g).substring(0,g.length-1)});g+=") VALUES ";f(this).find("tbody").first().find(a.tbodySelector).each(function(){trData="";t(this,"td",n,function(a,e,d){trData+="'"+u(a,e,d)+"',"});3',p=p+"";f(this).find("thead").first().find(a.theadSelector).each(function(){t(this,"th,td",n,function(a,e,d){p+=""+u(a,e,d)+""});n++});var p=p+"",D=1;f(this).find("tbody").first().find(a.tbodySelector).each(function(){var a=1,e="";t(this,"td",n,function(d,h,b){e+=""+u(d,h,b)+"";a++});""!=e&&(p+=''+e+"", 14 | D++);n++});p+="";!0===a.consoleLog&&console.log(p);if("string"==a.outputMode)return p;q=x(p);if("base64"==a.outputMode)return q;try{v=new Blob([p],{type:"application/xml;charset=utf-8"}),saveAs(v,a.fileName+".xml")}catch(R){y(a.fileName+".xml","data:application/xml;charset=utf-8;base64,"+q)}}else if("excel"==a.type||"doc"==a.type){var n=0,k="";f(this).find("thead").first().find(a.theadSelector).each(function(){k+="";t(this,"th,td",n,function(b,e,d){if(null!=b){k+=""}});n++;k+=""});D=1;f(this).find("tbody").first().find(a.tbodySelector).each(function(){k+="";t(this,"td",n,function(b,e,d){if(null!=b){k+=""}});D++;n++;k+=""});a.displayTableName&&(k+="");k+="
"+u(b,e,d)+"
"+u(b,e,d)+"
"+u(f("

"+a.tableName+"

"))+"
";!0===a.consoleLog&&console.log(k);b="";b+=''; 17 | b=b+'';b+="";"excel"===a.type&&(b+="\x3c!--[if gte mso 9]>",b+="",b+="",b+="",b+="",b+="",b+=a.worksheetName,b+="",b+="",b+="",b+="",b+="",b+="",b+="",b+="",b+="";b+="";b+=k;b+="";b+="";if("string"==a.outputMode)return b;q=x(b);if("base64"===a.outputMode)return q;var K="excel"===a.type?"xls":"doc";try{v=new Blob([b],{type:"application/vnd.ms-"+a.type}),saveAs(v,a.fileName+"."+K)}catch(S){y(a.fileName+"."+K,"data:application/vnd.ms-"+a.type+";base64,"+q)}}else if("png"==a.type)html2canvas(f(this),{onrendered:function(b){b=b.toDataURL();b=b.substring(22);for(var e=atob(b),d=new ArrayBuffer(e.length),h=new Uint8Array(d),f=0;f< 19 | e.length;f++)h[f]=e.charCodeAt(f);try{var g=new Blob([d],{type:"image/png"});saveAs(g,a.fileName+".png")}catch(k){y(a.fileName+".png","data:image/png;base64,"+b)}}});else if("pdf"==a.type)if(!1===a.jspdf.autotable){var v={dim:{w:F(f(this).first().get(0),"width","mm"),h:F(f(this).first().get(0),"height","mm")},pagesplit:!1},L=new jsPDF(a.jspdf.orientation,a.jspdf.unit,a.jspdf.format);L.addHTML(f(this).first(),a.jspdf.margins.left,a.jspdf.margins.top,v,function(){G(L)})}else{var m=a.jspdf.autotable.tableExport; 20 | if("string"===typeof a.jspdf.format&&"bestfit"===a.jspdf.format.toLowerCase()){var A={a0:[2383.94,3370.39],a1:[1683.78,2383.94],a2:[1190.55,1683.78],a3:[841.89,1190.55],a4:[595.28,841.89]},E="",B="",M=0;f(this).filter(":visible").each(function(){if("none"!=f(this).css("display")){var a=F(f(this).get(0),"width","pt");if(a>M){a>A.a0[0]&&(E="a0",B="l");for(var b in A)A.hasOwnProperty(b)&&A[b][1]>a&&(E=b,B="l",A[b][0]>a&&(B="p"));M=a}}});a.jspdf.format=""==E?"a4":E;a.jspdf.orientation=""==B?"w":B}m.doc= 21 | new jsPDF(a.jspdf.orientation,a.jspdf.unit,a.jspdf.format);f(this).filter(":visible").each(function(){if("none"!=f(this).css("display")){var b,e=0,d={};m.columns=[];m.rows=[];m.rowoptions={};if("function"===typeof m.onTable&&!1===m.onTable(f(this),a))return!0;Object.keys(a.jspdf.autotable).forEach(function(b){d[b]=a.jspdf.autotable[b]});d.margins={};f.extend(!0,d.margins,a.jspdf.margins);"function"!==typeof d.renderCell&&(d.renderCell=function(a,b,e,d,f,g,k,l){var m=l.tableExport.doc,n=0;m.setFillColor(0=== 22 | k%2?245:255);m.setTextColor(50);m.rect(a,b,e,d,"F");b+=l.lineHeight/2+m.autoTableTextHeight()/2-2.5;"undefined"!=typeof l.tableExport.columns[f]&&(d=l.tableExport.columns[f].style.align,f=l.tableExport.rowoptions[k+1+":"+f],void 0!==f&&(d=f.style.align),"right"==d?n=e-m.getStringUnitWidth(""+g)*m.internal.getFontSize()-l.padding:"center"==d&&(n=(e-m.getStringUnitWidth(""+g)*m.internal.getFontSize())/2));n 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | GeoJSON Dashboard 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | 37 | 38 | 66 | 67 |
68 |
69 |
70 | 71 |
72 |
73 |
74 | 77 |
78 | 81 | 86 |
87 |
88 | 89 |
90 |
91 |
92 | 93 | 146 | 147 | 176 | 177 | 195 | 196 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | -------------------------------------------------------------------------------- /screenshots/charts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-open-data/geojson-dashboard/d04f7f1ed476b66af87f05085df2b2b1ba005b9b/screenshots/charts.png -------------------------------------------------------------------------------- /screenshots/filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-open-data/geojson-dashboard/d04f7f1ed476b66af87f05085df2b2b1ba005b9b/screenshots/filter.png -------------------------------------------------------------------------------- /screenshots/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-open-data/geojson-dashboard/d04f7f1ed476b66af87f05085df2b2b1ba005b9b/screenshots/info.png -------------------------------------------------------------------------------- /screenshots/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/project-open-data/geojson-dashboard/d04f7f1ed476b66af87f05085df2b2b1ba005b9b/screenshots/map.png --------------------------------------------------------------------------------