From 9179b14fd4d876ea8997ce39bc0ec3cd4f6a0a73 Mon Sep 17 00:00:00 2001 From: Glenn Vorhes <gavorhes@wisc.edu> Date: Tue, 3 May 2016 12:58:15 -0500 Subject: [PATCH] set up gulp tasks, porting content --- .babelrc | 3 - css/all-ol-style.less | 3 + css/glrtoc/glrtoc-opsmap.less | 132 ++++ css/glrtoc/img/glrtoc-logo.png | Bin 0 -> 13466 bytes css/glrtoc/img/tops-logo.png | Bin 0 -> 6816 bytes css/itsMap.less | 116 +++ css/legend.less | 116 +++ css/media-control.less | 68 ++ css/npmrds-heatmap.less | 174 +++++ css/ol-popup.less | 68 ++ css/peergroup.less | 173 +++++ css/tip-colors.less | 30 + css/tip-results.less | 136 ++++ css/tip.less | 159 ++++ gulpfile.js | 230 ++++++ lib/jquery.floatThead.js | 967 +++++++++++++++++++++++++ package.json | 25 +- projects/glrtoc/appConfig.js | 150 ++++ projects/glrtoc/layerPopups.js | 37 + projects/glrtoc/layerStyles.js | 39 + projects/glrtoc/legendTest.js | 129 ++++ projects/glrtoc/main.js | 319 ++++++++ projects/glrtoc/mainUi.js | 105 +++ projects/itsMap.js | 27 + projects/npmrds/delay/delay-config.js | 3 + projects/npmrds/delay/delay-main.js | 32 + projects/npmrds/heatmap/appConfig.js | 50 ++ projects/npmrds/heatmap/layerStyles.js | 43 ++ projects/npmrds/heatmap/main-ui.js | 368 ++++++++++ projects/npmrds/heatmap/main.js | 47 ++ projects/tsmo/TipConfig.js | 149 ++++ projects/tsmo/TipSegmentLayer.js | 191 +++++ projects/tsmo/legend-test.js | 84 +++ projects/tsmo/main-report.js | 198 +++++ projects/tsmo/main-ui.js | 126 ++++ projects/tsmo/main.js | 166 +++++ projects/tsmo/slider-test.js | 29 + projects/tsmo/tipStyleFunction.js | 84 +++ src/collections/ItsLayerCollection.js | 2 +- src/collections/LayerLegend.js | 2 +- src/collections/Sliders.js | 2 +- src/jquery-plugin/dayRange.js | 2 +- src/jquery-plugin/mediaControl.js | 2 +- src/jquery-plugin/rangeChange.js | 2 +- src/jquery-plugin/rpPicker.js | 2 +- src/jquery-plugin/ssaCorridorPicker.js | 2 +- src/jquery.js | 6 + src/layers/LayerBase.js | 2 +- src/layers/LayerBaseVector.js | 4 +- src/layers/LayerBaseVectorEsri.js | 2 +- src/layers/LayerBaseVectorGeoJson.js | 2 +- src/layers/LayerBaseXyzTile.js | 2 +- src/layers/LayerEsriMapServer.js | 2 +- src/layers/LayerItsInventory.js | 2 +- src/layers/LayerRealEarthTile.js | 2 +- src/mixin/RealEarthAnimate.js | 2 +- src/olHelpers/mapMoveCls.js | 2 +- src/olHelpers/mapPopupCls.js | 2 +- src/olHelpers/quickMapBase.js | 2 +- 59 files changed, 4799 insertions(+), 25 deletions(-) delete mode 100644 .babelrc create mode 100644 css/all-ol-style.less create mode 100644 css/glrtoc/glrtoc-opsmap.less create mode 100644 css/glrtoc/img/glrtoc-logo.png create mode 100644 css/glrtoc/img/tops-logo.png create mode 100644 css/itsMap.less create mode 100644 css/legend.less create mode 100644 css/media-control.less create mode 100644 css/npmrds-heatmap.less create mode 100644 css/ol-popup.less create mode 100644 css/peergroup.less create mode 100644 css/tip-colors.less create mode 100644 css/tip-results.less create mode 100644 css/tip.less create mode 100644 gulpfile.js create mode 100644 lib/jquery.floatThead.js create mode 100644 projects/glrtoc/appConfig.js create mode 100644 projects/glrtoc/layerPopups.js create mode 100644 projects/glrtoc/layerStyles.js create mode 100644 projects/glrtoc/legendTest.js create mode 100644 projects/glrtoc/main.js create mode 100644 projects/glrtoc/mainUi.js create mode 100644 projects/itsMap.js create mode 100644 projects/npmrds/delay/delay-config.js create mode 100644 projects/npmrds/delay/delay-main.js create mode 100644 projects/npmrds/heatmap/appConfig.js create mode 100644 projects/npmrds/heatmap/layerStyles.js create mode 100644 projects/npmrds/heatmap/main-ui.js create mode 100644 projects/npmrds/heatmap/main.js create mode 100644 projects/tsmo/TipConfig.js create mode 100644 projects/tsmo/TipSegmentLayer.js create mode 100644 projects/tsmo/legend-test.js create mode 100644 projects/tsmo/main-report.js create mode 100644 projects/tsmo/main-ui.js create mode 100644 projects/tsmo/main.js create mode 100644 projects/tsmo/slider-test.js create mode 100644 projects/tsmo/tipStyleFunction.js create mode 100644 src/jquery.js diff --git a/.babelrc b/.babelrc deleted file mode 100644 index c6c9efb..0000000 --- a/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ -"presets": ["es2015"] -} \ No newline at end of file diff --git a/css/all-ol-style.less b/css/all-ol-style.less new file mode 100644 index 0000000..41a007c --- /dev/null +++ b/css/all-ol-style.less @@ -0,0 +1,3 @@ +@import (inline) "../node_modules/openlayers/dist/ol.css"; +@import "legend"; +@import "ol-popup"; diff --git a/css/glrtoc/glrtoc-opsmap.less b/css/glrtoc/glrtoc-opsmap.less new file mode 100644 index 0000000..6e0df65 --- /dev/null +++ b/css/glrtoc/glrtoc-opsmap.less @@ -0,0 +1,132 @@ +@import "../all-ol-style"; +@import "../media-control"; + + +body, html { + height: 100%; + width: 100%; + margin: 0; + padding: 0; +} + +#main-container { + height: 100%; +} + +.flex-container { + display: flex; + + //> div { + // flex-grow: 1; + //} +} + +#map{ + flex-grow: 1; +} + + +#sidebar { + height: 100%; + width: 350px; + flex-grow: initial; + position: relative; +} + +#logo-container { + > div { + flex-grow: 1; + } + + div { + margin: 7px; + height: 150px; + } + + div:first-child { + background: url('img/glrtoc-logo.png') no-repeat center; + background-size: contain; + } + + div:nth-child(2) { + background: url('img/tops-logo.png') no-repeat center; + background-size: contain; + } +} + +#map { + position: relative; +} + +#tabs { + height: 100%; + padding: 0; + border: none; + width: 100%; + + + > div { + padding: 0; + height: 98%; + + p { + text-align: justify; + padding: 7px 12px; + margin: 10px 0; + } + + } + + .ui-tab { + padding: 3px 7px !important; + } +} + +#operations-tab { + h3 { + margin-top: 0; + padding-top: 5px; + padding-bottom: 5px; + } + + > div{ + padding: 0; + } +} + +#hide-sidebar, #show-sidebar { + z-index: 5; + position: absolute; + color: white; + cursor: pointer; +} + +//hide sidebar span +#hide-sidebar { + right: 4px; + top: 9px; +} + +#show-sidebar { + display: none; + left: -12px; + top: 74px; + background: linear-gradient(#74BBD8, #3FA3CA); + width: 40px; + text-align: right; + padding: 10px 4px; + border-radius: 5px; + border: solid #4297D7 1px; +} + +#operations > div { + padding: 0; +} + +#animation-control { + text-align: center; + padding: 10px; +} + + + diff --git a/css/glrtoc/img/glrtoc-logo.png b/css/glrtoc/img/glrtoc-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e703e4220e4f9bfc334eb49e95d19b8e9720aefe GIT binary patch literal 13466 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 Cmu+?c literal 0 HcmV?d00001 diff --git a/css/glrtoc/img/tops-logo.png b/css/glrtoc/img/tops-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..436dbf5a4ff00a9dcea8dd51add6f68b5943c4f7 GIT binary patch literal 6816 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 literal 0 HcmV?d00001 diff --git a/css/itsMap.less b/css/itsMap.less new file mode 100644 index 0000000..7cbd153 --- /dev/null +++ b/css/itsMap.less @@ -0,0 +1,116 @@ +@import "./all-ol-style"; + + +@headerHeight: 80px; + +body, html { + height: 100%; + width: 100%; + margin: 0; + padding: 0; +} + +#header { + height: @headerHeight; + background-color: #808080; + + span { + display: inline-block; + margin: 9px; + font-size: 28px; + line-height: 30px; + } + + a { + float: right; + } + + img { + margin: 3px 10px; + max-height: @headerHeight - 10px; + width: auto; + } +} + +#container { + display: flex; + height: ~"calc(100% - " @headerHeight ~")"; + width: 100%; +} + +#left { + height: 100%; + width: 320px; + overflow-y: auto; +} + +#map { + flex: 1 +} + +.legend-container { + border: none; +} + +@media screen and (max-height: 650px) { + +} + +@media screen and (max-height: 640px), (max-width: 650px) { + + #header a { + display: none; + } + + #header{ + display: none; + } + + #container { + //display: block; + height: 100%; + } + + #left { + width: 246px; + height: auto; + position: absolute; + top: 5px; + right: 5px; + z-index: 10; + background-color: white; + -webkit-border-radius:5px; + -moz-border-radius:5px; + border-radius: 5px; + max-height: 250px; + overflow-y: scroll; + } + + #map{ + height: 100%; + } + + .legend-container ul{ + padding-left: 5px; + } + +} + +@media screen and (max-height: 500px), (max-width: 346px) { + #left{ + width: 204px; + max-height: 204px; + } + + .ol-popup{ + width: 240px; + min-width: 240px; + + iframe{ + width: 240px; + } + } +} + + + diff --git a/css/legend.less b/css/legend.less new file mode 100644 index 0000000..504f281 --- /dev/null +++ b/css/legend.less @@ -0,0 +1,116 @@ +@legendKeyOffset: 7px; + +@rectangleImg: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHQAAAATCAMAAAB2tdn3AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAAcHBwoKCgsLCw0NDQ4ODg8PDxAQEBYWFhcXFxsbGxwcHB0dHR4eHh8fHyAgICEhISIiIiQkJCUlJSYmJicnJygoKCkpKSoqKiwsLC0tLS4uLi8vLzAwMDQ0NDU1NTc3Nzg4ODk5OT09PT4+Pj8/P0FBQUJCQkNDQ0REREZGRkdHR0hISElJSUpKSktLS0xMTE1NTU5OTk9PT1FRUVJSUlNTU1RUVFZWVldXV1hYWFlZWVpaWl5eXmBgYGFhYWJiYmRkZGZmZmhoaGlpaWpqam1tbW5ubm9vb3Nzc3V1dXd3d3l5eXx8fH5+fn9/fwCADwGBEQKCEgGJEwKKEwSMFQGRFAKSFAKTFQiXGguUHRifKAynGAipFROjJhukLR+iMSaWNCuVOCGhMSSmND+oTT20SwnQGwzRHRDCJRPDKADjHQDmGgDmGwDlHQHpHwDyFwDzGQD1GAD2GQD3HQD3HgD/HgD/HwLqIAD/IAD/IQD/IkeFTkiFUEiGUFeNXlmPX0SrU0i4VVajX2CpaW2kdF7MbGHPbnyxgoCAgIGBgYKCgoODg4SEhIWFhYiIiImJiYuLi4yMjI6OjpCQkJWVlZiYmJqampubm5ycnImwjI+zkZqomKSkpKampqioqKurq6ysrK2tra6urq+vr6SwogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP4rSb8AAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4wLjOM5pdQAAAB+UlEQVRIS5WV6VfTQBTFA7YgoICsFtmxgLRShQIqCLKDKEFQ3FlERdlxwwTBBQRMKVqQRdSyCH/n803yevj65ndy8iY55957ZpJ5owDAgdceJkVSE6pMWlPoFRN7yS6qMNSbahlIUJdg1dM1VpXAUSRCL7fQoxQx4hZrDiVpvQjK/kkxajyf7Ujj4Eg/V7WBgp1KgMogDg6/9N7pus3iwcC8yDq1p3hEdRX7Aqs8At9rM9tQEglwHMvSo1eaPs1Dnxp+gpINjxKBpfqqX+Xju5mPGlxfsUZD73QZ3nxGjU0JA1h3Gt8kUI16nGo8wAmAxQlyY6K9+A1wTITWuVZUMmShGhUAcWboU7mJ6vrIJ4BwEVpe4ic7Jv7cUGinRmZMtPFZCvWWLpMbk5WcUGgHmbF5/4FCy2RDj2Z6i7y4aOMzFFrr9kt+07JQaN8UuXEZ/UihP/N8ZMdCNRqvh/7ehUky4zK4Lf5eG26cqmsy+9RoL0BNtLVPX8pN9e0z1NgV7L8AhaXLAW5L+tGUJbo1dqQoLF8fv5boSGP9KPnlVoK4TgA1ZzPTWZzJcJavCcUFvP5h/fO85173XRb3H84JZeJfBdz4geQxTxnzrJDlhlOcp66ETXpmc4XO0+RLVuWzlZJnHuKw67GFS5HYYDkANCfTKyY2VxAA/gOxObo6iNgi8wAAAABJRU5ErkJggg=='); + + +.legend-container { + list-style: none; + border: solid black 1px; + border-radius: 5px; + background-color: rgba(211, 211, 211, 0.2); + margin: 2px; + padding: 2px; + + ul { + list-style: none; + padding-left: 17px; + } + + li { + border-radius: 7px; + margin: 2px; + padding: 2px 4px; + } + + hr { + display: inline-block; + width: 40px; + height: 10px; + background-color: blue; + border: none; + margin: 0 0 3px @legendKeyOffset; + } + + > li:first-child { + font-weight: bold; + min-height: 25px; + + input { + display: none; + } + + input + label { + width: 100px; + height: 19px; + margin: 5px; + display: inline-block; + } + + input + label > span { + display: inline-block; + width: 59px; + height: 19px; + background: @rectangleImg no-repeat 0 0; + } + + + + input:checked + label > span { + background: @rectangleImg no-repeat -59px 0; + } + } +} + + +.legend-layer-subitem { + display: inline-block; + max-width: 148px; + overflow: hidden; + max-height: 20px; +} + +.legend-layer-icon { + margin-left: @legendKeyOffset; +} + +.legend-layer-div li { + margin: 0; + padding-top: 0; + padding-bottom: 0; +} + +.layer-not-visible { + background-color: gray; + display: none; +} + +.layer-force-show { + display: inherit; +} + +.layer-group-expander, .map-server-expander, .unique-symbol-expander, .legend-items-expander { + color: #59AFEE; + cursor: pointer; + padding-left: 4px; + font-size: 14px; +} + +.esri-popup-table{ + border-collapse: collapse; + + td, th { + border: solid black 1px; + padding: 0 4px; + } + + tr:nth-child(even){ + background-color: lightblue; + } +} + +.legend-layer-name, .legend-check{ + cursor: pointer +} + + + diff --git a/css/media-control.less b/css/media-control.less new file mode 100644 index 0000000..9233513 --- /dev/null +++ b/css/media-control.less @@ -0,0 +1,68 @@ +@mediaImg: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJEAAAAdCAMAAACddH6yAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAJycmKygmLCknKSkpKSkqLysqLCwsLS0tLi4uLi8vMCwrMi0sMS8tNCwpMTAvNzAvMDAwMTExMTEyMjIxMjIyMzMzMzM0MzQ0NjExNzMxNDQ0NTU1NTY2Njc3OTMxOTc2PDg2OTk5OTo7PTo5Pz4+Pj8/RDs2R0A9REA+QkNDQkRFR0hIS0NBS0VCTUdES0tLTU5NVFRUVVdYYFlXZl9caF9cYWBgZ2Jham1ubGxsc3JycXR2Zn6HaYCIcpSegHx7hIWFjo+PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAptsNGgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuM4zml1AAAAIpSURBVFhH7ZdrV9QwEIYriLDgbQsdUfCKchEVBBVUFOH//6c482a627Qz2VVzjl94PiQznZP02TRNz1bhETnUIYRa4wEbXNzUeEAza+S2xgP4ntWqxhb+tEwYaWARGg0sQvaelQYmT7U32dH+z3mmvUktRuu8jgPecmHLK4qNzCuPZ8A7XR+zeMgF+aFm8ZhHNmxkFrER2MgpfohGmvV4JT5ecR9GzrS70cgZGmC0rEmfnBEXmRVN+sBI3hqLOYz8eWcZjTTpk1ujG6PI3Ebj2+g+ob0vTdfomr7EoCUx+jUh5nMa3UO+iraJO6tr1CxI+xw7eemutKlR72clRjAAnbw10qud4sQIbY3WM6rxbtVkGRGNYwyKGBF9lbtJ4hjxAcVG3NpGRA9jxhQyosf4Ul04RhyykbSeEdFlzLlYxojW8O08qA0jKbT4Ru2jK2bUYhh1lXyj5iJeKGY0xhqNrTVawDLNeGrvYyrFMkZ3sI/OvJ29jp3NVxyjzstWyOgIX3SO/+rtxywtRYzQ5s+jcIQTctEyOo+RUsQIeVx4w2h0C91PtHvSJEYPYj8hMerDlalRn6mRQddoSNdowI0R+H9GTvUNjJzij5zRCYyckZ9zRqfRiF5rnsIFNqKXmqbwYSpGLzRN0dP/iaYpXGQj2tY0hQswosZAruOvp+YJM4tA8wS5nh3ZVNMJhuCE90i/zT3+YWSVGft98gAMPuL8d/iWKx7nilfhN6Q1MB5pcaF/AAAAAElFTkSuQmCC'); + +.media-control-container { + padding: 10px; + text-align: center; + + input[type=range]{ + width: 80%; + } + + input[type=range]:disabled{ + cursor: not-allowed; + background-color: lightgray; + } +} + +.media-player-button { + background: @mediaImg no-repeat; + height: 29px; + width: 30px; + display: inline-block; + margin: 0 2px; + cursor: pointer; +} + +.media-player-button:hover { + background-color: lightblue; +} + +.media-pause { + background-position: -86px 0; +} + +.media-play { + background-position: -28px 0; +} + +.media-stop { + background-position: -57px 0; +} + +.media-ahead { + background-position: -116px 0; +} + +.media-back { + background-position: 1px 0; +} + +.media-disabled { + display: none; +} + +.media-locked{ + background-color: lightgray !important; + cursor: not-allowed; +} + +.media-control-value-label-container{ + display: flex; + justify-content: space-between; + + span{ + display: block; + font-size: small; + } +} + diff --git a/css/npmrds-heatmap.less b/css/npmrds-heatmap.less new file mode 100644 index 0000000..16ffa8b --- /dev/null +++ b/css/npmrds-heatmap.less @@ -0,0 +1,174 @@ +@heatMapControlHeight: 135px; +@heatMapSliderHeight: 30px; +@import "./all-ol-style"; + + +html, body { + height: 100%; + width: 100%; + margin: 0; + /*position: relative;*/ +} + +#container { + display: flex; + height: 100%; + width: 100%; +} + +#map { + flex: 1; +} + +#left { + flex: initial; + width: 300px; + min-width: 100px; + + > div { + margin: 10px; + } +} + +#ul-hwy-dirs { + list-style: none; + padding-left: 5px; + max-height: 300px; + overflow-y: auto; + background-color: lightgrey; + + li { + padding: 2px; + } +} + +h4 { + margin: 10px 5px; +} + +#right { + width: 60%; + height: 100%; + + input[type=button] { + margin: 3px 0; + } +} + +#heat-map-control { + display: flex; + flex-wrap: wrap; + height: @heatMapControlHeight; + + > div { + margin: 0 5px; + } + + ul { + list-style: none; + padding-left: 0; + margin-top: 14px; + } +} + +#heat-slider-container { + height: @heatMapSliderHeight; +} + +#heat-map-slider { + border: none; + width: 95%; + padding: 0; + margin: 0 0 0 18px; +} + +#heatmap-canvas { + position: absolute; + top: 0; + left: 22px; + cursor: crosshair; +} + +#heat-slider-container, #canvas-container { + width: 100%; + position: relative; +} + +#canvas-container { + height: ~"calc(100% - " @heatMapControlHeight + @heatMapSliderHeight ~")"; + overflow-y: auto; +} + +#heat-map-vertical-bar { + position: absolute; + /*z-index: 4;*/ + border-right: solid blue 2px; + left: 22px; + top: 0; + width: 0; + height: 0; + background-color: rgba(100, 100, 100, 0.3); +} + +#date-ul { + list-style: none; + margin: 0; + padding: 0; + position: absolute; + left: 0; + top: 0; + z-index: -5; + + li { + border-bottom: solid #000000 1px; + height: 575px; + } + + li:nth-child(odd) { + background-color: lightblue; + } + + li div { + color: blue; + height: 150px; + transform: rotate(-90deg) translate(-259px, 0px); + transform-origin: left top 0; + float: left; + } +} + +#canvas-tooltip-span { + display: none; + z-index: 100; + position: fixed; + background-color: lightgrey; + border: solid black 1px; + border-radius: 5px; + padding: 5px; + /*height: 50px;*/ + width: 160px; + overflow: hidden; + text-align: center; +} + +#progress-indicator-div { + z-index: 200; + background-color: lightblue; + border: solid darkslategray 1px; + border-radius: 5px; + width: 200px; + padding: 10px; + margin: 20px; + display: none; +} + +#sel-hwy { + padding-left: 14px; + padding-top: 9px; + font-weight: bold; + display: inline-block; +} + +/*.ui-datepicker{*/ +/*z-index: 100 !important;*/ +/*}*/ \ No newline at end of file diff --git a/css/ol-popup.less b/css/ol-popup.less new file mode 100644 index 0000000..8e13d3e --- /dev/null +++ b/css/ol-popup.less @@ -0,0 +1,68 @@ +.ol-popup { + position: absolute; + background-color: white; + -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2)); + filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2)); + padding: 22px 5px 5px 5px; + border-radius: 10px; + border: 1px solid #cccccc; + bottom: 12px; + left: -50px; + min-width: 280px; + cursor: default; +} + +.ol-popup:after, .ol-popup:before { + top: 100%; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; +} + +.ol-popup:after { + border-top-color: white; + border-width: 10px; + left: 48px; + margin-left: -10px; +} + +.ol-popup:before { + border-top-color: #cccccc; + border-width: 11px; + left: 48px; + margin-left: -11px; +} + +.ol-popup-closer { + text-decoration: none; + position: absolute; + top: 2px; + right: 8px; +} + +.ol-popup-closer:after { + content: "X"; +} + +.ol-popup-nav { + background-color: lightgray; + padding: 3px; + margin-bottom: 7px; +} + +.ol-popup-nav-arrow{ + color: #419CC4; + cursor: pointer; + margin: 0 3px; + font-size: larger; +} + +.ol-inner-inner { + height: 300px; + //width: 392px; + //padding-right: 25px; + overflow-y: auto; +} diff --git a/css/peergroup.less b/css/peergroup.less new file mode 100644 index 0000000..e0fb5e7 --- /dev/null +++ b/css/peergroup.less @@ -0,0 +1,173 @@ +@import './all-ol-style'; + +@sidebarWidth: 280px; + +html, body { + margin: 0; + padding: 0; + height: 100%; + width: 100%; +} + +#app-container { + display: flex; + height: 100%; + + > div { + height: 100%; + overflow-y: auto; + } +} + +#left-sidebar { + width: @sidebarWidth; + + label { + display: inline-block; + margin-left: 4px; + } + + h6 { + margin-top: 5px; + margin-bottom: 2px; + } +} + +#accordion { + font-size: 0.9em !important; + + h3 { + padding-top: 1px; + padding-bottom: 1px; + margin-bottom: 2px; + } +} + +#right-sidebar { + width: 400px; +} + +#map { + flex: 1; +} + +#dialog{ + display: none; +} +// +.ui-accordion-content { + padding: 5px 10px !important; +} + +select { + margin: 4px; + padding: 0; +} + +input[type=text] { + margin: 2px 7px; + padding: 5px; +} + +.divUnd { + width: 100px; + +} + +.equality-compare { + width: 45px; +} + +.class-adtVal { + width: 90px; +} + +.class-laneVal, .class-speedVal { + width: 50px; +} + +.comma-list { + width: 250px; + +} + +#summary { + border-collapse: collapse; +} + +#summary tr { + height: 30px; +} + +#summary th, td { + border: 1px solid black; + padding: 1px 4px; + text-align: center; + //color: #636363; +} + +.invalid { + border: solid red 1px !important; +} + +.popup-table { + border-collapse: collapse; + margin-top: 5px; + +} + +.popup-table th, td { + border: 1px solid black; +} + +// +//.ol-popup { +// display: none; +// position: absolute; +// background-color: white; +// -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); +// -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2)); +// filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2)); +// padding: 15px; +// border-radius: 10px; +// border: 1px solid #cccccc; +// bottom: 12px; +// left: -50px; +//} +// +//.ol-popup:after, .ol-popup:before { +// top: 100%; +// border: solid transparent; +// content: " "; +// height: 0; +// width: 0; +// position: absolute; +// pointer-events: none; +//} +// +//.ol-popup:after { +// border-top-color: white; +// border-width: 10px; +// left: 48px; +// margin-left: -10px; +//} +// +//.ol-popup:before { +// border-top-color: #cccccc; +// border-width: 11px; +// left: 48px; +// margin-left: -11px; +//} +// +//.ol-popup-closer { +// text-decoration: none; +// position: absolute; +// top: 2px; +// right: 8px; +//} +// +//.ol-popup-closer:after { +// content: "✖"; +//} +// +// diff --git a/css/tip-colors.less b/css/tip-colors.less new file mode 100644 index 0000000..669e4c5 --- /dev/null +++ b/css/tip-colors.less @@ -0,0 +1,30 @@ +.cell-min { + background-color: #00ff00 !important; +} + +.cell-very-low { + background-color: #55ff00 !important; +} + +.cell-low { + background-color: #aaff00 !important; +} + +.cell-mid { + background-color: #ffff00 !important; +} + +.cell-high { + background-color: #ffaa00 !important; +} + +.cell-very-high { + background-color: #ff5500 !important; + font-weight: bold; +} + +.cell-max { + background-color: #ff0000 !important; + font-weight: bold; + text-decoration: underline; +} \ No newline at end of file diff --git a/css/tip-results.less b/css/tip-results.less new file mode 100644 index 0000000..8a04f94 --- /dev/null +++ b/css/tip-results.less @@ -0,0 +1,136 @@ +@import "tip-colors"; +@import "./all-ol-style"; + +body, html, #container { + height: 100%; + width: 100%; + margin: 0; + padding: 0; +} + +#container, #summary { + display: flex; +} + +#summary { + height: 38%; + + > div { + flex-grow: 1; + height: 100%; + overflow-y: auto; + } +} + +#crash-data { + table { + border-collapse: collapse; + margin: 7px 4px 0 4px; + } + + th, td { + border: solid black 1px; + text-align: center; + padding: 0 5px; + } +} + +#right { + flex: 1; +} + +#map { + height: 60%; + position: relative; +} + +#legend-container { + position: absolute; + width: 250px; + max-height: 80%; + min-height: 30px; + overflow-y: auto; + background-color: rgba(255, 255, 255, 0.8); + z-index: 10; + top: 5px; + right: 5px; + border-radius: 7px; + + > ul { + > li:first-child { + display: none; + } + } +} + +#summary { + h3, h4, ul { + margin: 5px 10px; + } +} + +#results-container { + width: 936px; + padding-right: 20px; + height: 100%; + overflow: auto; + position: relative; + table { + border-collapse: collapse; + margin: 4px; + width: 100%; + //height: 100%; + position: relative; + table-layout: fixed; + + th, td { + border: solid black 1px; + padding: 3px; + text-align: center; + } + + > *{ + width: 100%; + } + + th { + cursor: pointer; + } + + thead { + + display: block; + width: 100%; + + tr { + background-color: #4a4a4a; + color: #FDFDFD; + width: 100%; + } + } + + tbody { + display: block; + height: 400px; + overflow-y: auto; + width: 100%; + } + } +} + +.selectable-row:hover { + background-color: #00ffd0; + cursor: pointer; +} + +.selected-row { + background-color: #0074ff !important; +} + +.score-under-one { + display: none; +} + +#show-all-toggle, #show-all-toggle-label { + cursor: pointer; +} diff --git a/css/tip.less b/css/tip.less new file mode 100644 index 0000000..09ac1b5 --- /dev/null +++ b/css/tip.less @@ -0,0 +1,159 @@ +@import "./tip-colors"; +@import "./all-ol-style"; + +html, body { + width: 100%; + height: 100%; + margin: 0; +} + +#container { + display: flex; + height: 100%; + width: 100%; +} + +#left { + overflow-y: scroll; + background-color: lightblue; + height: 100%; + width: 320px; +} + +// suppress first li in legend +.legend-container { + > li:first-child { + display: none; + } +} + +//tip legend style +#tip-segments-layer-li { + display: inherit; + + > div { + height: 80px; + + hr { + height: 4px; + } + + ul:first-of-type { + float: right; + padding-left: 0; + + li { + height: 10px; + } + } + + ul:last-of-type { + float: right; + margin-top: 5px; + + li { + margin: 3px 0; + text-align: right; + border-right: solid black 1px; + border-radius: 0; + } + } + } +} + +//common border styling of legend and preset container +#preset-wrapper, .legend-container { + border: solid black 1px; + border-radius: 5px; +} + +#preset-wrapper { + margin: 3px; + padding: 3px; + border: solid black 1px; + border-radius: 5px; + + h4 { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + } + + select { + width: 141px; + } + + input[type=button] { + width: 88px; + margin: 0; + } +} + +.slider-container { + + > div { + padding: 2px; + border-bottom: solid darkblue 1px; + //min-height: 46px; + } + + label { + display: inline-block; + } + + .slider-label { + width: 97px; + } + + .hidden-select { + display: none; + } + + .percent-label { + padding: 2px 3px; + margin-left: 2px; + background-color: lightgray; + font-weight: bold; + color: orangered; + } + + input[type=range] { + width: 153px; + padding: 1px; + + } + + input[type=range][disabled] { + background-color: #59afee; + cursor: not-allowed; + } + + select { + margin-bottom: 2px; + width: 46px; + } + + .low-high { + font-size: 12px; + } +} + +// offset around show help button +#tip-help { + margin-left: 10px; + margin-top: 4px; +} + +#map { + background-color: slategray; + height: 100%; + flex: 1; + position: relative; +} + +#loading-gif { + left: 10px; + top: 80px; + z-index: 10; + position: absolute; +} diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..8ba80e8 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,230 @@ +const gulp = require('gulp'); +const babel = require('gulp-babel'); +const babelify = require('babelify'); +const browserify = require('browserify'); +const buffer = require('vinyl-buffer'); +const source = require('vinyl-source-stream'); +const sourcemaps = require('gulp-sourcemaps'); +const minify = require('gulp-minify'); +const less = require('gulp-less'); +const cssmin = require('gulp-cssmin'); +const rename = require('gulp-rename'); + + +/** + * + * @param {string} inputFile - input file + * @param {string} outputFile - output file + * @param {boolean|*} runMinify - if should minify + * @returns {object} return stream + */ +function processJsFile(inputFile, outputFile, runMinify) { + "use strict"; + runMinify = typeof runMinify == 'boolean' ? runMinify : false; + let pathParts = outputFile.split('/'); + let outFileName = pathParts[pathParts.length - 1]; + pathParts.splice(pathParts.length - 1, 1); + let outDir = pathParts.length === 0 ? '.' : pathParts.join('/'); + + let bundler = browserify({entries: inputFile, "debug": true, "extensions": ["js"]}); + + bundler.transform(babelify.configure({ + presets: ["es2015"], + "ignore": /custom-ol-build|jquery.min/ + })); + + + //bundler.transform(babelify.configure({ + // ignore: /custom-ol-build|jquery.min/ + //})); + //let bundler = browserify({entries: inputFile, extensions: ['.js'], debug: true}) + // .transform(babelify.configure({ + // ignore: /custom-ol-build.js|jquery.min|/, + // presets: ["es2015"], + // extensions: [".ts", ".js"] + // })); + + + //bundler.transform("babelify", {presets: ["es2015"], ignore: /custom-ol-build.js|jquery.min|/}, extensions: ['.js', '.ts']); + + + if (runMinify) { + return bundler.bundle() + .on('error', function (err) { + console.error(err); + }) + .pipe(source(outFileName)) + .pipe(buffer()) + .pipe(sourcemaps.init({loadMaps: true})) + .pipe(minify({ + ext: { + src: '-debug.js', + min: '.js' + }, + exclude: ['tasks'], + ignoreFiles: ['.combo.js', '-min.js'] + })) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(outDir)); + } else { + return bundler.bundle() + .on('error', function (err) { + console.error(err); + }) + .pipe(source(outFileName)) + .pipe(buffer()) + .pipe(sourcemaps.init({loadMaps: true})) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(outDir)); + } +} + +function processLessFile(inputFile, outputFile) { + "use strict"; + let pathParts = outputFile.split('/'); + let outFileName = pathParts[pathParts.length - 1]; + pathParts.splice(pathParts.length - 1, 1); + let outDir = pathParts.length === 0 ? '.' : pathParts.join('/'); + + let fileNameParts = outFileName.split('.'); + + return gulp.src(inputFile) + .pipe(less().on('error', function (err) { + console.log(err); + })) + .pipe(cssmin().on('error', function (err) { + console.log(err); + })) + .pipe(rename({ + basename: fileNameParts[0], + extname: '.' + fileNameParts[1], + suffix: '.min' + })) + .pipe(gulp.dest(outDir)); +} + +//gulp.task('default', function () { +// "use strict"; +// return gulp.src('src/app.js') +// .pipe(babel()) +// .pipe(gulp.dest('dist')) +//}); + +function _itsInventory(doMinify) { + "use strict"; + //processLessFile('./flaskApp/blueprints/its_inventory/static/css/itsMap.less', './flaskApp/blueprints/its_inventory/static/_build/itsMap.css'); + + return processJsFile('./projects/itsMap.js', './build/itsMap.js', doMinify); +} + +gulp.task('itsInventory-dev', () => { + return _itsInventory(false); +}); + +gulp.task('itsInventory-prod', () => { + return _itsInventory(true); +}); + +function _glrtoc(doMinify) { + "use strict"; + processJsFile('./projects/glrtoc/main.js', './build/glrtoc/main.js', doMinify); + + return processJsFile('./projects/glrtoc/legendTest.js', './build/glrtoc/legendTest.js', doMinify); +} + +gulp.task('glrtoc-dev', () => { + "use strict"; + + return _glrtoc(false); +}); + +gulp.task('glrtoc-prod', () => { + "use strict"; + + return _glrtoc(true); +}); + +function _tsmo(doMinify) { + "use strict"; + processJsFile('./projects/tsmo/legend-test.js', './build/legend-test.js', doMinify); + //processJsFile('./projects/tsmo/slider-test.js', './build/slider-test.js', doMinify); + //processJsFile('./projects/tsmo/main.js', './build/main.js', doMinify); + //return processJsFile('./projects/tsmo/main-report.js', './build/main-report.js', doMinify); +} + +gulp.task('tsmo-dev', () => { + "use strict"; + + return _tsmo(false); +}); + +gulp.task('tsmo-prod', () => { + "use strict"; + + return _tsmo(true); +}); + +function _npmrds(doMinify) { + "use strict"; + + return processJsFile('./flaskApp/blueprints/npmrds/static/js/heatmap/main.js', './flaskApp/blueprints/npmrds/static/_build/heatmap-main.js', doMinify); +} + +gulp.task('npmrds-dev', () => { + "use strict"; + + return _npmrds(false); +}); + +gulp.task('npmrds-prod', () => { + "use strict"; + + return _npmrds(true); +}); + +function _ssa(doMinify) { + "use strict"; + processLessFile('./flaskApp/blueprints/testing/static/css/ssa-corridor.less', './flaskApp/blueprints/testing/static/_build/ssa-corridor.css'); + + return processJsFile('./flaskApp/blueprints/testing/static/js/ssa-main.js', './flaskApp/blueprints/testing/static/_build/ssa-main.js', doMinify); +} + +gulp.task('ssa-dev', () => { + "use strict"; + + return _ssa(false); +}); + +gulp.task('ssa-prod', () => { + "use strict"; + + return _ssa(true); +}); + +gulp.task('peerGroup-dev', () => { + "use strict"; + + return processJsFile('./flaskApp/blueprints/peerGroup/static/js/main.js', './flaskApp/blueprints/peerGroup/static/_build/main.js', false); +}); + +gulp.task('peerGroup-prod', () => { + "use strict"; + + return processJsFile('./flaskApp/blueprints/peerGroup/static/js/main.js', './flaskApp/blueprints/peerGroup/static/_build/main.js', true); +}); + +function _buildTestApps() { + "use strict"; + //processJsFile('./flaskApp/blueprints/testing/static/js/test-custom-build.js', './flaskApp/blueprints/testing/static/_build/test-custom-build.js', false); + + return processJsFile('./flaskApp/blueprints/testing/static/js/test-corridor-layer.js', './flaskApp/blueprints/testing/static/_build/test-corridor-layer.js', false); + +} + +gulp.task('buildTestApps', () => { + "use strict"; + + return _buildTestApps(false); +}); + +gulp.task('build-prod', ['glrtoc-prod', 'tsmo-prod', 'npmrds-prod', 'ssa-prod', 'itsInventory-prod', 'peerGroup-prod']); diff --git a/lib/jquery.floatThead.js b/lib/jquery.floatThead.js new file mode 100644 index 0000000..42eba92 --- /dev/null +++ b/lib/jquery.floatThead.js @@ -0,0 +1,967 @@ +// @preserve jQuery.floatThead 1.3.2 - http://mkoryak.github.io/floatThead/ - Copyright (c) 2012 - 2015 Misha Koryak +// @license MIT + +/* @author Misha Koryak + * @projectDescription lock a table header in place while scrolling - without breaking styles or events bound to the header + * + * Dependencies: + * jquery 1.9.0 + [required] OR jquery 1.7.0 + jquery UI core + * + * http://mkoryak.github.io/floatThead/ + * + * Tested on FF13+, Chrome 21+, IE8, IE9, IE10, IE11 + * + */ +let jQuery = require('jQuery'); + +(function( $ ) { + /** + * provides a default config object. You can modify this after including this script if you want to change the init defaults + * @type {Object} + */ + $.floatThead = $.floatThead || {}; + $.floatThead.defaults = { + headerCellSelector: 'tr:visible:first>*:visible', //thead cells are this. + zIndex: 1001, //zindex of the floating thead (actually a container div) + position: 'auto', // 'fixed', 'absolute', 'auto'. auto picks the best for your table scrolling type. + top: 0, //String or function($table) - offset from top of window where the header should not pass above + bottom: 0, //String or function($table) - offset from the bottom of the table where the header should stop scrolling + scrollContainer: function($table){ + return $([]); //if the table has horizontal scroll bars then this is the container that has overflow:auto and causes those scroll bars + }, + getSizingRow: function($table, $cols, $fthCells){ // this is only called when using IE, + // override it if the first row of the table is going to contain colgroups (any cell spans greater than one col) + // it should return a jquery object containing a wrapped set of table cells comprising a row that contains no col spans and is visible + return $table.find('tbody tr:visible:first>*:visible'); + }, + floatTableClass: 'floatThead-table', + floatWrapperClass: 'floatThead-wrapper', + floatContainerClass: 'floatThead-container', + copyTableClass: true, //copy 'class' attribute from table into the floated table so that the styles match. + enableAria: false, //will copy header text from the floated header back into the table for screen readers. Might cause the css styling to be off. beware! + autoReflow: false, //(undocumented) - use MutationObserver api to reflow automatically when internal table DOM changes + debug: false //print possible issues (that don't prevent script loading) to console, if console exists. + }; + + var util = window._; + + var canObserveMutations = typeof MutationObserver !== 'undefined'; + + + //browser stuff + var ieVersion = function(){for(var a=3,b=document.createElement("b"),c=b.all||[];a = 1+a,b.innerHTML="<!--[if gt IE "+ a +"]><i><![endif]-->",c[0];);return 4<a?a:document.documentMode}(); + var isFF = /Gecko\//.test(navigator.userAgent); + var isWebkit = /WebKit\//.test(navigator.userAgent); + + //safari 7 (and perhaps others) reports table width to be parent container's width if max-width is set on table. see: https://github.com/mkoryak/floatThead/issues/108 + var isTableWidthBug = function(){ + if(isWebkit) { + var $test = $('<div style="width:0px"><table style="max-width:100%"><tr><th><div style="min-width:100px;">X</div></th></tr></table></div>'); + $("body").append($test); + var ret = ($test.find("table").width() == 0); + $test.remove(); + return ret; + } + return false; + }; + + var createElements = !isFF && !ieVersion; //FF can read width from <col> elements, but webkit cannot + + var $window = $(window); + + /** + * @param debounceMs + * @param cb + */ + function windowResize(eventName, cb){ + if(ieVersion == 8){ //ie8 is crap: https://github.com/mkoryak/floatThead/issues/65 + var winWidth = $window.width(); + var debouncedCb = util.debounce(function(){ + var winWidthNew = $window.width(); + if(winWidth != winWidthNew){ + winWidth = winWidthNew; + cb(); + } + }, 1); + $window.on(eventName, debouncedCb); + } else { + $window.on(eventName, util.debounce(cb, 1)); + } + } + + + function debug(str){ + window && window.console && window.console.error && window.console.error("jQuery.floatThead: " + str); + } + + //returns fractional pixel widths + function getOffsetWidth(el) { + var rect = el.getBoundingClientRect(); + return rect.width || rect.right - rect.left; + } + + /** + * try to calculate the scrollbar width for your browser/os + * @return {Number} + */ + function scrollbarWidth() { + var $div = $( //borrowed from anti-scroll + '<div style="width:50px;height:50px;overflow-y:scroll;' + + 'position:absolute;top:-200px;left:-200px;"><div style="height:100px;width:100%">' + + '</div>' + ); + $('body').append($div); + var w1 = $div.innerWidth(); + var w2 = $('div', $div).innerWidth(); + $div.remove(); + return w1 - w2; + } + /** + * Check if a given table has been datatableized (http://datatables.net) + * @param $table + * @return {Boolean} + */ + function isDatatable($table){ + if($table.dataTableSettings){ + for(var i = 0; i < $table.dataTableSettings.length; i++){ + var table = $table.dataTableSettings[i].nTable; + if($table[0] == table){ + return true; + } + } + } + return false; + } + + function tableWidth($table, $fthCells, isOuter){ + // see: https://github.com/mkoryak/floatThead/issues/108 + var fn = isOuter ? "outerWidth": "width"; + if(isTableWidthBug && $table.css("max-width")){ + var w = 0; + if(isOuter) { + w += parseInt($table.css("borderLeft"), 10); + w += parseInt($table.css("borderRight"), 10); + } + for(var i=0; i < $fthCells.length; i++){ + w += $fthCells.get(i).offsetWidth; + } + return w; + } else { + return $table[fn](); + } + } + $.fn.floatThead = function(map){ + map = map || {}; + if(!util){ //may have been included after the script? lets try to grab it again. + util = window._ || $.floatThead._; + if(!util){ + throw new Error("jquery.floatThead-slim.js requires underscore. You should use the non-lite version since you do not have underscore."); + } + } + + if(ieVersion < 8){ + return this; //no more crappy browser support. + } + + var mObs = null; //mutation observer lives in here if we can use it / make it + + if(util.isFunction(isTableWidthBug)) { + isTableWidthBug = isTableWidthBug(); + } + + if(util.isString(map)){ + var command = map; + var ret = this; + this.filter('table').each(function(){ + var $this = $(this); + var opts = $this.data('floatThead-lazy'); + if(opts){ + $this.floatThead(opts); + } + var obj = $this.data('floatThead-attached'); + if(obj && util.isFunction(obj[command])){ + var r = obj[command](); + if(typeof r !== 'undefined'){ + ret = r; + } + } + }); + return ret; + } + var opts = $.extend({}, $.floatThead.defaults || {}, map); + + $.each(map, function(key, val){ + if((!(key in $.floatThead.defaults)) && opts.debug){ + debug("Used ["+key+"] key to init plugin, but that param is not an option for the plugin. Valid options are: "+ (util.keys($.floatThead.defaults)).join(', ')); + } + }); + if(opts.debug){ + var v = $.fn.jquery.split("."); + if(parseInt(v[0], 10) == 1 && parseInt(v[1], 10) <= 7){ + debug("jQuery version "+$.fn.jquery+" detected! This plugin supports 1.8 or better, or 1.7.x with jQuery UI 1.8.24 -> http://jqueryui.com/resources/download/jquery-ui-1.8.24.zip") + } + } + + this.filter(':not(.'+opts.floatTableClass+')').each(function(){ + var floatTheadId = util.uniqueId(); + var $table = $(this); + if($table.data('floatThead-attached')){ + return true; //continue the each loop + } + if(!$table.is('table')){ + throw new Error('jQuery.floatThead must be run on a table element. ex: $("table").floatThead();'); + } + canObserveMutations = opts.autoReflow && canObserveMutations; //option defaults to false! + var $header = $table.children('thead:first'); + var $tbody = $table.children('tbody:first'); + if($header.length == 0 || $tbody.length == 0){ + $table.data('floatThead-lazy', opts); + $table.unbind("reflow").one('reflow', function(){ + $table.floatThead(opts); + }); + return; + } + if($table.data('floatThead-lazy')){ + $table.unbind("reflow"); + } + $table.data('floatThead-lazy', false); + + var headerFloated = true; + var scrollingTop, scrollingBottom; + var scrollbarOffset = {vertical: 0, horizontal: 0}; + var scWidth = scrollbarWidth(); + var lastColumnCount = 0; //used by columnNum() + var $scrollContainer = opts.scrollContainer($table) || $([]); //guard against returned nulls + var locked = $scrollContainer.length > 0; + + var useAbsolutePositioning = null; + if(typeof opts.useAbsolutePositioning !== 'undefined'){ + opts.position = 'auto'; + if(opts.useAbsolutePositioning){ + opts.position = opts.useAbsolutePositioning ? 'absolute' : 'fixed'; + } + debug("option 'useAbsolutePositioning' has been removed in v1.3.0, use `position:'"+opts.position+"'` instead. See docs for more info: http://mkoryak.github.io/floatThead/#options") + } + if(typeof opts.scrollingTop !== 'undefined'){ + opts.top = opts.scrollingTop; + debug("option 'scrollingTop' has been renamed to 'top' in v1.3.0. See docs for more info: http://mkoryak.github.io/floatThead/#options"); + } + if(typeof opts.scrollingBottom !== 'undefined'){ + opts.bottom = opts.scrollingBottom; + debug("option 'scrollingBottom' has been renamed to 'bottom' in v1.3.0. See docs for more info: http://mkoryak.github.io/floatThead/#options"); + } + + + if (opts.position == 'auto') { + useAbsolutePositioning = null; + } else if (opts.position == 'fixed') { + useAbsolutePositioning = false; + } else if (opts.position == 'absolute'){ + useAbsolutePositioning = true; + } else if (opts.debug) { + debug('Invalid value given to "position" option, valid is "fixed", "absolute" and "auto". You passed: ', opts.position); + } + + if(useAbsolutePositioning == null){ //defaults: locked=true, !locked=false + useAbsolutePositioning = locked; + } + var $caption = $table.find("caption"); + var haveCaption = $caption.length == 1; + if(haveCaption){ + var captionAlignTop = ($caption.css("caption-side") || $caption.attr("align") || "top") === "top"; + } + + var $fthGrp = $('<fthfoot style="display:table-footer-group;border-spacing:0;height:0;border-collapse:collapse;visibility:hidden"/>'); + + var wrappedContainer = false; //used with absolute positioning enabled. did we need to wrap the scrollContainer/table with a relative div? + var $wrapper = $([]); //used when absolute positioning enabled - wraps the table and the float container + var absoluteToFixedOnScroll = ieVersion <= 9 && !locked && useAbsolutePositioning; //on IE using absolute positioning doesn't look good with window scrolling, so we change position to fixed on scroll, and then change it back to absolute when done. + var $floatTable = $("<table/>"); + var $floatColGroup = $("<colgroup/>"); + var $tableColGroup = $table.children('colgroup:first'); + var existingColGroup = true; + if($tableColGroup.length == 0){ + $tableColGroup = $("<colgroup/>"); + existingColGroup = false; + } + var $fthRow = $('<fthtr style="display:table-row;border-spacing:0;height:0;border-collapse:collapse"/>'); //created unstyled elements (used for sizing the table because chrome can't read <col> width) + var $floatContainer = $('<div style="overflow: hidden;" aria-hidden="true"></div>'); + var floatTableHidden = false; //this happens when the table is hidden and we do magic when making it visible + var $newHeader = $("<thead/>"); + var $sizerRow = $('<tr class="size-row"/>'); + var $sizerCells = $([]); + var $tableCells = $([]); //used for sizing - either $sizerCells or $tableColGroup cols. $tableColGroup cols are only created in chrome for borderCollapse:collapse because of a chrome bug. + var $headerCells = $([]); + var $fthCells = $([]); //created elements + + $newHeader.append($sizerRow); + $table.prepend($tableColGroup); + if(createElements){ + $fthGrp.append($fthRow); + $table.append($fthGrp); + } + + $floatTable.append($floatColGroup); + $floatContainer.append($floatTable); + if(opts.copyTableClass){ + $floatTable.attr('class', $table.attr('class')); + } + $floatTable.attr({ //copy over some deprecated table attributes that people still like to use. Good thing people don't use colgroups... + 'cellpadding': $table.attr('cellpadding'), + 'cellspacing': $table.attr('cellspacing'), + 'border': $table.attr('border') + }); + var tableDisplayCss = $table.css('display'); + $floatTable.css({ + 'borderCollapse': $table.css('borderCollapse'), + 'border': $table.css('border'), + 'display': tableDisplayCss + }); + if(tableDisplayCss == 'none'){ + floatTableHidden = true; + } + + $floatTable.addClass(opts.floatTableClass).css({'margin': 0, 'border-bottom-width': 0}); //must have no margins or you won't be able to click on things under floating table + + if(useAbsolutePositioning){ + var makeRelative = function($container, alwaysWrap){ + var positionCss = $container.css('position'); + var relativeToScrollContainer = (positionCss == "relative" || positionCss == "absolute"); + var $containerWrap = $container; + if(!relativeToScrollContainer || alwaysWrap){ + var css = {"paddingLeft": $container.css('paddingLeft'), "paddingRight": $container.css('paddingRight')}; + $floatContainer.css(css); + $containerWrap = $container.data('floatThead-containerWrap') || $container.wrap("<div class='"+opts.floatWrapperClass+"' style='position: relative; clear:both;'></div>").parent(); + $container.data('floatThead-containerWrap', $containerWrap); //multiple tables inside one scrolling container - #242 + wrappedContainer = true; + } + return $containerWrap; + }; + if(locked){ + $wrapper = makeRelative($scrollContainer, true); + $wrapper.prepend($floatContainer); + } else { + $wrapper = makeRelative($table); + $table.before($floatContainer); + } + } else { + $table.before($floatContainer); + } + + + $floatContainer.css({ + position: useAbsolutePositioning ? 'absolute' : 'fixed', + marginTop: 0, + top: useAbsolutePositioning ? 0 : 'auto', + zIndex: opts.zIndex + }); + $floatContainer.addClass(opts.floatContainerClass); + updateScrollingOffsets(); + + var layoutFixed = {'table-layout': 'fixed'}; + var layoutAuto = {'table-layout': $table.css('tableLayout') || 'auto'}; + var originalTableWidth = $table[0].style.width || ""; //setting this to auto is bad: #70 + var originalTableMinWidth = $table.css('minWidth') || ""; + + function eventName(name){ + return name+'.fth-'+floatTheadId+'.floatTHead' + } + + function setHeaderHeight(){ + var headerHeight = 0; + $header.children("tr:visible").each(function(){ + headerHeight += $(this).outerHeight(true); + }); + if($table.css('border-collapse') == 'collapse') { + var tableBorderTopHeight = parseInt($table.css('border-top-width'), 10); + var cellBorderTopHeight = parseInt($table.find("thead tr:first").find(">*:first").css('border-top-width'), 10); + if(tableBorderTopHeight > cellBorderTopHeight) { + headerHeight -= (tableBorderTopHeight / 2); //id love to see some docs where this magic recipe is found.. + } + } + $sizerRow.outerHeight(headerHeight); + $sizerCells.outerHeight(headerHeight); + } + + + function setFloatWidth(){ + var tw = tableWidth($table, $fthCells, true); + var width = $scrollContainer.width() || tw; + var floatContainerWidth = $scrollContainer.css("overflow-y") != 'hidden' ? width - scrollbarOffset.vertical : width; + $floatContainer.width(floatContainerWidth); + if(locked){ + var percent = 100 * tw / (floatContainerWidth); + $floatTable.css('width', percent+'%'); + } else { + $floatTable.outerWidth(tw); + } + } + + function updateScrollingOffsets(){ + scrollingTop = (util.isFunction(opts.top) ? opts.top($table) : opts.top) || 0; + scrollingBottom = (util.isFunction(opts.bottom) ? opts.bottom($table) : opts.bottom) || 0; + } + + /** + * get the number of columns and also rebuild resizer rows if the count is different than the last count + */ + function columnNum(){ + var count; + var $headerColumns = $header.find(opts.headerCellSelector); + if(existingColGroup){ + count = $tableColGroup.find('col').length; + } else { + count = 0; + $headerColumns.each(function () { + count += parseInt(($(this).attr('colspan') || 1), 10); + }); + } + if(count != lastColumnCount){ + lastColumnCount = count; + var cells = [], cols = [], psuedo = [], content; + for(var x = 0; x < count; x++){ + if (opts.enableAria && (content = $headerColumns.eq(x).text()) ) { + cells.push('<th scope="col" class="floatThead-col">' + content + '</th>'); + } else { + cells.push('<th class="floatThead-col"/>'); + } + cols.push('<col/>'); + psuedo.push("<fthtd style='display:table-cell;height:0;width:auto;'/>"); + } + + cols = cols.join(''); + cells = cells.join(''); + + if(createElements){ + psuedo = psuedo.join(''); + $fthRow.html(psuedo); + $fthCells = $fthRow.find('fthtd'); + } + + $sizerRow.html(cells); + $sizerCells = $sizerRow.find("th"); + if(!existingColGroup){ + $tableColGroup.html(cols); + } + $tableCells = $tableColGroup.find('col'); + $floatColGroup.html(cols); + $headerCells = $floatColGroup.find("col"); + + } + return count; + } + + function refloat(){ //make the thing float + if(!headerFloated){ + headerFloated = true; + if(useAbsolutePositioning){ //#53, #56 + var tw = tableWidth($table, $fthCells, true); + var wrapperWidth = $wrapper.width(); + if(tw > wrapperWidth){ + $table.css('minWidth', tw); + } + } + $table.css(layoutFixed); + $floatTable.css(layoutFixed); + $floatTable.append($header); //append because colgroup must go first in chrome + $tbody.before($newHeader); + setHeaderHeight(); + } + } + function unfloat(){ //put the header back into the table + if(headerFloated){ + headerFloated = false; + if(useAbsolutePositioning){ //#53, #56 + $table.width(originalTableWidth); + } + $newHeader.detach(); + $table.prepend($header); + $table.css(layoutAuto); + $floatTable.css(layoutAuto); + $table.css('minWidth', originalTableMinWidth); //this looks weird, but it's not a bug. Think about it!! + $table.css('minWidth', tableWidth($table, $fthCells)); //#121 + } + } + var isHeaderFloatingLogical = false; //for the purpose of this event, the header is/isnt floating, even though the element + //might be in some other state. this is what the header looks like to the user + function triggerFloatEvent(isFloating){ + if(isHeaderFloatingLogical != isFloating){ + isHeaderFloatingLogical = isFloating; + $table.triggerHandler("floatThead", [isFloating, $floatContainer]) + } + } + function changePositioning(isAbsolute){ + if(useAbsolutePositioning != isAbsolute){ + useAbsolutePositioning = isAbsolute; + $floatContainer.css({ + position: useAbsolutePositioning ? 'absolute' : 'fixed' + }); + } + } + function getSizingRow($table, $cols, $fthCells, ieVersion){ + if(createElements){ + return $fthCells; + } else if(ieVersion) { + return opts.getSizingRow($table, $cols, $fthCells); + } else { + return $cols; + } + } + + /** + * returns a function that updates the floating header's cell widths. + * @return {Function} + */ + function reflow(){ + var i; + var numCols = columnNum(); //if the tables columns changed dynamically since last time (datatables), rebuild the sizer rows and get a new count + + return function(){ + $tableCells = $tableColGroup.find('col'); + var $rowCells = getSizingRow($table, $tableCells, $fthCells, ieVersion); + + if($rowCells.length == numCols && numCols > 0){ + if(!existingColGroup){ + for(i=0; i < numCols; i++){ + $tableCells.eq(i).css('width', ''); + } + } + unfloat(); + var widths = []; + for(i=0; i < numCols; i++){ + widths[i] = getOffsetWidth($rowCells.get(i)); + } + for(i=0; i < numCols; i++){ + $headerCells.eq(i).width(widths[i]); + $tableCells.eq(i).width(widths[i]); + } + refloat(); + } else { + $floatTable.append($header); + $table.css(layoutAuto); + $floatTable.css(layoutAuto); + setHeaderHeight(); + } + $table.triggerHandler("reflowed", [$floatContainer]); + }; + } + + function floatContainerBorderWidth(side){ + var border = $scrollContainer.css("border-"+side+"-width"); + var w = 0; + if (border && ~border.indexOf('px')) { + w = parseInt(border, 10); + } + return w; + } + /** + * first performs initial calculations that we expect to not change when the table, window, or scrolling container are scrolled. + * returns a function that calculates the floating container's top and left coords. takes into account if we are using page scrolling or inner scrolling + * @return {Function} + */ + function calculateFloatContainerPosFn(){ + var scrollingContainerTop = $scrollContainer.scrollTop(); + + //this floatEnd calc was moved out of the returned function because we assume the table height doesn't change (otherwise we must reinit by calling calculateFloatContainerPosFn) + var floatEnd; + var tableContainerGap = 0; + var captionHeight = haveCaption ? $caption.outerHeight(true) : 0; + var captionScrollOffset = captionAlignTop ? captionHeight : -captionHeight; + + var floatContainerHeight = $floatContainer.height(); + var tableOffset = $table.offset(); + var tableLeftGap = 0; //can be caused by border on container (only in locked mode) + var tableTopGap = 0; + if(locked){ + var containerOffset = $scrollContainer.offset(); + tableContainerGap = tableOffset.top - containerOffset.top + scrollingContainerTop; + if(haveCaption && captionAlignTop){ + tableContainerGap += captionHeight; + } + tableLeftGap = floatContainerBorderWidth('left'); + tableTopGap = floatContainerBorderWidth('top'); + tableContainerGap -= tableTopGap; + } else { + floatEnd = tableOffset.top - scrollingTop - floatContainerHeight + scrollingBottom + scrollbarOffset.horizontal; + } + var windowTop = $window.scrollTop(); + var windowLeft = $window.scrollLeft(); + var scrollContainerLeft = $scrollContainer.scrollLeft(); + + return function(eventType){ + var isTableHidden = $table[0].offsetWidth <= 0 && $table[0].offsetHeight <= 0; + if(!isTableHidden && floatTableHidden) { + floatTableHidden = false; + setTimeout(function(){ + $table.triggerHandler("reflow"); + }, 1); + return null; + } + if(isTableHidden){ //it's hidden + floatTableHidden = true; + if(!useAbsolutePositioning){ + return null; + } + } + + if(eventType == 'windowScroll'){ + windowTop = $window.scrollTop(); + windowLeft = $window.scrollLeft(); + } else if(eventType == 'containerScroll'){ + scrollingContainerTop = $scrollContainer.scrollTop(); + scrollContainerLeft = $scrollContainer.scrollLeft(); + } else if(eventType != 'init') { + windowTop = $window.scrollTop(); + windowLeft = $window.scrollLeft(); + scrollingContainerTop = $scrollContainer.scrollTop(); + scrollContainerLeft = $scrollContainer.scrollLeft(); + } + if(isWebkit && (windowTop < 0 || windowLeft < 0)){ //chrome overscroll effect at the top of the page - breaks fixed positioned floated headers + return; + } + + if(absoluteToFixedOnScroll){ + if(eventType == 'windowScrollDone'){ + changePositioning(true); //change to absolute + } else { + changePositioning(false); //change to fixed + } + } else if(eventType == 'windowScrollDone'){ + return null; //event is fired when they stop scrolling. ignore it if not 'absoluteToFixedOnScroll' + } + + tableOffset = $table.offset(); + if(haveCaption && captionAlignTop){ + tableOffset.top += captionHeight; + } + var top, left; + var tableHeight = $table.outerHeight(); + + if(locked && useAbsolutePositioning){ //inner scrolling, absolute positioning + if (tableContainerGap >= scrollingContainerTop) { + var gap = tableContainerGap - scrollingContainerTop + tableTopGap; + top = gap > 0 ? gap : 0; + triggerFloatEvent(false); + } else { + top = wrappedContainer ? tableTopGap : scrollingContainerTop; + //headers stop at the top of the viewport + triggerFloatEvent(true); + } + left = tableLeftGap; + } else if(!locked && useAbsolutePositioning) { //window scrolling, absolute positioning + if(windowTop > floatEnd + tableHeight + captionScrollOffset){ + top = tableHeight - floatContainerHeight + captionScrollOffset; //scrolled past table + } else if (tableOffset.top >= windowTop + scrollingTop) { + top = 0; //scrolling to table + unfloat(); + triggerFloatEvent(false); + } else { + top = scrollingTop + windowTop - tableOffset.top + tableContainerGap + (captionAlignTop ? captionHeight : 0); + refloat(); //scrolling within table. header floated + triggerFloatEvent(true); + } + left = 0; + } else if(locked && !useAbsolutePositioning){ //inner scrolling, fixed positioning + if (tableContainerGap > scrollingContainerTop || scrollingContainerTop - tableContainerGap > tableHeight) { + top = tableOffset.top - windowTop; + unfloat(); + triggerFloatEvent(false); + } else { + top = tableOffset.top + scrollingContainerTop - windowTop - tableContainerGap; + refloat(); + triggerFloatEvent(true); + //headers stop at the top of the viewport + } + left = tableOffset.left + scrollContainerLeft - windowLeft; + } else if(!locked && !useAbsolutePositioning) { //window scrolling, fixed positioning + if(windowTop > floatEnd + tableHeight + captionScrollOffset){ + top = tableHeight + scrollingTop - windowTop + floatEnd + captionScrollOffset; + //scrolled past the bottom of the table + } else if (tableOffset.top > windowTop + scrollingTop) { + top = tableOffset.top - windowTop; + refloat(); + triggerFloatEvent(false); //this is a weird case, the header never gets unfloated and i have no no way to know + //scrolled past the top of the table + } else { + //scrolling within the table + top = scrollingTop; + triggerFloatEvent(true); + } + left = tableOffset.left - windowLeft; + } + return {top: top, left: left}; + }; + } + /** + * returns a function that caches old floating container position and only updates css when the position changes + * @return {Function} + */ + function repositionFloatContainerFn(){ + var oldTop = null; + var oldLeft = null; + var oldScrollLeft = null; + return function(pos, setWidth, setHeight){ + if(pos != null && (oldTop != pos.top || oldLeft != pos.left)){ + $floatContainer.css({ + top: pos.top, + left: pos.left + }); + oldTop = pos.top; + oldLeft = pos.left; + } + if(setWidth){ + setFloatWidth(); + } + if(setHeight){ + setHeaderHeight(); + } + var scrollLeft = $scrollContainer.scrollLeft(); + if(!useAbsolutePositioning || oldScrollLeft != scrollLeft){ + $floatContainer.scrollLeft(scrollLeft); + oldScrollLeft = scrollLeft; + } + } + } + + /** + * checks if THIS table has scrollbars, and finds their widths + */ + function calculateScrollBarSize(){ //this should happen after the floating table has been positioned + if($scrollContainer.length){ + if($scrollContainer.data().perfectScrollbar){ + scrollbarOffset = {horizontal:0, vertical:0}; + } else { + var sw = $scrollContainer.width(), sh = $scrollContainer.height(), th = $table.height(), tw = tableWidth($table, $fthCells); + var offseth = sw < tw ? scWidth : 0; + var offsetv = sh < th ? scWidth : 0; + scrollbarOffset.horizontal = sw - offsetv < tw ? scWidth : 0; + scrollbarOffset.vertical = sh - offseth < th ? scWidth : 0; + } + } + } + //finish up. create all calculation functions and bind them to events + calculateScrollBarSize(); + + var flow; + + var ensureReflow = function(){ + flow = reflow(); + flow(); + }; + + ensureReflow(); + + var calculateFloatContainerPos = calculateFloatContainerPosFn(); + var repositionFloatContainer = repositionFloatContainerFn(); + + repositionFloatContainer(calculateFloatContainerPos('init'), true); //this must come after reflow because reflow changes scrollLeft back to 0 when it rips out the thead + + var windowScrollDoneEvent = util.debounce(function(){ + repositionFloatContainer(calculateFloatContainerPos('windowScrollDone'), false); + }, 1); + + var windowScrollEvent = function(){ + repositionFloatContainer(calculateFloatContainerPos('windowScroll'), false); + if(absoluteToFixedOnScroll){ + windowScrollDoneEvent(); + } + }; + var containerScrollEvent = function(){ + repositionFloatContainer(calculateFloatContainerPos('containerScroll'), false); + }; + + + var windowResizeEvent = function(){ + if($table.is(":hidden")){ + return; + } + updateScrollingOffsets(); + calculateScrollBarSize(); + ensureReflow(); + calculateFloatContainerPos = calculateFloatContainerPosFn(); + repositionFloatContainer = repositionFloatContainerFn(); + repositionFloatContainer(calculateFloatContainerPos('resize'), true, true); + }; + var reflowEvent = util.debounce(function(){ + if($table.is(":hidden")){ + return; + } + calculateScrollBarSize(); + updateScrollingOffsets(); + ensureReflow(); + calculateFloatContainerPos = calculateFloatContainerPosFn(); + repositionFloatContainer(calculateFloatContainerPos('reflow'), true); + }, 1); + if(locked){ //internal scrolling + if(useAbsolutePositioning){ + $scrollContainer.on(eventName('scroll'), containerScrollEvent); + } else { + $scrollContainer.on(eventName('scroll'), containerScrollEvent); + $window.on(eventName('scroll'), windowScrollEvent); + } + } else { //window scrolling + $window.on(eventName('scroll'), windowScrollEvent); + } + + $window.on(eventName('load'), reflowEvent); //for tables with images + + windowResize(eventName('resize'), windowResizeEvent); + $table.on('reflow', reflowEvent); + if(isDatatable($table)){ + $table + .on('filter', reflowEvent) + .on('sort', reflowEvent) + .on('page', reflowEvent); + } + + $window.on(eventName('shown.bs.tab'), reflowEvent); // people cant seem to figure out how to use this plugin with bs3 tabs... so this :P + $window.on(eventName('tabsactivate'), reflowEvent); // same thing for jqueryui + + + if (canObserveMutations) { + var mutationElement = null; + if(util.isFunction(opts.autoReflow)){ + mutationElement = opts.autoReflow($table, $scrollContainer) + } + if(!mutationElement) { + mutationElement = $scrollContainer.length ? $scrollContainer[0] : $table[0] + } + mObs = new MutationObserver(function(e){ + var wasTableRelated = function(nodes){ + return nodes && nodes[0] && (nodes[0].nodeName == "THEAD" || nodes[0].nodeName == "TD"|| nodes[0].nodeName == "TH"); + }; + for(var i=0; i < e.length; i++){ + if(!(wasTableRelated(e[i].addedNodes) || wasTableRelated(e[i].removedNodes))){ + reflowEvent(); + break; + } + } + }); + mObs.observe(mutationElement, { + childList: true, + subtree: true + }); + } + + //attach some useful functions to the table. + $table.data('floatThead-attached', { + destroy: function(){ + var ns = '.fth-'+floatTheadId; + unfloat(); + $table.css(layoutAuto); + $tableColGroup.remove(); + createElements && $fthGrp.remove(); + if($newHeader.parent().length){ //only if it's in the DOM + $newHeader.replaceWith($header); + } + if(canObserveMutations){ + mObs.disconnect(); + mObs = null; + } + $table.off('reflow reflowed'); + $scrollContainer.off(ns); + if (wrappedContainer) { + if ($scrollContainer.length) { + $scrollContainer.unwrap(); + } + else { + $table.unwrap(); + } + } + if(locked){ + $scrollContainer.data('floatThead-containerWrap', false); + } else { + $table.data('floatThead-containerWrap', false); + } + $table.css('minWidth', originalTableMinWidth); + $floatContainer.remove(); + $table.data('floatThead-attached', false); + $window.off(ns); + }, + reflow: function(){ + reflowEvent(); + }, + setHeaderHeight: function(){ + setHeaderHeight(); + }, + getFloatContainer: function(){ + return $floatContainer; + }, + getRowGroups: function(){ + if(headerFloated){ + return $floatContainer.find('>table>thead').add($table.children("tbody,tfoot")); + } else { + return $table.children("thead,tbody,tfoot"); + } + } + }); + }); + return this; + }; +})(jQuery); + +/* jQuery.floatThead.utils - http://mkoryak.github.io/floatThead/ - Copyright (c) 2012 - 2014 Misha Koryak + * License: MIT + * + * This file is required if you do not use underscore in your project and you want to use floatThead. + * It contains functions from underscore that the plugin uses. + * + * YOU DON'T NEED TO INCLUDE THIS IF YOU ALREADY INCLUDE UNDERSCORE! + * + */ + +(function($){ + + $.floatThead = $.floatThead || {}; + + $.floatThead._ = window._ || (function(){ + var that = {}; + var hasOwnProperty = Object.prototype.hasOwnProperty, isThings = ['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp']; + that.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + that.keys = function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (that.has(obj, key)) keys.push(key); + return keys; + }; + var idCounter = 0; + that.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + $.each(isThings, function(){ + var name = this; + that['is' + name] = function(obj) { + return Object.prototype.toString.call(obj) == '[object ' + name + ']'; + }; + }); + that.debounce = function(func, wait, immediate) { + var timeout, args, context, timestamp, result; + return function() { + context = this; + args = arguments; + timestamp = new Date(); + var later = function() { + var last = (new Date()) - timestamp; + if (last < wait) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) result = func.apply(context, args); + } + }; + var callNow = immediate && !timeout; + if (!timeout) { + timeout = setTimeout(later, wait); + } + if (callNow) result = func.apply(context, args); + return result; + }; + }; + return that; + })(); +})(jQuery); + +export default undefined; \ No newline at end of file diff --git a/package.json b/package.json index df446ff..bef02ff 100644 --- a/package.json +++ b/package.json @@ -12,11 +12,34 @@ "author": "TOPS Lab", "license": "ISC", "devDependencies": { + "angular2": "^2.0.0-beta.17", + "babel-cli": "^6.8.0", "babel-preset-es2015": "^6.6.0", - "openlayers": "^3.15.1" + "babelify": "^7.3.0", + "browserify": "^13.0.0", + "es6-mixins": "^1.0.2", + "es6-shim": "^0.35.0", + "gulp": "^3.9.1", + "gulp-babel": "^6.1.2", + "gulp-cssmin": "^0.1.7", + "gulp-less": "^3.0.5", + "gulp-minify": "0.0.11", + "gulp-rename": "^1.2.2", + "gulp-sourcemaps": "^2.0.0-alpha", + "jquery": "^2.2.3", + "jquery-ui": "^1.10.5", + "openlayers": "^3.15.1", + "reflect-metadata": "^0.1.2", + "rxjs": "^5.0.0-beta.6", + "vinyl-buffer": "^1.0.0", + "vinyl-source-stream": "^1.1.0", + "zone.js": "^0.6.12" }, "repository": { "type": "git", "url": "https://github.com/glennvorhes/webmapsjs.git" + }, + "dependencies": { + "angular2": "^2.0.0-beta.17" } } diff --git a/projects/glrtoc/appConfig.js b/projects/glrtoc/appConfig.js new file mode 100644 index 0000000..bc44356 --- /dev/null +++ b/projects/glrtoc/appConfig.js @@ -0,0 +1,150 @@ +/** + * Created by gavorhes on 12/8/2015. + */ + +import mapPopup from '../../src/olHelpers/mapPopup'; +import $ from '../../src/jquery'; +let homeTabId = 'home-tab'; +let coordinationTabId = 'coordination-tab'; +let operationsTabId = 'operations-tab'; + +let operationsStaticPanelId = 'operations-static'; +let operationsAnimatedPanelId = 'operations-animated'; + +class AppConfig { + /** + * app configuration object + */ + constructor() { + this.$opsAccordion = $("#" + operationsTabId); + this.debug = true; + this.map = undefined; + this._coordinationLayer = undefined; + this.lyrIds = []; + this.lyrLookup = {}; + this.lyrArray = []; + this.mediaControl = undefined; + this.animationLayers = []; + this.coordinationLayerId = 'coorindation-layer'; + + /** + * + * @type {Array<LayerBase>} + */ + this.operationsLayersStatic = []; + + /** + * + * @type {Array<LayerBase>} + */ + this.operationsLayersAnimated = []; + + this.currentOperationsLayers = this.operationsLayersStatic; + } + + init() { + for (let l of this.operationsLayersStatic) { + this.map.removeLayer(l['olLayer']); + } + + for (let l of this.operationsLayersAnimated) { + this.map.removeLayer(l['olLayer']); + } + + this.currentTabId = homeTabId; + } + + /** + * Add the layer to the config object + * @param {LayerBase|*} lyr - base layer + */ + _addLayer(lyr) { + this.lyrIds.push(lyr.id); + this.lyrLookup[lyr.id] = lyr; + this.lyrArray.push(lyr); + } + + get coordinationLayer() { + return this._coordinationLayer; + } + + set coordinationLayer(coordLayer) { + this._coordinationLayer = coordLayer; + this._addLayer(coordLayer); + } + + addOperationsLayerStatic(lyr) { + this.operationsLayersStatic.push(lyr); + this._addLayer(lyr); + } + + addOperationsLayerAnimate(lyr) { + this.operationsLayersAnimated.push(lyr); + this._addLayer(lyr); + } + + set currentTabId(tabId) { + mapPopup.closePopup(); + this.mediaControl.stopPlaying(); + if (tabId == operationsTabId) { + for (let l of this.currentOperationsLayers) { + this.map.addLayer(l['olLayer']); + } + } else { + for (let l of this.currentOperationsLayers) { + this.map.removeLayer(l['olLayer']); + } + } + + switch (tabId) { + case homeTabId: + this.coordinationLayer.visible = false; + break; + case coordinationTabId: + this.coordinationLayer.visible = true; + break; + case operationsTabId: + this.coordinationLayer.visible = false; + this.$opsAccordion.accordion("refresh"); + break; + default: + throw tabId + ' tab id not found' + } + } + + set currentOperationsPanelId(panelId) { + mapPopup.closePopup(); + this.mediaControl.stopPlaying(); + + for (let l of this.currentOperationsLayers) { + this.map.removeLayer(l['olLayer']); + } + + switch (panelId) { + case operationsStaticPanelId: + this.currentOperationsLayers = this.operationsLayersStatic; + break; + + case operationsAnimatedPanelId: + this.currentOperationsLayers = this.operationsLayersAnimated; + break; + default: + throw panelId + ' panel not found'; + } + for (let l of this.currentOperationsLayers) { + this.map.addLayer(l['olLayer']); + } + + } + + ///** + // * trick to trigger the map move event + // */ + //forceRefresh() { + // if (this.map) { + // this.map.getView().setZoom(this.map.getView().getZoom()); + // } + //} +} + +export default new AppConfig(); diff --git a/projects/glrtoc/layerPopups.js b/projects/glrtoc/layerPopups.js new file mode 100644 index 0000000..4362c1c --- /dev/null +++ b/projects/glrtoc/layerPopups.js @@ -0,0 +1,37 @@ +/** + * Created by gavorhes on 12/7/2015. + */ + + +/** + * coordination layer popup config + * @param {object} props + * @returns {string} + */ +export function coordination(props) { + "use strict"; + return `<iframe src="${window.location.href.replace('#', '') + + '/../toc?toc=' + props['toc']}" width="368" height="292"></iframe>`; +} + +/** + * wrs layer popup config + * @param {object} props + * @returns {string} + */ +export function wrs(props) { + "use strict"; + return `<p style="text-align: center">${props['WMS_INFO'].replace(/\n/g, '<br>')}</p>` +} + +export function specialEventWorkZone(props) { + "use strict"; + let startDate = new Date(props['EventStartDate']); + let endDate = new Date(props['EventEndDate']); + let theContent = '<p style="text-align:center">'; + theContent += props['EventDescription'] + '<br>'; + theContent += `${props['HwyName']} ${props['Location']}` + '<br>'; + theContent += `${startDate.toLocaleDateString()} - ${endDate.toLocaleDateString()}`; + theContent += '</p>'; + return theContent; +} diff --git a/projects/glrtoc/layerStyles.js b/projects/glrtoc/layerStyles.js new file mode 100644 index 0000000..7b2eaed --- /dev/null +++ b/projects/glrtoc/layerStyles.js @@ -0,0 +1,39 @@ +/** + * Created by gavorhes on 12/3/2015. + */ +import ol from '../../src/custom-ol'; + +export const workZoneAndEventStyle = new ol.style.Style({ + stroke: new ol.style.Stroke({ + color: 'red', + width: 7 + }), + image: new ol.style.Circle({ + radius: 8, + fill: new ol.style.Fill({ + color: 'magenta' + }), + stroke: new ol.style.Stroke({ + color: 'magenta' + }) + }) +}); + +export function wrsStyle(feature, resolution) { + let colorString = feature.getProperties()['COLOR']; + + let c; + if (typeof colorString === 'string') { + c = colorString.split(' '); + } else { + c = [125, 125, 125]; + } + + return [new ol.style.Style({ + stroke: new ol.style.Stroke({ + color: `rgba(${c[0]},${c[1]},${c[2]},0)`, + width: 5 + }) + })]; +} + diff --git a/projects/glrtoc/legendTest.js b/projects/glrtoc/legendTest.js new file mode 100644 index 0000000..71ecba4 --- /dev/null +++ b/projects/glrtoc/legendTest.js @@ -0,0 +1,129 @@ +/** + * Created by gavorhes on 1/4/2016. + */ +import quickMap from '../../src/olHelpers/quickMap'; +import LayerItsInventory from '../../src/layers/LayerItsInventory'; +import LayerBaseVectorEsri from '../../src/layers/LayerBaseVectorEsri'; +import LayerEsriMapServer from '../../src/layers/LayerEsriMapServer'; +import LayerBaseXyzTile from '../../src/layers/LayerBaseXyzTile'; +import LayerLegend from '../../src/collections/LayerLegend'; +import ItsLayerCollection from '../../src/collections/ItsLayerCollection'; +import mapPopup from '../../src/olHelpers/mapPopup'; + + +(function () { + "use strict"; + let map = quickMap({center: {x: -9907589, y: 5232317}, zoom: 12, minZoom: 3, maxZoom: 19}); + + let itsLayerCollection = new ItsLayerCollection(map); + + let oakRidgeCams = new LayerEsriMapServer( + `http://itsdpro.ornl.gov/arcgis/rest/services/ITSPublic/cameras33/MapServer`, + { + id: 'cameras33', + name: 'Oak Cameras', + visible: true, + minZoom: 7, + zIndex: 20, + addPopup: true + } + ); + + map.addLayer(oakRidgeCams.olLayer); + + glob.cat = (bird) => bird * 2; + + + + + glob.map = map; + + let itsLayer = new LayerItsInventory({itsType: 'CCTV', itsIcon: 'cctv.png', name: 'Camera', visible: false}); + + map.addLayer(itsLayer.olLayer); + + let legend = new LayerLegend( + [ + {groupName: 'its layers', collapse: true, items: itsLayerCollection.layers}, + itsLayer, oakRidgeCams + ], + 'legend-container', {}); + + + + //let legend = new LayerLegend( + // [ + // {groupName: 'its layers', expand: true, items: itsLayerCollection.layers}, + // itsLayer, testEsri, msg, tower, xyzTile, + // {groupName: 'new group', expand: true, items: [rwis, coord, seg, esriMap]} + // ], + // 'legend-container', {}); + + //let legend = new LayerLegend( + // [ + // itsLayerCollection.layers[1] + // ], + // 'legend-container', {}); + + map.getView().setZoom(13); + + return; + + let testEsri = new LayerBaseVectorEsri('http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/GLRTOC/LegendTest/MapServer/3', + {name: 'test esri', useEsriStyle: true, visible: false} + ); + map.addLayer(testEsri.olLayer); + + let msg = new LayerBaseVectorEsri('http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/GLRTOC/LegendTest/MapServer/8', + {name: 'message', useEsriStyle: true, visible: false} + ); + map.addLayer(msg.olLayer); + + let tower = new LayerBaseVectorEsri('http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/GLRTOC/LegendTest/MapServer/0', + {name: 'tower', useEsriStyle: true, visible: false} + ); + map.addLayer(tower.olLayer); + + + let rwis = new LayerBaseVectorEsri('http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/GLRTOC/LegendTest/MapServer/1', + {name: 'rwis', useEsriStyle: true, visible: false} + ); + map.addLayer(rwis.olLayer); + + let coord = new LayerBaseVectorEsri('http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/GLRTOC/LegendTest/MapServer/10', + {name: 'coord', useEsriStyle: true, minZoom: 6, visible: false, collapseLegend: true} + ); + map.addLayer(coord.olLayer); + + //let coord2 = new LayerBaseVectorEsri('http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/GLRTOC/LegendTest/MapServer/11', + // {name: 'coord2', useEsriStyle: true} + //); + //map.addLayer(coord.olLayer); + + let seg = new LayerBaseVectorEsri('http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/GLRTOC/LegendTest/MapServer/9', + {name: 'seg', useEsriStyle: true, visible: false} + ); + map.addLayer(seg.olLayer); + + let esriMap = new LayerEsriMapServer('http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/GLRTOC/LegendTest/MapServer', { + name: 'esri map', + legendCollapse: true, + legendCheckbox: false, + visible: false + }); + + map.addLayer(esriMap.olLayer); + + let xyzTile = new LayerBaseXyzTile('http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/NPMRDS/npmrds_tile/MapServer/tile/{z}/{y}/{x}', + {minZoom: 4, maxZoom: 11, name: "NPMRDS", useEsriStyle: true, collapseLegend: true}); + + //let esriMapServer = new LayerEsriMapServer('http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/NPMRDS/npmrds_dynamic/MapServer', + // {minZoom: 12, maxZoom: 18}); + + map.addLayer(xyzTile.olLayer); + //map.addLayer(esriMapServer.olLayer); + + glob.itsCollection = itsLayerCollection; + + +})(); diff --git a/projects/glrtoc/main.js b/projects/glrtoc/main.js new file mode 100644 index 0000000..2613e08 --- /dev/null +++ b/projects/glrtoc/main.js @@ -0,0 +1,319 @@ +/** + * Created by gavorhes on 12/2/2015. + */ + +// <editor-fold desc="imports"> + +import quickMap from '../../src/olHelpers/quickMap'; +import LayerBase from '../../src/layers/LayerBase'; +import LayerBaseVectorGeoJson from '../../src/layers/LayerBaseVectorGeoJson'; +import LayerBaseVectorEsri from '../../src/layers/LayerBaseVectorEsri'; +import LayerRealEarthTile from '../../src/layers/LayerRealEarthTile'; +import LayerRealEarthVector from '../../src/layers/LayerRealEarthVector'; +import LayerEsriMapServer from '../../src/layers/LayerEsriMapServer'; +import * as layerStyles from './layerStyles'; +import * as layerPopups from './layerPopups'; +import mapPopup from '../../src/olHelpers/mapPopup'; +import mapMove from '../../src/olHelpers/mapMove'; +import * as dteConvert from '../../src/util/dateConvert'; +import * as colors from '../../src/util/colors'; +import appConfig from './appConfig'; +import * as uiSetup from './mainUi'; +import LayerLegend from '../../src/collections/LayerLegend'; +// </editor-fold> + +(function () { + "use strict"; + uiSetup.uiInit(); + + let legendItemsStatic = []; + let legendItemsAnimated = []; + let oakRidgeGroup = {groupName: 'Oak Ridge ITS', collapse: false, addCheck: true, items: []}; + let realEarthGroup = {groupName: 'Real Earth', collapse: false, items: []}; + let workZoneEventGroup = {groupName: 'Work Zones / Events', collapse: false, items: []}; + legendItemsStatic.push(oakRidgeGroup); + legendItemsStatic.push(realEarthGroup); + legendItemsStatic.push(workZoneEventGroup); + + function animationLoadCallback() { + appConfig.animationLayers.push(this); + } + + let map = quickMap({center: {x: -85.413, y: 43.29320}, zoom: 6, minZoom: 3, maxZoom: 19}); + appConfig.map = map; + + // <editor-fold desc="Coordination Layer"> + let coordinationLayer = new LayerBaseVectorEsri( + 'http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/GLRTOC/GlrtocCoordination/MapServer/0', + { + id: appConfig.coordinationLayerId, + visible: true, + autoLoad: true, + name: 'Coordination', + useEsriStyle: true + } + ); + + map.addLayer(coordinationLayer.olLayer); + mapPopup.addVectorPopup(coordinationLayer, layerPopups.coordination); + appConfig.coordinationLayer = coordinationLayer; + + + //appConfig.addLayer(coordinationLayer); + // </editor-fold> + + // <editor-fold desc="Oak Ridge Layers "> + let oakRidgeLayers = [ + ['Cameras', 'cameras33'], + ['HAR', 'HAR33'], + ['DMS', 'MessageSigns33'], + //['State Summary', 'statesummary'], + ['Traffic Control', 'TrafficControl33'], + ['Traffic Detection', 'TrafficDetection33'], + ['Weather', 'Weather33'] + ]; + + + for (let i = 0; i < oakRidgeLayers.length; i++) { + let oakRidgeLayer = new LayerEsriMapServer( + `http://itsdpro.ornl.gov/arcgis/rest/services/ITSPublic/${oakRidgeLayers[i][1]}/MapServer`, + { + id: oakRidgeLayers[i][1], + name: oakRidgeLayers[i][0], + visible: false, + minZoom: 7, + zIndex: 20, + addPopup: true + } + ); + oakRidgeGroup.items.push(oakRidgeLayer); + map.addLayer(oakRidgeLayer.olLayer); + appConfig.addOperationsLayerStatic(oakRidgeLayer); + } + // </editor-fold> + + // <editor-fold desc="WRS Segments"> + + let wrsConfigVector = { + products: 'ROADS', + style: layerStyles.wrsStyle, + animate: false, + id: 'wrs-segments-vector-static', + name: 'Winter Roads', + minZoom: 5, + maxZoom: 13, + zIndex: 3 + }; + + let wrsSegmentLayerVectorStatic = new LayerRealEarthVector(wrsConfigVector); + map.addLayer(wrsSegmentLayerVectorStatic.olLayer); + mapPopup.addVectorPopup(wrsSegmentLayerVectorStatic, layerPopups.wrs); + appConfig.addOperationsLayerStatic(wrsSegmentLayerVectorStatic); + //realEarthGroup.items.push(wrsSegmentLayerVectorStatic); + + wrsConfigVector.animate = true; + wrsConfigVector.id = 'wrs-segments-vector-animate'; + wrsConfigVector.loadCallback = animationLoadCallback; + + let wrsSegmentLayerVectorAnimate = new LayerRealEarthVector(wrsConfigVector); + map.addLayer(wrsSegmentLayerVectorAnimate.olLayer); + mapPopup.addVectorPopup(wrsSegmentLayerVectorAnimate, layerPopups.wrs); + appConfig.addOperationsLayerAnimate(wrsSegmentLayerVectorAnimate); + + let wrsConfigTile = { + products: 'ROADS', + id: 'roads-tile-static', + opacity: 0.6, + animate: false, + name: 'Winter Roads', + zIndex: 10 + }; + + let wrsSegmentLayerTileStatic = new LayerRealEarthTile(wrsConfigTile); + map.addLayer(wrsSegmentLayerTileStatic.olLayer); + appConfig.addOperationsLayerStatic(wrsSegmentLayerTileStatic); + realEarthGroup.items.push(wrsSegmentLayerTileStatic); + + wrsConfigTile.animate = true; + wrsConfigTile.id = 'roads-tile-animate'; + wrsConfigTile.loadCallback = animationLoadCallback; + + let wrsSegmentLayerTileAnimate = new LayerRealEarthTile(wrsConfigTile); + map.addLayer(wrsSegmentLayerTileAnimate.olLayer); + appConfig.addOperationsLayerAnimate(wrsSegmentLayerTileAnimate); + legendItemsAnimated.push(wrsSegmentLayerTileAnimate); + + // </editor-fold> + + // <editor-fold desc="24 hour snow"> + + let snow24Config = { + products: 'SNOWDEPTH24', + id: 'snowdepth24-static', + opacity: 0.5, + animate: false, + name: '24HR Snow', + maxZoom: 9 + }; + + + let snowDepthStatic = new LayerRealEarthTile(snow24Config); + map.addLayer(snowDepthStatic.olLayer); + appConfig.addOperationsLayerStatic(snowDepthStatic); + realEarthGroup.items.push(snowDepthStatic); + + //snow24Config.animate = true; + //snow24Config.id = 'snowdepth24-animate'; + //snow24Config.loadCallback = animationLoadCallback; + // + //let snowDepthAnimate = new LayerRealEarthTile(snow24Config); + //map.addLayer(snowDepthAnimate.olLayer); + //appConfig.addOperationsLayerAnimate(snowDepthAnimate); + //legendItemsAnimated.push(snowDepthAnimate); + + // </editor-fold> + + // <editor-fold desc="nexrhres and precipitation layers"> + let nexrhresConfig = { + products: 'nexrhres', + id: 'nexrhres-static', + opacity: 0.6, + animate: false, + name: 'Hybrid Reflectivity', + maxZoom: 10 + }; + + let nexrhresStatic = new LayerRealEarthTile(nexrhresConfig); + map.addLayer(nexrhresStatic.olLayer); + appConfig.addOperationsLayerStatic(nexrhresStatic); + realEarthGroup.items.push(nexrhresStatic); + + nexrhresConfig.animate = true; + nexrhresConfig.id = 'nexrhres-animate'; + nexrhresConfig.loadCallback = animationLoadCallback; + + let nexrhresAnimate = new LayerRealEarthTile(nexrhresConfig); + map.addLayer(nexrhresAnimate.olLayer); + appConfig.addOperationsLayerAnimate(nexrhresAnimate); + legendItemsAnimated.push(nexrhresAnimate); + + let precipRateConfig = { + products: 'nexrcomp', + id: 'precip-rate-static', + opacity: 0.6, + animate: false, + name: 'Precipitation Rate', + maxZoom: 10 + }; + + let precipRateStatic = new LayerRealEarthTile(precipRateConfig); + map.addLayer(precipRateStatic.olLayer); + appConfig.addOperationsLayerStatic(precipRateStatic); + realEarthGroup.items.push(precipRateStatic); + + precipRateConfig.animate = true; + precipRateConfig.id = 'precip-rate-animate'; + precipRateConfig.loadCallback = animationLoadCallback; + + let precipRateAnimate = new LayerRealEarthTile(precipRateConfig); + map.addLayer(precipRateAnimate.olLayer); + appConfig.addOperationsLayerAnimate(precipRateAnimate); + legendItemsAnimated.push(precipRateAnimate); + + + // </editor-fold> + + // <editor-fold desc="Work Zones and special events"> + let d = new Date(); + d.setSeconds(0); + let endDate = dteConvert.dateToYyyyMmDdHhMmSs(d); + d.setYear(d.getYear() + 1901); + var startDate = dteConvert.dateToYyyyMmDdHhMmSs(d); + + let workZoneSegLayer = new LayerBaseVectorEsri( + 'http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/GLRTOC/GLRTOC_WZ_SE/MapServer/1', + { + where: `EventStartDate < '${startDate}' AND EventEndDate > '${endDate}' AND Impact IN('High', 'XXX')`, + name: "Work Zone Segments", + style: layerStyles.workZoneAndEventStyle, + id: 'work-zone-segments', + minZoom: 5, + maxZoom: 13 + } + ); + + map.addLayer(workZoneSegLayer.olLayer); + appConfig.addOperationsLayerStatic(workZoneSegLayer); + mapPopup.addVectorPopup(workZoneSegLayer, layerPopups.specialEventWorkZone); + workZoneEventGroup.items.push(workZoneSegLayer); + + let specialEventsLayer = new LayerBaseVectorEsri( + 'http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/GLRTOC/GLRTOC_WZ_SE/MapServer/2', + { + where: `EventStartDate < '${startDate}' AND EventEndDate > '${endDate}' AND Impact IN('High', 'XXX')`, + //where: '1=1', + name: "Special Events", + style: layerStyles.workZoneAndEventStyle, + id: 'special-event-points', + minZoom: 5, + maxZoom: 13 + } + ); + + map.addLayer(specialEventsLayer.olLayer); + appConfig.addOperationsLayerStatic(specialEventsLayer); + mapPopup.addVectorPopup(specialEventsLayer, layerPopups.specialEventWorkZone); + workZoneEventGroup.items.push(specialEventsLayer); + + // </editor-fold> + + let legendStatic = new LayerLegend(legendItemsStatic, 'legend-container-static', {}); + let legendAnimate = new LayerLegend(legendItemsAnimated, 'legend-container-animate', {}); + + appConfig.init(); + + uiSetup.uiAfterMap(); +})(); + + +// <editor-fold desc="Promise example"> + +//var promise = new Promise(function (resolve, reject) { +// console.log('doing stuff'); +// +// $.get('http://realearth.ssec.wisc.edu:80/api/products', {products: 'ROADS'}, function (d) { +// //if (d.length == 0) { +// // console.log(`${this._products} layer not available or does not have times`); +// // return; +// //} +// d = d[0]; +// console.log(d); +// resolve("Stuff worked!"); +// +// +// //for (let i = 0; i < d['times'].length; i++) { +// // _this._loadDates.call(_this, d['times'][i]); +// //} +// //console.log(_this._localDates); +// +// //_this._loadAtTimeIndex.call(_this, _this._localDates.length - 1) +// +// }, 'json').fail(function () { +// reject(Error("It broke")); +// }); +// +// +//}); +// +// +//promise.then( +// function (result) { +// console.log(result); // "Stuff worked!" +// }, +// function (err) { +// console.log(err); // Error: "It broke" +// } +//); +// </editor-fold> + + diff --git a/projects/glrtoc/mainUi.js b/projects/glrtoc/mainUi.js new file mode 100644 index 0000000..9e4f17c --- /dev/null +++ b/projects/glrtoc/mainUi.js @@ -0,0 +1,105 @@ +/** + * Created by gavorhes on 12/7/2015. + */ + +import {} from '../../src/jquery-plugin/mediaControl'; +import {} from '../../src/jquery-plugin/rangeChange'; +import appConfig from './appConfig'; +import $ from '../../src/jquery'; +require('jquery-ui/tabs'); +require('jquery-ui/accordion'); + + +/** + * Set up the UI + */ +export function uiInit() { + "use strict"; + + //$("#operations").accordion('refresh'); + + + let $sidebar = $('#sidebar'); + let $hideSideBar = $('#hide-sidebar'); + let $showSideBar = $('#show-sidebar'); + + let $tabs = $("#tabs"); + + let sidebarWidth = $sidebar.width(); + + //apply tab layout + $tabs.tabs({ + heightStyle: "fill", + activate: function (event, ui) { + appConfig.currentTabId = ui.newPanel[0].id; + } + }); + + //apply accordion + appConfig.$opsAccordion.accordion({ + heightStyle: "fill", + activate: function (event, ui) { + appConfig.currentOperationsPanelId = ui.newPanel[0].id; + } + }); + + $(window).resize(function () { + $tabs.tabs('refresh'); + setTimeout(function () { + appConfig.$opsAccordion.accordion("refresh"); + }, 50); + }); + + $hideSideBar.click(function () { + var mapCenter = appConfig.map.getView().getCenter(); + + appConfig.map.beforeRender(function () { + $sidebar.animate({'margin-left': -1 * sidebarWidth}, 200, + function () { + $hideSideBar.hide(); + $showSideBar.show(); + appConfig.map.updateSize(); + } + ); + }); + appConfig.map.getView().setCenter(mapCenter); + }); + + $showSideBar.click(function () { + var mapCenter = appConfig.map.getView().getCenter(); + + appConfig.map.beforeRender(function () { + $sidebar.animate({'margin-left': 0}, 200, + function () { + $showSideBar.hide(); + $hideSideBar.show(); + appConfig.map.updateSize(); + } + ); + }); + appConfig.map.getView().setCenter(mapCenter); + }); + + let d = new Date(); + let endTime = d.getTime(); + d.setHours(d.getHours() - 4); + let startTime = d.getTime(); + let rangeStep = Math.round((endTime - startTime) / 8); + + appConfig.mediaControl = $('#animation-control').mediaControl(startTime, endTime, endTime, rangeStep, + function (t) { + for (let l of appConfig.animationLayers) { + l.setLayerTime(t); + } + }, + 750, true); +} + + +//http://realearth.ssec.wisc.edu/api/image?products=nexrhres_20160108_180000&x=5&y=5&z=4 + +export function uiAfterMap() { + "use strict"; + + +} \ No newline at end of file diff --git a/projects/itsMap.js b/projects/itsMap.js new file mode 100644 index 0000000..d31b6c5 --- /dev/null +++ b/projects/itsMap.js @@ -0,0 +1,27 @@ +/** + * Created by gavorhes on 12/18/2015. + */ + +import quickMap from '../src/olHelpers/quickMap'; +import mapMove from '../src/olHelpers/mapMove'; +import mapPopup from '../src/olHelpers/mapPopup'; +import ItsLayerCollection from '../src/collections/ItsLayerCollection'; +import LayerLegend from '../src/collections/LayerLegend'; + +let map = quickMap(); +mapMove.init(map); +mapPopup.init(map); + +let itsLayerCollection = new ItsLayerCollection(map); + +let layerArray = [ + { + groupName: 'ITS Inventory Layers', + collapse: false, + addCheck: true, + items: itsLayerCollection.layers + } +]; + + +let legend = new LayerLegend(layerArray, 'legend-container', {}); diff --git a/projects/npmrds/delay/delay-config.js b/projects/npmrds/delay/delay-config.js new file mode 100644 index 0000000..5be9a94 --- /dev/null +++ b/projects/npmrds/delay/delay-config.js @@ -0,0 +1,3 @@ +/** + * Created by gavorhes on 2/9/2016. + */ diff --git a/projects/npmrds/delay/delay-main.js b/projects/npmrds/delay/delay-main.js new file mode 100644 index 0000000..b0783f4 --- /dev/null +++ b/projects/npmrds/delay/delay-main.js @@ -0,0 +1,32 @@ +/** + * Created by gavorhes on 2/9/2016. + */ + +import quickMap from '../../../src/olHelpers/quickMap'; +const angular = require('angular2'); + +let map = quickMap(); + +let app = angular.module('myApp', []); + + +app.controller('myCtrl', function($scope) { + $scope.firstName = "John"; + $scope.lastName = "Doe"; + + $scope.myFunction = function(){ + "use strict"; + console.log((new Date()).getTime()); + }; +}); + + +app.controller('myCtrl2', function($scope) { + //$scope.firstName = "John"; + //$scope.lastName = "Doe"; + // + //$scope.myFunction = function(){ + // "use strict"; + // console.log((new Date()).getTime()); + //} +}); diff --git a/projects/npmrds/heatmap/appConfig.js b/projects/npmrds/heatmap/appConfig.js new file mode 100644 index 0000000..32d4fcb --- /dev/null +++ b/projects/npmrds/heatmap/appConfig.js @@ -0,0 +1,50 @@ +/** + * Created by gavorhes on 12/23/2015. + */ + +class NpmrdsHeatmapConfig { + constructor() { + + this.map = undefined; + + /** + * + * @type {LayerBaseVectorGeoJson} + */ + this.featureOverlay = undefined; + + /** + * + * @type {LayerBaseVectorGeoJson} + */ + this.lineLayer = undefined; + + + /** + * + * @type {LayerBaseVectorGeoJson} + */ + this.pointLayer = undefined; + + + /** + * + * @type {LayerBaseVectorGeoJson} + */ + this.trackerLayer = undefined; + } + + +} + +///** +// * +// * @type {NpmrdsHeatmapConfig} +// */ +//const npmrdsHeatmapConfig = new NpmrdsHeatmapConfig(); + +/** + * @type {NpmrdsHeatmapConfig} + */ +export default new NpmrdsHeatmapConfig(); + diff --git a/projects/npmrds/heatmap/layerStyles.js b/projects/npmrds/heatmap/layerStyles.js new file mode 100644 index 0000000..e16bd69 --- /dev/null +++ b/projects/npmrds/heatmap/layerStyles.js @@ -0,0 +1,43 @@ +/** + * Created by gavorhes on 12/22/2015. + */ +import ol from '../../../src/custom-ol'; + + +export const overlayStyle = new ol.style.Style({ + fill: new ol.style.Fill({ + color: 'rgba(255, 0, 237, 0.1)' + }), + stroke: new ol.style.Stroke({ + color: 'rgb(255, 0, 237)', + width: 2 + }) +}); + + +export const lineIndicator = new ol.style.Style({ + stroke: new ol.style.Stroke({ + color: 'red', + width: 7 + }) +}); + + +export const pointIndices = new ol.style.Style({ + image: new ol.style.Circle({ + radius: 4, + fill: new ol.style.Fill({ + color: 'blue' + }) + }) +}); + + +export const trackerPoint = new ol.style.Style({ + image: new ol.style.Circle({ + radius: 8, + fill: new ol.style.Fill({ + color: 'blue' + }) + }) +}); diff --git a/projects/npmrds/heatmap/main-ui.js b/projects/npmrds/heatmap/main-ui.js new file mode 100644 index 0000000..7f6a44a --- /dev/null +++ b/projects/npmrds/heatmap/main-ui.js @@ -0,0 +1,368 @@ +/** + * Created by gavorhes on 12/22/2015. + */ + +import npmrdsHeatmapConfig from './appConfig'; +import {} from '../../../src/jquery-plugin/dayRange'; +import {} from '../../../src/jquery-plugin/rangeChange'; +import * as colors from '../../../src/util/colors'; +import SortedFeatures from '../../../src/olHelpers/SortedFeatures'; +import $ from '../../../src/jquery'; +import ol from '../../../src/custom-ol'; + + +let $btnCancelArea = $('#btn-cancel-area'); +let $btnSelectArea = $('#btn-select-area'); +let $divSelectArea = $('#div-select-area'); +let $ulHwyDirs = $('#ul-hwy-dirs'); +let $btnSelectHwy = $('#btn-select-hwy'); +//let $btnSelectHwyBack = $('#btn-select-hwy-back'); +let $divHighwaySelection = $('#div-highway-selection'); +let $divRight = $('#right'); +let $divLeft = $('#left'); +let $ckmapTrack = $('#chk-map-track'); +let $canvasToolTipSpan = $('#canvas-tooltip-span'); +let $canv = $('#heatmap-canvas'); +/** + * + * @type {*|jQuery|HTMLElement} + */ +let $canvContainer = $('#canvas-container'); +let $dateUl = $('#date-ul'); +let $heatMapVerticalBar = $('#heat-map-vertical-bar'); +let $selectedTmcs = $('#selected-tmcs'); + +let sldrHeatMapId = 'heat-map-slider'; +let $sldrHeatMap = $('#' + sldrHeatMapId); + + +let heatMapReady = false; + +/** + * @type {SortedFeatures} + */ +let sortedFeatures; + +/** + * @type {DayRange} + */ +let dayRange; + +function _leadingPad(num) { + let out = num.toFixed(); + if (out.length == 1) { + out = '0' + out; + } + + return out; +} + +function _formatDate(d) { + return `${_leadingPad(d.getMonth() + 1)}/${_leadingPad(d.getDate())}/${d.getYear() + 1900} ` + + `${_leadingPad(d.getHours())}:${_leadingPad(d.getMinutes())}:${_leadingPad(d.getSeconds())}`; +} + + + +function clearCanvas() { + $dateUl.html(''); + $canv.off('mousemove'); + let canv = $canv[0]; + let ctx = canv.getContext("2d"); + ctx.clearRect(0, 0, canv.width, canv.height); + + $canv.attr('width', $('#heat-map-slider').width()); + $canv.attr('height', 100); + $heatMapVerticalBar.height(0); +} + + +export function startUi() { + "use strict"; + dayRange = $('#div-date-range').dayRange(10); +} + +export function drawSetup() { + "use strict"; + let draw = new ol.interaction.Draw({ + source: npmrdsHeatmapConfig.featureOverlay.source, + type: 'Polygon' + }); + + draw.on('drawend', function (evt) { + //$divSelectArea.hide(); + $btnSelectArea.prop('disabled', false); + let geom = evt.feature.getGeometry(); + let geomClone = geom.clone(); + + geomClone.transform('EPSG:3857', 'EPSG:4326'); + + setTimeout(function () { + npmrdsHeatmapConfig.map.removeInteraction(draw); + }, 100); + $btnCancelArea.hide(); + + $.get('npmrds/gethighways', {polygon: JSON.stringify(geomClone.getCoordinates())}, + function (d) { + $ulHwyDirs.html(d); + $divHighwaySelection.show(); + + $('input[name=hwydirs]').change(function () { + $btnSelectHwy.prop('disabled', false); + }); + }, 'text'); + }); + + $btnCancelArea.click(function () { + npmrdsHeatmapConfig.map.removeInteraction(draw); + $btnSelectArea.prop('disabled', false); + $btnCancelArea.hide(); + }); + + $btnSelectArea.click(function () { + npmrdsHeatmapConfig.featureOverlay.source.clear(); + npmrdsHeatmapConfig.map.addInteraction(draw); + $btnSelectArea.prop('disabled', true); + $btnCancelArea.show(); + $ulHwyDirs.html(''); + $divHighwaySelection.hide(); + $btnSelectHwy.prop('disabled', true); + }); +} + + +export function endUi() { + "use strict"; + + $divSelectArea.show(); + $btnSelectArea.prop('disabled', false); + $btnCancelArea.hide(); + $divHighwaySelection.hide(); + + $btnSelectHwy.click(function () { + let selectedHwy = $('input[name=hwydirs]:checked:first').val(); + $('#sel-hwy').html(selectedHwy); + $.get('npmrds/getroute', + { + hwyDir: selectedHwy + }, function (d) { + npmrdsHeatmapConfig.lineLayer.clear(); + npmrdsHeatmapConfig.lineLayer.addFeatures(d['line']); + + npmrdsHeatmapConfig.pointLayer.clear(); + npmrdsHeatmapConfig.pointLayer.addFeatures(d['points']); + + sortedFeatures = new SortedFeatures(npmrdsHeatmapConfig.pointLayer.source.getFeatures(), 'distReal'); + + npmrdsHeatmapConfig.trackerLayer.clear(); + npmrdsHeatmapConfig.trackerLayer.source.addFeature(sortedFeatures.sortedFeatures[0]); + + + $divLeft.hide(); + $divRight.show(); + npmrdsHeatmapConfig.map.updateSize(); + + let mapView = npmrdsHeatmapConfig.map.getView(); + + let panAnimation = ol.animation.pan({ + duration: 500, + source: mapView.getCenter() + }); + npmrdsHeatmapConfig.map.beforeRender(panAnimation); + + mapView.fit( + npmrdsHeatmapConfig.featureOverlay.source.getFeatures()[0].getGeometry().getExtent(), + npmrdsHeatmapConfig.map.getSize() + ); + + mapView.setZoom(mapView.getZoom() - 1); + + $('#vehicle-all').prop('checked', true); + + npmrdsHeatmapConfig.featureOverlay.visible = false; + npmrdsHeatmapConfig.lineLayer.visible = true; + npmrdsHeatmapConfig.pointLayer.visible = true; + npmrdsHeatmapConfig.trackerLayer.visible = true; + + $sldrHeatMap.prop('max', d['totalDistance']); + $sldrHeatMap.val(0); + $heatMapVerticalBar.css('left', '22px'); + $selectedTmcs.val(JSON.stringify(d['tmcs'])); + + //console.log(d); + }, 'json').fail(function () { + alert("something went wrong, try another area selection"); + }); + }); +} + + +export function heatMapUi() { + "use strict"; + + $('#heat-map-back').click(function () { + $divLeft.show(); + $divRight.hide(); + npmrdsHeatmapConfig.map.updateSize(); + npmrdsHeatmapConfig.featureOverlay.visible = true; + npmrdsHeatmapConfig.lineLayer.visible = false; + npmrdsHeatmapConfig.pointLayer.visible = false; + npmrdsHeatmapConfig.trackerLayer.visible = false; + + clearCanvas(); + }); + + $canv.mouseenter(function () { + if (heatMapReady) { + $canvasToolTipSpan.css('display', 'block'); + } + }); + + $canv.mouseleave(function () { + $canvasToolTipSpan.css('display', 'none'); + $canvasToolTipSpan.html(''); + }); + + //add the slider change interaction + $('#' + sldrHeatMapId).rangeChange(function(newVal, percent, evt){ + + let canvWidth = parseFloat($canv.width()); + + $heatMapVerticalBar.css('left', (canvWidth * percent + 22).toFixed() + 'px'); + + let selectedFeature = sortedFeatures.getFeature(newVal); + + npmrdsHeatmapConfig.trackerLayer.clear(); + npmrdsHeatmapConfig.trackerLayer.source.addFeature(selectedFeature); + + if ($ckmapTrack.prop('checked')) { + let panAnimation = ol.animation.pan({ + duration: 500, + source: npmrdsHeatmapConfig.map.getView().getCenter() + }); + npmrdsHeatmapConfig.map.beforeRender(panAnimation); + npmrdsHeatmapConfig.map.getView().setCenter(selectedFeature.getGeometry().getCoordinates()); + } + }, 25); + + + $('#heat-map-confirm').click(function () { + clearCanvas(); + let canv = $canv[0]; + let ctx = canv.getContext("2d"); + let $progressDiv = $('#progress-indicator-div'); + $dateUl.html(''); + + $progressDiv.show(); + + $.get('npmrds/getheatmap', + { + vehicleType: $('input[name=vehicle-type]:checked:first').val(), + startDate: _formatDate(dayRange.startDate), + endDate: _formatDate(dayRange.endDate), + tmcs: $selectedTmcs.val() + }, function (d) { + if (d['error']) { + alert(d['error']); + + return; + } + + let canvasWidth = parseInt($canv.attr('width')); + let colorGradient = colors.makeBlueGreenRedGradient(d['minSpeedVsFree'], d['maxSpeedVsFree'], true); + let colorGradientStdDev = colors.makeBlueGreenRedGradientZScore(d['medianSpeedVsFree'], d['stdDevSpeedVsFree'], true); + + let recordLength = d['tmcResult'][0].values.length; + $canv.attr('height', (recordLength * 2).toFixed()); + $heatMapVerticalBar.height(recordLength * 2); + + let columnPosition = 0; + let tmcEndPositionArray = []; + + for (let i = 0; i < d['tmcResult'].length; i++) { + let tmc = d['tmcResult'][i]; + let rectangleWidth = canvasWidth * tmc['distPercent'] / 100; + let valLength = tmc['values'].length; + + for (let j = 0; j < valLength; j++) { + let speedVFreeSpeed = (tmc['values'][j] == null ? null : tmc['values'][j] / tmc['freeFlowSpeed']); + let speedVFreeZScore = (speedVFreeSpeed - d['medianSpeedVsFree']) / d['stdDevSpeedVsFree']; + //console.log(colorGradientStdDev(speedVFreeSpeed)); + //let z_score = + //let z_score = + + ctx.fillStyle = colorGradientStdDev(speedVFreeSpeed); + ctx.fillRect(columnPosition, j * 2, rectangleWidth, 2); + } + + columnPosition += rectangleWidth; + tmcEndPositionArray.push([tmc['tmc'], columnPosition]); + } + + for (let i = 0; i < d['dateList'].length; i++) { + $dateUl.append('<li><div>' + d['dateList'][i] + '</div></ul>'); + } + + // set the date li height + //$('#date-ul li').css('height', (2 + (parseInt($canv.attr('height')) / d['dateList'].length) - d['dateList'].length).toFixed()); + + let tmcResultDict = {}; + for (let i = 0; i < d['tmcResult'].length; i++) { + tmcResultDict[d['tmcResult'][i]['tmc']] = d['tmcResult'][i]; + } + + $canv.mousemove(function (evt) { + + // coordinates relative the canvas + let offsetX = evt.offsetX; + let offsetY = evt.offsetY; + + // coordinates relative the window + let clientX = evt.clientX; + let clientY = evt.clientY; + + // get the tmc + let tmcId = null; + for (let i = 0; i < tmcEndPositionArray.length; i++) { + if (offsetX < tmcEndPositionArray[i][1]) { + tmcId = tmcEndPositionArray[i][0]; + break; + } + } + + if (tmcId == null) { + tmcId = tmcEndPositionArray[tmcEndPositionArray.length - 1][0]; + } + + // since each retangle in the heatmap is 2px high, get the index by divding by 2, round down + let rowIndex = Math.floor(offsetY / 2); + + // make a date equal to the query start date + let dte = new Date(d['dateList'][0]); + // add minutes as 5X the row index + dte.setMinutes(dte.getMinutes() + rowIndex * 5); + + let tmcObj = tmcResultDict[tmcId]; + + //set the html + $canvasToolTipSpan.html(`TMC: ${tmcId}<br>${dte.toLocaleDateString()} ${dte.toLocaleTimeString()}<br>` + + `Speed: ${(tmcObj['values'][rowIndex] == null ? 'null' : tmcObj['values'][rowIndex].toFixed(1))}, Free: ${tmcObj['freeFlowSpeed'].toFixed(1)}` + ); + + //set the position + let canvasToolipSpan = $canvasToolTipSpan[0]; + canvasToolipSpan.style.left = (clientX - 150).toFixed() + 'px'; + canvasToolipSpan.style.top = (clientY - 85).toFixed() + 'px'; + + }); + //console.log(d); + + $canvContainer.scrollTop(0); + heatMapReady = true; + }, 'json').fail(function(){ + alert('Something went wrong with the request'); + }).always(function(){ + $progressDiv.hide(); + }); + }); +} diff --git a/projects/npmrds/heatmap/main.js b/projects/npmrds/heatmap/main.js new file mode 100644 index 0000000..2397377 --- /dev/null +++ b/projects/npmrds/heatmap/main.js @@ -0,0 +1,47 @@ +/** + * Created by gavorhes on 12/22/2015. + */ + +import npmrdsHeatmapConfig from './appConfig'; +import quickMap from '../../../src/olHelpers/quickMap'; +import LayerBaseXyzTile from '../../../src/layers/LayerBaseXyzTile'; +import LayerEsriMapServer from '../../../src/layers/LayerEsriMapServer'; +import LayerBaseVectorGeoJson from '../../../src/layers/LayerBaseVectorGeoJson'; +import * as layerStyles from './layerStyles'; +import * as uiSetup from './main-ui'; + +//glob.appConfig = npmrdsHeatmapConfig; + +(function(){ + "use strict"; + uiSetup.startUi(); + let map = quickMap({center: {x: -10012438, y: 5548095}, zoom: 8, minZoom: 5}); + + npmrdsHeatmapConfig.map = map; + + let xyzTile = new LayerBaseXyzTile('http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/NPMRDS/npmrds_tile/MapServer/tile/{z}/{y}/{x}', + {minZoom: 4, maxZoom: 11}); + + let esriMapServer = new LayerEsriMapServer('http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/NPMRDS/npmrds_dynamic/MapServer', + {minZoom: 12, maxZoom: 18}); + + map.addLayer(xyzTile.olLayer); + map.addLayer(esriMapServer.olLayer); + + let transform = {dataProjection: 'EPSG:3857', featureProjection: 'EPSG:3857'}; + + npmrdsHeatmapConfig.featureOverlay = new LayerBaseVectorGeoJson('', {style: layerStyles.overlayStyle, transform: transform}); + npmrdsHeatmapConfig.lineLayer = new LayerBaseVectorGeoJson('', {style: layerStyles.lineIndicator, transform: transform}); + npmrdsHeatmapConfig.pointLayer = new LayerBaseVectorGeoJson('', {style: layerStyles.pointIndices, transform: transform}); + npmrdsHeatmapConfig.trackerLayer = new LayerBaseVectorGeoJson('', {style: layerStyles.trackerPoint, transform: transform}); + + map.addLayer(npmrdsHeatmapConfig.featureOverlay.olLayer); + map.addLayer(npmrdsHeatmapConfig.lineLayer.olLayer); + //map.addLayer(npmrdsHeatmapConfig.pointLayer.olLayer); + map.addLayer(npmrdsHeatmapConfig.trackerLayer.olLayer); + + uiSetup.drawSetup(); + uiSetup.heatMapUi(); + uiSetup.endUi(); +})(); + diff --git a/projects/tsmo/TipConfig.js b/projects/tsmo/TipConfig.js new file mode 100644 index 0000000..705a404 --- /dev/null +++ b/projects/tsmo/TipConfig.js @@ -0,0 +1,149 @@ +/** + * Created by gavorhes on 12/14/2015. + */ + +/** + * Tip config object + */ +class TipConfig { + constructor() { + + /** + * + * @type {Sliders} + */ + this.sliders = undefined; + + /** + * + * @type {Map} + */ + this.map = null; + + this.$loadingGif = null; + this.$regionSelector = undefined; + + /** + * + * @type {TipSegmentLayer} + */ + this.tipSegmentLayer = undefined; + + + /** + * + * @type {LayerBase|*} + */ + this.metamanagerSegments = undefined; + this.tipSegmentLayerMinZoom = 10; + + /** + * its layer collection + * @type {ItsLayerCollection} + */ + this.itsLayerCollection = undefined; + + /** + * param list to set up the sliders, initial weight and drop down selection added later + */ + this._sliderParamArray = [ + ['AADT', [['aadtyr_1', '1']]], + ['AADT Future', [['aadtyr_5', '5'], ['aadtyr_10', '10'], ['aadtyr_15', '15'], ['aadtyr_20', '20']]], + ['Growth', [['growth_5', '5'], ['growth_10', '10'], ['growth_15', '15'], ['growth_20', '20']]], + ['Truck', [['trkdyr_1', '1'], ['trkdyr_20', '20']]], + ['LOS', [['losyr_1', '1']]], + ['LOS Future', [['losyr_5', '5'], ['losyr_10', '10'], ['losyr_15', '15'], ['losyr_20', '20']]], + ['Crash Rate', [['crash_rate', '1']]], + ['Severity', [['crash_severity', '1']]], + ['Weather', [['weather', '1']]], + ['Event', [['event', '1']]] + ]; + + /** + * Presets list, order of the parameters is important, must match that of the slider param list + */ + this._presetArray = + [ + ['Default TIP', [ + [10.0, 'aadtyr_1'], + [7.0, 'aadtyr_20'], + [7.0, 'growth_20'], + [4.0, 'trkdyr_1'], + [12.0, 'losyr_1'], + [12.0, 'losyr_20'], + [15.0, 'crash_rate'], + [13.0, 'crash_severity'], + [9.0, 'weather'], + [11.0, 'event']] + ], + ['Safety', [ + [20.0, 'aadtyr_1'], + [0.0, 'aadtyr_20'], + [0.0, 'growth_20'], + [0.0, 'trkdyr_1'], + [0.0, 'losyr_1'], + [0.0, 'losyr_20'], + [40.0, 'crash_rate'], + [40.0, 'crash_severity'], + [0.0, 'weather'], + [0.0, 'event']] + ], + ['Mobility Present', [ + [25.0, 'aadtyr_1'], + [25.0, 'aadtyr_5'], + [0.0, 'growth_20'], + [25.0, 'trkdyr_1'], + [25.0, 'losyr_1'], + [0.0, 'losyr_20'], + [0.0, 'crash_rate'], + [0.0, 'crash_severity'], + [0.0, 'weather'], + [0.0, 'event']] + ], + ['Mobility Future', [ + [0.0, 'aadtyr_1'], + [25.0, 'aadtyr_20'], + [25.0, 'growth_20'], + [25.0, 'trkdyr_20'], + [0.0, 'losyr_1'], + [25.0, 'losyr_20'], + [0.0, 'crash_rate'], + [0.0, 'crash_severity'], + [0.0, 'weather'], + [0.0, 'event']] + ], + ['Service', [ + [30.0, 'aadtyr_1'], + [0.0, 'aadtyr_20'], + [10.0, 'growth_20'], + [0.0, 'trkdyr_1'], + [30.0, 'losyr_1'], + [30.0, 'losyr_20'], + [0.0, 'crash_rate'], + [0.0, 'crash_severity'], + [0.0, 'weather'], + [0.0, 'event']] + ], + ['Freight Performance', [ + [20.0, 'aadtyr_1'], + [0.0, 'aadtyr_20'], + [0.0, 'growth_20'], + [60.0, 'trkdyr_1'], + [20.0, 'losyr_1'], + [0.0, 'losyr_20'], + [0.0, 'crash_rate'], + [0.0, 'crash_severity'], + [0.0, 'weather'], + [0.0, 'event']] + ] + ]; + + for (var i = 0; i < this._sliderParamArray.length; i++) { + this._sliderParamArray[i].push(this._presetArray[0][1][i][0]); + this._sliderParamArray[i].push(this._presetArray[0][1][i][1]); + } + + } +} + +export default new TipConfig(); diff --git a/projects/tsmo/TipSegmentLayer.js b/projects/tsmo/TipSegmentLayer.js new file mode 100644 index 0000000..60f299b --- /dev/null +++ b/projects/tsmo/TipSegmentLayer.js @@ -0,0 +1,191 @@ +/** + * Created by gavorhes on 12/10/2015. + */ + +import LayerBaseVectorGeoJson from '../../src/layers/LayerBaseVectorGeoJson'; +import mapMove from '../../src/olHelpers/mapMove'; +import mapPopup from '../../src/olHelpers/mapPopup'; +import tipConfig from './TipConfig' +import * as tipLayerStyles from './tipStyleFunction'; +const $ = require('jquery'); + +/** + * Tip Segment layer with a bunch of configuration applied, extends base GeoJSON + */ +class TipSegmentLayer extends LayerBaseVectorGeoJson { + + /** + * ITS device layer, types available at http://transportal.cee.wisc.edu/its/inventory/ + * @param {Sliders} sliders + * @param {object} options + * @param {boolean} [options.visible=true] + * @param {boolean} [options.onDemand=true] + * @param {number} [options.onDemandDelay=300] delay before the map move callback should be called + * @param [options.$loadingGif=undefined] jquery reference to loading gif + * @param [options.$regionSelector=undefined] jquery reference to region selector + * + * @param {object} [options.selectionStyle={}] the selection style configuration + * @param {string} [options.selectionStyle.color=rgba(255,170,0,0.5)] the selection color + * @param {number} [options.selectionStyle.width=10] the selection width for linear features + * @param {object} [options.selectionStyle.olStyle=undefined] an openlayers style object + * @param {propertiesZoomStyle} [options.selectionStyle.olStyleFunction=undefined] modified OL style function + */ + constructor(sliders, options) { + options['name'] = "TIP Segments"; + options.onDemand = true; + options.style = tipLayerStyles.tipStyle; + options['minZoom'] = tipConfig.tipSegmentLayerMinZoom; + options['transform'] = {}; + options.transform.dataProjection = 'EPSG:3857'; + options.transform.featureProjection = 'EPSG:3857'; + options['id'] = 'tip-segments'; + super('tip/gettipfeatures?callback=?', options); + this._$regionSelector = options.$regionSelector || undefined; + + + this._$loadingGif = options.$loadingGif; + + this.legendContent += '<ul><li><hr class="cell-min"></li><li><hr class="cell-very-low"></li>' + + '<li><hr class="cell-low"></li><li><hr class="cell-mid"></li><li><hr class="cell-high"></li>' + + '<li><hr class="cell-very-high"></li><li><hr class="cell-max">' + + '</li></ul>'; + + this.legendContent += '<ul>'; + this.legendContent += '<li style="height: 15px;">low</li>'; + this.legendContent += '<li style="height: 25px; margin-top: 4px;">medium</li>'; + this.legendContent += '<li style="height: 15px; margin-top: 5px;">high</li>'; + this.legendContent += '</ul>'; + + this.legendContent += '<span style="margin: 12px 0 0 52px; display: block">Relative Need</span>'; + + this._geometry_cache = []; + + this.sliders = sliders; + tipConfig.tipSegmentLayer = this; + + let _this = this; + + mapPopup.addVectorPopup(this, function (props) { + + let parms = { + pdpId: props['p'], + paramWeights: JSON.stringify(_this.sliders.getParams()) + }; + + return '<iframe style="margin-top:5px;" ' + + `src="tip/getsegprops?${$.param(parms)}" ` + + `height="250" width="350"></iframe>`; + }, options.selectionStyle); + } + + /** + * override base method to include show or hide loading indicator + * @param {number} zoom + * @param {string} [evtType=undefined] undefined for initial load, otherwise one of 'change:center', 'change:resolution' + * @returns {boolean} + */ + mapMoveBefore(zoom, evtType) { + let returnVal = super.mapMoveBefore(zoom, evtType); + + if (this._$loadingGif) { + if (returnVal) { + this._$loadingGif.fadeIn(); + } else { + this._$loadingGif.fadeOut(); + } + } + return returnVal; + } + + /** + * callback to generate the parameters passed in the get request + * @param {object} extent + * @param {number} extent.minX + * @param {number} extent.minY + * @param {number} extent.maxX + * @param {number} extent.maxY + * @param {number} zoomLevel + */ + mapMoveMakeGetParams(extent, zoomLevel) { + super.mapMoveMakeGetParams(extent, zoomLevel); + $.extend(this.mapMoveParams, extent); + this.mapMoveParams['param_weights'] = JSON.stringify(this.sliders.getParams()); + if (this._$regionSelector){ + this.mapMoveParams['region'] = this._$regionSelector.val(); + } + } + + + /** + * callback function on map move + * @param d the json response + */ + mapMoveCallback(d) { + if (d['geojson'].features.length > 0) { + this._geometry_cache = this._geometry_cache.concat(d['geojson'].features); + this._geometry_cache.sort(function (a, b) { + return (a.properties['p'] - b.properties['p']); + }); + } + + let passFeatures = []; + + for (let s of d['scores']) { + + let feat = this._set_pdp_score(s['p'], s['z']); + if (feat) { + passFeatures.push(feat); + } + } + + d['geojson'].features = passFeatures; + super.mapMoveCallback(d['geojson']); + if (this._$loadingGif) { + this._$loadingGif.fadeOut(); + } + } + + /** + * set the score for the feature + * @param {number} pdp pdp_id + * @param {number} score to assign + * @param {object} [in_array=this._geometry_cache] + * @returns {*} the feature with the score assigned + * @private + */ + _set_pdp_score(pdp, score, in_array) { + if (typeof in_array == 'undefined') { + in_array = this._geometry_cache; + } + + if (in_array.length == 0) { + return undefined; + } + + if (in_array.length == 1) { + let feat = in_array[0]; + if (feat.properties['p'] == pdp) { + feat.properties['z'] = score; + return feat; + } else { + return undefined; + } + } + + let midPoint = Math.floor(in_array.length / 2); + + let midFeature = in_array[midPoint]; + if (midFeature.properties['p'] == pdp) { + midFeature.properties['z'] = score; + return midFeature; + } else if (pdp < midFeature.properties['p']) { + return this._set_pdp_score(pdp, score, in_array.slice(0, midPoint)); + } else { + return this._set_pdp_score(pdp, score, in_array.slice(midPoint + 1)); + } + } + +} + + +export default TipSegmentLayer; diff --git a/projects/tsmo/legend-test.js b/projects/tsmo/legend-test.js new file mode 100644 index 0000000..361da67 --- /dev/null +++ b/projects/tsmo/legend-test.js @@ -0,0 +1,84 @@ +/** + * Created by gavorhes on 12/18/2015. + */ +import quickMap from '../../src/olHelpers/quickMap'; +import mapMove from '../../src/olHelpers/mapMove'; +import mapPopup from '../../src/olHelpers/mapPopup'; +import ItsLayerCollection from '../../src/collections/ItsLayerCollection'; +import LayerLegend from '../../src/collections/LayerLegend'; + +let map = quickMap(); + +mapMove.init(map); +mapPopup.init(map); + +let itsLayerCollection = new ItsLayerCollection(map); + +let layerArray = [ + { + groupName: 'ITS Inventory Layers', + collapse: false, + addCheck: false, + items: itsLayerCollection.layers + } +]; + +let legend = new LayerLegend(layerArray, 'legend-container', {}); + +// +//let layerArry = itsLayerCollection.layers.slice(0, 3); +// +//layerArry.push( +// { +// groupName: 'Group 1', +// collapse: false, +// items: itsLayerCollection.layers.slice(3, 6) +// } +//); +// +//layerArry.push(itsLayerCollection.layers[6]); +// +//let collection2 = itsLayerCollection.layers.slice(7, 9); +//collection2.push({ +// +// groupName: 'Group 3', +// collapse: false, +// items: itsLayerCollection.layers.slice(10, 12) +// +//}); +// +//layerArry.push( +// { +// groupName: 'Group 2', +// collapse: true, +// items: collection2 +// } +//); +// +//let layerArray = [ +// itsLayerCollection.layers[0], +// itsLayerCollection.layers[1], +// { +// +// groupName: 'Group 1', +// collapse: false, +// items: [itsLayerCollection.layers[2], itsLayerCollection.layers[3]] +// }, +// { +// groupName: 'Group 2', +// collapse: true, +// addCheck: false, +// items: [ +// itsLayerCollection.layers[4], +// itsLayerCollection.layers[5], +// { +// groupName: 'Group 3', +// collapse: false, +// items: [itsLayerCollection.layers[6], itsLayerCollection.layers[7]] +// } +// ] +// } +//]; + + + diff --git a/projects/tsmo/main-report.js b/projects/tsmo/main-report.js new file mode 100644 index 0000000..6b8d948 --- /dev/null +++ b/projects/tsmo/main-report.js @@ -0,0 +1,198 @@ +/** + * Created by gavorhes on 12/22/2015. + */ + +import quickMap from '../../src/olHelpers/quickMap'; +import LayerBaseVectorGeoJson from '../../src/layers/LayerBaseVectorGeoJson'; +import mapPopup from '../../src/olHelpers/mapPopup'; +import * as tipLayerStyles from './tipStyleFunction'; +import LayerEsriMapServer from '../../src/layers/LayerEsriMapServer'; +import ItsLayerCollection from '../../src/collections/ItsLayerCollection'; +import LayerLegend from '../../src/collections/LayerLegend'; +import {} from '../../lib/jquery.floatThead'; +let $ = require('jquery'); + +let suppressLowScores = true; + +function tipStyleReport(feature, resolution) { + "use strict"; + + let seg_score = feature.getProperties()['z']; + + if (seg_score < 1 && suppressLowScores) { + return null; + } else { + return tipLayerStyles.tipStyle(feature, resolution); + } +} + + +(function () { + "use strict"; + + let $crashData = $('#crash-data'); + + function getCrashData(pdpId) { + $crashData.html(''); + + $.get('getcrash', {pdpId: pdpId}, function (d) { + $crashData.html(d); + }, 'text') + } + + // add the cell classes + $('.param-val').each(function () { + let z = parseFloat($(this).attr('data-crumb')); + let cellClass = 'cell-max'; + + if (z < -2.5) { + cellClass = 'cell-min'; + } else if (z < -1.5) { + cellClass = 'cell-very-low'; + } else if (z < -0.5) { + cellClass = 'cell-low'; + } else if (z < 0.5) { + cellClass = 'cell-mid'; + } else if (z < 1.5) { + cellClass = 'cell-high'; + } else if (z < 2.5) { + cellClass = 'cell-very-high'; + } + + $(this).addClass(cellClass); + }); + + let map = quickMap({center: {x: -10012438, y: 5548095}, zoom: 6, minZoom: 6}); + + let wisDotRegions = new LayerEsriMapServer( + 'http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/MetaManager/Metamanager_regions/MapServer', + { + minZoom: 6, + maxZoom: 15, + opacity: 0.4 + }); + + map.addLayer(wisDotRegions.olLayer); + + let reportSegments = new LayerBaseVectorGeoJson('', + { + loadCallback: function (theLayer) { + map.getView().fit(theLayer.source.getExtent(), map.getSize()); + }, + transform: {featureProjection: 'EPSG:3857', dataProjection: 'EPSG:3857'}, + style: tipStyleReport, + params: {d: (new Date()).getTime().toString()}, + zIndex: 10 + } + ); + + let geoJsonData = JSON.parse($('#geojson-data').val()); + reportSegments.addFeatures(geoJsonData); + + map.addLayer(reportSegments.olLayer); + map.getView().fit(reportSegments.source.getExtent(), map.getSize()); + + let itsLayerCollection = new ItsLayerCollection(map); + + for (let l of itsLayerCollection.layers) { + l.zIndex = 10; + l.opacity = 0.5; + } + + let layerArray = [ + { + groupName: 'ITS Inventory Layers', + collapse: true, + addCheck: true, + items: itsLayerCollection.layers + } + ]; + + let legend = new LayerLegend(layerArray, 'legend-container', {}); + + let $resultsTable = $('#results-table'); + let $resultsContainer = $('#results-container'); + + + + mapPopup.addMapClickFunction(function () { + $('.selected-row').removeClass('selected-row'); + }); + + //return undefined in popup callback to prevent default popup display + let selectionLayer = mapPopup.addVectorPopup(reportSegments, function (props) { + let pdp = props['p']; + getCrashData(pdp); + let $selectedRow = $resultsTable.find(`#${pdp}`); + $selectedRow.addClass('selected-row'); + $resultsContainer.find('table tbody').scrollTop(0); + $resultsContainer.find('table tbody').scrollTop($selectedRow.offset().top - 60); + return undefined; + }, + {olStyle: tipLayerStyles.tipStyleSelection} + ); + + mapPopup.addMapClickFunction(function () { + $crashData.html(''); + }); + + $('.selectable-row').click(function () { + let mapView = map.getView(); + selectionLayer.getSource().clear(); + $('.selected-row').removeClass('selected-row'); + $(this).addClass('selected-row'); + let pdp = parseInt(this.id); + let feats = reportSegments.source.getFeatures(); + getCrashData(pdp); + for (let feature of feats) { + if (feature.getProperties()['p'] == pdp) { + selectionLayer.getSource().addFeature(feature); + mapView.fit(feature.getGeometry().getExtent(), map.getSize()); + mapView.setZoom(mapView.getZoom() - 2); + return; + } + } + }); + + let $scoreUnderOneRows = $('.score-under-one-flag'); + + $('#show-all-toggle').click(function () { + if (this.checked) { + $scoreUnderOneRows.removeClass('score-under-one'); + suppressLowScores = false; + } else { + $scoreUnderOneRows.addClass('score-under-one'); + suppressLowScores = true; + } + reportSegments.refresh(); + mapPopup.closePopup(); + $('.selected-row').removeClass('selected-row'); + $('#crash-table').html(''); + + }).prop('checked', false); + + let oneRowTd = $resultsTable.find('tr:nth-of-type(2)').children('td'); + let $firstTrTh = $resultsTable.find('tr:first-of-type').children('th'); + + function updateTableColumnWidth(){ + + let colWidths = []; + + $firstTrTh.each(function(i, el){ + colWidths.push($(el).width()); + }); + + oneRowTd.each(function(i, el){ + $(el).width(colWidths[i]); + }); + } + + updateTableColumnWidth(); + + $resultsTable.find('tr:first-of-type').click(function(){ + setTimeout(updateTableColumnWidth, 50); + + }); + + +})(); diff --git a/projects/tsmo/main-ui.js b/projects/tsmo/main-ui.js new file mode 100644 index 0000000..48be215 --- /dev/null +++ b/projects/tsmo/main-ui.js @@ -0,0 +1,126 @@ +/** + * Created by gavorhes on 12/14/2015. + */ +import tipConfig from './TipConfig'; +import mapMove from '../../src/olHelpers/mapMove'; +import LayerLegend from '../../src/collections/LayerLegend'; +const $ = require('jquery'); + +/** + * start the UI setup + */ +export function startUi() { + + tipConfig.$loadingGif = $('#loading-gif'); + tipConfig.$loadingGif.fadeIn(); + + tipConfig.$regionSelector = $('#region-selector'); + tipConfig.$regionSelector.val('all'); + + // configure the preset selector + let $presetSelector = $('#preset-selector'); + for (let i = 0; i < tipConfig._presetArray.length; i++) { + let weights = {}; + let sumCheck = 0; + for (let j = 0; j < tipConfig._sliderParamArray.length; j++) { + sumCheck += tipConfig._presetArray[i][1][j][0]; + weights[tipConfig._sliderParamArray[j][0].toLowerCase().replace(/ /g, '-')] = tipConfig._presetArray[i][1][j]; + } + if (sumCheck != 100) { + alert('Sum not equal to 100 for preset ' + tipConfig._presetArray[i][0]); + } + + let optionHtml = '<option value="'; + optionHtml += JSON.stringify(weights).replace(/"/g, '"'); + optionHtml += '"'; + optionHtml += (i == 0 ? ' selected="selected"' : '') + '>' + tipConfig._presetArray[i][0] + '</option>'; + + $presetSelector.append(optionHtml); + } + + //enable get help button + $('#tip-help').click(function () { + + let win = window.open('tip/help', '_blank'); + if (win) { + //Browser has allowed it to be opened + win.focus(); + } else { + //Browser has blocked it + alert('Please allow popups for this site'); + } + }); +} + + +/** + * finish the UI setup + */ +export function endUi() { + tipConfig.$loadingGif.fadeOut(); + + $('#make-report').click(function () { + let params = mapMove.mapExtent; + params['paramWeights'] = JSON.stringify(tipConfig.sliders.getParams()); + params['region'] = $('#region-selector').val(); + params['preset'] = $('#preset-selector option:selected').text(); + + let win = window.open('tip/getreport?' + $.param(params), '_blank'); + if (win) { + //Browser has allowed it to be opened + win.focus(); + } else { + //Browser has blocked it + alert('Please allow popups for this site'); + } + }); + + //add events to the preset selector + let $presetSelector = $('#preset-selector'); + + // add preset selector change handler + let first = true; + $presetSelector.change(function () { + + var weightSelection = JSON.parse(this.value); + tipConfig.sliders.setValues(weightSelection); + if (first) { + first = false; + } else { + mapMove.triggerLyrLoad(tipConfig.tipSegmentLayer); + } + }); + + $presetSelector.trigger('change'); + + $('#region-selector').change(function(){ + "use strict"; + mapMove.triggerLyrLoad(tipConfig.tipSegmentLayer); + }); + + + tipConfig.sliders.addSlideFinishedFunction(function () { + $presetSelector[0].selectedIndex = 0; + mapMove.triggerLyrLoad(tipConfig.tipSegmentLayer); + }); +} + +export function endUiMap() { + + mapMove.addCallback(function (ext, zoom, evt) { + $('#make-report').prop('disabled', !(zoom >= tipConfig.tipSegmentLayerMinZoom)); + }); + + let layerArray = [ + tipConfig.tipSegmentLayer, + tipConfig.metamanagerSegments, + { + groupName: 'ITS Inventory Layers', + collapse: true, + addCheck: false, + items: tipConfig.itsLayerCollection.layers + } + ]; + + let legend = new LayerLegend(layerArray, 'legend-container', {}); +} diff --git a/projects/tsmo/main.js b/projects/tsmo/main.js new file mode 100644 index 0000000..3a73607 --- /dev/null +++ b/projects/tsmo/main.js @@ -0,0 +1,166 @@ +/** + * Created by gavorhes on 12/14/2015. + */ +import Sliders from '../../src/collections/Sliders'; +import tipConfig from './TipConfig'; +import mapPopup from '../../src/olHelpers/mapPopup'; +import * as uiSetup from './main-ui'; +import LayerEsriMapServer from '../../src/layers/LayerEsriMapServer'; +import ItsLayerCollection from '../../src/collections/ItsLayerCollection'; +import quickMap from '../../src/olHelpers/quickMap'; +import TipSegmentLayer from './TipSegmentLayer'; + +(function () { + "use strict"; + + glob.config = tipConfig; + + uiSetup.startUi(); + + let sliders = new Sliders(tipConfig._sliderParamArray, 'slider-container'); + tipConfig.sliders = sliders; + + let map = quickMap({minZoom: 7}); + + tipConfig.map = map; + + let wisDotRegions = new LayerEsriMapServer( + 'http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/MetaManager/Metamanager_regions/MapServer', + { + minZoom: 6, + maxZoom: 12, + name: 'WisDOT Regions', + useEsriStyle: true + }); + + map.addLayer(wisDotRegions.olLayer); + + //initialize the tip segment layer + let tipSegmentLayer = new TipSegmentLayer(sliders, + { + selectionStyle: { + color: 'rgba(0,0,255,0.5)', + width: 7 + }, + $loadingGif: tipConfig.$loadingGif, + $regionSelector: tipConfig.$regionSelector + } + ); + map.addLayer(tipSegmentLayer.olLayer); + tipConfig.tipSegmentLayer = tipSegmentLayer; + + let metamanagerSegments = new LayerEsriMapServer( + 'http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/MetaManager/MM_All_Segments/MapServer', + { + minZoom: 7, + visible: false, + name: 'Metamanager Segments' + }); + + map.addLayer(metamanagerSegments.olLayer); + tipConfig.metamanagerSegments = metamanagerSegments; + + //initialize the ITS layer collection + tipConfig.itsLayerCollection = new ItsLayerCollection(map); + + uiSetup.endUi(); + uiSetup.endUiMap(); + +})(); + + +// +//let sliders; +// let app; +// let extraLayers = {}; +// +// $(function () { +// return; +// // create the sliders object +// sliders = new SliderGroup(tipConfig._sliderParamArray, 'slider-container'); +// +// $('#btnResetDefault').click(function () { +// sliders.reset(); +// }); +// + +// +// let geoJsonArray = []; +// +// for (i = 0; i < itsLayerConfig.length; i++) { +// geoJsonArray.push(new ItsGeoJsonLayer(itsLayerConfig[i], app.map, 'its-legend-items')); +// } +// +// $('#showVis').prop('checked', true); +// +// $('input[name=showAll]').change(function () { +// let $legendDivs = $('#its-legend-items > div'); +// if (this.id == 'showAll' && this.checked) { +// $legendDivs.addClass('force-show'); +// } else { +// $legendDivs.removeClass('force-show'); +// } +// }); +// +// function showHide() { +// let shown = true; +// let $legend = $('#its-legend-items'); +// let $pic = $('#show-hide'); +// return function () { +// if (shown) { +// $legend.slideUp(); +// shown = false; +// $pic.attr('src', $pic.attr('src').replace('up', 'down')); +// } else { +// $legend.slideDown(); +// shown = true; +// $pic.attr('src', $pic.attr('src').replace('down', 'up')); +// } +// } +// } +// +// +// $('#show-hide').click(showHide()).trigger('click'); +// +// $('#show-hide-all-its').prop('checked', true).change(function () { +// +// for (let i = 0; i < geoJsonArray.length; i++) { +// geoJsonArray[i].groupVisible = this.checked; +// } +// +// }); +// +// +// let url = 'http://transportal.cee.wisc.edu/applications/arcgis2/rest/services/MetaManager/MM_All_Segments/MapServer'; +// +// extraLayers['mm-layer'] = new ol.layer.Tile({ +// source: new ol.source.TileArcGISRest({ +// url: url +// }) +// }); +// +// let layerCheckboxes = $('#layer-switch').find('input[type="checkbox"]'); +// +// layerCheckboxes.each(function (idx, val) { +// val.checked = false; +// }); +// +// layerCheckboxes.click(function () { +// if (this.checked) { +// app.map.addLayer(extraLayers[this.id]) +// } else { +// app.map.removeLayer(extraLayers[this.id]) +// } +// }); +// +// //fade out the loading gif when complete +// $gif.fadeOut(); +// + +// + +// }); + + + + diff --git a/projects/tsmo/slider-test.js b/projects/tsmo/slider-test.js new file mode 100644 index 0000000..6bf939d --- /dev/null +++ b/projects/tsmo/slider-test.js @@ -0,0 +1,29 @@ +/** + * Created by gavorhes on 12/14/2015. + */ + +import Sliders from '../../src/collections/Sliders'; +import {} from '../../src/jquery-plugin/dayRange'; +import tipConfig from './TipConfig'; +const $ = require('jquery'); + +(function(){ + //alert('here'); + + let dayRange = $('#dates').dayRange(10); + + + //let sliders = new Sliders(tipConfig._sliderParamArray, 'slider-container'); + //glob.sliders = sliders; + // + // + // + // + //console.log(tipConfig); +})(); + + + + + + diff --git a/projects/tsmo/tipStyleFunction.js b/projects/tsmo/tipStyleFunction.js new file mode 100644 index 0000000..33d6c2f --- /dev/null +++ b/projects/tsmo/tipStyleFunction.js @@ -0,0 +1,84 @@ +/** + * Created by gavorhes on 12/22/2015. + */ +import * as zoomResolutionConvert from '../../src/olHelpers/zoomResolutionConvert'; +import ol from '../../src/custom-ol'; + + +/** + * tip style function + * @param feature + * @param resolution + * @returns {*[]} + */ +export function tipStyle(feature, resolution) { + + let zoom = zoomResolutionConvert.resolutionToZoom(resolution); + + let width = 5; + + if (zoom >= 18){ + width = 10; + } else if (zoom >= 14) { + width = 8; + } else if (zoom >= 12) { + width = 7; + } else if (zoom >= 10) { + width = 6; + } + + let seg_score = feature.getProperties()['z']; + let hex_color; + if (seg_score < -2.5) { + hex_color = '#00ff00'; + } else if (seg_score < -1.5) { + hex_color = '#55ff00'; + } else if (seg_score < -0.5) { + hex_color = '#aaff00'; + } else if (seg_score < 0.5) { + hex_color = '#ffff00'; + } else if (seg_score < 1.5) { + hex_color = '#ffaa00'; + } else if (seg_score < 2.5) { + hex_color = '#ff5500'; + } else { + hex_color = '#ff0000' + } + + return [new ol.style.Style({ + stroke: new ol.style.Stroke({ + color: hex_color, + width: width + }) + })]; +} + +/** + * selection style + * @param feature + * @param resolution + * @returns {*[]} + */ +export function tipStyleSelection (feature, resolution) { + + let zoom = zoomResolutionConvert.resolutionToZoom(resolution); + + let width = 5; + + if (zoom >= 18){ + width = 10; + } else if (zoom >= 14) { + width = 8; + } else if (zoom >= 12) { + width = 7; + } else if (zoom >= 10) { + width = 6; + } + + return [new ol.style.Style({ + stroke: new ol.style.Stroke({ + color: '#0074ff', + width: width + }) + })]; +} \ No newline at end of file diff --git a/src/collections/ItsLayerCollection.js b/src/collections/ItsLayerCollection.js index 78d4078..d446ae3 100644 --- a/src/collections/ItsLayerCollection.js +++ b/src/collections/ItsLayerCollection.js @@ -123,7 +123,7 @@ class ItsLayerCollection { /** * Create a collection of all ITS layers - * @param {Map} theMap the openlayers map + * @param {ol.Map} theMap the openlayers map * @param {Array} [exclude=[]] array of Its layer identifiers to exclude * * BLUE Bluetooth Detector - Bluetooth Detector diff --git a/src/collections/LayerLegend.js b/src/collections/LayerLegend.js index 6d7bb32..d852685 100644 --- a/src/collections/LayerLegend.js +++ b/src/collections/LayerLegend.js @@ -1,7 +1,7 @@ /** * Created by gavorhes on 12/16/2015. */ -const $ = require('jquery'); +import $ from '../jquery'; import provide from '../util/provide'; import makeGuid from '../util/makeGuid'; import mapMove from '../olHelpers/mapMove'; diff --git a/src/collections/Sliders.js b/src/collections/Sliders.js index 3ea46e3..6254f48 100644 --- a/src/collections/Sliders.js +++ b/src/collections/Sliders.js @@ -3,7 +3,7 @@ */ import provide from '../util/provide'; let nm = provide('collections'); -let $ = require('jquery'); +import $ from '../jquery'; class _Slider { diff --git a/src/jquery-plugin/dayRange.js b/src/jquery-plugin/dayRange.js index 21037cd..75b3b51 100644 --- a/src/jquery-plugin/dayRange.js +++ b/src/jquery-plugin/dayRange.js @@ -1,4 +1,4 @@ -let $ = require('jquery'); +import $ from '../jquery'; require('jquery-ui/datepicker'); import provide from '../util/provide'; let nm = provide('jQueryPlugin'); diff --git a/src/jquery-plugin/mediaControl.js b/src/jquery-plugin/mediaControl.js index 10565ea..5fbe63a 100644 --- a/src/jquery-plugin/mediaControl.js +++ b/src/jquery-plugin/mediaControl.js @@ -1,4 +1,4 @@ -const $ = require('jquery'); +import $ from '../jquery'; import provide from '../util/provide'; let nm = provide('jQueryPlugin'); diff --git a/src/jquery-plugin/rangeChange.js b/src/jquery-plugin/rangeChange.js index 19d8f69..eea8b88 100644 --- a/src/jquery-plugin/rangeChange.js +++ b/src/jquery-plugin/rangeChange.js @@ -4,7 +4,7 @@ * Created by gavorhes on 11/2/2015. */ -const $ = require('jquery'); +import $ from '../jquery'; let mouseIn = false; let mouseDown = false; let timeout = null; diff --git a/src/jquery-plugin/rpPicker.js b/src/jquery-plugin/rpPicker.js index dc7d958..05ffd49 100644 --- a/src/jquery-plugin/rpPicker.js +++ b/src/jquery-plugin/rpPicker.js @@ -1,4 +1,4 @@ -const $ = require('jquery'); +import $ from '../jquery'; import ol from '../custom-ol'; import quickMap from '../olHelpers/quickMap'; diff --git a/src/jquery-plugin/ssaCorridorPicker.js b/src/jquery-plugin/ssaCorridorPicker.js index eaded16..67855fb 100644 --- a/src/jquery-plugin/ssaCorridorPicker.js +++ b/src/jquery-plugin/ssaCorridorPicker.js @@ -1,4 +1,4 @@ -const $ = require('jquery'); +import $ from '../jquery'; import ol from '../custom-ol'; import quickMap from '../olHelpers/quickMap'; diff --git a/src/jquery.js b/src/jquery.js new file mode 100644 index 0000000..c863dfd --- /dev/null +++ b/src/jquery.js @@ -0,0 +1,6 @@ +/** + * Created by gavorhes on 5/3/2016. + */ +const $ = require('jquery/dist/jquery.min'); + +export default $; diff --git a/src/layers/LayerBase.js b/src/layers/LayerBase.js index ed07436..699e4a9 100644 --- a/src/layers/LayerBase.js +++ b/src/layers/LayerBase.js @@ -1,4 +1,4 @@ -const $ = require('jquery'); +import $ from '../jquery'; import makeGuid from '../util/makeGuid'; import * as zoomResolutionConvert from '../olHelpers/zoomResolutionConvert'; import provide from '../util/provide'; diff --git a/src/layers/LayerBaseVector.js b/src/layers/LayerBaseVector.js index 70af827..8dc214a 100644 --- a/src/layers/LayerBaseVector.js +++ b/src/layers/LayerBaseVector.js @@ -1,4 +1,4 @@ -const $ = require('jquery'); +import $ from '../jquery'; import ol from '../custom-ol'; import LayerBase from './LayerBase'; import mapMove from '../olHelpers/mapMove'; @@ -183,7 +183,7 @@ class LayerBaseVector extends LayerBase { /** * get the style definition - * @type {ol.Style|function} + * @type {ol.Style|styleFunc} */ get style() { return this._style; diff --git a/src/layers/LayerBaseVectorEsri.js b/src/layers/LayerBaseVectorEsri.js index 941cd3a..70862a3 100644 --- a/src/layers/LayerBaseVectorEsri.js +++ b/src/layers/LayerBaseVectorEsri.js @@ -1,7 +1,7 @@ /** * Created by gavorhes on 11/2/2015. */ -const $ = require('jquery'); +import $ from '../jquery'; import ol from '../custom-ol'; import LayerBaseVector from './LayerBaseVector'; import * as esriToOl from '../olHelpers/esriToOlStyle'; diff --git a/src/layers/LayerBaseVectorGeoJson.js b/src/layers/LayerBaseVectorGeoJson.js index 73c381c..884a280 100644 --- a/src/layers/LayerBaseVectorGeoJson.js +++ b/src/layers/LayerBaseVectorGeoJson.js @@ -1,7 +1,7 @@ /** * Created by gavorhes on 11/2/2015. */ -const $ = require('jquery'); +import $ from '../jquery'; import ol from '../custom-ol'; import LayerBaseVector from './LayerBaseVector'; import provide from '../util/provide'; diff --git a/src/layers/LayerBaseXyzTile.js b/src/layers/LayerBaseXyzTile.js index 3ccefd8..5b6ec6e 100644 --- a/src/layers/LayerBaseXyzTile.js +++ b/src/layers/LayerBaseXyzTile.js @@ -1,7 +1,7 @@ /** * Created by gavorhes on 12/4/2015. */ -const $ = require('jquery'); +import $ from '../jquery'; import ol from '../custom-ol'; import LayerBase from './LayerBase'; import * as esriToOl from '../olHelpers/esriToOlStyle'; diff --git a/src/layers/LayerEsriMapServer.js b/src/layers/LayerEsriMapServer.js index 47a23d5..759775a 100644 --- a/src/layers/LayerEsriMapServer.js +++ b/src/layers/LayerEsriMapServer.js @@ -1,7 +1,7 @@ /** * Created by gavorhes on 12/7/2015. */ -const $ = require('jquery'); +import $ from '../jquery'; import ol from '../custom-ol'; import LayerBase from './LayerBase'; import * as esriToOl from '../olHelpers/esriToOlStyle'; diff --git a/src/layers/LayerItsInventory.js b/src/layers/LayerItsInventory.js index cb793ff..e440543 100644 --- a/src/layers/LayerItsInventory.js +++ b/src/layers/LayerItsInventory.js @@ -2,7 +2,7 @@ * Created by gavorhes on 12/8/2015. */ -const $ = require('jquery'); +import $ from '../jquery'; import ol from '../custom-ol'; import LayerBaseVectorGeoJson from './LayerBaseVectorGeoJson'; import mapMove from '../olHelpers/mapMove'; diff --git a/src/layers/LayerRealEarthTile.js b/src/layers/LayerRealEarthTile.js index c7bdddd..de86709 100644 --- a/src/layers/LayerRealEarthTile.js +++ b/src/layers/LayerRealEarthTile.js @@ -2,7 +2,7 @@ * Created by gavorhes on 11/4/2015. */ -const $ = require('jquery'); +import $ from '../jquery'; import LayerBaseXyzTile from './LayerBaseXyzTile'; import RealEarthAnimateTile from '../mixin/RealEarthAnimateTile'; let mixIns = require('es6-mixins'); diff --git a/src/mixin/RealEarthAnimate.js b/src/mixin/RealEarthAnimate.js index 900105d..d2f38fc 100644 --- a/src/mixin/RealEarthAnimate.js +++ b/src/mixin/RealEarthAnimate.js @@ -3,7 +3,7 @@ */ import provide from '../util/provide'; import mapPopup from '../olHelpers/mapPopup'; -const $ = require('jquery'); +import $ from '../jquery'; let nm = provide('mixin'); diff --git a/src/olHelpers/mapMoveCls.js b/src/olHelpers/mapMoveCls.js index c93ba7f..127ac8b 100644 --- a/src/olHelpers/mapMoveCls.js +++ b/src/olHelpers/mapMoveCls.js @@ -3,7 +3,7 @@ */ -const $ = require('jquery'); +import $ from '../jquery'; import MapInteractionBase from './mapInteractionBase'; import * as checkDefined from '../util/checkDefined'; import provide from '../util/provide'; diff --git a/src/olHelpers/mapPopupCls.js b/src/olHelpers/mapPopupCls.js index 86c9256..8519140 100644 --- a/src/olHelpers/mapPopupCls.js +++ b/src/olHelpers/mapPopupCls.js @@ -2,7 +2,7 @@ * Created by gavorhes on 11/3/2015. */ -const $ = require('jquery'); +import $ from '../jquery'; import ol from '../custom-ol'; import MapInteractionBase from './mapInteractionBase'; import propertiesZoomStyle from '../olHelpers/propertiesZoomStyle'; diff --git a/src/olHelpers/quickMapBase.js b/src/olHelpers/quickMapBase.js index 0990140..338af57 100644 --- a/src/olHelpers/quickMapBase.js +++ b/src/olHelpers/quickMapBase.js @@ -6,7 +6,7 @@ * Created by gavorhes on 12/15/2015. */ -const $ = require('jquery'); +import $ from '../jquery'; import ol from '../custom-ol'; import provide from '../util/provide'; import mapMove from './mapMove'; -- GitLab