1jQuery(document).ready(function($) { 2 Freemium.init(); 3}); 4function numberWithCommas(x) { 5 return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 6} 7var Freemium = {}; 8 9Freemium.init = function() { 10 11 12 13 if(jQuery('#gform_wrapper_7').length>0) 14 { 15 Freemium.registerForm(); 16 } 17 18 if(jQuery('.fixed-report-gen').length > 0) 19 { 20 Freemium.getCrossingData(); 21 } 22 23 24 if(jQuery('.view-freemium-report-btn').length>0) 25 { 26 jQuery('.view-freemium-report-btn').on('click',function(e){ 27 28 if(!jQuery(this).hasClass('active')) 29 { 30 e.preventDefault(); 31 return false; 32 } 33 }); 34 35 } 36 37 if(jQuery('#crossing-map').length >0) 38 { 39 var data = { 40 action:'freemium_load_crossing_json' 41 }; 42 jQuery.post(freemiumVars.ajax_url,data,function(res){ 43 44 Freemium.crossingData = JSON.parse(res); 45 46 Freemium.DC(); 47 48 jQuery('.reset-table-data-after-click').on('click',function(){ 49 50 Freemium.resetDataTableAfterClick(); 51 52 }); 53 54 jQuery('.freemium-filter-reset').on('click',function(e){ 55 56 Freemium.countySelect.replaceFilter([[]]); 57 Freemium.citySelect.replaceFilter([[]]); 58 59 Freemium.choro.replaceFilter([[]]); 60 dc.redrawAll(); 61 Freemium.fitMap(); 62 e.preventDefault(); 63 Freemium.CheckReset(); 64 return false; 65 }); 66 }); 67 } 68} 69 70Freemium.getCrossingData = function() { 71 72 var data = { 73 action:'freemium_get_crossing_data' 74 } 75 jQuery.post(freemiumVars.ajax_url,data,function(res){ 76 77 78 jQuery('.view-freemium-report-btn').addClass('active'); 79 jQuery('.report-gen-progress').fadeOut('fast'); 80 }); 81 82 83} 84 85Freemium.registerForm = function() { 86 87 jQuery('#input_7_14').prepend('<option value="" selected="selected">All Counties</option>'); 88 jQuery('#input_7_16').prepend('<option value="" selected="selected">All Cities</option>'); 89 90 jQuery('#gform_7').on('change','#input_7_14',function(){ 91 92 var data = { 93 action:'freemium_get_cities', 94 county:jQuery('#input_7_14').val() 95 }; 96 jQuery.post(freemiumVars.ajax_url,data,function(res){ 97 res = '<option value="">All Cities</option>'+res; 98 jQuery('#input_7_16').empty().append(res) 99 }); 100 }); 101 102 103} 104 105 106Freemium.DC = function(){ 107 108 109 var data = []; 110 111 if(Freemium.crossingData) 112 { 113 114 Freemium.crossingData.value.lstCrossing.forEach(function(crossing,i){ 115 116 var crossProductFormatted = numberWithCommas(crossing.crossProduct); 117 data.push({ 118 name:'<span class="crossing-name-label">'+crossing.street + '</span> <span class="crossing-id-label">' + crossing.code + '</span>', 119 id:crossing.code, 120 city:crossing.city.name, 121 county:crossing.city.county.name, 122 crossProduct:crossProductFormatted, 123 aadt:numberWithCommas(crossing.aadt), 124 blockages:crossing.dailyVolume, 125 vehicleImpact:numberWithCommas(crossing.vehImpacted), 126 hoursDelay:numberWithCommas(crossing.vehDelayHour), 127 accidents:crossing.numAccident, 128 fatalities:crossing.numFatality, 129 fraIncidents:crossing.numFraReported, 130 geo:[crossing.latitude,crossing.longitude], 131 }); 132 }); 133 134 135 } 136/* 137 data.push({ 138 name:'test', 139 id:'1234', 140 city:'Chicago', 141 county:'kankalee', 142 crossProduct:1950000, 143 aadt:31600, 144 blockages:4, 145 vehicleImpact:7000, 146 hoursDelay:1600, 147 accidents:0, 148 fatalities:0, 149 fraIncidents:0, 150 geo:[41.833871,-87.8967701], 151 }); 152 data.push({ 153 name:'test2', 154 id:'12345', 155 city:'Casper', 156 county:'Natrona', 157 crossProduct:1950000, 158 aadt:31600, 159 blockages:8, 160 vehicleImpact:7000, 161 hoursDelay:800, 162 accidents:0, 163 fatalities:0, 164 fraIncidents:0, 165 geo:[42.8546679,-106.3655912], 166 }); 167 data.push({ 168 name:'test3', 169 id:'123456', 170 city:'Douglas', 171 county:'Converse', 172 crossProduct:1250000, 173 aadt:32600, 174 blockages:16, 175 vehicleImpact:7000, 176 hoursDelay:400, 177 accidents:0, 178 fatalities:0, 179 fraIncidents:0, 180 geo:[42.7542784,-105.4180932], 181 }); 182 183 184 185*/ 186 187 var xf = crossfilter(data);// primary data 188 189 190 Freemium.xf = xf; 191 192 /////// select fields ////////////// 193 Freemium.countySelect = new dc.SelectMenu('#county-select'), 194 Freemium.citySelect = new dc.SelectMenu('#city-select'); 195 196 var countyDimension = xf.dimension(function(d) { return d.county; }); 197 var cityDimension = xf.dimension(function(d) { return d.city; }); 198 199 Freemium.countySelect 200 .dimension(countyDimension) 201 .group(countyDimension.group()) 202 .controlsUseVisibility(true); 203 204 Freemium.citySelect 205 .dimension(cityDimension) 206 .group(cityDimension.group()) 207 .controlsUseVisibility(true); 208 209 // fly to crossings upon select field change 210 211 212 jQuery('.freemium-flexbox').on('change','#city-select select',function(){ 213 var filtered = Freemium.xf.allFiltered(); 214 //Freemium.choro.map().flyTo(filtered[0].geo); 215 // Freemium.choro.map().setZoom(16); 216 217 Freemium.CheckReset(); 218 Freemium.fitMap(); 219 }); 220 jQuery('.freemium-flexbox').on('change','#county-select select',function(){ 221 var filtered = Freemium.xf.allFiltered(); 222 //Freemium.choro.map().flyTo(filtered[0].geo); 223 // Freemium.choro.map().setZoom(16); 224 Freemium.CheckReset(); 225 Freemium.fitMap(); 226 }); 227 228
229 ////////// DataTable ///////////// 230 231 Freemium.crossingTable = new dc.tableview('#crossing-table'); 232 var fmt = d3.format('02d'); 233 234 var crossingTableDimension = xf.dimension(function(d) {return fmt(+d.name);}); 235 var group = crossingTableDimension.group(); 236 237 Freemium.crossingTable 238 .dimension(crossingTableDimension) 239 .group(group) 240 .columns([ 241 { title: "CROSSING NAME", data: "name" }, 242 { title: "CITY", data: "city" }, 243 { title: "COUNTY", data: "county" }, 244 { title: "CROSS PRODUCT", data: "crossProduct" }, 245 { title: "AADT", data: "aadt" }, 246 { title: "AVG. TRAINS PER DAY", data: "blockages" }, 247 { title: "AVG. NUMBER OF VEHICLES IMPACTED PER DAY", data: "vehicleImpact" }, 248 { title: "AVG. NUMBER OF VEHICLE DELAY PER DAY IN HOURS", data: "hoursDelay" }, 249 { title: "ACCIDENTS (LAST 5 YEARS)", data: "accidents" }, 250 { title: "FATALITIES (LAST 5 YEARS)", data: "fatalities" }, 251 { title: "FRA Blocked Crossing Reports (Since 2021)", data: "fraIncidents" }, 252 ]) 253 .enableColumnReordering(false) 254 .enablePaging(true) 255 //.enablePagingSizeChange(false) 256 //.enableSearch(false) 257 // .enableScrolling(false) 258/* 259 .scrollingOptions({ 260 scrollY: "31rem", 261 scrollX: "31rem", 262 scrollCollapse: false, 263 deferRender: true, 264 }) 265*/ 266 .rowId("id") 267 // .showGroups(true) 268 // .groupBy("Expt") 269 // .responsive(false) 270 // .select(false) 271 // .fixedHeader(false) 272 //.buttons(["pdf", "csv", "excel", "print"]) 273 .sortBy([["crossProduct"]]) 274 .order('asc') 275 .listeners({ 276 rowClicked: function (row, data, index) { 277 278 filterCrossing(`Click on row ${index}!`, data); 279 }, 280 rowDblClicked: function (row, data, index) { 281 282 filterCrossing(`Double click on row ${index}!`, data); 283 }, 284 rowEnter: function (row, data, index) { 285 row.style.backgroundColor = "#eff9ff"; 286 }, 287 rowLeave: function (row, data, index) { 288 row.style.backgroundColor = ""; 289 } 290 }); 291 292 293 294 ////// filter crossing on table row click 295 296 297 filterCrossing = function(event,data){ 298 299 if(Freemium.xf.allFiltered().length < Freemium.xf.all().length) 300 { 301 Freemium.tempData = Freemium.xf.allFiltered(); 302 jQuery('.reset-table-data-after-click').show(); 303 } 304 305 306 Freemium.choro.replaceFilter([[data.geo]]); 307 308 Freemium.countySelect.filter([[data.county]]); 309 Freemium.citySelect.filter([[data.city]]); 310 dc.redrawAll(); 311 312 Freemium.fitMap(); 313 314 315 316 Freemium.CheckReset(); 317 318 319 }; 320 321 Freemium.resetDataTableAfterClick = function(){ 322 323 if(Freemium.tempData) 324 { 325 var tempMap = Freemium.tempData.map((x)=> x.geo); 326 327 Freemium.choro.replaceFilter([tempMap]); 328 dc.redrawAll(); 329 Freemium.fitMap(); 330 jQuery('.reset-table-data-after-click').hide(); 331 332 } 333 Freemium.CheckReset(); 334 } 335 ///////// Map //////////// 336 337 var groupname = "Bubbles"; 338 var crossings = xf.dimension(function(d) { return d.geo; }); 339 crossingsGroup = crossings.group().reduceSum(function(d) { return d.blockages;}); 340 var delayGroup = crossingsGroup 341 var max = 12; 342 343 344 345 346 dataP = []; 347 var pos = {}; 348 var dataByLoc = []; 349 data.forEach(function(d) { 350 351 var points = d.geo; 352 353/* 354 if(Array.isArray(points[0][0])) 355 points = geo.geometry.coordinates.reduce(function(p, v) { 356 return p.concat(v); 357 }, []); 358*/ 359 // var p = [d3.sum(points, p => +p[1])/points.length, d3.sum(points, p => +p[0])/points.length]; 360 361 pos[d.id] = points; 362 d.sum = 0; 363 364 dataByLoc[d.geo] = d; 365 366 367 for(var p in d) 368 if (p && p!="id" && p!="sum") { 369 dataP.push({'id':d.id,'type':p,'hoursDelay':d.hoursDelay,'value':+d[p]}); 370 d.sum+=+d[p]; 371 } 372 if(d.sum > max) 373 max = d.sum; 374 }); 375 376 377 378 var startingPosition = [40.4236726,-96.6671147]; 379 380 if(Freemium.crossingData.value.lstCrossing.length>0) 381 { 382 startingPosition = [Freemium.crossingData.value.lstCrossing[0].latitude, 383 Freemium.crossingData.value.lstCrossing[0].longitude]; 384 } 385 386 387 388 // guess zoom level based on number of crossings, hope to zoom to boun
388ds at some point, this will work for now 389 var defaultMapZoom = 12; 390/* 391 if(xf.allFiltered().length>10) defaultMapZoom = 10; 392 if(xf.allFiltered().length>30) defaultMapZoom = 8; 393 if(xf.allFiltered().length>60) defaultMapZoom = 6; 394 395*/ 396 397 398 399 400 Freemium.choro = dc_leaflet.bubbleChart("#crossing-map") 401 .dimension(crossings) 402 .group(crossingsGroup) 403 .width(100) 404 .height(600) 405 .center(startingPosition) 406 .renderPopup(true) 407 .colors(colorbrewer.Reds[3]) 408 .colorDomain([ 409 d3.min(crossingsGroup.all(), dc.pluck('value')), 410 Freemium.crossingData.value.blockageMetric.average 411 ]) 412 .colorAccessor(function(d,i) { 413 414 return d.value; 415 }) 416 .popup(function(d){ 417 418 return 'crossing ' + dataByLoc[d.key].id; 419 }) 420 .zoom(defaultMapZoom) 421 .valueAccessor(function(d,i){ 422 423 424 // if the data is currently filtered, check to see if the crossing should be showing on the map 425 if(Freemium.xf.allFiltered().length < Freemium.xf.all().length) 426 { 427 var found = Freemium.xf.allFiltered().find(o => o.geo == d.key ); 428 if(!found) return 0; 429 } 430 431 432 if(d.value ==0) return 0; 433 var val = dataByLoc[d.key].hoursDelay * 100; 434 435// console.log(d3.scaleLog().domain([2, 8]).range([2,8])(val)); 436 return val; 437 }) 438 .locationAccessor(d => pos[d.id]) 439 .r(d3.scaleLog().domain([1, 4]).range([2,5])) 440 // .legend(dc_leaflet.legend().position('bottomright').legendTitle("Bubble")); 441 442 // var types = xf.dimension(function(d) { return d.type; }); 443 // var typesGroup = types.group().reduceSum(function(d) { return d.value;}); 444 445 446 ///////////////////////////////////////////////////////////////// 447 Freemium.map = Freemium.choro.map; 448 Freemium.choro.on('filtered',function(e){ 449 Freemium.CheckReset(); 450 }); 451 452 453 dc.renderAll(); 454 455 setTimeout(function(){ 456 Freemium.fitMap(); 457 458 if(typeof mapImageData == 'undefined') 459 { 460 Freemium.getScreenshotOfElement(); 461 } 462 else { 463 jQuery('.freemium-report-card-summary-btn').addClass('active'); 464 jQuery('.freemium-report-card-summary-btn').attr('target','_blank'); 465 jQuery('.freemium-report-card-summary-btn').attr('href',jQuery('.freemium-report-card-summary-btn').data('href')); 466 467 468 } 469 470 471 }, 300); 472 // dc.renderAll(groupname); 473 474 } 475/* 476 477 Freemium.getScreenshotOfElement(jQuery("div#crossing-map").get(0), 0, 0, 1920, 400, function(data) { 478 // in the data variable there is the base64 image 479 // exmaple for displaying the image in an <img> 480 jQuery("img#capture").attr("src", "data:image/png;base64,"+data); 481 }); 482*/ 483 484Freemium.fitMap = function() { 485 486 if(typeof Freemium.choro.layerGroup().getLayers() !='undefined'){ 487 _featureGroup = new L.featureGroup(Freemium.choro.layerGroup().getLayers()); 488 Freemium.choro.map().fitBounds(_featureGroup.getBounds()); 489 } 490 491} 492Freemium.getScreenshotOfElement = function() { 493 494 495 496 497 var pluginOptions = { 498 cropImageByInnerWH: true, // crop blank opacity from image borders 499 hidden: false, // hide screen icon 500 preventDownload: false, // prevent download on button click 501 domtoimageOptions: {}, // see options for dom-to-image 502 position: 'topleft', // position of take screen icon 503 screenName: 'screen', // string or function 504 hideElementsWithSelectors: ['.leaflet-control-container'], // by default hide map controls All els must be child of _map._container 505 mimeType: 'image/png', // used if format == image, 506 caption: null, // string or function, added caption to bottom of screen 507 captionFontSize: 15, 508 captionFont: 'Arial', 509 captionColor: 'black', 510 captionBgColor: 'white', 511 captionOffset: 5, 512 // callback for manually edit map if have warn: "May be map size very big on that zoom level, we have error" 513 // and screenshot not created 514 onPixelDataFail: async function({ node, plugin, error, mapPane, domtoimageOptions }) { 515 // Solutions: 516 // decrease size of map 517 // or decrease zoom level 518 // or remove elements with big distanses 519 // and after that return image in Promise - plugin._getPixelDataOfNormalMap 520 return plugin._getPixelDataOfNormalMap(domtoimageOptions) 521 } 522 } 523 524 var simpleMapScreenshoter = L.simpleMapScreenshoter(pluginOptions).addTo(Freemium.map()) 525 var format = 'canvas' // 'image' - return base64, 'canvas' - return canvas 526 var overridedPluginOptions = { 527 mimeType: 'image/jpeg' 528 } 529 simpleMapScreenshoter.takeScreen(format, overridedPluginOptions).then(canvas => { 530 531 var context = canvas.getContext('2d'); 532 var imageData = context.getImageData(jQuery(window).width()/2-400, 0, 800, 400).data; 533 var outputCanvas = document.createElement('canvas'); 534 var outputContext = outputCanvas.getContext('2d'); 535 outputCanvas.width = 800; 536 outputCanvas.height = 400; 537 538 var idata = outputContext.createImageData(800, 400); 539 idata.data.set(imageData); 540 outputContext.putImageData(idata, 0, 0); 541 var data = outputCanvas.toDataURL().replace("data:image/png;base64,", ""); 542 // jQuery("img.capture").attr("src", "data:image/png;base64,"+data); 543 544 var ajax_data = { 545 action:'freemium_save_map_image', 546 map_image_data:data, 547 }; 548 jQuery.post(freemiumVars.ajax_url,ajax_data,function(res){ 549 550 jQuery('.freemium-report-card-summary-btn').addClass('active'); 551 jQuery('.freemium-report-card-summary-btn').attr('target','_blank'); 552 553 jQuery('.freemium-report-card-summary-btn').attr('href',jQuery('.freemium-report-card-summary-btn').data('href')); 554 }); 555 556 // FileSaver.saveAs(blob, 'screen.png') 557 }).catch(e => { 558 console.error(e); 559 jQuery('.freemium-report-card-summary-btn').addClass('active'); 560 jQuery('.freemium-report-card-summary-btn').attr('target','_blank'); 561 562 jQuery('.freemium-report-card-summary-btn').attr('href',jQuery('.freemium-report-card-summary-btn').data('href')); 563 564 }) 565} 566 567 568Freemium.CheckReset = function(){ 569 570 var filtered = Freemium.xf.allFiltered(); 571 //Freemium.choro.map().flyTo(filtered[0].geo); 572 // Freemium.choro.map().setZoom(16); 573
574 if(filtered.length<Freemium.xf.all().length) 575 { 576 jQuery('.freemium-filter-reset').addClass('active'); 577 } 578 else { 579 jQuery('.freemium-filter-reset').removeClass('active'); 580 } 581}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.