WME DOT Advisories

Overlay DOT Advisories on the WME Map Object

  1. // ==UserScript==
  2. // @name WME DOT Advisories
  3. // @namespace https://greasyfork.org/en/users/668704-phuz
  4. // @require https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js
  5. // @version 1.93
  6. // @description Overlay DOT Advisories on the WME Map Object
  7. // @author phuz
  8. // @include /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor\/?.*$/
  9. // @require http://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js
  10. // @require https://cdnjs.cloudflare.com/ajax/libs/tablesort/5.2.1/tablesort.min.js
  11. // @require https://cdnjs.cloudflare.com/ajax/libs/tablesort/5.2.1/sorts/tablesort.number.min.js
  12. // @require https://cdnjs.cloudflare.com/ajax/libs/tablesort/5.2.1/sorts/tablesort.date.min.js
  13. // @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js
  14. // @grant GM_xmlhttpRequest
  15. // @grant GM_info
  16. // @grant GM_fetch
  17. // @grant GM_addStyle
  18. // @connect 511nj.org
  19. // @connect 511ny.org
  20. // @connect 511pa.com
  21. // @connect 511wi.gov
  22. // @connect arcgis.com
  23. // @connect deldot.gov
  24. // @connect essentialintegrations.com
  25. // @connect fl511.com
  26. // @connect md.gov
  27. // @connect mi.us
  28. // @connect ohgo.com
  29. // @connect rehostjson.phuz.repl.co
  30. // @connect tripcheck.com
  31. // @connect iteris-atis.com
  32. // @connect carsprogram.org
  33. // @connect phoenix.gov
  34. // @connect 511virginia.org
  35. // @connect 72.167.49.86
  36. // @connect 72.167.49.86
  37. // @connect ncdot.gov
  38. /* global OpenLayers */
  39. /* global W */
  40. /* global WazeWrap */
  41. /* global $ */
  42. /* global I18n */
  43. /* global _ */
  44. /* global MutationObserver */
  45. /* global localStorage */
  46.  
  47. // ==/UserScript==
  48.  
  49. let promises = {};
  50. let advisories = {};
  51. let feeds = {};
  52. let endpointsLayer;
  53. let settings, settingID;
  54. var loadedSettings = {}, localsettings = {};
  55. let mapBounds;
  56. let state, stateLength;
  57. const updateMessage = "► Fixed stuff that the last release broke.";
  58. const DEIconC = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo2NTZCOTQ4MEMxM0FFNDExOTJCNzgxMEFBMkM5Q0QzRSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGRjU0MDFBMUJBMEYxMUU1OERGQ0YxMTRGNzU2OUVFMCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGRjU0MDFBMEJBMEYxMUU1OERGQ0YxMTRGNzU2OUVFMCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkYwRjVFQTIwMDlCQUU1MTE4NEU2OTRCNTE0QTVGRkIzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjY1NkI5NDgwQzEzQUU0MTE5MkI3ODEwQUEyQzlDRDNFIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+iRjjNgAABVBJREFUeNqsVwlsVFUUPX+Z+Z1OoaWFSqFaU0hYBSSiCdYQhaRKNdFAUlRcMAFL1ABBESMouEYxwTSxRutWIkbBqKQEwxZoWKKGrcoiAqKsBStLO+1s/8/zvP+nzLTzZzpRX+a00+n999x391GEEOh5xOXTsM7+Amgq0px8ojT++wJxjgi6SsZiUIw8aEPuABTl2se6m6z560Z0rpoNJcdI/ngg8QAxlRhFFBNSIEC0ED8R3xIbiEhCWRjqwBHIW9zMi3gyE9M0+xW3UEovJBZAkIyKhEUvJRxVQNkCxaMNp+JH+fcBYhmxzlGldLtpL8TXDBjEHw3EFEQdT6qDxkAfUgG1ZDQUf6ETltN7YZ7YCfH3GZqpj6MB31F0BbGYOmLOLbInlq7cZLs1FIR243gYdy+FPoqe1rxAOADr1D5o46udvAj8heiPDQhvfovvWwGv7znbG8AcN+Wu2aNoHmnix12knomPwz+/CfqY+x1SntC65xF4ZZJNZj+TNwDeyc/CP2871ME3Mcq2h2YT87Imti4enUXv3GuT3vogfDM/5Q3yEgLBK4juXwtB82zipMpQS0bBX7Meav9yJpadY6/TrGE93Z3iatHW0iey+6OXZT6oxUOQU/1earlZURiVLzo3ZalAmHyTyFil3w3ImfE+OuuqZD35IWJLyTuzuxJam4xwU231lRqIK3MhIjvqxH85HR/cZ+tpW5gXsM4fHpTMk3Jj61hTpSwVtV8x9LHTUuPA7A6ufdpJIJWPR8PQym6BMXVZiqh3wiMwmxshOgJ+83hThXfgiDXurjYjitVyZKx8q8ly6VOcGv/fdyGy/RMnO2TYLL6Ob4O34kkofUu6yWplE1hy+Yi1X4V1cvftqKhZ45pcInTVJzovDXDidL1rjUWPbISSmwu1oAhqPlFYxBDS5mNNqdXh70/ZQrvZiFB7QYbkkhIxJV5TrsRG5RIYUxZ170Yxwfbqd6lL1UHc82mJFU9uWPH6A7YJ7RdSFUU6IIJXaZOW3DIdk9s7oRQMduLe9Rll6UVHty//YvobG3mWet3w/VbLyeGxlkN2d4KRqN/w98sR3vIub5fbs8AgwiHkPrEa+rjpCUecP8gkvGQ7Ryu9eU/GBqKPvKfRfqj1T5hHt8QVHOLE2oTogW/IEeWrsweCLOUIWP8wf9vG/n3KyQfZZEyORZ8vpA+dtCMz8eiqzWqfvq2yG0W2vuPcdP0SdLxdSWNO0HS6OWalgNMJ5uGNCLx5Fw38mo3gDKJ7v4KiK1AKy7aoJSP/yNi51KLyVs/46vrIzvoXzGO7EN70BnKmrYT3zvnJiZJporEiShH8fBZj3OYsE5pe2/NZ1+mklU+sFTvq5yiGURRuXGqXhLeiBtmeYMPDvD3DlOOTiwB9L7aix6ajpllX5Ebxmm2lpiP05VyEeAPb1RmOxfh2rLiNg+MLh5S0xCKpMct5bFtXRzwEVZsAbw4T5zNEDzZyHldBHzYZ6oChHPq5EJ2XETvXDPPQBibWdrJHu0jlWUnscWPItAjImSb9u1NWoVQmQm2I/LDKhqLzUZWJZkWYucIJoYcrmHaN9DCxPJ3y3rJlH/FMQlrnGPTZkCFwTDdY1z65cSQnX8D2FtDxb4kR30Tq3BfCrkmRcqSnmjMpVbNM1AXE1ixlXyJW9yaULbGM94zebsHzIfFqNgpVZH84+bmHAT+n+f/auIvxfxPLw8UZVS7kco9+DCkzK/1xLyc52S3YpZKGXH6NWU+MI+qJp+RMcO8qMae2syGWLVIbPIIj0Uhn8FlCLmTT498Y0t/UjLLZlKd8jflHgAEAjYU+RhKpTDQAAAAASUVORK5CYII=';
  59. const DEIconSchRestriction = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTdDRTI5RjhFOENFNTExQkIwQkQ3QjFGMjA1NkNGMiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo0MzMwRkNCMUJBMDcxMUU1OTE5RjkwMEI5NThDNEVCMCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo0MzMwRkNCMEJBMDcxMUU1OTE5RjkwMEI5NThDNEVCMCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjI4Q0M2MTJGNEVCOUU1MTE4NEU2OTRCNTE0QTVGRkIzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA1N0NFMjlGOEU4Q0U1MTFCQjBCRDdCMUYyMDU2Q0YyIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+YotOJgAABWdJREFUeNqcVwlsFFUY/nY7e7S0tPbQSkstUUu01NBWSzQKIjQaUbAxapAEj5g0KtEYRdEIeETjFYRglEDEIBgleIBnrGgjQY5C01SKFmrTi5ZSethjt7vt7o7fmzfb3ens0fqSL7Mz7/3/995/vX8tqqpCG2oA+LcRCPgAC+KNDCJZ/z0MW0o/rLbYEhYrkJgtn+J1gnh8CNhXBLguAFaTmINYSiwjridyiCR9zgXF2QmLcoK/vyd+I8YM0oLCMRO4pwZwZmqfFMOsfxTweScTP0QLrOV0Ifx8ExAWSdBn/UiD6s3hexnxJL/8SbxDfGYgVr3SqvoIIxbarPIhTX0psZ1YAZ+cQnYJMOs2IItPJZFu4S58LqCHJ+n8FehtFLLXcQN7uLqCqCT6pHpSWSyRiA0jj/iBO52nkeYtAkpepoGXTOwK395CUg/N9wdw9WpugtZt+w6ofR3orgfsuJerrtTd0zWZwBqBNIXYr5EKy9z4GnB3NUmXhkhPchOth4FzJ4Fjz+ma7MAcclUcAeY/zpjRvs4nvg6Lh5jEbxPFmi8XbuFJ18MQ5kNNQP37MtycRMM2oL8+NJ9Ajps/ZAg+GyRfQLwRj7iYHJWaQNFjQOFT5m0dfx5wu4HyvTzdMRltR58xr1vwHi1QDs1VwBqiMAqxRTh/DfVYMZNxVfaWWVlnFdC0X/gPSJ8HZJby5PRMC13R8qV5/U2budYholqh7ifCLRci9vYnM5fv0ExcwGBxZBiViOAJ+lOkxxjzfnxYFhyhpWadjPDwkXYtcMWd8tR+7zL43E4z8cDpAnjcsyAKUP4K8+7/+gg4f0rmgQg6Ty/JB6nULb9dbAZObTLLzamQB/W68zDcfJWZ2N2Vq+0skRUmtcAoPNot00QJKwieHoIp6tMrn9hw3bvASKtRNp3V0GYRoWDByLkcM7Ewg9BhI7Et2Shcu4EVuS9UrVT9xN5+efqgplGavuZFo6w9jRu2Sxm/22EmtqeOaCYRvgz4QoK9LMGnd8qAUsPKTgcD7ewu42bEqc9+QZdUG2MjePHY00bMxDNy26lQhYencHeHBEVA+f1m3xU9DZRuCEZtGJGQWctv+uZH2hmElFcsPiTPbjcTp81thsPRDg8FLhyW3/5hnW87FLmw9taxNLJcBgLGa1Ss7aoFGnfoKVgto1qxNSE5v9VM7MgYReo1P2m7b9rNxcJfL0il6iSIb0c3AlWP0hrj5nmhtfZVEbDM733yPb3oG8aOz0ycwNumdP02+iyAjt9Ziw/IPLQ5IyORSIoypxAZxfLUvU2CxY3SV3ZogRvxdkq6vJ7EuxBQH8Hxl4C7fuEKLg54p9KVhNVDEg+dAX5cLoMvgE1IcBjyzEgsAkLFOn4tx2BHLqru56XGpiIlH9MaffT/wVVMtyHBUEfiN0N5F/126iH5aqaGDxfZTHzFy6X586kRBujvhq28VBcy7zsFaT91rRIZPnlptEagmgKVJP8YrvPAzw/yPuZVN/dhdiC3ss2bLe9frfWhzuEW5jXdcuYTZkS91KrAQx0P8NffkQiUGPvfScEU2mSzZpdOcfETTvpvBiuf4xIZwqKCuXg6r35ZyGZzjFMr+TwYTbkSx3hb9PZu68RK0e4MNIfSKohQdyvMKkgPxIy/KXjuA63TDPYTwQ5T0Z9WQ4MyQCyPRzpVYjE+1bvGwRhrOojbo5pX/X/E0LpONjxEm2nGjwbmwBLihFYeI0H1x/CxGpdc/FtYTIg+p0S/FA6hbON9yCzuiSol9GbdECu41Ml5Hmm06H9n9opbmaddiZzFLmQvmlaNCf13kn0Xb5wjUy2PNm2nKg15GYuMM2taxP8JMAC5wMrd7FP1/wAAAABJRU5ErkJggg==';
  60. const DEIconSchClosure = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAoCAYAAADpE0oSAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIFdpbmRvd3MiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RTYxOTU5RkJGMkQ3MTFFNkI5NERERDM2Qzg4NzcwRUYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RTYxOTU5RkNGMkQ3MTFFNkI5NERERDM2Qzg4NzcwRUYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFNjE5NTlGOUYyRDcxMUU2Qjk0REREMzZDODg3NzBFRiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFNjE5NTlGQUYyRDcxMUU2Qjk0REREMzZDODg3NzBFRiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuSU594AAAfTSURBVHja5Fh7cJTV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';
  61. const Incident = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA/ppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ1dWlkOjVEMjA4OTI0OTNCRkRCMTE5MTRBODU5MEQzMTUwOEM4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjk4MDFDMjUwNzIzRDExRTNBQTczRjkyOTZEQ0IyOTY0IiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjk4MDFDMjRGNzIzRDExRTNBQTczRjkyOTZEQ0IyOTY0IiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIElsbHVzdHJhdG9yIENDIChXaW5kb3dzKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ1dWlkOmFiMzczNzVkLWIwYTYtNDRjNC04OTE4LWU4M2ZiOTRhOGY4NSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpjMjUyYWZlMC1mMjU0LWY5NDMtOGZiZi0wMTc3Mzc1ZWEzYzYiLz4gPGRjOnRpdGxlPiA8cmRmOkFsdD4gPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5JbmNpZGVudHNfb3V0bGluZWQ8L3JkZjpsaT4gPC9yZGY6QWx0PiA8L2RjOnRpdGxlPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pmcc3z4AAASdSURBVHja7FdLaFxVGP7OPfc1M5lMJ5M0Gk0nNdE+sogPLNG2KNaFUksqlkAjSGtcCBJUWgouhErAUOhCwb2uXJQupCtF0I102SrEUsFNkRaxJJ3MTGbu+/j/J2lnKp04HdNkY+AnZ875/u9853/ce65QSmEz/wxs8t//AjZdgDkytL1j5whIaRKgvuERCIH9UDjHpsedRqATJwE8Yimcn5LuVv79deztEQJPU0Nf35AILCZq7lXX3jqds8DGY5574Cmgk6OS4PCoJaamcvSjO9HGY57jtQcqwFPot1V85lhByPHptzBw7jttz9H4eK8hnSQ+4xPmfjhlz5YtbQHprChH6vRrTuXQqddfgP3+HGSuANnVDYw9ix3XL+G3X68UfgkduFJ8L9Y7AvUYL+7MipMndig4eQdKNOqXx07exomdCoxh7LqmIFRwbYHP3t1uYHevgXq9CgRNre/X9ByvMYax7LN+EVA4/XKfMTbRJ3GzYiKs+lCh31gOA4Tlul5jDGPZZ10ERAp7C7aYmX7YgvIl6p4Fv+IjCcJGfZAAvxroNcYwln3Y978KkLVEfXK0z0yPmAbKNYEglAjKAZ06bIpAhKASIvBXMIxlH/Zljo4EcBUvRsl7e7vkgYMZC/Ua554E0An98j8iEFAEyh6CwNQYxrIP+zKH6ERATanhHtP46M2sgxydurRMdeeRAM+Ed8tD4gcNAV6g53zf1BjGsg/7Mgdz3ZcAeqbTo158fiRtP/SMsPAnEYYU3sAz6L+EV/IQeY0ijFnAko+I1lYwhvZhX+ZgLuZsW0BVqalRUx6ckA7lVMH3WMCqhSSEU+A3UhBTOgIWEBp3cOzDvszBXMzZlgCiHcwL8ekbho1UYIAKHoqinfirFlIaKAJJEDfVQKTnYlq7jWMf9mUO5mJO5l5TgNKXDDW3H/bAk7GFcqD0hnGTJTGFWatqdiRRVIS8dheWjDmYizmZW60lgACHt0EemVAOkdFJknubYbtY+nn+jl+ZxobltsQzF3MyN+9xV7cNF4f0YahVBkKlLp6UmeI+Kp4qvX5afjEkCjLloO/QK/rnXxe+pU6gqBiiZUt30Vl/UiHOxsvXLCGeJ+4b4nYEeHBLqVMHLKu4zzWROAmodmC2MEP4SA32Izu6W1u62K/nWuGZizmZm/fgvUTzlWw5US8Nm3JmMuMgQzOlVj2jn3pUSl0mRmY/RveecT2X2TWMq++8Te0QQtj39uSSzdKuk5aD+Uoy80cUX8gY4geTaiRPX2ezk92WMZaTWIiTNV9jyo8gM1m4xcZt2t1WRLrgIi6XIdzW10x6gGNMSkwKyzi7EM/S3pdlKpv7YCJvHf/wURvKVrApXKm1LC1h+SU4jgV7eBddk+qof/Mloks/IpNPI+W29nU5fY7CU90GbgRq8Eo9LplpQ4w/QZeaJBVhgaIr2rnKOGlUzn8BZ/7iynXg6mUYhfRqoP/lzU7p7aUs8Z7pJTEuHisOHe1z8FUPvUljhfY+lVkl9VdSXVrp5QyxUWjR5pe2FBCLVC43fRwTj1Mb0kVypBbrLtqQb3XqYkGZhCPw+98CDACt/EZVMWT0ogAAAABJRU5ErkJggg==';
  62. const Roadwork = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA/VpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ1dWlkOjVEMjA4OTI0OTNCRkRCMTE5MTRBODU5MEQzMTUwOEM4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkUzRjQ0OTg5NzIzOTExRTM4ODlCRkYwNDVGNDI0RjlEIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkUzRjQ0OTg4NzIzOTExRTM4ODlCRkYwNDVGNDI0RjlEIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIElsbHVzdHJhdG9yIENDIChXaW5kb3dzKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ1dWlkOmFkOTA4NmJkLTAzMGEtNDA0MS04ZTdiLWJhZGYwNWRmZDMzZiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDplNDcyMTVk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';
  63. const endpointMarker = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIZSURBVEhLtZZNSwJRGIVflf6AkGFEHwgJugjbtHDRol/QxpAE921qE0X76GcEQfS1bNXGiKDog6RFbWsRFJjI1K6auZ1zxxGrO5bDdOARHZ1z7tz73vcakc7qBwUwBbKgF1DP4AZUwC54AEb5BdB4FcyCnnhcZGxMJJnkVyJPTyLX1yL1uv74AbbACvANatc0aESjogoFUUdHomxblFJf4bXjY1HFoij+FvdYgE/bUXPATqVEnZz8NPXj7EzU6KgOccA8jUziyO2JCVF4dKNRJxoNUfl8K2SGhu3inDc48iDmHgxJp3XICxiksad1zmM30+LHxYWoWEyHbLrW7ujfuKCmG4JQKukAVtcQAxaArhbTj4NweqoDyBID9lHnxlIMiuOI6uvTAQdRvGS5ibAGoSmC7ZvL6bdZ2vZ6OzRMNT0TetxM/C8xoPb46H4IU+xXUI0Bt2xcWJjQhIWWalW/vWFAhV0Rmyw0XV62nuCQLwPgnV3xe7kFpVzWJWqDEQZQG2wV7IqmG7rh6qrVKrZda1d8Costlw3LdONfsCxRmYw2fwXDNG4XDwuHLTdICM0nJ7U5y6VEQ5N4WDhsueyKJiMTnJbmyGm+SKNO4mFhcR7ZFdm42Fu+m/La+bm7oM0557T8GLnfHuZhsQYYFkskRMbHvx76rPNmKXLUe2AZ3PNCu35rEuznDPH+tiBKqwa8vy074A4YJPIJl9zwywT3hMMAAAAASUVORK5CYII=';
  64. const PLIcon = 'data:image/gif;base64,R0lGODlhFgAUANUAAOHh4t7e34iKj0dLU0VJUUhMVEpOVk1RWU9TW2xvdXF0enx/hZOVmcbHyVJWXVFVXFRYX1dbYl5iaTtASD5DSz1CSj9ETEFGTkNIUEVKUn6BhoSHjFpeZGBkamVpb2RobmpudGltc2ZqcG1xd2tvdaqsr0ZLUklOVU9UW3h8gdHS08nKy////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACwALAAAAAAWABQAAAZrQJZwSCwaj8ikcskkmTpMI2JSmUxSUaFjIhJCJlkhiHjJMD2YUDECVqKsVuJk4OYGSqeDcEJRTkUACgkrKgx8SgsTH0IcExgeh0oFbUICFo5MBpRCDVkbEyNDEw9hbAYSkWEaVQRhrq+wTEEAOw==';
  65. const reportIcon = 'data:image/gif;base64,R0lGODlhFAAUALMAANcsLNgvL9g4OAMBAc5RUcZVVW1tbQAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAgALAAAAAAUABQAAARdEKFDqz0y6zO695S2FUBpAkNliBNxmmnFHu6LXmtG2+iXbjWeiYDRuXw2IhAg+CSLkp1wCG31fB6A0jilLrva6g7r3EaDU7MVEGi72yX1mNwJj8CAgpiOFV/+FhIRADs=';
  66. const NJURLDetail = 'https://511nj.org/API/client/Map/getEventPopupData?EventId=';
  67. const NotNY = ['Pennsylvania Statewide', 'New Jersey Statewide', 'Connecticut Statewide'];
  68. const NJConstruction = ['Construction', 'ScheduledConstruction'];
  69.  
  70. //Begin script function
  71. (function () {
  72. 'use strict';
  73. //Bootstrap
  74. function bootstrap(tries = 1) {
  75. if (W && W.loginManager && W.map && W.loginManager.user && W.model && W.model.states && W.model.states.getObjectArray().length && WazeWrap && WazeWrap.Ready) {
  76. console.log("WME DOT Advisories Loaded!");
  77. init();
  78. addListeners();
  79. if (!OpenLayers.Icon) {
  80. installIcon();
  81. }
  82. } else if (tries < 1000) {
  83. setTimeout(function () { bootstrap(++tries); }, 200);
  84. }
  85. }
  86. // Function.prototype.bind = function (thisObject) {
  87. // var method = this;
  88. // var oldargs = [].slice.call(arguments, 1);
  89. // return function () {
  90. // var newargs = [].slice.call(arguments);
  91. // return method.apply(thisObject, oldargs.concat(newargs));
  92. // };
  93. // }
  94. //Build the Tab and Settings Division
  95. function init() {
  96. var $section = $('<div id="WMEDOTAdvisoriesPanel">');
  97. $section.html([
  98. '<div id="chkAdvisoryEnables">',
  99. '<a href="https://www.waze.com/forum/viewtopic.php?f=819&t=308141" target="_blank">WME DOT Advisories</a> v' + GM_info.script.version + '<br>',
  100. '* The WME Refresh Button will update reports.',
  101. '<div id="chkSettings">',
  102. '<table border=1 style="text-align:center;width:90%;padding:10px;">',
  103. '<tr><td width=20% style="text-align:center"><b>Enable</b></td><td style="text-align:center"><b>Setting</b></td></tr>',
  104. '<tr><td align=center><input type="checkbox" id="chkDOTHideZoomOut" class="wmeDOTSettings"></td><td align=center>',
  105. 'Hide at zoom: <select class="wmeDOTSettings" id="valueHideZoomLevel">',
  106. '<option value=12>12</option>',
  107. '<option value=13>13</option>',
  108. '<option value=14>14</option>',
  109. '<option value=15>15</option>',
  110. '<option value=16>16</option>',
  111. '<option value=17>17</option>',
  112. '<option value=18>18</option>',
  113. '</select>or lower',
  114. '</td></tr>',
  115. '</table>',
  116. '</div><br>',
  117. '<table border=1 style="text-align:center;width:90%;padding:10px;">',
  118. '<tr><td width=20% style="text-align:center"><b>Enable</b></td><td style="text-align"><b>State</b></td><td width=15%><b>Rpt</b></td></tr>',
  119. '<tr><td><input type="checkbox" id="chkAKDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>AK</td><td><div class=DOTreport data-report="report" data-state="Alaska" id="AK"><img src=' + reportIcon + '></div></td></tr>',
  120. '<tr><td><input type="checkbox" id="chkAZDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>AZ</td><td><div class=DOTreport data-report="report" data-state="Arizona" id="AZ"><img src=' + reportIcon + '></div></td></tr>',
  121. '<tr><td><input type="checkbox" id="chkCTDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>CT</td><td><div class=DOTreport data-report="report" data-state="Connecticut" id="CT"><img src=' + reportIcon + '></div></td></tr>',
  122. '<tr><td><input type="checkbox" id="chkDEDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>DE</td><td><div class=DOTreport data-report="report" data-state="Delaware" id="DE"><img src=' + reportIcon + '></div></td></tr>',
  123. '<tr><td><input type="checkbox" id="chkFLDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>FL</td><td><div class=DOTreport data-report="report" data-state="Florida" id="FL"><img src=' + reportIcon + '></div></td></tr>',
  124. '<tr><td><input type="checkbox" id="chkGADOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>GA</td><td><div class=DOTreport data-report="report" data-state="Georgia" id="GA"><img src=' + reportIcon + '></div></td></tr>',
  125. '<tr><td><input type="checkbox" id="chkIADOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>IA</td><td><div class=DOTreport data-report="report" data-state="Iowa" id="IA"><img src=' + reportIcon + '></div></td></tr>',
  126. '<tr><td><input type="checkbox" id="chkILDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>IL</td><td><div class=DOTreport data-report="report" data-state="Illinois" id="IL"><img src=' + reportIcon + '></div></td></tr>',
  127. '<tr><td><input type="checkbox" id="chkINDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>IN</td><td><div class=DOTreport data-report="report" data-state="Indiana" id="IN"><img src=' + reportIcon + '></div></td></tr>',
  128. '<tr><td><input type="checkbox" id="chkLADOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>LA</td><td><div class=DOTreport data-report="report" data-state="Louisiana" id="LA"><img src=' + reportIcon + '></div></td></tr>',
  129. '<tr><td><input type="checkbox" id="chkMDDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>MD</td><td><div class=DOTreport data-report="report" data-state="Maryland" id="MD"><img src=' + reportIcon + '></div></td></tr>',
  130. '<tr><td><input type="checkbox" id="chkMIDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>MI</td><td><div class=DOTreport data-report="report" data-state="Michigan" id="MI"><img src=' + reportIcon + '></div></td></tr>',
  131. '<tr><td><input type="checkbox" id="chkMNDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>MN</td><td><div class=DOTreport data-report="report" data-state="Minnesota" id="MN"><img src=' + reportIcon + '></div></td></tr>',
  132. '<tr><td><input type="checkbox" id="chkNCDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>NC</td><td><div class=DOTreport data-report="report" data-state="North Carolina" id="NC"><img src=' + reportIcon + '></div></td></tr>',
  133. '<tr><td><input type="checkbox" id="chkNJDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>NJ</td><td><div class=DOTreport data-report="report" data-state="New Jersey" id="NJ"><img src=' + reportIcon + '></div></td></tr>',
  134. '<tr><td><input type="checkbox" id="chkNVDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>NV</td><td><div class=DOTreport data-report="report" data-state="Nevada" id="NV"><img src=' + reportIcon + '></div></td></tr>',
  135. '<tr><td><input type="checkbox" id="chkNYDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>NY</td><td><div class=DOTreport data-report="report" data-state="New York" id="NY"><img src=' + reportIcon + '></div></td></tr>',
  136. '<tr><td><input type="checkbox" id="chkOHDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>OH</td><td><div class=DOTreport data-report="report" data-state="Ohio" id="OH"><img src=' + reportIcon + '></div></td></tr>',
  137. '<tr><td><input type="checkbox" id="chkORDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>OR</td><td><div class=DOTreport data-report="report" data-state="Oregon" id="OR"><img src=' + reportIcon + '></div></td></tr>',
  138. '<tr><td><input type="checkbox" id="chkPADOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>PA</td><td><div class=DOTreport data-report="report" data-state="Pennsylvania" id="PA"><img src=' + reportIcon + '></div></td></tr>',
  139. '<tr><td><input type="checkbox" id="chkTXDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>TX (Houston)</td><td><div class=DOTreport data-report="report" data-state="Texas" id="TX"><img src=' + reportIcon + '></div></td></tr>',
  140. '<tr><td><input type="checkbox" id="chkVADOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>VA</td><td><div class=DOTreport data-report="report" data-state="Virginia" id="VA"><img src=' + reportIcon + '></div></td></tr>',
  141. '<tr><td><input type="checkbox" id="chkWADOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>WA</td><td><div class=DOTreport data-report="report" data-state="Washington" id="WA"><img src=' + reportIcon + '></div></td></tr>',
  142. '<tr><td><input type="checkbox" id="chkWIDOTEnabled" class="WMEDOTAdvSettingsCheckbox"></td><td>WI</td><td><div class=DOTreport data-report="report" data-state="Wisconsin" id="WI"><img src=' + reportIcon + '></div></td></tr>',
  143. '<tr><td><input type="checkbox" id="chkWVDOTEnabled" class="WMEDOTAdvSettingsCheckbox" disabled></td><td>WV</td><td><div class=DOTreport data-report="report" data-state="West Virginia" id="WV"><img src=' + reportIcon + '></div></td></tr>',
  144. '</table>',
  145. '</div></div>'
  146. ].join(' '));
  147. WazeWrap.Interface.Tab('DOT Advisories', $section.html(), initializeSettings, '<span title="DOT Advisories">DOT Advisories</span>');
  148. //WazeWrap.Interface.ShowScriptUpdate("WME DOT Advisories", GM_info.script.version, updateMessage, "https://greasyfork.org/en/scripts/412976-wme-dot-advisories", "https://www.waze.com/forum/viewtopic.php?f=819&t=308141");
  149. getBounds();
  150. W.map.events.register("moveend", W.map, function () {
  151. if (localsettings.enabled) {
  152. getBounds();
  153. redrawAdvs();
  154. }
  155. });
  156. $('#chkDOTHideZoomOut').change(function () {
  157. redrawAdvs();
  158. })
  159. $('#valueHideZoomLevel').change(function () {
  160. redrawAdvs();
  161. })
  162. }
  163. function setEnabled(value) {
  164. localsettings.enabled = value;
  165. saveSettings();
  166. const color = value ? '#00bd00' : '#ccc';
  167. $('span#dot-advisories-power-btn').css({ color });
  168. for (var i = 0; i < stateLength; i++) {
  169. state = document.getElementsByClassName("WMEDOTAdvSettingsCheckbox")[i].id.replace("chk", "").replace("DOTEnabled", "");
  170. W.map.getLayersByName(state + 'DOTLayer')[0]?.setVisibility(value);
  171. }
  172. }
  173. function getBounds() {
  174. mapBounds = new OpenLayers.Bounds(W.map.getExtent());
  175. mapBounds = mapBounds.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:3857"));
  176. return mapBounds;
  177. }
  178.  
  179. //Load the CSS
  180. GM_xmlhttpRequest({
  181. method: "GET",
  182. url: 'http://72.167.49.86:8080/CSS',
  183. onload: function (response) {
  184. var result = response.responseText;
  185. GM_addStyle(result);
  186. }
  187. });
  188.  
  189. //Build the State Layers
  190. function buildDOTAdvLayers(state) {
  191. const layer = new OpenLayers.Layer.Markers(state.substring(0, 2) + 'DOTLayer');
  192. W.map.addLayer(layer);
  193. //W.map.getOLMap().setLayerIndex(eval(state.substring(0, 2) + 'DOTLayer'), 10);
  194. }
  195. function redrawAdvs() {
  196. for (const property in settings) {
  197. let state = property.replace("chk", "").replace("DOTEnabled", "");
  198. if (state.length == 2) {
  199. const layer = W.map.getLayersByName(state + 'DOTLayer')[0];
  200. if (document.getElementById('chk' + state + 'DOTEnabled').checked && layer) {
  201. W.map.removeLayer(layer);
  202. buildDOTAdvLayers(state);
  203. testAdv(feeds[state], config[state]);
  204. if (W.map.getZoom() >= 12) {
  205. if (document.getElementById('chkDOTHideZoomOut').checked) {
  206. if (W.map.getZoom() > document.getElementById('valueHideZoomLevel').value) {
  207. layer.setVisibility(true);
  208. } else {
  209. layer.setVisibility(false);
  210. }
  211. } else {
  212. layer.setVisibility(true);
  213. }
  214. } else {
  215. layer.setVisibility(false);
  216. }
  217. }
  218. }
  219. }
  220. }
  221. function testAdv(resultObj, state) {
  222. let i = 0;
  223. while (i < resultObj?.length) {
  224. if ((resultObj[i].lon > mapBounds.left) && (resultObj[i].lon < mapBounds.right)) {
  225. if ((resultObj[i].lat > mapBounds.bottom) && (resultObj[i].lat < mapBounds.top)) {
  226. drawMarkers(resultObj[i]);
  227. }
  228. }
  229. i++;
  230. }
  231. }
  232. function getFeed(url, callback) {
  233. GM_xmlhttpRequest({
  234. method: "GET",
  235. url: url,
  236. onload: callback_function1.bind({}, callback)
  237. //onload: function (response) {
  238. // var result = response;
  239. // callback(result);
  240. //}
  241. });
  242. }
  243. function callback_function1(callback, response) {
  244. var result = response;
  245. setTimeout(function () { callback(result) }, 150);
  246. }
  247. const timer = ms => new Promise(res => setTimeout(res, ms))
  248. function getAdvisories(state, stateAbv, type) {
  249. promises[stateAbv] = [];
  250. advisories[stateAbv] = [];
  251. let thesepromises = [];
  252. for (let j = 0; j < state.URL.length; j++) {
  253. let thispromise = new Promise((resolve, reject) => {
  254. getFeed(state.URL[j], function (result) {
  255. let resultObj = [];
  256. resultObj = state.data(JSON.parse(result.responseText), j);
  257. async function innerLoop() {
  258. for (let i = 0; i < resultObj.length; i++) {
  259. const filter = state.filters[j];
  260. if (!filter || filter(resultObj[i])) {
  261. state.scheme(resultObj[i], j);
  262. }
  263. if (i == (resultObj.length - 1)) {
  264. resolve();
  265. }
  266. await timer(1);
  267. }
  268. if (resultObj.length == 0) {
  269. resolve();
  270. }
  271. }
  272. innerLoop();
  273. });
  274. })
  275. thesepromises.push(thispromise);
  276. }
  277. Promise.all(thesepromises).then(function () {
  278. setTimeout(function () { promiseWorker(stateAbv, type) }, 1000);
  279. })
  280. }
  281. function promiseWorker(stateAbv, type) {
  282. let thisadvisory = advisories[stateAbv];
  283. Promise.all(promises[stateAbv])
  284. .then(function () {
  285. for (let i = 0; i < thisadvisory.length; i++) {
  286. if (type == "report") {
  287. let parms = thisadvisory[i];
  288. let table = document.getElementById("reportTable").getElementsByTagName('tbody')[0];
  289. var row = table.insertRow(-1);
  290. var cell1 = row.insertCell(0);
  291. var cell2 = row.insertCell(1);
  292. var cell3 = row.insertCell(2);
  293. var cell4 = row.insertCell(3);
  294. cell1.innerHTML = '<div class="gotoPL" data-lat="' + parms.lat + '" data-lon="' + parms.lon + '"><img src=' + PLIcon + '></div>'; //PL
  295. cell2.innerHTML = parms.desc; //Description
  296. cell3.innerHTML = parms.title; //Location
  297. cell4.innerHTML = parms.time; //Time
  298. } else {
  299. //drawMarkers(thisadvisory[i]);
  300. feeds[thisadvisory[i].state[0]] = thisadvisory;
  301. testAdv(thisadvisory, state);
  302. }
  303. }
  304. if ((type == "report")) { //Wait until we loop through all the advisory URLs before sorting the table
  305. reportWorker();
  306. }
  307. });
  308. }
  309. function reportWorker() {
  310. var elements = document.getElementsByClassName("gotoPL");
  311. for (var i = 0; i < elements.length; i++) {
  312. elements[i].addEventListener('click', moveMap, false);
  313. }
  314. refreshReportTable();
  315. }
  316. function refreshReportTable() {
  317. var sort = new Tablesort(document.getElementById('reportTable'), { descending: true });
  318. sort.refresh();
  319. document.getElementById("spinner").style.visibility = "hidden";
  320. }
  321. function getReportData(stateAbv, stateName) {
  322. popupdetails(stateName);
  323. //if (stateAbv != "NJ") {
  324. getAdvisories(config[stateAbv], stateAbv, "report");
  325. //} else { getNJDOT("report"); }
  326. }
  327.  
  328. //Generate the Advisory markers
  329. function drawMarkers(parms) {
  330. var icontype;
  331. var size = new OpenLayers.Size(20, 20);
  332. var offset = new OpenLayers.Pixel(-(size.w / 2), -size.h);
  333. for (let i = 0; i < parms.keyword.length; i++) { //Check each of the keywords for roadwork/construction
  334. if (parms.type == parms.keyword[i]) {
  335. icontype = Roadwork;
  336. break;
  337. } else {
  338. icontype = Incident;
  339. }
  340. }
  341. var icon = new OpenLayers.Icon(icontype, size);
  342. var epsg4326 = new OpenLayers.Projection("EPSG:4326"); //WGS 1984 projection
  343. var projectTo = W.map.getProjectionObject(); //The map projection (Spherical Mercator)
  344. var lonLat = new OpenLayers.LonLat(parms.lon, parms.lat).transform(epsg4326, projectTo);
  345. var newMarker = new OpenLayers.Marker(lonLat, icon);
  346. newMarker.eventId = parms.id;
  347. newMarker.title = parms.title;
  348. newMarker.desc = parms.desc;
  349. newMarker.popupType = parms.popupType;
  350. newMarker.state = parms.state;
  351. newMarker.timestamp = parms.time;
  352. newMarker.startTime = parms.startTime;
  353. newMarker.plannedEndTime = parms.plannedEndTime;
  354. newMarker.events.register('click', newMarker, popup);
  355. newMarker.location = lonLat;
  356. newMarker.recurrence = parms.recurrence;
  357. if (parms.hasEndpoints) {
  358. newMarker.fromLon = parms.fromLon;
  359. newMarker.toLon = parms.toLon;
  360. newMarker.fromLat = parms.fromLat;
  361. newMarker.toLat = parms.toLat;
  362. }
  363. if (parms.link != '') {
  364. newMarker.link = '<a href="' + parms.link + '" target="_blank">Publication Link</a>';
  365. } else {
  366. newMarker.link = '';
  367. }
  368. W.map.getLayersByName(parms.state[0] + "DOTLayer")[0].addMarker(newMarker);
  369. }
  370.  
  371. //Draw the endpoint markers
  372. function drawEndpoints(lon, lat) {
  373. var size = new OpenLayers.Size(24, 24);
  374. var icon = new OpenLayers.Icon(endpointMarker, size);
  375. var epsg4326 = new OpenLayers.Projection("EPSG:4326"); //WGS 1984 projection
  376. var projectTo = W.map.getProjectionObject(); //The map projection (Spherical Mercator)
  377. var lonLat = new OpenLayers.LonLat(lon, lat).transform(epsg4326, projectTo);
  378. var endpoint = new OpenLayers.Marker(lonLat, icon);
  379. endpointsLayer.addMarker(endpoint);
  380. endpointsLayer.setOpacity(0.75);
  381. }
  382.  
  383. //Generate the Popup
  384. function popup(evt) {
  385. $("#gmPopupContainer").remove();
  386. $("#gmPopupContainer").hide();
  387. if (W.map.getLayersByName("endpointsLayer").length > 0) {
  388. W.map.removeLayer(endpointsLayer);
  389. }
  390. endpointsLayer = new OpenLayers.Layer.Markers("endpointsLayer");
  391. W.map.addLayer(endpointsLayer);
  392. if ((this.fromLon != this.toLon) || (this.fromLat != this.toLat)) {
  393. drawEndpoints(this.fromLon, this.fromLat);
  394. drawEndpoints(this.toLon, this.toLat);
  395. }
  396. var popupHTML;
  397. W.map.moveTo(this.location);
  398. let htmlString = '<div id="gmPopupContainer" style="max-width:500px;margin: 1;text-align: center;padding: 5px;z-index: 1100">' +
  399. '<a href="#close" id="gmCloseDlgBtn" title="Close" class="modalclose" style="color:#FF0000;">X</a>' +
  400. '<table border=0><tr><td><div id="mydivheader" style="min-height: 20px;">' + this.title + '</div></div>' +
  401. '<hr class="myhrline"/>Updated: ' + this.timestamp.toLocaleString();
  402. if (this.startTime != null) {
  403. htmlString += '<br/>Start: ' + this.startTime.toLocaleString();
  404. }
  405. if (this.plannedEndTime != null) {
  406. htmlString += '<br/>Planned End: ' + this.plannedEndTime.toLocaleString();
  407. }
  408. if (this.recurrence != null) {
  409. htmlString += '<br/>Recurrence: ' + this.recurrence;
  410. }
  411. htmlString += '<hr class="myhrline"/></td></tr><tr><td>' + this.desc + '</td></tr>' +
  412. '<tr><td>' + this.link + '</td></tr>' +
  413. '</table>' +
  414. '</div>';
  415. popupHTML = ([htmlString]);
  416. $("body").append(popupHTML);
  417. //Position the modal based on the position of the click event
  418. $("#gmPopupContainer").css({ left: document.getElementById("user-tabs").offsetWidth + W.map.getPixelFromLonLat(W.map.getUnprojectedCenter()).x - document.getElementById("gmPopupContainer").clientWidth - 10 });
  419. $("#gmPopupContainer").css({ top: document.getElementById("left-app-head").offsetHeight + W.map.getPixelFromLonLat(W.map.getUnprojectedCenter()).y - (document.getElementById("gmPopupContainer").clientHeight / 2) });
  420. $("#gmPopupContainer").show();
  421. //Add listener for popup's "Close" button
  422. $("#gmCloseDlgBtn").click(function () {
  423. $("#gmPopupContainer").remove();
  424. $("#gmPopupContainer").hide();
  425. W.map.removeLayer(endpointsLayer);
  426. });
  427. dragElement(document.getElementById("gmPopupContainer"));
  428. }
  429. function popupdetails(stateName) {
  430. $("#gmPopupContainer").remove();
  431. $("#gmPopupContainer").hide();
  432. var popupHTML;
  433. popupHTML = (['<div id="gmPopupContainer" style="max-width:750px;max-height:500px;margin:1;text-align:center;padding: 5px;z-index: 1100">' +
  434. '<a href="#close" id="popupdetailsclose" title="Close" class="modalclose" style="color:#FF0000;">X</a>' +
  435. '<table border=0><tr><td><div id="mydivheader" style="float:center">' + stateName + ' Reports <div id="spinner" class="spinner" style="float:left;position:relative;left:70%">' +
  436. '<div class="bounce1" style="float:left;position:relative;left:40%"></div><div class="bounce2" style="float:left;position:relative;left:50%"></div><div class="bounce3" style="float:left;position:relative;left:60%"></div></div></td></tr>' +
  437. '<tr><td>' +
  438. '<div style="width:720px; height:450px; overflow:auto;"><table id="reportTable" border=1>' +
  439. '<thead><tr><td data-sort-method="none" width=30><b>PL</b></td><th width=394>Description</th><th width=100>Misc.</th><th data-sort-default width=210>Time</th></tr></thead>' +
  440. '<tbody></tbody></table></div>' +
  441. '</td></tr></table>' +
  442. '</div>'
  443. ]);
  444. $("body").append(popupHTML);
  445. //Position the modal based on the position of the click event
  446. $("#gmPopupContainer").css({ left: 350 });
  447. $("#gmPopupContainer").css({ top: 100 });
  448. $("#gmPopupContainer").show();
  449. //Add listener for popup's "Close" button
  450. $("#popupdetailsclose").click(function () {
  451. $("#gmPopupContainer").remove();
  452. $("#gmPopupContainer").hide();
  453. });
  454. dragElement(document.getElementById("gmPopupContainer"));
  455. }
  456. // Make the DIV element draggable
  457. function dragElement(elmnt) {
  458. var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  459. if (document.getElementById("mydivheader")) {
  460. // if present, the header is where you move the DIV from:
  461. document.getElementById("mydivheader").onmousedown = dragMouseDown;
  462. } else {
  463. // otherwise, move the DIV from anywhere inside the DIV:
  464. elmnt.onmousedown = dragMouseDown;
  465. }
  466. function dragMouseDown(e) {
  467. e = e || window.event;
  468. e.preventDefault();
  469. // get the mouse cursor position at startup:
  470. pos3 = e.clientX;
  471. pos4 = e.clientY;
  472. document.onmouseup = closeDragElement;
  473. // call a function whenever the cursor moves:
  474. document.onmousemove = elementDrag;
  475. }
  476.  
  477. function elementDrag(e) {
  478. e = e || window.event;
  479. e.preventDefault();
  480. // calculate the new cursor position:
  481. pos1 = pos3 - e.clientX;
  482. pos2 = pos4 - e.clientY;
  483. pos3 = e.clientX;
  484. pos4 = e.clientY;
  485. // set the element's new position:
  486. elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
  487. elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  488. }
  489. function closeDragElement() {
  490. // stop moving when mouse button is released:
  491. document.onmouseup = null;
  492. document.onmousemove = null;
  493. }
  494. }
  495. //Move map to coordinates specified
  496. function moveMap() {
  497. var epsg4326 = new OpenLayers.Projection("EPSG:4326"); //WGS 1984 projection
  498. var projectTo = W.map.getProjectionObject(); //The map projection (Spherical Mercator)
  499. var lat = this.getAttribute("data-lat");
  500. var lon = this.getAttribute("data-lon");
  501. W.map.moveTo(new OpenLayers.LonLat(lon, lat).transform(epsg4326, projectTo), 16);
  502. }
  503. //Initialize Settings
  504. function initializeSettings() {
  505. stateLength = document.getElementsByClassName("WMEDOTAdvSettingsCheckbox").length;
  506. loadSettings();
  507. //Set the state checkboxes according to saved settings
  508. for (var i = 0; i < stateLength; i++) {
  509. state = document.getElementsByClassName("WMEDOTAdvSettingsCheckbox")[i].id.replace("chk", "").replace("DOTEnabled", "");
  510. setChecked('chk' + state + 'DOTEnabled', settings[state + 'DOTEnabled']);
  511. }
  512. for (var i = 0; i < document.getElementsByClassName("wmeDOTSettings").length; i++) {
  513. settingID = document.getElementsByClassName("wmeDOTSettings")[i].id;
  514. if (document.getElementsByClassName("wmeDOTSettings")[i].type == "checkbox") {
  515. setChecked(settingID, settings[settingID]);
  516. } else if (document.getElementsByClassName("wmeDOTSettings")[i].type == "select-one") {
  517. $("#valueHideZoomLevel").val(settings[settingID]).change();
  518. }
  519. }
  520. //Build the layers for the selected states
  521. for (var i = 0; i < stateLength; i++) {
  522. state = document.getElementsByClassName("WMEDOTAdvSettingsCheckbox")[i].id.replace("chk", "").replace("DOTEnabled", "");
  523. if (document.getElementById('chk' + state + 'DOTEnabled').checked) {
  524. buildDOTAdvLayers(state);
  525. getAdvisories(config[state], state);
  526. console.log("enabling" + state);
  527. }
  528. }
  529. $('.wmeDOTSettings').change(function () {
  530. var settingName = $(this)[0].id;
  531. settings[settingName] = this.checked;
  532. saveSettings();
  533. });
  534. setEnabled(localsettings.enabled);
  535. }
  536. function addListeners() {
  537. //Add event listener to report icon
  538. for (var i = 0; i < document.getElementsByClassName("DOTreport").length; i++) {
  539. document.getElementsByClassName("DOTreport")[i].addEventListener('click', function (e) { getReportData(this.getAttribute("id"), this.getAttribute("data-state")); }, false);
  540. }
  541. //Refresh selected states when WME's refresh button is clicked
  542. document.getElementsByClassName("reload-button")[0].addEventListener('click', function (e) {
  543. for (var i = 0; i < stateLength; i++) {
  544. state = document.getElementsByClassName("WMEDOTAdvSettingsCheckbox")[i].id.replace("chk", "").replace("DOTEnabled", "");
  545. if (document.getElementsByClassName("WMEDOTAdvSettingsCheckbox")[i].checked) {
  546. W.map.removeLayer(W.map.getLayersByName(state + 'DOTLayer')[0]);
  547. }
  548. }
  549. initializeSettings();
  550. });
  551. //Add Handler for Checkbox Setting Changes
  552. $('.WMEDOTAdvSettingsCheckbox').change(function () {
  553. var settingName = $(this)[0].id.substr(3);
  554. settings[settingName] = this.checked;
  555. saveSettings();
  556. if (this.checked) {
  557. buildDOTAdvLayers(settingName.substring(0, 2));
  558. getAdvisories(config[settingName.substring(0, 2)], settingName.substring(0, 2));
  559. }
  560. else {
  561. W.map.removeLayer(W.map.getLayersByName(settingName.substring(0, 2) + 'DOTLayer')[0]);
  562. }
  563. });
  564. }
  565. //Set Checkbox from Settings
  566. function setChecked(checkboxId, checked) {
  567. $('#' + checkboxId).prop('checked', checked);
  568. }
  569. //Load Saved Settings
  570. function loadSettings() {
  571. if (!localStorage.WMEDOT_Settings) {
  572. localsettings.enabled = true;
  573. localStorage.setItem("WMEDOT_Settings", JSON.stringify(localsettings));
  574. }
  575. localsettings = $.parseJSON(localStorage.getItem("WMEDOT_Settings"));
  576. var defaultSettings = {
  577. Enabled: false,
  578. };
  579. settings = localsettings ? localsettings : defaultSettings;
  580. for (var prop in defaultSettings) {
  581. if (!settings.hasOwnProperty(prop)) {
  582. settings[prop] = defaultSettings[prop];
  583. }
  584. }
  585. const color = localsettings.enabled ? '#00bd00' : '#ccc';
  586. if (!document.getElementById('dot-advisories-power-btn')) {
  587. $('span[title="DOT Advisories"]').prepend(
  588. $('<span>', {
  589. class: 'fa fa-power-off',
  590. id: 'dot-advisories-power-btn',
  591. style: `margin-right: 5px;cursor: pointer;color: ${color};font-size: 13px;`,
  592. title: 'Toggle DOT Advisories'
  593. }).click(evt => {
  594. evt.stopPropagation();
  595. setEnabled(!localsettings.enabled);
  596. })
  597. );
  598. }
  599. }
  600. //Save Tab Settings
  601. function saveSettings() {
  602. if (localStorage) {
  603. //var localsettings = {};
  604. for (var i = 0; i < stateLength; i++) {
  605. state = document.getElementsByClassName("WMEDOTAdvSettingsCheckbox")[i].id.replace("chk", "").replace("DOTEnabled", "");
  606. localsettings[state + 'DOTEnabled'] = document.getElementsByClassName("WMEDOTAdvSettingsCheckbox")[i].checked;
  607. }
  608. }
  609. for (var i = 0; i < document.getElementsByClassName("wmeDOTSettings").length; i++) {
  610. if (document.getElementsByClassName("wmeDOTSettings")[i].type == "checkbox") {
  611. settingID = document.getElementsByClassName("wmeDOTSettings")[i].id;
  612. localsettings[settingID] = document.getElementsByClassName("wmeDOTSettings")[i].checked;
  613. } else if (document.getElementsByClassName("wmeDOTSettings")[i].type == "select-one") {
  614. settingID = document.getElementsByClassName("wmeDOTSettings")[i].id;
  615. localsettings[settingID] = document.getElementsByClassName("wmeDOTSettings")[i].value;
  616. }
  617. }
  618. localStorage.setItem("WMEDOT_Settings", JSON.stringify(localsettings));
  619. }
  620. //Add the Icon Class to OpenLayers
  621. function installIcon() {
  622. console.log('Installing OpenLayers.Icon');
  623. OpenLayers.Icon = OpenLayers.Class({
  624. url: null,
  625. size: null,
  626. offset: null,
  627. calculateOffset: null,
  628. imageDiv: null,
  629. px: null,
  630. initialize: function (a, b, c, d) {
  631. this.url = a;
  632. this.size = b || { w: 20, h: 20 };
  633. this.offset = c || { x: -(this.size.w / 2), y: -(this.size.h / 2) };
  634. this.calculateOffset = d;
  635. a = OpenLayers.Util.createUniqueID("OL_Icon_");
  636. let div = this.imageDiv = OpenLayers.Util.createAlphaImageDiv(a);
  637. $(div.firstChild).removeClass('olAlphaImg'); // LEAVE THIS LINE TO PREVENT WME-HARDHATS SCRIPT FROM TURNING ALL ICONS INTO HARDHAT WAZERS --MAPOMATIC
  638. },
  639. destroy: function () { this.erase(); OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild); this.imageDiv.innerHTML = ""; this.imageDiv = null; },
  640. clone: function () { return new OpenLayers.Icon(this.url, this.size, this.offset, this.calculateOffset); },
  641. setSize: function (a) { null !== a && (this.size = a); this.draw(); },
  642. setUrl: function (a) { null !== a && (this.url = a); this.draw(); },
  643. draw: function (a) {
  644. OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, this.size, this.url, "absolute");
  645. this.moveTo(a);
  646. return this.imageDiv;
  647. },
  648. erase: function () { null !== this.imageDiv && null !== this.imageDiv.parentNode && OpenLayers.Element.remove(this.imageDiv); },
  649. setOpacity: function (a) { OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, null, null, null, null, null, a); },
  650. moveTo: function (a) {
  651. null !== a && (this.px = a);
  652. null !== this.imageDiv && (null === this.px ? this.display(!1) : (
  653. this.calculateOffset && (this.offset = this.calculateOffset(this.size)),
  654. OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, { x: this.px.x + this.offset.x, y: this.px.y + this.offset.y })
  655. ));
  656. },
  657. display: function (a) { this.imageDiv.style.display = a ? "" : "none"; },
  658. isDrawn: function () { return this.imageDiv && this.imageDiv.parentNode && 11 != this.imageDiv.parentNode.nodeType; },
  659. CLASS_NAME: "OpenLayers.Icon"
  660. });
  661. }
  662. bootstrap();
  663.  
  664. const config = { //Configuration data for each state
  665. AK: {
  666. data(res, index) {
  667. let resultText = [res];
  668. return (resultText[index]);
  669. },
  670. filters: [], //['(resultObj[i].LanesAffected).replace(/ +(?= )/g, "") == ("All Lanes Closed")'];
  671. scheme(obj, index) {
  672. promises.AK.push(new Promise((resolve, reject) => {
  673. advisories.AK.push({
  674. state: ['AK', 'Alaska'],
  675. id: obj.ID,
  676. popupType: 0,
  677. title: obj.RoadwayName,
  678. lon: obj.Longitude,
  679. lat: obj.Latitude,
  680. type: obj.EventType,
  681. keyword: ['roadwork'], //keywords for roadwork/construction
  682. desc: obj.Description,
  683. time: moment(new Date(obj.LastUpdated * 1000)).format('LLL'),
  684. link: ''
  685. });
  686. resolve();
  687. }))
  688. },
  689. URL: ['http://72.167.49.86:8080/AK']
  690. },
  691. AZ: {
  692. data(res, index) {
  693. let resultText = [res, res.features, res.features, res.features];
  694. return (resultText[index]);
  695. },
  696. filters: [
  697. obj => ((obj.LanesAffected).replace(/ +(?= )/g, "") == ("All Lanes Closed")) || (obj.RoadwayName).includes("Road Closed")
  698. ],
  699. scheme(obj, index) {
  700.  
  701. promises.AZ.push(new Promise((resolve, reject) => {
  702. advisories.AZ.push({
  703. state: ['AZ', 'Arizona'],
  704. id: obj.ID,
  705. popupType: 0,
  706. title: obj.RoadwayName,
  707. lon: obj.Longitude,
  708. lat: obj.Latitude,
  709. type: obj.EventType,
  710. keyword: ['roadwork'], //keywords for roadwork/construction
  711. desc: obj.Description,
  712. time: moment(new Date(obj.LastUpdated * 1000)).format('LLL'),
  713. link: ''
  714. });
  715. resolve();
  716. }))
  717. },
  718. URL: ['http://72.167.49.86:8080/AZ', 'https://maps.phoenix.gov/pub/rest/services/Public/STR_PubTraffRes/MapServer/0/query?where=Closure_Type+LIKE+%27FULL%27&text=&objectIds=&time=&geometry=&geometryType=esriGeometryPoint&inSR=&spatialRel=esriSpatialRelIntersects&distance=&units=esriSRUnit_Foot&relationParam=&outFields=*&returnGeometry=true&returnTrueCurves=false&maxAllowableOffset=&geometryPrecision=&outSR=4326&havingClause=&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&gdbVersion=&historicMoment=&returnDistinctValues=false&resultOffset=0&resultRecordCount=300&returnExtentOnly=false&datumTransformation=&parameterValues=&rangeValues=&quantizationParameters=&featureEncoding=esriDefault&f=pjson', 'https://maps.phoenix.gov/pub/rest/services/Public/STR_PubTraffRes/MapServer/1/query?where=Closure_Type+LIKE+%27FULL%27&text=&objectIds=&time=&geometry=&geometryType=esriGeometryPoint&inSR=&spatialRel=esriSpatialRelIntersects&distance=&units=esriSRUnit_Foot&relationParam=&outFields=*&returnGeometry=true&returnTrueCurves=false&maxAllowableOffset=&geometryPrecision=&outSR=4326&havingClause=&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&gdbVersion=&historicMoment=&returnDistinctValues=false&resultOffset=0&resultRecordCount=200&returnExtentOnly=false&datumTransformation=&parameterValues=&rangeValues=&quantizationParameters=&featureEncoding=esriDefault&f=pjson', 'https://maps.phoenix.gov/pub/rest/services/Public/STR_PubTraffRes/MapServer/2/query?f=json&where=1%3D1&returnGeometry=true&outSR=4326&spatialRel=esriSpatialRelIntersects&outFields=*&resultOffset=0&resultRecordCount=25']
  719. },
  720. CT: {
  721. data(res, index) {
  722. let resultText = [res];
  723. return (resultText[index]);
  724. },
  725. filters: [obj => obj.eventSubType == "closures"],
  726. scheme(obj, index) {
  727. promises.CT.push(new Promise((resolve, reject) => {
  728. advisories.CT.push({
  729. state: ['CT', 'Connecticut'],
  730. id: obj.ID,
  731. popupType: 0,
  732. title: obj.Location,
  733. lon: obj.Longitude,
  734. lat: obj.Latitude,
  735. type: obj.eventType,
  736. keyword: ['roadwork'], //keywords for roadwork/construction
  737. desc: obj.Description,
  738. startTime: obj.StartDate,
  739. plannedEndTime: obj.PlannedEndDate,
  740. time: obj.LastUpdated,
  741. link: ''
  742. });
  743. resolve();
  744. }))
  745. },
  746. URL: ['http://72.167.49.86:8080/CT']
  747. },
  748. DE: {
  749. data(res, index) {
  750. let resultText = [res.advisories, res.restrictions, res.features];
  751. return (resultText[index]);
  752. },
  753. filters: [
  754. null,
  755. obj => (obj.impactType == "Closure") || ((obj.impactType == "Restriction") && ((obj.construction.toUpperCase().includes("AMP CLOS") || (obj.construction.toUpperCase().includes("ROAD CLOS"))))),
  756. null
  757. ],
  758. scheme(obj, index) {
  759. switch (index) {
  760. case 0:
  761. promises.DE.push(new Promise((resolve, reject) => {
  762. advisories.DE.push({
  763. state: ['DE', 'Delaware'],
  764. id: obj.id,
  765. popupType: 0,
  766. title: obj.where.county.name,
  767. lon: obj.where.lon,
  768. lat: obj.where.lat,
  769. type: obj.type.name,
  770. keyword: ['Construction'], //keyword for roadwork/construction
  771. desc: obj.where.location,
  772. time: moment(new Date(obj.timestamp)).format('LLL'),
  773. link: obj.published.linkbackUrl
  774. });
  775. resolve();
  776. }))
  777. break;
  778. case 1:
  779. var pubLink;
  780. if (obj.releaseId) {
  781. if (obj.releaseId.toString() == "-1") {
  782. pubLink = '';
  783. } else {
  784. pubLink = 'https://deldot.gov/About/news/index.shtml?dc=release&id=' + obj.releaseId;
  785. }
  786. }
  787. promises.DE.push(new Promise((resolve, reject) => {
  788. advisories.DE.push({
  789. state: ['DE', 'Delaware'],
  790. id: obj.restrictionId,
  791. popupType: 0,
  792. title: obj.where.county.name,
  793. lon: obj.where.lon,
  794. lat: obj.where.lat,
  795. type: obj.impactType,
  796. keyword: ['Closure'], //keywords for roadwork/construction
  797. desc: obj.title + " - " + obj.construction,
  798. time: moment(new Date(obj.startDate)).format('LLL'),
  799. link: pubLink
  800. });
  801. resolve();
  802. }))
  803. break;
  804. case 2:
  805. var direction, WorkType;
  806. switch (obj.attributes.direction) {
  807. case 'ONE_DIRECTION':
  808. direction = "One Way from ";
  809. break;
  810. case 'BOTH_DIRECTIONS':
  811. direction = "Both Ways between ";
  812. }
  813. switch (obj.attributes.WorkType) {
  814. case "1":
  815. WorkType = "Gas Work";
  816. break;
  817. case "2":
  818. WorkType = "Street Work (city)";
  819. break;
  820. case "3":
  821. WorkType = "Street Work (DelDOT)";
  822. break;
  823. case "4":
  824. WorkType = "Water Work";
  825. break;
  826. case "5":
  827. WorkType = "Work (other)";
  828. break;
  829. case "6":
  830. WorkType = "Sewer Work";
  831. }
  832. if (obj.attributes.street != null) {
  833. var originShift = 2.0 * Math.PI * 6378137.0 / 2.0;
  834. var lon = (obj.geometry.paths[0][0][0] / originShift) * 180.0;
  835. var lat = (obj.geometry.paths[0][0][1] / originShift) * 180.0;
  836. lat = 180.0 / Math.PI * (2.0 * Math.atan(Math.exp(lat * Math.PI / 180.0)) - Math.PI / 2.0);
  837. promises.DE.push(new Promise((resolve, reject) => {
  838. advisories.DE.push({
  839. state: ['DE', 'Delaware'],
  840. id: obj.attributes.OBJECTID,
  841. popupType: 0,
  842. title: 'Wilmington Road Closures',
  843. lon: lon,
  844. lat: lat,
  845. type: 'Closure',
  846. keyword: ['Closure'], //keywords for roadwork/construction
  847. desc: WorkType + ' - ' + direction + obj.attributes.StartingFrom + ' to ' + obj.attributes.EndingAt + '<br> from ' + moment(new Date(obj.attributes.starttime)).format('LLL') + ' to ' + moment(new Date(obj.attributes.endtime)).format('LLL'),
  848. time: moment(new Date(obj.attributes.EditDate)).format('LLL'),
  849. link: ''
  850. });
  851. resolve();
  852. }))
  853. }
  854. }
  855. },
  856. URL: ['https://tmc.deldot.gov/json/advisory.json', 'https://tmc.deldot.gov/json/restriction.json?id=ACVN', 'https://services.arcgis.com/hQ3wdpbjO3fPf612/ArcGIS/rest/services/RoadClosures_5b3e88c5556242dfa6e058198be7eb52_public/FeatureServer/1/query?where=1%3D1&objectIds=&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&resultType=standard&distance=0.0&units=esriSRUnit_Meter&returnGeodetic=false&outFields=*&returnGeometry=true&featureEncoding=esriDefault&multipatchOption=xyFootprint&maxAllowableOffset=&geometryPrecision=&outSR=&datumTransformation=&applyVCSProjection=false&returnIdsOnly=false&returnUniqueIdsOnly=false&returnCountOnly=false&returnExtentOnly=false&returnQueryGeometry=false&returnDistinctValues=false&cacheHint=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&having=&resultOffset=&resultRecordCount=&returnZ=false&returnM=false&returnExceededLimitFeatures=true&quantizationParameters=&sqlFormat=none&f=pjson&token=']
  857. },
  858. FL: {
  859. data(res, index) {
  860. let resultText = [res.item2, res.item2, res.item2];
  861. return (resultText[index]);
  862. },
  863. filters: [],
  864. scheme(obj, index) {
  865. switch (index) {
  866. case 0:
  867. promises.FL.push(new Promise((resolve, reject) => {
  868. //setTimeout(function () { resolve() }, 4000);
  869. getFeed(config.FL.detailURL[0] + obj.itemId.replace("/ /g", "%20"), async function (result) {
  870. var eventObj = JSON.parse(result.responseText);
  871. if (eventObj.details.detailLang1.eventTypeName == "Closures") {
  872. advisories.FL.push({
  873. state: ['FL', 'Florida'],
  874. id: eventObj.id.id,
  875. popupType: 0,
  876. title: eventObj.areas.area5.areaLang1,
  877. lon: eventObj.coordinates.locationLongitude / 1000000,
  878. lat: eventObj.coordinates.locationLatitude / 1000000,
  879. type: eventObj.details.detailLang1.eventTypeName,
  880. keyword: ['Construction'], //keywords for roadwork/construction
  881. desc: eventObj.details.detailLang1.eventDescription,
  882. time: moment(new Date(eventObj.dates.lastUpdated)).format('LLL'),
  883. link: ''
  884. });
  885. }
  886. resolve();
  887. });
  888. }));
  889. break;
  890. case 1:
  891. promises.FL.push(new Promise((resolve, reject) => {
  892. //setTimeout(function () { resolve() }, 4000);
  893. getFeed(config.FL.detailURL[1] + obj.itemId.replace("/ /g", "%20"), async function (result) {
  894. var eventObj = JSON.parse(result.responseText);
  895. if (eventObj.details.detailLang1.eventTypeName == "Closures") {
  896. advisories.FL.push({
  897. state: ['FL', 'Florida'],
  898. id: eventObj.id.id,
  899. popupType: 0,
  900. title: eventObj.areas.area5.areaLang1,
  901. lon: eventObj.coordinates.locationLongitude / 1000000,
  902. lat: eventObj.coordinates.locationLatitude / 1000000,
  903. type: eventObj.details.detailLang1.eventTypeName,
  904. keyword: ['Closures'], //keywords for roadwork/construction
  905. desc: eventObj.details.detailLang1.eventDescription,
  906. time: moment(new Date(eventObj.dates.lastUpdated)).format('LLL'),
  907. link: ''
  908. });
  909. }
  910. resolve();
  911. });
  912. }));
  913. break;
  914. case 2:
  915. promises.FL.push(new Promise((resolve, reject) => {
  916. //setTimeout(function () { resolve() }, 4000);
  917. getFeed(config.FL.detailURL[1] + obj.itemId.replace("/ /g", "%20"), async function (result) {
  918. var eventObj = JSON.parse(result.responseText);
  919. if (eventObj.details.detailLang1.eventTypeName == "Closures") {
  920. advisories.FL.push({
  921. state: ['FL', 'Florida'],
  922. id: eventObj.id.id,
  923. popupType: 0,
  924. title: eventObj.areas.area5.areaLang1,
  925. lon: eventObj.coordinates.locationLongitude / 1000000,
  926. lat: eventObj.coordinates.locationLatitude / 1000000,
  927. type: eventObj.details.detailLang1.eventTypeName,
  928. keyword: ['Constructions'], //keywords for roadwork/construction
  929. desc: eventObj.details.detailLang1.eventDescription,
  930. time: moment(new Date(eventObj.dates.lastUpdated)).format('LLL'),
  931. link: ''
  932. });
  933. }
  934. resolve();
  935. });
  936. }));
  937. }
  938. },
  939. URL: ['https://fl511.com/map/mapIcons/Incidents?_=1604955914474', 'https://fl511.com/map/mapIcons/Construction?_=1604965926997', 'https://fl511.com/map/mapIcons/Closures?_=1604965926997'],
  940. detailURL: ['https://fl511.com/map/data/Incidents/', 'https://fl511.com/map/data/Construction/', 'https://fl511.com/map/data/Closures/']
  941. },
  942. GA: {
  943. data(res, index) {
  944. let resultText = [res];
  945. return (resultText[index]);
  946. },
  947. filters: [obj => (obj.IsFullClosure == true)],
  948. scheme(obj, index) {
  949. let secondLon, secondLat;
  950. if ((obj.LongitudeSecondary != 0) && (obj.LatitudeSecondary != 0)) {
  951. secondLon = obj.LongitudeSecondary;
  952. secondLat = obj.LatitudeSecondary;
  953. }
  954. promises.GA.push(new Promise((resolve, reject) => {
  955. advisories.GA.push({
  956. state: ['GA', 'Georgia'],
  957. id: obj.ID,
  958. popupType: 0,
  959. title: obj.RoadwayName,
  960. lon: obj.Longitude,
  961. lat: obj.Latitude,
  962. type: obj.Subtype,
  963. hasEndpoints: true,
  964. fromLon: obj.Longitude,
  965. fromLat: obj.Latitude,
  966. toLon: secondLon,
  967. toLat: secondLat,
  968. toLon: obj.LongitudeSecondary,
  969. toLat: obj.LatitudeSecondary,
  970. keyword: ['roadwork', 'road construction', 'road maintenance'], //keyword for roadwork/construction
  971. desc: obj.Description + "<br>" + moment(new Date(obj.StartDate * 1000)).format('LLL') + " to " + moment(new Date(obj.PlannedEndDate * 1000)).format('LLL'),
  972. time: moment(new Date(obj.LastUpdated * 1000)).format('LLL'),
  973. link: ''
  974. });
  975. resolve();
  976. }))
  977. },
  978. URL: ['http://72.167.49.86:8080/GA']
  979. },
  980. IA: {
  981. data(res, index) {
  982. let resultText = [res[0].data.mapFeaturesQuery.mapFeatures];
  983. return (resultText[index]);
  984. },
  985. filters: [
  986. obj => obj.features[0].properties.icon.url == "/images/tg_closure_critical.svg"
  987. || obj.features[0].properties.icon.url == "/images/tg_closure_routine.svg"
  988. || obj.features[0].properties.icon.url == "/images/tg_crash_routine.svg"
  989. || obj.features[0].properties.icon.url == "/images/tg_warning_urgent.svg"
  990. || (obj.features[0].properties.icon.url == "/images/tg_warning_routine.svg" && obj.tooltip.toUpperCase().includes("RAMP CLOSE"))
  991. ],
  992. scheme(obj, index) {
  993. let advType = "";
  994. if (obj.tooltip.toUpperCase().includes("CONSTRUCTION")) {
  995. advType = "Construction";
  996. } else { advType = "Incident"; }
  997. promises.IA.push(new Promise((resolve, reject) => {
  998. advisories.IA.push({
  999. state: ['IA', 'Iowa'],
  1000. id: obj.features[0].id,
  1001. popupType: 0,
  1002. title: "N/A",
  1003. lon: obj.features[0].geometry.coordinates[0],
  1004. lat: obj.features[0].geometry.coordinates[1],
  1005. type: advType,
  1006. keyword: ['Construction'], //keywords for roadwork/construction
  1007. desc: obj.tooltip,
  1008. time: "N/A",
  1009. link: ''
  1010. });
  1011. resolve();
  1012. }))
  1013. },
  1014. URL: ['http://72.167.49.86:8080/IA']
  1015. },
  1016. IL: {
  1017. data(res, index) {
  1018. let resultText = [res.features, res.features, res.features];
  1019. return (resultText[index]);
  1020. },
  1021. filters: [],
  1022. scheme(obj, index) {
  1023. switch (index) {
  1024. case 0:
  1025. promises.IL.push(new Promise((resolve, reject) => {
  1026. advisories.IL.push({
  1027. state: ['IL', 'Illinois'],
  1028. id: obj.attributes.OBJECTID,
  1029. popupType: 0,
  1030. title: obj.attributes.NearTown,
  1031. lon: obj.geometry.x,
  1032. lat: obj.geometry.y,
  1033. type: "Construction",
  1034. keyword: ['Construction'], //keywords for roadwork/construction
  1035. desc: 'Closed from ' + obj.attributes.Location + '<br> from ' + moment(new Date(obj.attributes.StartDate)).format('LLL') + ' to ' + moment(new Date(obj.attributes.EndDate)).format('LLL'),
  1036. time: moment(new Date(obj.attributes.StartDate)).format('LLL'),
  1037. link: obj.attributes.WebAddress
  1038. });
  1039. resolve();
  1040. }))
  1041. break;
  1042. case 1:
  1043. var DateUpdate;
  1044. if (obj.attributes.DateUpdate == null) {
  1045. DateUpdate = moment(new Date(obj.attributes.DateEntered)).format('LLL');
  1046. } else {
  1047. DateUpdate = moment(new Date(obj.attributes.DateUpdate)).format('LLL');
  1048. }
  1049. var originShift = 2.0 * Math.PI * 6378137.0 / 2.0;
  1050. var lon = (obj.geometry.paths[0][0][0] / originShift) * 180.0;
  1051. var lat = (obj.geometry.paths[0][0][1] / originShift) * 180.0;
  1052. lat = 180.0 / Math.PI * (2.0 * Math.atan(Math.exp(lat * Math.PI / 180.0)) - Math.PI / 2.0);
  1053. if (obj.attributes.SuggestionToMotorist.includes("Closed")) {
  1054. promises.IL.push(new Promise((resolve, reject) => {
  1055. advisories.IL.push({
  1056. state: ['IL', 'Illinois'],
  1057. id: obj.attributes.OBJECTID,
  1058. popupType: 0,
  1059. title: obj.attributes.County,
  1060. lon: lon,
  1061. lat: lat,
  1062. type: "Construction",
  1063. keyword: ['Construction'], //keywords for roadwork/construction
  1064. desc: 'Closed from ' + obj.attributes.Location + '<br> from ' + moment(new Date(obj.attributes.StartDate)).format('LLL') + ' to ' + moment(new Date(obj.attributes.EndDate)).format('LLL'),
  1065. time: DateUpdate,
  1066. link: obj.attributes.WebAddress
  1067. });
  1068. resolve();
  1069. }))
  1070. }
  1071. break;
  1072. case 2:
  1073. promises.IL.push(new Promise((resolve, reject) => {
  1074. advisories.IL.push({
  1075. state: ['IL', 'Illinois'],
  1076. id: obj.attributes.OBJECTID,
  1077. popupType: 0,
  1078. title: obj.attributes.NearTown,
  1079. lon: obj.geometry.paths[0][0][0],
  1080. lat: obj.geometry.paths[0][0][1],
  1081. type: "",
  1082. keyword: ['Flooding'], //keywords for roadwork/construction
  1083. desc: 'Closed from ' + obj.attributes.Location + '<br> from ' + moment(new Date(obj.attributes.StartDate)).format('LLL') + ' to ' + moment(new Date(obj.attributes.EndDate)).format('LLL'),
  1084. time: moment(new Date(obj.attributes.StartDate)).format('LLL'),
  1085. link: ''
  1086. });
  1087. resolve();
  1088. }))
  1089. }
  1090. },
  1091.  
  1092. URL: ['https://services2.arcgis.com/aIrBD8yn1TDTEXoz/ArcGIS/rest/services/ClosureIncidents/FeatureServer/0/query?where=1%3D1&objectIds=&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&resultType=none&distance=0.0&units=esriSRUnit_Meter&returnGeodetic=false&outFields=*&returnGeometry=true&featureEncoding=esriDefault&multipatchOption=xyFootprint&maxAllowableOffset=&geometryPrecision=&outSR=&datumTransformation=&applyVCSProjection=false&returnIdsOnly=false&returnUniqueIdsOnly=false&returnCountOnly=false&returnExtentOnly=false&returnQueryGeometry=false&returnDistinctValues=false&cacheHint=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&having=&resultOffset=&resultRecordCount=&returnZ=false&returnM=false&returnExceededLimitFeatures=true&quantizationParameters=&sqlFormat=none&f=pjson&token=', 'https://services2.arcgis.com/aIrBD8yn1TDTEXoz/ArcGIS/rest/services/RoadConstruction_View/FeatureServer/0/query?where=1%3D1&objectIds=&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&resultType=none&distance=0.0&units=esriSRUnit_Meter&returnGeodetic=false&outFields=*&returnGeometry=true&featureEncoding=esriDefault&multipatchOption=xyFootprint&maxAllowableOffset=&geometryPrecision=&outSR=&datumTransformation=&applyVCSProjection=false&returnIdsOnly=false&returnUniqueIdsOnly=false&returnCountOnly=false&returnExtentOnly=false&returnQueryGeometry=false&returnDistinctValues=false&cacheHint=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&having=&resultOffset=&resultRecordCount=&returnZ=false&returnM=false&returnExceededLimitFeatures=true&quantizationParameters=&sqlFormat=none&f=pjson&token=', 'https://services2.arcgis.com/aIrBD8yn1TDTEXoz/ArcGIS/rest/services/Flooding_Road_Closures/FeatureServer/0/query?where=1%3D1&objectIds=&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&resultType=none&distance=0.0&units=esriSRUnit_Meter&returnGeodetic=false&outFields=*&returnGeometry=true&featureEncoding=esriDefault&multipatchOption=xyFootprint&maxAllowableOffset=&geometryPrecision=&outSR=&datumTransformation=&applyVCSProjection=false&returnIdsOnly=false&returnUniqueIdsOnly=false&returnCountOnly=false&returnExtentOnly=false&returnQueryGeometry=false&returnDistinctValues=false&cacheHint=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&having=&resultOffset=&resultRecordCount=&returnZ=false&returnM=false&returnExceededLimitFeatures=true&quantizationParameters=&sqlFormat=none&f=pjson&token=']
  1093. },
  1094. IN: {
  1095. data(res, index) {
  1096. let resultText = [res[0].data.mapFeaturesQuery.mapFeatures];
  1097. return (resultText[index]);
  1098. },
  1099. filters: [],
  1100. scheme(obj, index) {
  1101. let advType = "";
  1102. if (obj.tooltip.toUpperCase().includes("CONSTRUCTION")) {
  1103. advType = "Construction";
  1104. } else { advType = "Incident"; }
  1105. if (obj.features[0].properties.icon.url == "/images/tg_closure_urgent.svg" || obj.features[0].properties.icon.url == "/images/tg_closure_critical.svg" || obj.features[0].properties.icon.url == "/images/tg_closure_routine.svg" || obj.features[0].properties.icon.url == "/images/tg_crash_routine.svg" || (obj.features[0].properties.icon.url == "/images/tg_warning_routine.svg" && obj.tooltip.toUpperCase().includes("RAMP CLOSE"))) {
  1106. promises.IN.push(new Promise((resolve, reject) => {
  1107. advisories.IN.push({
  1108. state: ['IN', 'Indiana'],
  1109. id: obj.features[0].id,
  1110. popupType: 0,
  1111. title: "N/A",
  1112. lon: obj.features[0].geometry.coordinates[0],
  1113. lat: obj.features[0].geometry.coordinates[1],
  1114. type: advType,
  1115. keyword: ['Construction'], //keywords for roadwork/construction
  1116. desc: obj.tooltip,
  1117. time: "N/A",
  1118. link: ''
  1119. });
  1120. resolve();
  1121. }))
  1122. }
  1123. },
  1124. URL: ['http://72.167.49.86:8080/IN']
  1125. },
  1126. LA: {
  1127. data(res, index) {
  1128. let resultText = [res];
  1129. return (resultText[index]);
  1130. },
  1131. filters: [obj => obj.LanesAffected.replace(/ +(?= )/g, "") == ("All Lanes Closed")],
  1132. scheme(obj, index) {
  1133. promises.LA.push(new Promise((resolve, reject) => {
  1134. advisories.LA.push({
  1135. state: ['LA', 'Louisiana'],
  1136. id: obj.ID,
  1137. popupType: 0,
  1138. title: obj.RoadwayName,
  1139. lon: obj.Longitude,
  1140. lat: obj.Latitude,
  1141. type: obj.EventType,
  1142. keyword: ['roadwork'], //keywords for roadwork/construction
  1143. desc: obj.Description,
  1144. time: moment(new Date(obj.LastUpdated * 1000)).format('LLL'),
  1145. link: ''
  1146. });
  1147. resolve();
  1148. }))
  1149. },
  1150. URL: ['http://72.167.49.86:8080/LA']
  1151. },
  1152. MD: {
  1153. data(res, index) {
  1154. let resultText = [res.features];
  1155. return (resultText[index]);
  1156. },
  1157. filters: [],
  1158. scheme(obj, index) {
  1159. promises.MD.push(new Promise((resolve, reject) => {
  1160. advisories.MD.push({
  1161. state: ['MD', 'Maryland'],
  1162. id: obj.attributes.OBJECTID,
  1163. popupType: 0,
  1164. title: obj.attributes.Jurisdiction,
  1165. lon: obj.attributes.Longitude,
  1166. lat: obj.attributes.Latitude,
  1167. type: obj.attributes.typeSummary,
  1168. keyword: ['Construction'], //keywords for roadwork/construction
  1169. desc: obj.attributes.ClosureSummary,
  1170. time: moment(new Date(obj.attributes.EditDate)).format('LLL'),
  1171. link: ''
  1172. });
  1173. resolve();
  1174. }))
  1175. },
  1176. URL: ['https://geodata.md.gov/appdata/rest/services/SHA_RoadClosure/RoadClosureActive/MapServer//0/query?where=1%3D1&outFields=*&outSR=4326&f=json']
  1177. },
  1178. MI: {
  1179. data(res, index) {
  1180. let resultText = [res, res];
  1181. return (resultText[index]);
  1182. },
  1183. filters: [obj => (obj.type == "Total")],
  1184. scheme(obj, index) {
  1185. switch (index) {
  1186. case 0:
  1187. promises.MI.push(new Promise((resolve, reject) => {
  1188. advisories.MI.push({
  1189. state: ['MI', 'Michigan'],
  1190. id: "00",
  1191. popupType: 0,
  1192. title: obj.county,
  1193. lon: obj.description.match(/(?<=lon=)[\s\S]*(?=&zoom)/)[0],
  1194. lat: obj.description.match(/(?<=lat=)[\s\S]*(?=&lon)/)[0],
  1195. type: "Construction",
  1196. keyword: ['Construction'], //keyword for roadwork/construction
  1197. desc: obj.description.match(/(?:(?!<).)*/),
  1198. time: moment(new Date(obj.startDate)).format('LL'),
  1199. link: ''
  1200. });
  1201. resolve();
  1202. }))
  1203. break;
  1204. case 1:
  1205. promises.MI.push(new Promise((resolve, reject) => {
  1206. advisories.MI.push({
  1207. state: ['MI', 'Michigan'],
  1208. id: "",
  1209. popupType: 0,
  1210. title: obj.county,
  1211. lon: obj.location.match(/(?<=lon=)[\s\S]*(?=&zoom)/)[0],
  1212. lat: obj.location.match(/(?<=lat=)[\s\S]*(?=&lon)/)[0],
  1213. type: "Incident",
  1214. keyword: ['Construction'], //keyword for roadwork/construction
  1215. desc: obj.location.match(/(?:(?!<).)*/),
  1216. time: moment(new Date(obj.reported)).format('LLL'),
  1217. link: ''
  1218. });
  1219. resolve();
  1220. }))
  1221. }
  1222. },
  1223. URL: ['https://mdotjboss.state.mi.us/MiDrive//construction/list/loadConstruction', 'https://mdotjboss.state.mi.us/MiDrive//incident/list/loadIncidents']
  1224. },
  1225. MN: {
  1226. data(res, index) {
  1227. let resultText = [res[0].data.mapFeaturesQuery.mapFeatures];
  1228. return (resultText[index]);
  1229. },
  1230. filters: [
  1231. obj => obj.features[0].properties.icon.url == "/images/tg_closure_critical.svg"
  1232. || obj.features[0].properties.icon.url == "/images/tg_closure_routine.svg"
  1233. || obj.features[0].properties.icon.url == "/images/tg_crash_routine.svg"
  1234. || (obj.features[0].properties.icon.url == "/images/tg_warning_routine.svg" && obj.tooltip.toUpperCase().includes("RAMP CLOSE"))
  1235. ],
  1236. scheme(obj, index) {
  1237. let advType = "";
  1238. if (obj.tooltip.toUpperCase().includes("CONSTRUCTION")) {
  1239. advType = "Construction";
  1240. } else { advType = "Incident"; }
  1241. promises.MN.push(new Promise((resolve, reject) => {
  1242. advisories.MN.push({
  1243. state: ['MN', 'Minnesota'],
  1244. id: obj.features[0].id,
  1245. popupType: 0,
  1246. title: "N/A",
  1247. lon: obj.features[0].geometry.coordinates[0],
  1248. lat: obj.features[0].geometry.coordinates[1],
  1249. type: advType,
  1250. keyword: ['Construction'], //keywords for roadwork/construction
  1251. desc: obj.tooltip,
  1252. time: "N/A",
  1253. link: ''
  1254. });
  1255. resolve();
  1256. }))
  1257. },
  1258. URL: ['http://72.167.49.86:8080/MN']
  1259. },
  1260. NC: {
  1261. data(res, index) {
  1262. let resultText = [res];
  1263. return (resultText[index]);
  1264. },
  1265. filters: [],
  1266. scheme(obj, index) {
  1267. promises.NC.push(new Promise((resolve, reject) => {
  1268. advisories.NC.push({
  1269. state: ['NC', 'North Carolina'],
  1270. id: obj.id,
  1271. popupType: 0,
  1272. title: obj.city + " (" + obj.countyName + ")",
  1273. lon: obj.longitude,
  1274. lat: obj.latitude,
  1275. type: obj.incidentType,
  1276. keyword: ['Construction', 'Emergency Road Work', 'Night Time Construction', 'Weekend Construction'], //keywords for roadwork/construction
  1277. desc: obj.reason,
  1278. time: moment(new Date(obj.lastUpdate)).format('LLL'),
  1279. link: ''
  1280. });
  1281. resolve();
  1282. }))
  1283. },
  1284. URL: ['https://eapps.ncdot.gov/services/traffic-prod/v1/incidents']
  1285. },
  1286. NJ: {
  1287. data(res, index) {
  1288. let resultText = [res.Data.features];
  1289. return (resultText[index]);
  1290. },
  1291. filters: [],
  1292. scheme(obj, index) {
  1293. promises.NJ.push(new Promise((resolve, reject) => {
  1294. //setTimeout(function () { resolve() }, 4000);
  1295. getFeed(config.NJ.detailURL[0] + obj.properties.EventID, function (result) {
  1296. var eventObj = JSON.parse(result.responseText).Data;
  1297. console.log(result.status);
  1298. if (((eventObj[0].FullText.toUpperCase()).includes("ALL LANES CLOSE") || (eventObj[0].FullText.toUpperCase()).includes("RAMP CLOSE")) && ((eventObj[0].FullText).includes("NYSDOT") != true)) {
  1299. advisories.NJ.push({
  1300. state: ['NJ', 'New Jersey'],
  1301. id: eventObj[0].markerId,
  1302. popupType: 0,
  1303. title: eventObj[0].County,
  1304. lon: eventObj[0].Longitude,
  1305. lat: eventObj[0].Latitude,
  1306. type: eventObj[0].CategoryName,
  1307. keyword: ['Construction', 'ScheduledConstruction'], //keywords for roadwork/construction
  1308. desc: eventObj[0].FullText,
  1309. time: moment(new Date(eventObj[0].LastUpdateDate_String)).format('LLL'),
  1310. link: ''
  1311. });
  1312. }
  1313. resolve(true);
  1314. });
  1315. }));
  1316. },
  1317. URL: ['https://publicmap1.511nj.org/API/client/Map/getEventData'],
  1318. detailURL: ['https://publicmap1.511nj.org/API/client/Map/getEventPopupData?EventId=']
  1319. },
  1320. NV: {
  1321. data(res, index) {
  1322. let resultText = [res.d];
  1323. return (resultText[index]);
  1324. },
  1325. filters: [],
  1326. scheme(obj, index) {
  1327. promises.NV.push(new Promise((resolve, reject) => {
  1328. let unix = obj.LastUpdate.replace(/\\\//g, "").replace("/Date(", "").replace(")/", "");
  1329. advisories.NV.push({
  1330. state: ['NV', 'Nevada'],
  1331. id: obj.ID,
  1332. popupType: 0,
  1333. title: obj.Facility,
  1334. lon: obj.Lon,
  1335. lat: obj.Lat,
  1336. type: obj.CategoryName,
  1337. keyword: ['Construction'], //keywords for roadwork/construction
  1338. desc: obj.Description,
  1339. time: moment(new Date(parseInt(unix))).format('LLL'),
  1340. link: ''
  1341. });
  1342. resolve();
  1343. }))
  1344. },
  1345. URL: ['http://72.167.49.86:8080/NV']
  1346. },
  1347. NY: {
  1348. data(res, index) {
  1349. let resultText = [res];
  1350. return (resultText[index]);
  1351. },
  1352. filters: [
  1353. obj => (
  1354. (NotNY.includes(obj.RegionName) == false && obj.EventType != "transitMode" && obj.EventSubType != "Capacity related")
  1355. && (obj.EventType == "closures" || (
  1356. obj.EventType != "closures" && obj.LanesAffected == "all lanes" && (obj.LanesStatus == "closed" || obj.LanesStatus == "blocked")
  1357. ))
  1358. )
  1359. ],
  1360. scheme(obj, index) {
  1361. promises.NY.push(new Promise((resolve, reject) => {
  1362. advisories.NY.push({
  1363. state: ['NY', 'New York'],
  1364. id: obj.ID,
  1365. popupType: 0,
  1366. title: obj.CountyName,
  1367. lon: obj.Longitude,
  1368. lat: obj.Latitude,
  1369. type: obj.EventType,
  1370. keyword: ['roadwork', 'transitMode', 'closures'], //keywords for roadwork/construction
  1371. desc: obj.Description,
  1372. time: moment(moment(obj.LastUpdated, "DD/MM/YYYY HH:mm:ss")).format('LLL'),
  1373. link: ''
  1374. });
  1375. resolve();
  1376. }))
  1377. },
  1378. URL: ['http://72.167.49.86:8080/NY']
  1379. },
  1380. OH: {
  1381. data(res, index) {
  1382. let resultText = [res.ConstructionMarkers];
  1383. return (resultText[index]);
  1384. },
  1385. filters: [obj => obj.Status == "Closed"],
  1386. scheme(obj, index) {
  1387. promises.OH.push(new Promise((resolve, reject) => {
  1388. advisories.OH.push({
  1389. state: ['OH', 'Ohio'],
  1390. id: obj.ID,
  1391. popupType: 0,
  1392. title: obj.District,
  1393. lon: obj.Longitude,
  1394. lat: obj.Latitude,
  1395. type: obj.Category,
  1396. keyword: ['Roadwork - Planned', 'Roadwork - Unplanned'], //keywords for roadwork/construction
  1397. desc: obj.Description,
  1398. time: moment(new Date(obj.StartDate)).format('LL'),
  1399. link: ''
  1400. });
  1401. resolve();
  1402. }))
  1403. },
  1404. URL: ['https://api.ohgo.com/roadmarkers/TrafficSpeedAndAlertMarkers']
  1405. },
  1406. OR: {
  1407. data(res, index) {
  1408. let resultText = [res.features, res.features, res.features];
  1409. return (resultText[index]);
  1410. },
  1411. filters: [
  1412. null,
  1413. obj => obj.attributes.comments.includes("clos"),
  1414. obj => obj.attributes.tmddOther.includes("clos")
  1415. ],
  1416. scheme(obj, index) {
  1417. switch (index) {
  1418. case 0:
  1419. let x, y;
  1420. var lonlat = obj.geometry.paths[0][0];
  1421. promises.OR.push(new Promise((resolve, reject) => {
  1422. x = obj.geometry.paths[0][0].toString().split(",")[0];
  1423. y = obj.geometry.paths[0][0].toString().split(",")[1];
  1424. advisories.OR.push({
  1425. state: ['OR', 'Oregon'],
  1426. id: obj.attributes.OBJECTID,
  1427. popupType: 0,
  1428. title: obj.attributes.FROM_TO,
  1429. lon: x,
  1430. lat: y,
  1431. type: obj.attributes.CLOSURE_EFFECT,
  1432. keyword: ['Street'], //keywords for roadwork/construction
  1433. desc: obj.attributes.FROM_TO + " - " + obj.attributes.REMARKS,
  1434. time: moment(new Date(obj.attributes.LAST_EDITED_DATE)).format('LLL'),
  1435. link: ''
  1436. });
  1437. resolve();
  1438. }))
  1439. break;
  1440. case 1:
  1441. promises.OR.push(new Promise((resolve, reject) => {
  1442. advisories.OR.push({
  1443. state: ['OR', 'Oregon'],
  1444. id: obj.attributes.incidentId,
  1445. popupType: 0,
  1446. title: obj.attributes.locationName,
  1447. lon: obj.attributes.startLongitude,
  1448. lat: obj.attributes.startLatitude,
  1449. type: obj.attributes.type,
  1450. keyword: ['ROADWORK'], //keywords for roadwork/construction
  1451. desc: obj.attributes.comments + " <br> " + obj.attributes.beginMarker + " to " + obj.attributes.endMarker,
  1452. time: moment(new Date(obj.attributes.lastUpdated)).format('LLL'),
  1453. link: ''
  1454. });
  1455. resolve();
  1456. }))
  1457. break;
  1458. case 2:
  1459. promises.OR.push(new Promise((resolve, reject) => {
  1460. advisories.OR.push({
  1461. state: ['OR', 'Oregon'],
  1462. id: obj.attributes.incidentId,
  1463. popupType: 0,
  1464. title: obj.attributes.locationName,
  1465. lon: obj.attributes.startLongitude,
  1466. lat: obj.attributes.startLatitude,
  1467. type: obj.attributes.type,
  1468. keyword: ['EVENT'], //keywords for roadwork/construction
  1469. desc: obj.attributes.tmddOther + " <br> " + obj.attributes.beginMarker + " to " + obj.attributes.endMarker,
  1470. time: moment(new Date(obj.attributes.lastUpdated)).format('LLL'),
  1471. link: ''
  1472. });
  1473. resolve();
  1474. }))
  1475. }
  1476. },
  1477. URL: ['https://services.arcgis.com/kIA6yS9KDGqZL7U3/ArcGIS/rest/services/RoadWork/FeatureServer/1/query?where=objectid+like+%27%25%27&objectIds=&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&resultType=none&distance=0.0&units=esriSRUnit_Meter&returnGeodetic=false&outFields=*&returnGeometry=true&featureEncoding=esriDefault&multipatchOption=xyFootprint&maxAllowableOffset=&geometryPrecision=&outSR=4326&datumTransformation=&applyVCSProjection=true&returnIdsOnly=false&returnUniqueIdsOnly=false&returnCountOnly=false&returnExtentOnly=false&returnQueryGeometry=true&returnDistinctValues=false&cacheHint=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&having=&resultOffset=&resultRecordCount=&returnZ=false&returnM=false&returnExceededLimitFeatures=true&quantizationParameters=&sqlFormat=none&f=pjson&token=', 'https://tripcheck.com/Scripts/map/data/INCD.js?dt=1607132941398', 'https://tripcheck.com/Scripts/map/data/EVENT.js?dt=1607134261397']
  1478. },
  1479. PA: {
  1480. data(res, index) {
  1481. let resultText = [res, res.features];
  1482. return (resultText[index]);
  1483. },
  1484. filters: [
  1485. obj => (obj.LaneStatus == "closed") || (obj.LaneStatus == "ramp closure")
  1486. ],
  1487. scheme(obj, index) {
  1488. switch (index) {
  1489. case 0:
  1490. let status = obj.LaneStatus;
  1491. let x, y, fromlat, fromlon, tolat, tolon;
  1492. if (typeof obj.IncidentLocLatLong != "string" && typeof obj.FromLocLatLong != "string") {
  1493. return;
  1494. }
  1495. if (typeof obj.IncidentLocLatLong == "string") {
  1496. x = obj.IncidentLocLatLong.split(",")[1];
  1497. y = obj.IncidentLocLatLong.split(",")[0];
  1498. } else {
  1499. x = obj.FromLocLatLong.split(",")[1];
  1500. y = obj.FromLocLatLong.split(",")[0];
  1501. }
  1502. if (typeof obj.FromLocLatLong == "string") {
  1503. fromlon = obj.FromLocLatLong.split(",")[1];
  1504. fromlat = obj.FromLocLatLong.split(",")[0];
  1505. tolon = obj.ToLocLatLong.split(",")[1];
  1506. tolat = obj.ToLocLatLong.split(",")[0];
  1507. } else {
  1508. fromlon = "";
  1509. fromlat = "";
  1510. tolon = "";
  1511. tolat = "";
  1512. }
  1513. promises.PA.push(new Promise((resolve, reject) => {
  1514. advisories.PA.push({
  1515. state: ['PA', 'Pennsylvania'],
  1516. id: obj.EventID,
  1517. popupType: 0,
  1518. title: obj.CountyName,
  1519. lon: x,
  1520. lat: y,
  1521. hasEndpoints: true,
  1522. fromLon: fromlon,
  1523. fromLat: fromlat,
  1524. toLon: tolon,
  1525. toLat: tolat,
  1526. type: obj.EventType,
  1527. keyword: ['roadwork', 'bridge outage'], //keywords for roadwork/construction
  1528. desc: obj.Description + '<br><br>Estimated Opening: ' + moment(new Date(obj.EstDateTimeToOpen)).format('LLL'),
  1529. time: moment(new Date(obj.LastUpdate)).format('LLL'),
  1530. link: ''
  1531. });
  1532. resolve();
  1533. }))
  1534. break;
  1535. case 1:
  1536. var timing;
  1537. if (obj.attributes.endtime == null) {
  1538. timing = moment(new Date(obj.attributes.starttime)).format('LLL');
  1539. } else {
  1540. timing = moment(new Date(obj.attributes.starttime)).format('LLL') + ' to ' + moment(new Date(obj.attributes.endtime)).format('LLL');
  1541. }
  1542. promises.PA.push(new Promise((resolve, reject) => {
  1543. if (obj.attributes.endtime > Date.now()) {
  1544. advisories.PA.push({
  1545. state: ['PA', 'Pennsylvania'],
  1546. id: obj.attributes.GlobalID,
  1547. popupType: 0,
  1548. title: 'HARRISBURG',
  1549. lon: obj.geometry.paths[0][0][0],
  1550. lat: obj.geometry.paths[0][0][1],
  1551. hasEndpoints: true,
  1552. fromLon: obj.geometry.paths[0][0][0],
  1553. fromLat: obj.geometry.paths[0][0][1],
  1554. toLon: obj.geometry.paths[0][obj.geometry.paths[0].length - 1][0],
  1555. toLat: obj.geometry.paths[0][obj.geometry.paths[0].length - 1][1],
  1556. type: 'Closure',
  1557. keyword: ['Closure'], //keywords for roadwork/construction
  1558. desc: obj.attributes.street + ': ' + obj.attributes.description + '<br>' + timing,
  1559. time: moment(new Date(obj.attributes.EditDate)).format('LLL'),
  1560. link: ''
  1561. });
  1562. }
  1563. resolve();
  1564. }))
  1565. }
  1566. },
  1567. URL: ['http://72.167.49.86:8080/PAnew', 'https://services5.arcgis.com/9n3LUAMi3B692MBL/ArcGIS/rest/services/RoadClosures_f0c23ca29f394e03a9ea06a2ffcb317a/FeatureServer/1/query?where=1%3D1&objectIds=&time=&geometry=&geometryType=esriGeometryPoint&inSR=&spatialRel=esriSpatialRelIntersects&resultType=none&distance=0.0&units=esriSRUnit_StatuteMile&returnGeodetic=false&outFields=*&returnGeometry=true&featureEncoding=esriDefault&multipatchOption=xyFootprint&maxAllowableOffset=&geometryPrecision=&outSR=4326&datumTransformation=&applyVCSProjection=false&returnIdsOnly=false&returnUniqueIdsOnly=false&returnCountOnly=false&returnExtentOnly=false&returnQueryGeometry=true&returnDistinctValues=false&cacheHint=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&having=&resultOffset=&resultRecordCount=&returnZ=false&returnM=false&returnExceededLimitFeatures=true&quantizationParameters=&sqlFormat=none&f=pjson&token=']
  1568. },
  1569. VA: {
  1570. data(res, index) {
  1571. let resultText = [res.features, res.features, res.features];
  1572. return (resultText[index]);
  1573. },
  1574. filters: [],
  1575. scheme(obj, index) {
  1576. switch (index) {
  1577. case 0:
  1578. promises.VA.push(new Promise((resolve, reject) => {
  1579. let lat = obj.geometry.coordinates[1];
  1580. let lon = obj.geometry.coordinates[0];
  1581. let thisID = obj.id;
  1582. getFeed(config.VA.detailURL + obj.id, async function (result) {
  1583. var eventObj = JSON.parse(result.responseText);
  1584. if (eventObj[thisID].display_text.toLowerCase().includes("all west lanes are closed")) {
  1585. advisories.VA.push({
  1586. state: ['VA', 'Virginia'],
  1587. id: eventObj[thisID].fid,
  1588. popupType: 0,
  1589. title: "Construction",
  1590. lon: lon,
  1591. lat: lat,
  1592. type: eventObj[thisID].type,
  1593. keyword: ['Constructions'], //keywords for roadwork/construction
  1594. desc: eventObj[thisID].report,
  1595. time: moment(new Date(eventObj[thisID].update * 1000)).format('LLL'),
  1596. link: ''
  1597. });
  1598. }
  1599. resolve();
  1600. });
  1601. }));
  1602. break;
  1603. case 1:
  1604. promises.VA.push(new Promise((resolve, reject) => {
  1605. let lat = obj.geometry.coordinates[1];
  1606. let lon = obj.geometry.coordinates[0];
  1607. let thisID = obj.id;
  1608. getFeed(config.VA.detailURL + obj.id, async function (result) {
  1609. var eventObj = JSON.parse(result.responseText);
  1610. advisories.VA.push({
  1611. state: ['VA', 'Virginia'],
  1612. id: eventObj[thisID].fid,
  1613. popupType: 0,
  1614. title: "High Impact Incident",
  1615. lon: lon,
  1616. lat: lat,
  1617. type: eventObj[thisID].type,
  1618. keyword: ['Constructions'], //keywords for roadwork/construction
  1619. desc: eventObj[thisID].report,
  1620. time: moment(new Date(eventObj[thisID].update * 1000)).format('LLL'),
  1621. link: ''
  1622. });
  1623. resolve();
  1624. });
  1625. }));
  1626. break;
  1627. case 2:
  1628. promises.VA.push(new Promise((resolve, reject) => {
  1629. let lat = obj.geometry.coordinates[1];
  1630. let lon = obj.geometry.coordinates[0];
  1631. let thisID = obj.id;
  1632. getFeed(config.VA.detailURL + obj.id, async function (result) {
  1633. var eventObj = JSON.parse(result.responseText);
  1634. advisories.VA.push({
  1635. state: ['VA', 'Virginia'],
  1636. id: eventObj[thisID].fid,
  1637. popupType: 0,
  1638. title: "Weather",
  1639. lon: lon,
  1640. lat: lat,
  1641. type: eventObj[thisID].type,
  1642. keyword: ['Constructions'], //keywords for roadwork/construction
  1643. desc: eventObj[thisID].report,
  1644. time: moment(new Date(eventObj[thisID].update * 1000)).format('LLL'),
  1645. link: ''
  1646. });
  1647. resolve();
  1648. });
  1649. }));
  1650. }
  1651. },
  1652. URL: ['https://www.511virginia.org/data/geojson/icons.construction.geojson', 'https://www.511virginia.org/data/geojson/icons.high_impact_incident.geojson', 'https://www.511virginia.org/data/geojson/icons.weather_closure.geojson'],
  1653. detailURL: ['https://www.511virginia.org/report-json.pl?idents='],
  1654. },
  1655. WA: {
  1656. data(res, index) {
  1657. let resultText = [res];
  1658. return (resultText[index]);
  1659. },
  1660. filters: [
  1661. obj => (obj.EventCategory == "Closure" || obj.EventCategory == "Construction" || obj.EventCategory == "Bridge")
  1662. ],
  1663. scheme(obj, index) {
  1664. let county;
  1665. if (obj.County == null) {
  1666. county = obj.Region;
  1667. } else {
  1668. county = obj.County;
  1669. }
  1670. let unixtime = parseInt(obj.LastUpdatedTime.replace("/Date(", "").replace(")/", "").split("-")[0]);
  1671. promises.WA.push(new Promise((resolve, reject) => {
  1672. advisories.WA.push({
  1673. state: ['WA', 'Washington'],
  1674. id: obj.AlertID,
  1675. popupType: 0,
  1676. title: county,
  1677. lon: obj.StartRoadwayLocation.Longitude,
  1678. lat: obj.StartRoadwayLocation.Latitude,
  1679. type: obj.EventCategory,
  1680. keyword: ['Construction', 'Closures'], //keywords for roadwork/construction
  1681. desc: obj.HeadlineDescription,
  1682. time: moment(new Date(unixtime)).format('LLL'),
  1683. link: ''
  1684. });
  1685. resolve();
  1686. }))
  1687. },
  1688. URL: ['http://72.167.49.86:8080/WA']
  1689. },
  1690. WI: {
  1691. data(res, index) {
  1692. let resultText = [res];
  1693. return (resultText[index]);
  1694. },
  1695. filters: [
  1696. obj => (obj.EventType == "roadwork" || obj.EventType == "closures" || obj.EventType == "accidentsAndIncidents")
  1697. ],
  1698. scheme(obj, index) {
  1699. let linkvar = '';
  1700. let eText = '';
  1701.  
  1702. let addObj = function () {
  1703. if (obj.PlannedEndDate == null || obj.PlannedEndDate > moment().unix()) {
  1704. promises.WI.push(new Promise((resolve, reject) => {
  1705. advisories.WI.push({
  1706. state: ['WI', 'Wisconsin'],
  1707. id: obj.ID,
  1708. popupType: 0,
  1709. title: obj.County,
  1710. lon: obj.Longitude,
  1711. lat: obj.Latitude,
  1712. type: obj.EventType,
  1713. keyword: ['roadwork', 'closure'], //keywords for roadwork/construction
  1714. desc: eText + ': ' + obj.Description,
  1715. startTime: moment.unix(obj.StartDate).format('LLL'),
  1716. plannedEndTime: moment.unix(obj.PlannedEndDate).format('LLL'),
  1717. time: moment.unix(obj.LastUpdated).format('LLL'),
  1718. link: linkvar,
  1719. recurrence: obj.Recurrence
  1720. });
  1721. resolve();
  1722. }))
  1723. }
  1724. };
  1725.  
  1726. if (obj.EventType == 'closures') {
  1727. linkvar = 'https://511wi.gov/map#ConstructionClosures-' + obj.ID.replace(' ', '%20');
  1728. new Promise((resolve, reject) => {
  1729. getFeed('https://511wi.gov/map/data/ConstructionClosures/' + obj.ID.replace(' ', '%20'), function (result) {
  1730. let resultObj = [];
  1731. resultObj = JSON.parse(result.responseText);
  1732. eText = resultObj.details.detailLang1.eventDescription + ' on ' + resultObj.location.linkDesignator + ' at ' + resultObj.location.crossStreetName
  1733. resolve();
  1734. });
  1735. }).then((result) => addObj());
  1736. }
  1737. else if (obj.EventType == 'accidentsAndIncidents') {
  1738. linkvar = 'https://511wi.gov/map#Incidents-' + obj.ID.replace(' ', '%20');
  1739. addObj();
  1740. }
  1741. else {
  1742. addObj();
  1743. }
  1744. },
  1745. URL: ['http://72.167.49.86:8080/WI']
  1746. },
  1747. WV: {
  1748. data(res, index) {
  1749. let resultText = [res.changes["com.orci.opentms.web.public511.components.plannedevent.shared.data.PlannedEventBean"].changes];
  1750. return (resultText[index]);
  1751. },
  1752. filters: [],
  1753. scheme(obj, index) {
  1754. promises.WV.push(new Promise((resolve, reject) => {
  1755. advisories.WV.push({
  1756. state: ['WV', 'West Virginia'],
  1757. id: obj.entity.dataGatewayId,
  1758. popupType: 0,
  1759. title: obj.entity.routeName,
  1760. lon: obj.entity.x,
  1761. lat: obj.entity.y,
  1762. type: 'Construction',
  1763. keyword: ['Construction'], //keywords for roadwork/construction
  1764. desc: obj.entity.message,
  1765. time: moment(new Date(obj.entity.startTime.millis)).format('LLL'),
  1766. link: ''
  1767. });
  1768. resolve();
  1769. }))
  1770. },
  1771. URL: ['http://72.167.49.86:8080/WV']
  1772. }
  1773. };
  1774. })();